mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Bug fixes.
Fixed resource paths in report being wrong, updating masterlist no longer displays command line window, settings file is now read after creation if creation is necessary, and fixed some error handling during sorting.
This commit is contained in:
@@ -129,11 +129,11 @@ namespace boss {
|
||||
node = head.append_child();
|
||||
node.set_name("link");
|
||||
node.append_attribute("rel").set_value("stylesheet");
|
||||
node.append_attribute("href").set_value("../resources/style.css");
|
||||
node.append_attribute("href").set_value(ToFileURL(css_path).c_str());
|
||||
|
||||
node = head.append_child();
|
||||
node.set_name("script");
|
||||
node.append_attribute("src").set_value("../resources/polyfill.js");
|
||||
node.append_attribute("src").set_value(ToFileURL(polyfill_path).c_str());
|
||||
node.text().set(" ");
|
||||
}
|
||||
|
||||
@@ -448,7 +448,7 @@ namespace boss {
|
||||
|
||||
node = body.append_child();
|
||||
node.set_name("script");
|
||||
node.append_attribute("src").set_value("../resources/script.js");
|
||||
node.append_attribute("src").set_value(ToFileURL(js_path).c_str());
|
||||
node.text().set(" ");
|
||||
|
||||
}
|
||||
|
||||
@@ -49,10 +49,13 @@ namespace boss {
|
||||
const unsigned int VERSION_PATCH = 0;
|
||||
|
||||
//Common paths.
|
||||
const boost::filesystem::path readme_path = "Docs/BOSS Readme.html";
|
||||
const boost::filesystem::path readme_path = "docs/BOSS Readme.html";
|
||||
const boost::filesystem::path libespm_options_path = "resources/libespm.yaml";
|
||||
const boost::filesystem::path svn_path = "resources/svn/svn.exe";
|
||||
const boost::filesystem::path local_path = GetLocalAppDataPath() / "BOSS";
|
||||
const boost::filesystem::path css_path = boost::filesystem::current_path() / "resources" / "style.css";
|
||||
const boost::filesystem::path js_path = boost::filesystem::current_path() / "resources" / "script.js";
|
||||
const boost::filesystem::path polyfill_path = boost::filesystem::current_path() / "resources" / "polyfill.js";
|
||||
const boost::filesystem::path settings_path = local_path / "settings.yaml";
|
||||
const boost::filesystem::path log_path = local_path / "BOSSDebugLog.txt";
|
||||
}
|
||||
|
||||
@@ -54,6 +54,9 @@ namespace boss {
|
||||
extern const boost::filesystem::path readme_path;
|
||||
extern const boost::filesystem::path settings_path;
|
||||
extern const boost::filesystem::path libespm_options_path;
|
||||
extern const boost::filesystem::path css_path;
|
||||
extern const boost::filesystem::path js_path;
|
||||
extern const boost::filesystem::path polyfill_path;
|
||||
extern const boost::filesystem::path svn_path;
|
||||
extern const boost::filesystem::path log_path;
|
||||
}
|
||||
|
||||
@@ -220,6 +220,31 @@ namespace boss {
|
||||
return fs::path("");
|
||||
#endif
|
||||
}
|
||||
|
||||
//Turns an absolute filesystem path into a valid file:// URL.
|
||||
std::string ToFileURL(const fs::path& file) {
|
||||
//URLs are UTF-8 encoded then any characters (equiv. their corresponding bytes) not in the unreserved set (equiv. their corresponding bytes) are replaced by a percentage sign followed by the hex representation of their binary value.
|
||||
string unreserved = "-.0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; //Unreserved in byte value order, plus the colon character since that's allowed for drive paths.
|
||||
|
||||
string url = "file://";
|
||||
for (boost::filesystem::path::const_iterator it=file.begin(), endit=file.end(); it != endit; ++it) {
|
||||
string part = it->string();
|
||||
if (part == "/") //Skip exta backslash after drive path.
|
||||
continue;
|
||||
//String iterator is byte-by-byte, not character-by-character, which is good.
|
||||
for (string::const_iterator jt=part.begin(), endjt=part.end(); jt != endjt; ++jt) {
|
||||
if (!binary_search(unreserved.begin(), unreserved.end(), *jt))
|
||||
//Replace with percentage-hex value.
|
||||
url += '%' + IntToHexString(*jt);
|
||||
else
|
||||
url += *jt;
|
||||
}
|
||||
url += '/';
|
||||
}
|
||||
url.resize(url.length()-1); //Get rid of trailing forward slash.
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
@@ -66,6 +66,9 @@ namespace boss {
|
||||
//Get the local application data path.
|
||||
boost::filesystem::path GetLocalAppDataPath();
|
||||
|
||||
//Turns an absolute filesystem path into a valid file:// URL.
|
||||
std::string ToFileURL(const boost::filesystem::path& file);
|
||||
|
||||
//Version class for more robust version comparisons.
|
||||
class Version {
|
||||
private:
|
||||
|
||||
+25
-23
@@ -73,7 +73,8 @@ namespace boss {
|
||||
siStartInfo.cb = sizeof(STARTUPINFO);
|
||||
siStartInfo.hStdError = consoleWrite;
|
||||
siStartInfo.hStdOutput = consoleWrite;
|
||||
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||
siStartInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||
siStartInfo.wShowWindow = SW_HIDE;
|
||||
|
||||
const int utf16Len = MultiByteToWideChar(CP_UTF8, 0, command.c_str(), -1, NULL, 0);
|
||||
wchar_t * cmdLine = new wchar_t[utf16Len];
|
||||
@@ -126,36 +127,37 @@ namespace boss {
|
||||
if (!RunCommand(command, output))
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Subversion could not update the masterlist. Details: " + output);
|
||||
|
||||
//Now test masterlist to see if it parses OK.
|
||||
bool good = false;
|
||||
while (!good) {
|
||||
|
||||
string revision;
|
||||
while (true) {
|
||||
try {
|
||||
|
||||
//Now get the masterlist revision.
|
||||
command = svn_path.string() + " info \"" + game.MasterlistPath().string() + "\"";
|
||||
if (!RunCommand(command, output))
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Subversion could not read the masterlist revision number. Details: " + output);
|
||||
|
||||
size_t pos1 = output.rfind("Revision: ");
|
||||
size_t pos2 = output.find('\n', pos1);
|
||||
|
||||
revision = output.substr(pos1+10, pos2-pos1-10);
|
||||
|
||||
pos1 = output.find("Last Changed Date: ", pos2);
|
||||
pos2 = output.find(' ', pos1+19);
|
||||
|
||||
string date = output.substr(pos1+19, pos2-pos1-19);
|
||||
|
||||
//Now test masterlist to see if it parses OK.
|
||||
YAML::Node mlist = YAML::LoadFile(game.MasterlistPath().string());
|
||||
good = true;
|
||||
|
||||
return revision + " (" + date + ")";
|
||||
} catch (YAML::Exception& e) {
|
||||
//Roll back one revision if there's an error.
|
||||
parsingErrors.push_back(e.what());
|
||||
parsingErrors.push_back("Masterlist revision " + revision + ": " + e.what());
|
||||
command = svn_path.string() + " update --revision PREV \"" + game.MasterlistPath().string() + "\"";
|
||||
if (!RunCommand(command, output))
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Subversion could not update the masterlist. Details: " + output);
|
||||
}
|
||||
}
|
||||
|
||||
//Now get the masterlist revision. Can either create a pipe using the Win32 API (http://msdn.microsoft.com/en-us/library/ms682499.aspx), or output to a file, read it, then delete it.
|
||||
command = svn_path.string() + " info \"" + game.MasterlistPath().string() + "\"";
|
||||
if (!RunCommand(command, output))
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Subversion could not read the masterlist revision number. Details: " + output);
|
||||
|
||||
size_t pos1 = output.rfind("Revision: ");
|
||||
size_t pos2 = output.find('\n', pos1);
|
||||
|
||||
string revision = output.substr(pos1+10, pos2-pos1-10);
|
||||
|
||||
pos1 = output.find("Last Changed Date: ", pos2);
|
||||
pos2 = output.find(' ', pos1+19);
|
||||
|
||||
string date = output.substr(pos1+19, pos2-pos1-19);
|
||||
|
||||
return revision + " (" + date + ")";
|
||||
}
|
||||
}
|
||||
|
||||
+27
-32
@@ -79,19 +79,7 @@ bool BossGUI::OnInit() {
|
||||
}
|
||||
|
||||
//Load settings.
|
||||
if (fs::exists(settings_path)) {
|
||||
try {
|
||||
_settings = YAML::LoadFile(settings_path.string());
|
||||
} catch (YAML::ParserException& e) {
|
||||
//LOG_ERROR("Error: %s", e.getString().c_str());
|
||||
wxMessageBox(
|
||||
FromUTF8(format(loc::translate("Error: Settings parsing failed. %1%")) % e.what()),
|
||||
translate("BOSS: Error"),
|
||||
wxOK | wxICON_ERROR,
|
||||
NULL);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!fs::exists(settings_path)) {
|
||||
try {
|
||||
if (!fs::exists(settings_path.parent_path()))
|
||||
fs::create_directory(settings_path.parent_path());
|
||||
@@ -105,6 +93,19 @@ bool BossGUI::OnInit() {
|
||||
}
|
||||
GenerateDefaultSettingsFile(settings_path.string());
|
||||
}
|
||||
if (fs::exists(settings_path)) {
|
||||
try {
|
||||
_settings = YAML::LoadFile(settings_path.string());
|
||||
} catch (YAML::ParserException& e) {
|
||||
//LOG_ERROR("Error: %s", e.getString().c_str());
|
||||
wxMessageBox(
|
||||
FromUTF8(format(loc::translate("Error: Settings parsing failed. %1%")) % e.what()),
|
||||
translate("BOSS: Error"),
|
||||
wxOK | wxICON_ERROR,
|
||||
NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Skip logging initialisation for tester.
|
||||
/* if (gl_log_debug_output)
|
||||
@@ -327,6 +328,11 @@ void Launcher::OnClose(wxCloseEvent& event) {
|
||||
|
||||
void Launcher::OnSortPlugins(wxCommandEvent& event) {
|
||||
|
||||
YAML::Node mlist, ulist;
|
||||
list<boss::Message> messages, mlist_messages, ulist_messages;
|
||||
list<boss::Plugin> mlist_plugins, ulist_plugins;
|
||||
time_t start, end;
|
||||
|
||||
wxProgressDialog *progDia = new wxProgressDialog(translate("BOSS: Working..."),translate("BOSS working..."), 1000, this, wxPD_APP_MODAL|wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME);
|
||||
|
||||
time_t t0 = time(NULL);
|
||||
@@ -334,7 +340,6 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) {
|
||||
ofstream out((local_path / "out.txt").string().c_str());
|
||||
|
||||
out << "Updating masterlist..." << endl;
|
||||
time_t start, end;
|
||||
start = time(NULL);
|
||||
|
||||
vector<string> parsingErrors;
|
||||
@@ -342,13 +347,10 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) {
|
||||
try {
|
||||
revision = UpdateMasterlist(_game, parsingErrors);
|
||||
} catch (boss::error& e) {
|
||||
//LOG_ERROR("Error: %s", e.what());
|
||||
wxMessageBox(
|
||||
FromUTF8(format(loc::translate("Error: Condition evaluation failed. %1%")) % e.what()),
|
||||
translate("BOSS: Error"),
|
||||
wxOK | wxICON_ERROR,
|
||||
this);
|
||||
return;
|
||||
messages.push_back(boss::Message(boss::MESSAGE_ERROR, string("Masterlist update failed. Details: ") + e.what()));
|
||||
}
|
||||
for (vector<string>::const_iterator it=parsingErrors.begin(), endit=parsingErrors.end(); it != endit; ++it) {
|
||||
messages.push_back(boss::Message(boss::MESSAGE_ERROR, *it));
|
||||
}
|
||||
|
||||
end = time(NULL);
|
||||
@@ -376,10 +378,6 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) {
|
||||
out << "Time taken to read plugins: " << (end - start) << " seconds." << endl;
|
||||
start = time(NULL);
|
||||
|
||||
YAML::Node mlist, ulist;
|
||||
list<boss::Message> messages, mlist_messages, ulist_messages;
|
||||
list<boss::Plugin> mlist_plugins, ulist_plugins;
|
||||
|
||||
if (fs::exists(_game.MasterlistPath())) {
|
||||
out << "Parsing masterlist..." << endl;
|
||||
|
||||
@@ -392,6 +390,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) {
|
||||
translate("BOSS: Error"),
|
||||
wxOK | wxICON_ERROR,
|
||||
this);
|
||||
progDia->Destroy();
|
||||
return;
|
||||
}
|
||||
if (mlist["globals"])
|
||||
@@ -416,6 +415,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) {
|
||||
translate("BOSS: Error"),
|
||||
wxOK | wxICON_ERROR,
|
||||
this);
|
||||
progDia->Destroy();
|
||||
return;
|
||||
}
|
||||
if (ulist["plugins"])
|
||||
@@ -461,13 +461,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) {
|
||||
try {
|
||||
it->EvalAllConditions(_game, lang);
|
||||
} catch (boss::error& e) {
|
||||
//LOG_ERROR("Error: %s", e.what());
|
||||
wxMessageBox(
|
||||
FromUTF8(format(loc::translate("Error: Condition evaluation failed. %1%")) % e.what()),
|
||||
translate("BOSS: Error"),
|
||||
wxOK | wxICON_ERROR,
|
||||
this);
|
||||
return;
|
||||
messages.push_back(boss::Message(boss::MESSAGE_ERROR, "\"" + it->Name() + "\" contains a condition that could not be evaluated. Details: " + e.what()));
|
||||
}
|
||||
|
||||
progDia->Pulse();
|
||||
@@ -652,6 +646,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) {
|
||||
translate("BOSS: Error"),
|
||||
wxOK | wxICON_ERROR,
|
||||
this);
|
||||
progDia->Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+13
-13
@@ -262,14 +262,14 @@ LangString TEXT_USERFILES ${LANG_SIMPCHINESE} "BOSS的userlist和BOSS.ini文件
|
||||
File "..\build\libboss64.dll"
|
||||
|
||||
;Now install readme files.
|
||||
SetOutPath "$INSTDIR\Docs"
|
||||
SetOutPath "$INSTDIR\docs"
|
||||
File "..\docs\BOSS API Readme.html"
|
||||
File "..\docs\BOSS Metadata Syntax.html"
|
||||
File "..\docs\BOSS Readme.html"
|
||||
File "..\docs\Licenses.txt"
|
||||
|
||||
;Now install readme images.
|
||||
SetOutPath "$INSTDIR\Docs\images"
|
||||
SetOutPath "$INSTDIR\docs\images"
|
||||
File "..\docs\images\editor.png"
|
||||
File "..\docs\images\main.png"
|
||||
File "..\docs\images\settings.png"
|
||||
@@ -383,19 +383,19 @@ LangString TEXT_USERFILES ${LANG_SIMPCHINESE} "BOSS的userlist和BOSS.ini文件
|
||||
RMDir "$INSTDIR\API"
|
||||
|
||||
;Remove readme files.
|
||||
Delete "$INSTDIR\Docs\BOSS API Readme.html"
|
||||
Delete "$INSTDIR\Docs\BOSS Metadata Syntax.html"
|
||||
Delete "$INSTDIR\Docs\BOSS Readme.html"
|
||||
Delete "$INSTDIR\Docs\Licenses.txt"
|
||||
RMDir "$INSTDIR\Docs"
|
||||
Delete "$INSTDIR\docs\BOSS API Readme.html"
|
||||
Delete "$INSTDIR\docs\BOSS Metadata Syntax.html"
|
||||
Delete "$INSTDIR\docs\BOSS Readme.html"
|
||||
Delete "$INSTDIR\docs\Licenses.txt"
|
||||
RMDir "$INSTDIR\docs"
|
||||
|
||||
;Remove readme images.
|
||||
Delete "$INSTDIR\Docs\images\editor.png"
|
||||
Delete "$INSTDIR\Docs\images\main.png"
|
||||
Delete "$INSTDIR\Docs\images\settings.png"
|
||||
Delete "$INSTDIR\Docs\images\viewer-1.png"
|
||||
Delete "$INSTDIR\Docs\images\viewer-2.png"
|
||||
RMDir "$INSTDIR\Docs\images"
|
||||
Delete "$INSTDIR\docs\images\editor.png"
|
||||
Delete "$INSTDIR\docs\images\main.png"
|
||||
Delete "$INSTDIR\docs\images\settings.png"
|
||||
Delete "$INSTDIR\docs\images\viewer-1.png"
|
||||
Delete "$INSTDIR\docs\images\viewer-2.png"
|
||||
RMDir "$INSTDIR\docs\images"
|
||||
|
||||
;Remove resource files.
|
||||
Delete "$INSTDIR\resources\libespm.yaml"
|
||||
|
||||
Reference in New Issue
Block a user