Convert to structured bindings

This commit is contained in:
Dr. Dystopia 2024-08-17 07:47:59 +02:00
parent e91784e7ec
commit 13e343c30b
4 changed files with 72 additions and 73 deletions

View File

@ -286,9 +286,9 @@ int ConvertCommand(const std::vector<std::string>& args)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
const std::pair<int, int> range = const auto [min_level, max_level] =
DiscIO::GetAllowedCompressionLevels(compression_o.value(), false); DiscIO::GetAllowedCompressionLevels(compression_o.value(), false);
if (compression_level_o.value() < range.first || compression_level_o.value() > range.second) if (compression_level_o.value() < min_level || compression_level_o.value() > max_level)
{ {
fmt::print(std::cerr, "Error: Compression level not in acceptable range\n"); fmt::print(std::cerr, "Error: Compression level not in acceptable range\n");
return EXIT_FAILURE; return EXIT_FAILURE;

View File

@ -48,10 +48,10 @@ static void PrintFullReport(const DiscIO::VolumeVerifier::Result& result)
fmt::print(std::cout, "Problems Found: {}\n", result.problems.empty() ? "No" : "Yes"); fmt::print(std::cout, "Problems Found: {}\n", result.problems.empty() ? "No" : "Yes");
for (const auto& problem : result.problems) for (const auto& [severity, text] : result.problems)
{ {
fmt::print(std::cout, "\nSeverity: "); fmt::print(std::cout, "\nSeverity: ");
switch (problem.severity) switch (severity)
{ {
case DiscIO::VolumeVerifier::Severity::Low: case DiscIO::VolumeVerifier::Severity::Low:
fmt::print(std::cout, "Low"); fmt::print(std::cout, "Low");
@ -69,7 +69,7 @@ static void PrintFullReport(const DiscIO::VolumeVerifier::Result& result)
ASSERT(false); ASSERT(false);
break; break;
} }
fmt::print(std::cout, "\nSummary: {}\n\n", problem.text); fmt::print(std::cout, "\nSummary: {}\n\n", text);
} }
} }

View File

@ -184,21 +184,20 @@ void TodoList::Log() const
if (to_update.size()) if (to_update.size())
{ {
LogToFile("Updating:\n"); LogToFile("Updating:\n");
for (const auto& op : to_update) for (const auto& [filename, old_hash, new_hash] : to_update)
{ {
std::string old_desc = std::string old_desc = old_hash ? HexEncode(old_hash->data(), old_hash->size()) : "(new)";
op.old_hash ? HexEncode(op.old_hash->data(), op.old_hash->size()) : "(new)"; LogToFile(" - %s: %s -> %s\n", filename.c_str(), old_desc.c_str(),
LogToFile(" - %s: %s -> %s\n", op.filename.c_str(), old_desc.c_str(), HexEncode(new_hash.data(), new_hash.size()).c_str());
HexEncode(op.new_hash.data(), op.new_hash.size()).c_str());
} }
} }
if (to_delete.size()) if (to_delete.size())
{ {
LogToFile("Deleting:\n"); LogToFile("Deleting:\n");
for (const auto& op : to_delete) for (const auto& [filename, old_hash] : to_delete)
{ {
LogToFile(" - %s (%s)\n", op.filename.c_str(), LogToFile(" - %s (%s)\n", filename.c_str(),
HexEncode(op.old_hash.data(), op.old_hash.size()).c_str()); HexEncode(old_hash.data(), old_hash.size()).c_str());
} }
} }
} }
@ -214,16 +213,16 @@ bool DownloadContent(const std::vector<TodoList::DownloadOp>& to_download,
{ {
UI::SetTotalProgress(static_cast<int>(i + 1), static_cast<int>(to_download.size())); UI::SetTotalProgress(static_cast<int>(i + 1), static_cast<int>(to_download.size()));
auto& download = to_download[i]; const auto& [filename, hash] = to_download[i];
std::string hash_filename = HexEncode(download.hash.data(), download.hash.size()); std::string hash_filename = HexEncode(hash.data(), hash.size());
// File already exists, skipping // File already exists, skipping
if (File::Exists(temp_path + DIR_SEP + hash_filename)) if (File::Exists(temp_path + DIR_SEP + hash_filename))
continue; continue;
UI::SetDescription("Downloading " + download.filename + "... (File " + std::to_string(i + 1) + UI::SetDescription("Downloading " + filename + "... (File " + std::to_string(i + 1) + " of " +
" of " + std::to_string(to_download.size()) + ")"); std::to_string(to_download.size()) + ")");
UI::SetCurrentMarquee(false); UI::SetCurrentMarquee(false);
// Add slashes where needed. // Add slashes where needed.
@ -239,7 +238,7 @@ bool DownloadContent(const std::vector<TodoList::DownloadOp>& to_download,
return false; return false;
UI::SetCurrentMarquee(true); UI::SetCurrentMarquee(true);
UI::SetDescription("Verifying " + download.filename + "..."); UI::SetDescription("Verifying " + filename + "...");
std::string contents(reinterpret_cast<char*>(resp->data()), resp->size()); std::string contents(reinterpret_cast<char*>(resp->data()), resp->size());
std::optional<std::string> maybe_decompressed = GzipInflate(contents); std::optional<std::string> maybe_decompressed = GzipInflate(contents);
@ -249,7 +248,7 @@ bool DownloadContent(const std::vector<TodoList::DownloadOp>& to_download,
// Check that the downloaded contents have the right hash. // Check that the downloaded contents have the right hash.
Manifest::Hash contents_hash = ComputeHash(decompressed); Manifest::Hash contents_hash = ComputeHash(decompressed);
if (contents_hash != download.hash) if (contents_hash != hash)
{ {
LogToFile("Wrong hash on downloaded content %s.\n", url.c_str()); LogToFile("Wrong hash on downloaded content %s.\n", url.c_str());
return false; return false;
@ -277,38 +276,38 @@ TodoList ComputeActionsToDo(Manifest this_manifest, Manifest next_manifest)
TodoList todo; TodoList todo;
// Delete if present in this manifest but not in next manifest. // Delete if present in this manifest but not in next manifest.
for (const auto& entry : this_manifest.entries) for (const auto& [filename, hash] : this_manifest.entries)
{ {
if (!next_manifest.entries.contains(entry.first)) if (!next_manifest.entries.contains(filename))
{ {
TodoList::DeleteOp del; TodoList::DeleteOp del;
del.filename = entry.first; del.filename = filename;
del.old_hash = entry.second; del.old_hash = hash;
todo.to_delete.push_back(std::move(del)); todo.to_delete.push_back(std::move(del));
} }
} }
// Download and update if present in next manifest with different hash from this manifest. // Download and update if present in next manifest with different hash from this manifest.
for (const auto& entry : next_manifest.entries) for (const auto& [filename, hash] : next_manifest.entries)
{ {
std::optional<Manifest::Hash> old_hash; std::optional<Manifest::Hash> old_hash;
const auto& old_entry = this_manifest.entries.find(entry.first); const auto& old_entry = this_manifest.entries.find(filename);
if (old_entry != this_manifest.entries.end()) if (old_entry != this_manifest.entries.end())
old_hash = old_entry->second; old_hash = old_entry->second;
if (!old_hash || *old_hash != entry.second) if (!old_hash || *old_hash != hash)
{ {
TodoList::DownloadOp download; TodoList::DownloadOp download;
download.filename = entry.first; download.filename = filename;
download.hash = entry.second; download.hash = hash;
todo.to_download.push_back(std::move(download)); todo.to_download.push_back(std::move(download));
TodoList::UpdateOp update; TodoList::UpdateOp update;
update.filename = entry.first; update.filename = filename;
update.old_hash = old_hash; update.old_hash = old_hash;
update.new_hash = entry.second; update.new_hash = hash;
todo.to_update.push_back(std::move(update)); todo.to_update.push_back(std::move(update));
} }
} }
@ -319,8 +318,8 @@ TodoList ComputeActionsToDo(Manifest this_manifest, Manifest next_manifest)
void CleanUpTempDir(const std::string& temp_dir, const TodoList& todo) void CleanUpTempDir(const std::string& temp_dir, const TodoList& todo)
{ {
// This is best-effort cleanup, we ignore most errors. // This is best-effort cleanup, we ignore most errors.
for (const auto& download : todo.to_download) for (const auto& [filename, hash] : todo.to_download)
File::Delete(temp_dir + DIR_SEP + HexEncode(download.hash.data(), download.hash.size())); File::Delete(temp_dir + DIR_SEP + HexEncode(hash.data(), hash.size()));
File::DeleteDir(temp_dir); File::DeleteDir(temp_dir);
} }
@ -339,13 +338,13 @@ bool BackupFile(const std::string& path)
bool DeleteObsoleteFiles(const std::vector<TodoList::DeleteOp>& to_delete, bool DeleteObsoleteFiles(const std::vector<TodoList::DeleteOp>& to_delete,
const std::string& install_base_path) const std::string& install_base_path)
{ {
for (const auto& op : to_delete) for (const auto& [filename, old_hash] : to_delete)
{ {
std::string path = install_base_path + DIR_SEP + op.filename; std::string path = install_base_path + DIR_SEP + filename;
if (!File::Exists(path)) if (!File::Exists(path))
{ {
LogToFile("File %s is already missing.\n", op.filename.c_str()); LogToFile("File %s is already missing.\n", filename.c_str());
continue; continue;
} }
else else
@ -353,11 +352,11 @@ bool DeleteObsoleteFiles(const std::vector<TodoList::DeleteOp>& to_delete,
std::string contents; std::string contents;
if (!File::ReadFileToString(path, contents)) if (!File::ReadFileToString(path, contents))
{ {
LogToFile("Could not read file planned for deletion: %s.\n", op.filename.c_str()); LogToFile("Could not read file planned for deletion: %s.\n", filename.c_str());
return false; return false;
} }
Manifest::Hash contents_hash = ComputeHash(contents); Manifest::Hash contents_hash = ComputeHash(contents);
if (contents_hash != op.old_hash) if (contents_hash != old_hash)
{ {
if (!BackupFile(path)) if (!BackupFile(path))
return false; return false;
@ -377,12 +376,12 @@ bool UpdateFiles(const std::vector<TodoList::UpdateOp>& to_update,
const auto self_filename = self_path.filename(); const auto self_filename = self_path.filename();
#endif #endif
for (const auto& op : to_update) for (const auto& [filename, old_hash, new_hash] : to_update)
{ {
std::string path = install_base_path + DIR_SEP + op.filename; std::string path = install_base_path + DIR_SEP + filename;
if (!File::CreateFullPath(path)) if (!File::CreateFullPath(path))
{ {
LogToFile("Could not create directory structure for %s.\n", op.filename.c_str()); LogToFile("Could not create directory structure for %s.\n", filename.c_str());
return false; return false;
} }
@ -416,7 +415,7 @@ bool UpdateFiles(const std::vector<TodoList::UpdateOp>& to_update,
// after entire update has completed, and have it delete our relocated executable. For now we // after entire update has completed, and have it delete our relocated executable. For now we
// just let the relocated file hang around. // just let the relocated file hang around.
// It is enough to match based on filename, don't need File/VolumeId etc. // It is enough to match based on filename, don't need File/VolumeId etc.
const bool is_self = op.filename == self_filename; const bool is_self = filename == self_filename;
#else #else
// On other platforms, the renaming is handled by Dolphin before running the Updater. // On other platforms, the renaming is handled by Dolphin before running the Updater.
const bool is_self = false; const bool is_self = false;
@ -425,16 +424,16 @@ bool UpdateFiles(const std::vector<TodoList::UpdateOp>& to_update,
std::string contents; std::string contents;
if (!File::ReadFileToString(path, contents)) if (!File::ReadFileToString(path, contents))
{ {
LogToFile("Could not read existing file %s.\n", op.filename.c_str()); LogToFile("Could not read existing file %s.\n", filename.c_str());
return false; return false;
} }
Manifest::Hash contents_hash = ComputeHash(contents); Manifest::Hash contents_hash = ComputeHash(contents);
if (contents_hash == op.new_hash) if (contents_hash == new_hash)
{ {
LogToFile("File %s was already up to date. Partial update?\n", op.filename.c_str()); LogToFile("File %s was already up to date. Partial update?\n", filename.c_str());
continue; continue;
} }
else if (!op.old_hash || contents_hash != *op.old_hash || is_self) else if (!old_hash || contents_hash != *old_hash || is_self)
{ {
if (!BackupFile(path)) if (!BackupFile(path))
return false; return false;
@ -442,9 +441,8 @@ bool UpdateFiles(const std::vector<TodoList::UpdateOp>& to_update,
} }
// Now we can safely move the new contents to the location. // Now we can safely move the new contents to the location.
std::string content_filename = HexEncode(op.new_hash.data(), op.new_hash.size()); std::string content_filename = HexEncode(new_hash.data(), new_hash.size());
LogToFile("Updating file %s from content %s...\n", op.filename.c_str(), LogToFile("Updating file %s from content %s...\n", filename.c_str(), content_filename.c_str());
content_filename.c_str());
#ifdef __APPLE__ #ifdef __APPLE__
// macOS caches the code signature of Mach-O executables when they're first loaded. // macOS caches the code signature of Mach-O executables when they're first loaded.
// Unfortunately, there is a quirk in the kernel with how it handles the cache: if the file is // Unfortunately, there is a quirk in the kernel with how it handles the cache: if the file is
@ -466,7 +464,7 @@ bool UpdateFiles(const std::vector<TodoList::UpdateOp>& to_update,
if (!File::CopyRegularFile(temp_path + DIR_SEP + content_filename, path)) if (!File::CopyRegularFile(temp_path + DIR_SEP + content_filename, path))
#endif #endif
{ {
LogToFile("Could not update file %s.\n", op.filename.c_str()); LogToFile("Could not update file %s.\n", filename.c_str());
return false; return false;
} }
@ -695,31 +693,32 @@ bool RunUpdater(std::vector<std::string> args)
UI::SetVisible(false); UI::SetVisible(false);
Common::ScopeGuard ui_guard{[] { UI::Stop(); }}; Common::ScopeGuard ui_guard{[] { UI::Stop(); }};
Options opts = std::move(*maybe_opts); auto [this_manifest_url, next_manifest_url, content_store_url, install_base_path,
binary_to_restart, parent_pid, log_file_path] = std::move(*maybe_opts);
if (opts.log_file) if (log_file_path)
{ {
if (!log_file.Open(opts.log_file.value(), "w")) if (!log_file.Open(log_file_path.value(), "w"))
log_file.SetHandle(stderr); log_file.SetHandle(stderr);
else else
atexit(FlushLog); atexit(FlushLog);
} }
LogToFile("Updating from: %s\n", opts.this_manifest_url.c_str()); LogToFile("Updating from: %s\n", this_manifest_url.c_str());
LogToFile("Updating to: %s\n", opts.next_manifest_url.c_str()); LogToFile("Updating to: %s\n", next_manifest_url.c_str());
LogToFile("Install path: %s\n", opts.install_base_path.c_str()); LogToFile("Install path: %s\n", install_base_path.c_str());
if (!File::IsDirectory(opts.install_base_path)) if (!File::IsDirectory(install_base_path))
{ {
FatalError("Cannot find install base path, or not a directory."); FatalError("Cannot find install base path, or not a directory.");
return false; return false;
} }
if (opts.parent_pid) if (parent_pid)
{ {
LogToFile("Waiting for parent PID %d to complete...\n", *opts.parent_pid); LogToFile("Waiting for parent PID %d to complete...\n", *parent_pid);
auto pid = opts.parent_pid.value(); auto pid = parent_pid.value();
UI::WaitForPID(static_cast<u32>(pid)); UI::WaitForPID(static_cast<u32>(pid));
@ -732,7 +731,7 @@ bool RunUpdater(std::vector<std::string> args)
Manifest this_manifest, next_manifest; Manifest this_manifest, next_manifest;
{ {
std::optional<Manifest> maybe_manifest = FetchAndParseManifest(opts.this_manifest_url); std::optional<Manifest> maybe_manifest = FetchAndParseManifest(this_manifest_url);
if (!maybe_manifest) if (!maybe_manifest)
{ {
FatalError("Could not fetch current manifest. Aborting."); FatalError("Could not fetch current manifest. Aborting.");
@ -740,7 +739,7 @@ bool RunUpdater(std::vector<std::string> args)
} }
this_manifest = std::move(*maybe_manifest); this_manifest = std::move(*maybe_manifest);
maybe_manifest = FetchAndParseManifest(opts.next_manifest_url); maybe_manifest = FetchAndParseManifest(next_manifest_url);
if (!maybe_manifest) if (!maybe_manifest)
{ {
FatalError("Could not fetch next manifest. Aborting."); FatalError("Could not fetch next manifest. Aborting.");
@ -763,7 +762,7 @@ bool RunUpdater(std::vector<std::string> args)
UI::SetDescription("Performing Update..."); UI::SetDescription("Performing Update...");
bool ok = PerformUpdate(todo, opts.install_base_path, opts.content_store_url, temp_dir); bool ok = PerformUpdate(todo, install_base_path, content_store_url, temp_dir);
CleanUpTempDir(temp_dir, todo); CleanUpTempDir(temp_dir, todo);
if (!ok) if (!ok)
{ {
@ -782,9 +781,9 @@ bool RunUpdater(std::vector<std::string> args)
// Let the user process that we are done. // Let the user process that we are done.
UI::Sleep(1); UI::Sleep(1);
if (opts.binary_to_restart) if (binary_to_restart)
{ {
UI::LaunchApplication(opts.binary_to_restart.value()); UI::LaunchApplication(binary_to_restart.value());
} }
return true; return true;

View File

@ -225,8 +225,9 @@ static bool VCRuntimeUpdate(const BuildInfo& build_info)
static BuildVersion CurrentOSVersion() static BuildVersion CurrentOSVersion()
{ {
OSVERSIONINFOW info = WindowsRegistry::GetOSVersion(); auto [dwOSVersionInfoSize, dwMajorVersion, dwMinorVersion, dwBuildNumber, dwPlatformId,
return {.major = info.dwMajorVersion, .minor = info.dwMinorVersion, .build = info.dwBuildNumber}; szCSDVersion] = WindowsRegistry::GetOSVersion();
return {.major = dwMajorVersion, .minor = dwMinorVersion, .build = dwBuildNumber};
} }
static VersionCheckResult OSVersionCheck(const BuildInfo& build_info) static VersionCheckResult OSVersionCheck(const BuildInfo& build_info)
@ -255,12 +256,11 @@ std::optional<BuildInfos> InitBuildInfos(const std::vector<TodoList::UpdateOp>&
if (op_it == to_update.cend()) if (op_it == to_update.cend())
return {}; return {};
const auto op = *op_it; const auto [_filename, old_hash, new_hash] = *op_it;
std::string build_info_path = std::string build_info_path = temp_dir + DIR_SEP + HexEncode(new_hash.data(), new_hash.size());
temp_dir + DIR_SEP + HexEncode(op.new_hash.data(), op.new_hash.size());
std::string build_info_content; std::string build_info_content;
if (!File::ReadFileToString(build_info_path, build_info_content) || if (!File::ReadFileToString(build_info_path, build_info_content) ||
op.new_hash != ComputeHash(build_info_content)) new_hash != ComputeHash(build_info_content))
{ {
LogToFile("Failed to read %s\n.", build_info_path.c_str()); LogToFile("Failed to read %s\n.", build_info_path.c_str());
return {}; return {};
@ -272,7 +272,7 @@ std::optional<BuildInfos> InitBuildInfos(const std::vector<TodoList::UpdateOp>&
build_infos.current = Platform::BuildInfo(); build_infos.current = Platform::BuildInfo();
if (File::ReadFileToString(build_info_path, build_info_content)) if (File::ReadFileToString(build_info_path, build_info_content))
{ {
if (op.old_hash != ComputeHash(build_info_content)) if (old_hash != ComputeHash(build_info_content))
LogToFile("Using modified existing BuildInfo %s.\n", build_info_path.c_str()); LogToFile("Using modified existing BuildInfo %s.\n", build_info_path.c_str());
build_infos.current = Platform::BuildInfo(build_info_content); build_infos.current = Platform::BuildInfo(build_info_content);
} }
@ -284,8 +284,8 @@ bool CheckBuildInfo(const BuildInfos& build_infos)
// The existing BuildInfo may have been modified. Be careful not to overly trust its contents! // The existing BuildInfo may have been modified. Be careful not to overly trust its contents!
// If the binary requires more recent OS, inform the user. // If the binary requires more recent OS, inform the user.
auto os_check = OSVersionCheck(build_infos.next); auto [status, current_version, target_version] = OSVersionCheck(build_infos.next);
if (os_check.status == VersionCheckStatus::UpdateRequired) if (status == VersionCheckStatus::UpdateRequired)
{ {
UI::Error("Please update Windows in order to update Dolphin."); UI::Error("Please update Windows in order to update Dolphin.");
return false; return false;