mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Finished work on issue #8.
This commit is contained in:
@@ -55,7 +55,6 @@ namespace boss {
|
||||
const boost::filesystem::path libespm_options_path = "resources/libespm.yaml";
|
||||
const boost::filesystem::path svn_path = "resources/svn/svn.exe";
|
||||
const boost::filesystem::path log_path = "BOSSDebugLog.txt";
|
||||
const boost::filesystem::path svn_log_path = "svn.log";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+101
-29
@@ -25,7 +25,17 @@
|
||||
#include "error.h"
|
||||
#include "parsers.h"
|
||||
|
||||
#include <iostream>
|
||||
#if _WIN32 || _WIN64
|
||||
# ifndef UNICODE
|
||||
# define UNICODE
|
||||
# endif
|
||||
# ifndef _UNICODE
|
||||
# define _UNICODE
|
||||
# endif
|
||||
# include "windows.h"
|
||||
# include "shlobj.h"
|
||||
#endif
|
||||
#define BUFSIZE 4096
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -33,22 +43,88 @@ namespace fs = boost::filesystem;
|
||||
|
||||
namespace boss {
|
||||
|
||||
unsigned int UpdateMasterlist(const Game& game, std::vector<std::string>& parsingErrors) {
|
||||
string command;
|
||||
//First check if the working copy is set up or not.
|
||||
command = svn_path.string() + " info " + game.MasterlistPath().parent_path().string() + " > " + svn_log_path.string();
|
||||
bool RunCommand(const std::string& command, std::string& output) {
|
||||
HANDLE consoleWrite = NULL;
|
||||
HANDLE consoleRead = NULL;
|
||||
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
|
||||
PROCESS_INFORMATION piProcInfo;
|
||||
STARTUPINFO siStartInfo;
|
||||
|
||||
CHAR chBuf[BUFSIZE];
|
||||
DWORD dwRead;
|
||||
|
||||
if (system(command.c_str()) != 0) {
|
||||
DWORD exitCode;
|
||||
|
||||
//Init attributes.
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
//Create I/O pipes.
|
||||
if (!CreatePipe(&consoleRead, &consoleWrite, &saAttr, 0))
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Could not create pipe for Subversion process.");
|
||||
|
||||
//Create a child process.
|
||||
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
|
||||
|
||||
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
|
||||
siStartInfo.cb = sizeof(STARTUPINFO);
|
||||
siStartInfo.hStdError = consoleWrite;
|
||||
siStartInfo.hStdOutput = consoleWrite;
|
||||
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||
|
||||
const int utf16Len = MultiByteToWideChar(CP_UTF8, 0, command.c_str(), -1, NULL, 0);
|
||||
wchar_t * cmdLine = new wchar_t[utf16Len];
|
||||
MultiByteToWideChar(CP_UTF8, 0, command.c_str(), -1, cmdLine, utf16Len);
|
||||
|
||||
bool result = CreateProcess(NULL,
|
||||
cmdLine, // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
0, // creation flags
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&piProcInfo); // receives PROCESS_INFORMATION
|
||||
|
||||
delete [] cmdLine;
|
||||
|
||||
if (!result)
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Could not create Subversion process.");
|
||||
|
||||
WaitForSingleObject(piProcInfo.hProcess, INFINITE);
|
||||
|
||||
if (!GetExitCodeProcess(piProcInfo.hProcess, &exitCode))
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Could not get Subversion process exit code.");
|
||||
|
||||
if (!ReadFile(consoleRead, chBuf, BUFSIZE, &dwRead, NULL))
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Could not read Subversion process output.");
|
||||
|
||||
output = string(chBuf, dwRead);
|
||||
|
||||
return exitCode == 0;
|
||||
}
|
||||
|
||||
std::string UpdateMasterlist(const Game& game, std::vector<std::string>& parsingErrors) {
|
||||
|
||||
string command, output;
|
||||
//First check if the working copy is set up or not.
|
||||
command = svn_path.string() + " info " + game.MasterlistPath().parent_path().string();
|
||||
|
||||
if (!RunCommand(command, output)) {
|
||||
//Working copy not set up, perform a checkout.
|
||||
command = svn_path.string() + " co --depth empty " + game.URL().substr(0, game.URL().rfind('/')) + " " + game.MasterlistPath().parent_path().string() + "/. > " + svn_log_path.string();
|
||||
if (system(command.c_str()) != 0)
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Subversion could not perform a checkout. See " + svn_log_path.string() + " in the BOSS folder for details.");
|
||||
command = svn_path.string() + " co --depth empty " + game.URL().substr(0, game.URL().rfind('/')) + " " + game.MasterlistPath().parent_path().string() + "/.";
|
||||
if (!RunCommand(command, output))
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Subversion could not perform a checkout. Details: " + output);
|
||||
}
|
||||
|
||||
//Now update masterlist.
|
||||
command = svn_path.string() + " update " + game.MasterlistPath().string() + " > " + svn_log_path.string();
|
||||
if (system(command.c_str()) != 0)
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Subversion could not update the masterlist. See " + svn_log_path.string() + " in the BOSS folder for details.");
|
||||
command = svn_path.string() + " update " + game.MasterlistPath().string();
|
||||
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;
|
||||
@@ -59,31 +135,27 @@ namespace boss {
|
||||
} catch (YAML::Exception& e) {
|
||||
//Roll back one revision if there's an error.
|
||||
parsingErrors.push_back(e.what());
|
||||
command = svn_path.string() + " update --revision PREV " + game.MasterlistPath().string() + " > " + svn_log_path.string();
|
||||
if (system(command.c_str()) != 0)
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Subversion could not update the masterlist. See " + svn_log_path.string() + " in the BOSS folder for details.");
|
||||
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().parent_path().string() + " > " + svn_log_path.string();
|
||||
if (system(command.c_str()) != 0)
|
||||
throw error(ERROR_SUBVERSION_ERROR, "Subversion could not read the masterlist revision number. See " + svn_log_path.string() + " in the BOSS folder for details.");
|
||||
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);
|
||||
|
||||
ifstream in(svn_log_path.string().c_str());
|
||||
size_t pos1 = output.rfind("Revision: ");
|
||||
size_t pos2 = output.find('\n', pos1);
|
||||
|
||||
int revision = 0;
|
||||
while (in.good()) {
|
||||
string line;
|
||||
getline(in, line);
|
||||
string revision = output.substr(pos1+10, pos2-pos1-10);
|
||||
|
||||
if (line.substr(0, 10) == "Revision: ")
|
||||
revision = atoi(line.substr(10).c_str());
|
||||
}
|
||||
in.close();
|
||||
pos1 = output.find("Last Changed Date: ", pos2);
|
||||
pos2 = output.find(' ', pos1+19);
|
||||
|
||||
fs::remove(svn_log_path);
|
||||
string date = output.substr(pos1+19, pos2-pos1-19);
|
||||
|
||||
return revision;
|
||||
return revision + " (" + date + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,6 @@ namespace boss {
|
||||
```svn info masterlist.txt``` returns a bunch of info: the line "Revision: XXXX" contains the revision number.
|
||||
*/
|
||||
|
||||
unsigned int UpdateMasterlist(const Game& game, std::vector<std::string>& parsingErrors);
|
||||
std::string UpdateMasterlist(const Game& game, std::vector<std::string>& parsingErrors);
|
||||
}
|
||||
#endif
|
||||
|
||||
+3
-2
@@ -323,8 +323,9 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) {
|
||||
out << "Updating masterlist..." << endl;
|
||||
|
||||
vector<string> parsingErrors;
|
||||
string revision;
|
||||
try {
|
||||
UpdateMasterlist(_game, parsingErrors);
|
||||
revision = UpdateMasterlist(_game, parsingErrors);
|
||||
} catch (boss::error& e) {
|
||||
//LOG_ERROR("Error: %s", e.what());
|
||||
wxMessageBox(
|
||||
@@ -625,7 +626,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) {
|
||||
messages,
|
||||
plugins,
|
||||
oldDetails,
|
||||
"4030 (2020-13-13)",
|
||||
revision,
|
||||
_settings["Update Masterlist"].as<bool>());
|
||||
} catch (boss::error& e) {
|
||||
wxMessageBox(
|
||||
|
||||
Reference in New Issue
Block a user