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
|
||||
|
||||
std::string& GetExeDirectory()
|
||||
std::string GetExePath()
|
||||
{
|
||||
static std::string DolphinPath;
|
||||
if (DolphinPath.empty())
|
||||
static std::string dolphin_path;
|
||||
if (dolphin_path.empty())
|
||||
{
|
||||
#ifdef _WIN32
|
||||
TCHAR Dolphin_exe_Path[2048];
|
||||
TCHAR Dolphin_exe_Clean_Path[MAX_PATH];
|
||||
GetModuleFileName(nullptr, Dolphin_exe_Path, 2048);
|
||||
if (_tfullpath(Dolphin_exe_Clean_Path, Dolphin_exe_Path, MAX_PATH) != nullptr)
|
||||
DolphinPath = TStrToUTF8(Dolphin_exe_Clean_Path);
|
||||
TCHAR dolphin_exe_path[2048];
|
||||
TCHAR dolphin_exe_expanded_path[MAX_PATH];
|
||||
GetModuleFileName(nullptr, dolphin_exe_path, ARRAYSIZE(dolphin_exe_path));
|
||||
if (_tfullpath(dolphin_exe_expanded_path, dolphin_exe_path,
|
||||
ARRAYSIZE(dolphin_exe_expanded_path)) != nullptr)
|
||||
dolphin_path = TStrToUTF8(dolphin_exe_expanded_path);
|
||||
else
|
||||
DolphinPath = TStrToUTF8(Dolphin_exe_Path);
|
||||
DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\'));
|
||||
dolphin_path = TStrToUTF8(dolphin_exe_path);
|
||||
#else
|
||||
char Dolphin_exe_Path[PATH_MAX];
|
||||
ssize_t len = ::readlink("/proc/self/exe", Dolphin_exe_Path, sizeof(Dolphin_exe_Path));
|
||||
if (len == -1 || len == sizeof(Dolphin_exe_Path))
|
||||
char dolphin_exe_path[PATH_MAX];
|
||||
ssize_t len = ::readlink("/proc/self/exe", dolphin_exe_path, sizeof(dolphin_exe_path));
|
||||
if (len == -1 || len == sizeof(dolphin_exe_path))
|
||||
{
|
||||
len = 0;
|
||||
}
|
||||
Dolphin_exe_Path[len] = '\0';
|
||||
DolphinPath = Dolphin_exe_Path;
|
||||
DolphinPath = DolphinPath.substr(0, DolphinPath.rfind('/'));
|
||||
dolphin_exe_path[len] = '\0';
|
||||
dolphin_path = dolphin_exe_path;
|
||||
#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()
|
||||
|
@ -882,4 +891,4 @@ bool ReadFileToString(const std::string& filename, std::string& str)
|
|||
return retval;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace File
|
||||
|
|
|
@ -191,7 +191,8 @@ void SetSysDirectory(const std::string& path);
|
|||
std::string GetBundleDirectory();
|
||||
#endif
|
||||
|
||||
std::string& GetExeDirectory();
|
||||
std::string GetExePath();
|
||||
std::string GetExeDirectory();
|
||||
|
||||
bool WriteStringToFile(const std::string& str, const std::string& filename);
|
||||
bool ReadFileToString(const std::string& filename, std::string& str);
|
||||
|
|
|
@ -80,7 +80,8 @@ void Updater::OnUpdateAvailable(const NewVersionInformation& info)
|
|||
|
||||
if (choice == QDialog::Accepted)
|
||||
{
|
||||
TriggerUpdate(info);
|
||||
TriggerUpdate(info, later ? AutoUpdateChecker::RestartMode::NO_RESTART_AFTER_UPDATE :
|
||||
AutoUpdateChecker::RestartMode::RESTART_AFTER_UPDATE);
|
||||
|
||||
if (!later)
|
||||
m_parent->close();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "UICommon/AutoUpdate.h"
|
||||
|
||||
#include <picojson/picojson.h>
|
||||
#include <string>
|
||||
|
||||
#include "Common/CommonPaths.h"
|
||||
#include "Common/FileUtil.h"
|
||||
|
@ -46,6 +47,48 @@ void CleanupFromPreviousUpdate()
|
|||
File::Delete(reloc_updater_path);
|
||||
}
|
||||
#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
|
||||
|
||||
bool AutoUpdateChecker::SystemSupportsAutoUpdates()
|
||||
|
@ -106,12 +149,13 @@ void AutoUpdateChecker::CheckForUpdate()
|
|||
nvi.new_hash = obj["new"].get<picojson::object>()["hash"].get<std::string>();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInformation& info)
|
||||
void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInformation& info,
|
||||
AutoUpdateChecker::RestartMode restart_mode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
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["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.
|
||||
std::string updater_path = File::GetExeDirectory() + DIR_SEP + UPDATER_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!
|
||||
std::wstring command_line = MakeUpdaterCommandLine(updater_flags);
|
||||
STARTUPINFO sinfo = {sizeof(info)};
|
||||
sinfo.dwFlags = STARTF_FORCEOFFFEEDBACK; // No hourglass cursor after starting the process.
|
||||
PROCESS_INFORMATION pinfo;
|
||||
INFO_LOG(COMMON, "Updater command line: %s", UTF16ToUTF8(command_line).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.
|
||||
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:
|
||||
virtual void OnUpdateAvailable(const NewVersionInformation& info) = 0;
|
||||
|
|
|
@ -47,6 +47,7 @@ struct Options
|
|||
std::string next_manifest_url;
|
||||
std::string content_store_url;
|
||||
std::string install_base_path;
|
||||
std::optional<std::string> binary_to_restart;
|
||||
std::optional<DWORD> parent_pid;
|
||||
std::optional<std::string> log_file;
|
||||
};
|
||||
|
@ -90,6 +91,10 @@ std::optional<Options> ParseCommandLine(PCWSTR command_line)
|
|||
.dest("install-base-path")
|
||||
.help("Base path of the Dolphin install to be updated.")
|
||||
.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")
|
||||
.dest("log-file")
|
||||
.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"];
|
||||
|
||||
// Optional arguments.
|
||||
if (options.is_set("binary-to-restart"))
|
||||
opts.binary_to_restart = options["binary-to-restart"];
|
||||
if (options.is_set("parent-pid"))
|
||||
opts.parent_pid = (DWORD)options.get("parent-pid");
|
||||
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");
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue