Started to improve error handling during LOOT init.

Also some settings file code refactoring.
This commit is contained in:
WrinklyNinja
2014-08-19 19:16:34 +01:00
parent fa085ac144
commit d9f6ce7ec8
5 changed files with 86 additions and 111 deletions
+4 -3
View File
@@ -237,9 +237,6 @@ namespace loot {
espm_settings = espm::Settings("fonv");
_repositoryURL = "https://github.com/loot/falloutnv.git";
_repositoryBranch = "master";
} else {
BOOST_LOG_TRIVIAL(error) << "Invalid game ID supplied.";
throw error(error::invalid_args, lc::translate("Invalid game ID supplied.").str());
}
if (!folder.empty())
@@ -279,6 +276,10 @@ namespace loot {
}
Game& Game::Init() {
if (id != Game::tes4 && id != Game::tes5 && id != Game::fo3 && id != Game::fonv) {
throw error(error::invalid_args, lc::translate("Invalid game ID supplied.").str());
}
BOOST_LOG_TRIVIAL(info) << "Initialising filesystem-related data for game: " << _name;
//First look for local install, then look for Registry.
-50
View File
@@ -35,56 +35,6 @@ along with LOOT. If not, see
using namespace std;
namespace loot {
bool AreSettingsValid(const YAML::Node& settings) {
if (!settings["language"])
return false;
if (!settings["game"])
return false;
if (!settings["lastGame"])
return false;
if (!settings["debugVerbosity"])
return false;
if (!settings["updateMasterlist"])
return false;
if (!settings["games"])
return false;
return true;
}
//Default settings file generation.
void GenerateDefaultSettingsFile(const boost::filesystem::path& file) {
BOOST_LOG_TRIVIAL(info) << "Generating default settings file.";
YAML::Node root;
std::vector<Game> games;
root["language"] = "en";
root["game"] = "auto";
root["lastGame"] = "auto";
root["debugVerbosity"] = 0;
root["updateMasterlist"] = true;
games.push_back(Game(Game::tes4));
games.push_back(Game(Game::tes5));
games.push_back(Game(Game::fo3));
games.push_back(Game(Game::fonv));
games.push_back(Game(Game::tes4, "Nehrim").SetDetails("Nehrim - At Fate's Edge", "Nehrim.esm", "https://github.com/loot/oblivion.git", "master", "", "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Nehrim - At Fate's Edge_is1\\InstallLocation"));
root["games"] = games;
//Save settings.
YAML::Emitter yout;
yout.SetIndent(2);
yout << root;
loot::ofstream out(file);
out << yout.c_str();
out.close();
}
}
namespace YAML {
Emitter& operator << (Emitter& out, const loot::PluginDirtyInfo& rhs) {
-9
View File
@@ -32,15 +32,6 @@
#include <list>
#include <boost/filesystem.hpp>
namespace loot {
// Check if the settings file has the right root keys (doesn't check
// their values).
bool AreSettingsValid(const YAML::Node& settings);
//Default settings file generation.
void GenerateDefaultSettingsFile(const boost::filesystem::path& file);
}
namespace YAML {
template<class T, class Compare>
Emitter& operator << (Emitter& out, const std::set<T, Compare>& rhs) {
+74 -48
View File
@@ -25,8 +25,10 @@
#include "app.h"
#include "handler.h"
#include "../backend/error.h"
#include "../backend/globals.h"
#include "../backend/helpers.h"
#include "../backend/parsers.h"
#include "../backend/generators.h"
#include "../backend/streams.h"
@@ -117,40 +119,30 @@ namespace loot {
LootState::LootState() : _currentGame(0) {}
void LootState::Init(const std::string& cmdLineGame) {
string initError;
//Load settings.
if (!fs::exists(g_path_settings)) {
BOOST_LOG_TRIVIAL(error) << "Settings file doesn't exist, generating new file.";
// Check if the LOOT local app data folder exists, and create it if not.
if (!fs::exists(g_path_local)) {
BOOST_LOG_TRIVIAL(info) << "Local app data LOOT folder doesn't exist, creating it.";
try {
fs::create_directory(g_path_settings.parent_path());
GenerateDefaultSettingsFile(g_path_settings);
fs::create_directory(g_path_local);
}
catch (fs::filesystem_error& /*e*/) {
initError = "Error: Could not create local app data LOOT folder.";
catch (exception& e) {
_initErrors.push_back((format(translate("Error: Could not create LOOT settings file. %1%")) % e.what()).str());
}
}
BOOST_LOG_TRIVIAL(info) << "Parsing settings file.";
try {
loot::ifstream in(g_path_settings);
_settings = YAML::Load(in);
in.close();
}
catch (YAML::ParserException& e) {
initError = (format(translate("Error: Settings parsing failed. %1%")) % e.what()).str();
}
if (!AreSettingsValid(_settings)) {
BOOST_LOG_TRIVIAL(error) << "Settings file invalid, generating new file.";
GenerateDefaultSettingsFile(g_path_settings);
if (fs::exists(g_path_settings)) {
try {
loot::ifstream in(g_path_settings);
_settings = YAML::Load(in);
in.close();
}
catch (YAML::ParserException& e) {
initError = (format(translate("Error: Settings parsing failed. %1%")) % e.what()).str();
catch (exception& e) {
_initErrors.push_back((format(translate("Error: Settings parsing failed. %1%")) % e.what()).str());
}
}
// Check if the settings are valid (or if they don't exist).
if (!AreSettingsValid(_settings)) {
_settings = GetDefaultSettings();
}
//Set up logging.
boost::log::add_file_log(
@@ -212,33 +204,33 @@ namespace loot {
}
catch (YAML::Exception& e) {
BOOST_LOG_TRIVIAL(error) << "Games' settings parsing failed. " << e.what();
initError = (format(translate("Error: Games' settings parsing failed. %1%")) % e.what()).str();
return;
_initErrors.push_back((format(translate("Error: Games' settings parsing failed. %1%")) % e.what()).str());
// Now redo, but with no games settings, so only the hardcoded defaults get loaded. It means the user can
// at least still then edit them.
_games = GetGames(YAML::Node());
}
catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Game-specific settings could not be initialised. " << e.what();
initError = (format(translate("Error: Game-specific settings could not be initialised. %1%")) % e.what()).str();
return;
}
BOOST_LOG_TRIVIAL(debug) << "Selecting game.";
try {
BOOST_LOG_TRIVIAL(debug) << "Selecting game.";
_currentGame = SelectGame(_settings, _games, cmdLineGame);
}
catch (exception &) {
BOOST_LOG_TRIVIAL(error) << "None of the supported games were detected.";
}
BOOST_LOG_TRIVIAL(debug) << "Game selected is " << _games[_currentGame].Name();
//Now that game is selected, initialise it.
BOOST_LOG_TRIVIAL(debug) << "Initialising game-specific settings.";
try {
BOOST_LOG_TRIVIAL(debug) << "Initialising game-specific settings.";
_games[_currentGame].Init();
}
catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Game-specific settings could not be initialised. " << e.what();
catch (loot::error &e) {
if (e.code() == loot::error::no_game_detected) {
BOOST_LOG_TRIVIAL(error) << e.what();
_initErrors.push_back(e.what());
}
else {
BOOST_LOG_TRIVIAL(error) << "Game-specific settings could not be initialised. " << e.what();
_initErrors.push_back((format(translate("Error: Game-specific settings could not be initialised. %1%")) % e.what()).str());
}
}
BOOST_LOG_TRIVIAL(debug) << "Game selected is " << _games[_currentGame].Name();
}
const std::vector<std::string>& LootState::InitErrors() const {
return _initErrors;
}
void LootState::ChangeGame(const std::string& newGameFolder) {
@@ -248,18 +240,14 @@ namespace loot {
});
_currentGame = std::distance(_games.begin(), it);
try {
_games[_currentGame].Init();
BOOST_LOG_TRIVIAL(debug) << "New game is " << _games[_currentGame].Name();
}
catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Game-specific settings could not be initialised." << e.what();
}
}
Game& LootState::CurrentGame() {
return _games[_currentGame];
}
const std::vector<Game>& LootState::InstalledGames() const {
return _games;
}
@@ -290,4 +278,42 @@ namespace loot {
BOOST_LOG_TRIVIAL(error) << "Failed to save LOOT's settings. Error: " << e.what();
}
}
bool LootState::AreSettingsValid(const YAML::Node& settings) {
if (!settings["language"])
return false;
if (!settings["game"])
return false;
if (!settings["lastGame"])
return false;
if (!settings["debugVerbosity"])
return false;
if (!settings["updateMasterlist"])
return false;
if (!settings["games"])
return false;
return true;
}
YAML::Node LootState::GetDefaultSettings() {
YAML::Node root;
root["language"] = "en";
root["game"] = "auto";
root["lastGame"] = "auto";
root["debugVerbosity"] = 0;
root["updateMasterlist"] = true;
std::vector<Game> games;
games.push_back(Game(Game::tes4));
games.push_back(Game(Game::tes5));
games.push_back(Game(Game::fo3));
games.push_back(Game(Game::fonv));
games.push_back(Game(Game::tes4, "Nehrim").SetDetails("Nehrim - At Fate's Edge", "Nehrim.esm", "https://github.com/loot/oblivion.git", "master", "", "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Nehrim - At Fate's Edge_is1\\InstallLocation"));
root["games"] = games;
return root;
}
}
+8 -1
View File
@@ -66,10 +66,12 @@ namespace loot {
public:
LootState();
// Init may fail with no
void Init(const std::string& cmdLineGame);
void ChangeGame(const std::string& newGameFolder);
const std::vector<std::string>& InitErrors() const;
Game& CurrentGame();
void ChangeGame(const std::string& newGameFolder);
const std::vector<Game>& InstalledGames() const;
const YAML::Node& GetSettings() const;
@@ -79,6 +81,11 @@ namespace loot {
YAML::Node _settings;
std::vector<Game> _games;
size_t _currentGame;
std::vector<std::string> _initErrors;
// Check if the settings file has the right root keys (doesn't check their values).
bool AreSettingsValid(const YAML::Node& settings);
YAML::Node GetDefaultSettings();
};
extern LootState g_app_state;