From 4eb9085e7178f1464d360456ff17af034e151cf8 Mon Sep 17 00:00:00 2001 From: jdp_ <42700985+jdpatdiscord@users.noreply.github.com> Date: Sun, 7 May 2023 01:06:30 -0400 Subject: [PATCH] Fix pack updating & Modrinth overrides The mechanism that both pack updating and Modrinth overrides use utilize std::filesystem::copy, which with GCC's libstdc++ has a bug on Windows where `overwrite_existing` isn't obeyed. In addition, made it clear what `overrideFolder` does by renaming it and rewriting an error message. --- launcher/FileSystem.cpp | 35 +++++++++++-------- launcher/FileSystem.h | 2 +- launcher/InstanceList.cpp | 2 +- .../modrinth/ModrinthInstanceCreationTask.cpp | 4 +-- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 9e510d91..689d1ff6 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -414,24 +414,29 @@ bool createShortCut(QString location, QString dest, QStringList args, QString na #endif } -bool overrideFolder(QString overwritten_path, QString override_path) +bool mergeFolders(QString dstpath, QString srcpath) { - using copy_opts = fs::copy_options; - - if (!FS::ensureFolderPathExists(overwritten_path)) - return false; - - std::error_code err; - fs::copy_options opt = copy_opts::recursive | copy_opts::overwrite_existing; - - fs::copy(toStdString(override_path), toStdString(overwritten_path), opt, err); - - if (err) { - qCritical() << QString("Failed to apply override from %1 to %2").arg(override_path, overwritten_path); - qCritical() << "Reason:" << QString::fromStdString(err.message()); + std::error_code ec; + fs::path fullSrcPath = srcpath.toStdString(); + fs::path fullDstPath = dstpath.toStdString(); + for (auto& entry : fs::recursive_directory_iterator(fullSrcPath)) + { + fs::path relativeChild = fs::relative(entry, fullSrcPath); + if (entry.is_directory()) + if (!fs::exists(fullDstPath / relativeChild)) + fs::create_directory(fullDstPath / relativeChild); + if (entry.is_regular_file()) + { + fs::path childDst = fullDstPath / relativeChild; + if (fs::exists(childDst)) + fs::remove(childDst); + fs::copy(entry, childDst, fs::copy_options::none, ec); + if (ec.value() != 0) + qCritical() << QString("File copy failed with: %1. File was %2 -> %3").arg(QString::fromStdString(ec.message()), entry.path().c_str(), childDst.c_str()); + } } - return err.value() == 0; + return ec.value() == 0; } } diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index b46f3281..7e66daff 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -154,5 +154,5 @@ QString getDesktopDir(); // Overrides one folder with the contents of another, preserving items exclusive to the first folder // Equivalent to doing QDir::rename, but allowing for overrides -bool overrideFolder(QString overwritten_path, QString override_path); +bool mergeFolders(QString dstpath, QString srcpath); } diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index c98d1e90..07e8c686 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -904,7 +904,7 @@ bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& QString destination = FS::PathCombine(m_instDir, instID); if (should_override) { - if (!FS::overrideFolder(destination, path)) { + if (!FS::mergeFolders(destination, path)) { qWarning() << "Failed to override" << path << "to" << destination; return false; } diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 661ec31a..bd4c9461 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -195,8 +195,8 @@ bool ModrinthCreationTask::createInstance() Override::createOverrides("client-overrides", parent_folder, client_override_path); // Apply the overrides - if (!FS::overrideFolder(mcPath, client_override_path)) { - setError(tr("Could not rename the client overrides folder:\n") + "client overrides"); + if (!FS::mergeFolders(mcPath, client_override_path)) { + setError(tr("Could not overwrite / create new files:\n") + "client overrides"); return false; } }