Merge pull request #6496 from delroth/updater
Moar auto-updater improvements
This commit is contained in:
commit
733186d48b
|
@ -664,33 +664,42 @@ std::string GetBundleDirectory()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string& GetExeDirectory()
|
std::string GetExePath()
|
||||||
{
|
{
|
||||||
static std::string DolphinPath;
|
static std::string dolphin_path;
|
||||||
if (DolphinPath.empty())
|
if (dolphin_path.empty())
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
TCHAR Dolphin_exe_Path[2048];
|
TCHAR dolphin_exe_path[2048];
|
||||||
TCHAR Dolphin_exe_Clean_Path[MAX_PATH];
|
TCHAR dolphin_exe_expanded_path[MAX_PATH];
|
||||||
GetModuleFileName(nullptr, Dolphin_exe_Path, 2048);
|
GetModuleFileName(nullptr, dolphin_exe_path, ARRAYSIZE(dolphin_exe_path));
|
||||||
if (_tfullpath(Dolphin_exe_Clean_Path, Dolphin_exe_Path, MAX_PATH) != nullptr)
|
if (_tfullpath(dolphin_exe_expanded_path, dolphin_exe_path,
|
||||||
DolphinPath = TStrToUTF8(Dolphin_exe_Clean_Path);
|
ARRAYSIZE(dolphin_exe_expanded_path)) != nullptr)
|
||||||
|
dolphin_path = TStrToUTF8(dolphin_exe_expanded_path);
|
||||||
else
|
else
|
||||||
DolphinPath = TStrToUTF8(Dolphin_exe_Path);
|
dolphin_path = TStrToUTF8(dolphin_exe_path);
|
||||||
DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\'));
|
|
||||||
#else
|
#else
|
||||||
char Dolphin_exe_Path[PATH_MAX];
|
char dolphin_exe_path[PATH_MAX];
|
||||||
ssize_t len = ::readlink("/proc/self/exe", Dolphin_exe_Path, sizeof(Dolphin_exe_Path));
|
ssize_t len = ::readlink("/proc/self/exe", dolphin_exe_path, sizeof(dolphin_exe_path));
|
||||||
if (len == -1 || len == sizeof(Dolphin_exe_Path))
|
if (len == -1 || len == sizeof(dolphin_exe_path))
|
||||||
{
|
{
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
Dolphin_exe_Path[len] = '\0';
|
dolphin_exe_path[len] = '\0';
|
||||||
DolphinPath = Dolphin_exe_Path;
|
dolphin_path = dolphin_exe_path;
|
||||||
DolphinPath = DolphinPath.substr(0, DolphinPath.rfind('/'));
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return DolphinPath;
|
return dolphin_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetExeDirectory()
|
||||||
|
{
|
||||||
|
std::string exe_path = GetExePath();
|
||||||
|
#ifdef _WIN32
|
||||||
|
return exe_path.substr(0, exe_path.rfind('\\'));
|
||||||
|
#else
|
||||||
|
return exe_path.substr(0, exe_path.rfind('/'));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetSysDirectory()
|
std::string GetSysDirectory()
|
||||||
|
@ -882,4 +891,4 @@ bool ReadFileToString(const std::string& filename, std::string& str)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace File
|
||||||
|
|
|
@ -191,7 +191,8 @@ void SetSysDirectory(const std::string& path);
|
||||||
std::string GetBundleDirectory();
|
std::string GetBundleDirectory();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string& GetExeDirectory();
|
std::string GetExePath();
|
||||||
|
std::string GetExeDirectory();
|
||||||
|
|
||||||
bool WriteStringToFile(const std::string& str, const std::string& filename);
|
bool WriteStringToFile(const std::string& str, const std::string& filename);
|
||||||
bool ReadFileToString(const std::string& filename, std::string& str);
|
bool ReadFileToString(const std::string& filename, std::string& str);
|
||||||
|
|
|
@ -80,7 +80,8 @@ void Updater::OnUpdateAvailable(const NewVersionInformation& info)
|
||||||
|
|
||||||
if (choice == QDialog::Accepted)
|
if (choice == QDialog::Accepted)
|
||||||
{
|
{
|
||||||
TriggerUpdate(info);
|
TriggerUpdate(info, later ? AutoUpdateChecker::RestartMode::NO_RESTART_AFTER_UPDATE :
|
||||||
|
AutoUpdateChecker::RestartMode::RESTART_AFTER_UPDATE);
|
||||||
|
|
||||||
if (!later)
|
if (!later)
|
||||||
m_parent->close();
|
m_parent->close();
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "UICommon/AutoUpdate.h"
|
#include "UICommon/AutoUpdate.h"
|
||||||
|
|
||||||
#include <picojson/picojson.h>
|
#include <picojson/picojson.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "Common/CommonPaths.h"
|
#include "Common/CommonPaths.h"
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
|
@ -46,6 +47,48 @@ void CleanupFromPreviousUpdate()
|
||||||
File::Delete(reloc_updater_path);
|
File::Delete(reloc_updater_path);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// This ignores i18n because most of the text in there (change descriptions) is only going to be
|
||||||
|
// written in english anyway.
|
||||||
|
std::string GenerateChangelog(const picojson::array& versions)
|
||||||
|
{
|
||||||
|
std::string changelog;
|
||||||
|
for (const auto& ver : versions)
|
||||||
|
{
|
||||||
|
if (!ver.is<picojson::object>())
|
||||||
|
continue;
|
||||||
|
picojson::object ver_obj = ver.get<picojson::object>();
|
||||||
|
|
||||||
|
if (ver_obj["changelog_html"].is<picojson::null>())
|
||||||
|
{
|
||||||
|
if (!changelog.empty())
|
||||||
|
changelog += "<div style=\"margin-top: 0.4em;\"></div>"; // Vertical spacing.
|
||||||
|
|
||||||
|
// Try to link to the PR if we have this info. Otherwise just show shortrev.
|
||||||
|
if (ver_obj["pr_url"].is<std::string>())
|
||||||
|
{
|
||||||
|
changelog += "<a href=\"" + ver_obj["pr_url"].get<std::string>() + "\">" +
|
||||||
|
ver_obj["shortrev"].get<std::string>() + "</a>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
changelog += ver_obj["shortrev"].get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
changelog += " by <a href = \"" + ver_obj["author_url"].get<std::string>() + "\">" +
|
||||||
|
ver_obj["author"].get<std::string>() + "</a> — " +
|
||||||
|
ver_obj["short_descr"].get<std::string>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!changelog.empty())
|
||||||
|
changelog += "<hr>";
|
||||||
|
changelog += "<b>Dolphin " + ver_obj["shortrev"].get<std::string>() + "</b>";
|
||||||
|
changelog += "<p>" + ver_obj["changelog_html"].get<std::string>() + "</p>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changelog;
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool AutoUpdateChecker::SystemSupportsAutoUpdates()
|
bool AutoUpdateChecker::SystemSupportsAutoUpdates()
|
||||||
|
@ -106,12 +149,13 @@ void AutoUpdateChecker::CheckForUpdate()
|
||||||
nvi.new_hash = obj["new"].get<picojson::object>()["hash"].get<std::string>();
|
nvi.new_hash = obj["new"].get<picojson::object>()["hash"].get<std::string>();
|
||||||
|
|
||||||
// TODO: generate the HTML changelog from the JSON information.
|
// TODO: generate the HTML changelog from the JSON information.
|
||||||
nvi.changelog_html = "<h2>TBD</h2>";
|
nvi.changelog_html = GenerateChangelog(obj["changelog"].get<picojson::array>());
|
||||||
|
|
||||||
OnUpdateAvailable(nvi);
|
OnUpdateAvailable(nvi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInformation& info)
|
void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInformation& info,
|
||||||
|
AutoUpdateChecker::RestartMode restart_mode)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::map<std::string, std::string> updater_flags;
|
std::map<std::string, std::string> updater_flags;
|
||||||
|
@ -122,6 +166,9 @@ void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInforma
|
||||||
updater_flags["install-base-path"] = File::GetExeDirectory();
|
updater_flags["install-base-path"] = File::GetExeDirectory();
|
||||||
updater_flags["log-file"] = File::GetExeDirectory() + DIR_SEP + UPDATER_LOG_FILE;
|
updater_flags["log-file"] = File::GetExeDirectory() + DIR_SEP + UPDATER_LOG_FILE;
|
||||||
|
|
||||||
|
if (restart_mode == RestartMode::RESTART_AFTER_UPDATE)
|
||||||
|
updater_flags["binary-to-restart"] = File::GetExePath();
|
||||||
|
|
||||||
// Copy the updater so it can update itself if needed.
|
// Copy the updater so it can update itself if needed.
|
||||||
std::string updater_path = File::GetExeDirectory() + DIR_SEP + UPDATER_FILENAME;
|
std::string updater_path = File::GetExeDirectory() + DIR_SEP + UPDATER_FILENAME;
|
||||||
std::string reloc_updater_path = File::GetExeDirectory() + DIR_SEP + UPDATER_RELOC_FILENAME;
|
std::string reloc_updater_path = File::GetExeDirectory() + DIR_SEP + UPDATER_RELOC_FILENAME;
|
||||||
|
@ -130,6 +177,7 @@ void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInforma
|
||||||
// Run the updater!
|
// Run the updater!
|
||||||
std::wstring command_line = MakeUpdaterCommandLine(updater_flags);
|
std::wstring command_line = MakeUpdaterCommandLine(updater_flags);
|
||||||
STARTUPINFO sinfo = {sizeof(info)};
|
STARTUPINFO sinfo = {sizeof(info)};
|
||||||
|
sinfo.dwFlags = STARTF_FORCEOFFFEEDBACK; // No hourglass cursor after starting the process.
|
||||||
PROCESS_INFORMATION pinfo;
|
PROCESS_INFORMATION pinfo;
|
||||||
INFO_LOG(COMMON, "Updater command line: %s", UTF16ToUTF8(command_line).c_str());
|
INFO_LOG(COMMON, "Updater command line: %s", UTF16ToUTF8(command_line).c_str());
|
||||||
if (!CreateProcessW(UTF8ToUTF16(reloc_updater_path).c_str(),
|
if (!CreateProcessW(UTF8ToUTF16(reloc_updater_path).c_str(),
|
||||||
|
|
|
@ -33,7 +33,12 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Starts the updater process, which will wait in the background until the current process exits.
|
// Starts the updater process, which will wait in the background until the current process exits.
|
||||||
void TriggerUpdate(const NewVersionInformation& info);
|
enum class RestartMode
|
||||||
|
{
|
||||||
|
NO_RESTART_AFTER_UPDATE = 0,
|
||||||
|
RESTART_AFTER_UPDATE,
|
||||||
|
};
|
||||||
|
void TriggerUpdate(const NewVersionInformation& info, RestartMode restart_mode);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void OnUpdateAvailable(const NewVersionInformation& info) = 0;
|
virtual void OnUpdateAvailable(const NewVersionInformation& info) = 0;
|
||||||
|
|
|
@ -47,6 +47,7 @@ struct Options
|
||||||
std::string next_manifest_url;
|
std::string next_manifest_url;
|
||||||
std::string content_store_url;
|
std::string content_store_url;
|
||||||
std::string install_base_path;
|
std::string install_base_path;
|
||||||
|
std::optional<std::string> binary_to_restart;
|
||||||
std::optional<DWORD> parent_pid;
|
std::optional<DWORD> parent_pid;
|
||||||
std::optional<std::string> log_file;
|
std::optional<std::string> log_file;
|
||||||
};
|
};
|
||||||
|
@ -90,6 +91,10 @@ std::optional<Options> ParseCommandLine(PCWSTR command_line)
|
||||||
.dest("install-base-path")
|
.dest("install-base-path")
|
||||||
.help("Base path of the Dolphin install to be updated.")
|
.help("Base path of the Dolphin install to be updated.")
|
||||||
.metavar("PATH");
|
.metavar("PATH");
|
||||||
|
parser.add_option("--binary-to-restart")
|
||||||
|
.dest("binary-to-restart")
|
||||||
|
.help("Binary to restart after the update is over.")
|
||||||
|
.metavar("PATH");
|
||||||
parser.add_option("--log-file")
|
parser.add_option("--log-file")
|
||||||
.dest("log-file")
|
.dest("log-file")
|
||||||
.help("File where to log updater debug output.")
|
.help("File where to log updater debug output.")
|
||||||
|
@ -123,6 +128,8 @@ std::optional<Options> ParseCommandLine(PCWSTR command_line)
|
||||||
opts.install_base_path = options["install-base-path"];
|
opts.install_base_path = options["install-base-path"];
|
||||||
|
|
||||||
// Optional arguments.
|
// Optional arguments.
|
||||||
|
if (options.is_set("binary-to-restart"))
|
||||||
|
opts.binary_to_restart = options["binary-to-restart"];
|
||||||
if (options.is_set("parent-pid"))
|
if (options.is_set("parent-pid"))
|
||||||
opts.parent_pid = (DWORD)options.get("parent-pid");
|
opts.parent_pid = (DWORD)options.get("parent-pid");
|
||||||
if (options.is_set("log-file"))
|
if (options.is_set("log-file"))
|
||||||
|
@ -685,5 +692,11 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
|
||||||
fprintf(log_fp, "Failed to apply the update.\n");
|
fprintf(log_fp, "Failed to apply the update.\n");
|
||||||
|
|
||||||
CleanUpTempDir(temp_dir, todo);
|
CleanUpTempDir(temp_dir, todo);
|
||||||
|
|
||||||
|
if (opts.binary_to_restart)
|
||||||
|
{
|
||||||
|
ShellExecuteW(nullptr, L"open", UTF8ToUTF16(*opts.binary_to_restart).c_str(), L"", nullptr,
|
||||||
|
SW_SHOW);
|
||||||
|
}
|
||||||
return !ok;
|
return !ok;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue