aboutsummaryrefslogtreecommitdiff
path: root/primedev/mods/autodownload/moddownloader.cpp
diff options
context:
space:
mode:
authorRémy Raes <raes.remy@gmail.com>2024-12-06 09:05:05 +0100
committerGitHub <noreply@github.com>2024-12-06 09:05:05 +0100
commitfeab262e44372c937903bcc48aab360976fa24a6 (patch)
tree32fa61902f01e64cab3cd5c7fc59976bf75f2d40 /primedev/mods/autodownload/moddownloader.cpp
parent5e07df82e7bbd3296863995f688213e8639e8dcf (diff)
downloadNorthstarLauncher-feab262e44372c937903bcc48aab360976fa24a6.tar.gz
NorthstarLauncher-feab262e44372c937903bcc48aab360976fa24a6.zip
Rework MAD `cleanup` handles (#817)HEADv1.29.1-rc4v1.29.1main
Mods are no longer marked as successfully installed when the process failed. When mod downloading/extraction fails, the mod directory is removed again.
Diffstat (limited to 'primedev/mods/autodownload/moddownloader.cpp')
-rw-r--r--primedev/mods/autodownload/moddownloader.cpp57
1 files changed, 39 insertions, 18 deletions
diff --git a/primedev/mods/autodownload/moddownloader.cpp b/primedev/mods/autodownload/moddownloader.cpp
index 21b98942..de95a0c2 100644
--- a/primedev/mods/autodownload/moddownloader.cpp
+++ b/primedev/mods/autodownload/moddownloader.cpp
@@ -176,7 +176,7 @@ int ModDownloader::ModFetchingProgressCallback(
return 0;
}
-std::optional<fs::path> ModDownloader::FetchModFromDistantStore(std::string_view modName, VerifiedModVersion version)
+std::tuple<fs::path, bool> ModDownloader::FetchModFromDistantStore(std::string_view modName, VerifiedModVersion version)
{
std::string url = version.downloadLink;
std::string archiveName = fs::path(url).filename().generic_string();
@@ -190,7 +190,7 @@ std::optional<fs::path> ModDownloader::FetchModFromDistantStore(std::string_view
modState.state = DOWNLOADING;
// Download the actual archive
- bool failed = false;
+ bool success = false;
FILE* fp = fopen(downloadPath.generic_string().c_str(), "wb");
CURLcode result;
CURL* easyhandle;
@@ -219,13 +219,14 @@ std::optional<fs::path> ModDownloader::FetchModFromDistantStore(std::string_view
if (result == CURLcode::CURLE_OK)
{
spdlog::info("Mod archive successfully fetched.");
- return std::optional<fs::path>(downloadPath);
+ success = true;
}
else
{
spdlog::error("Fetching mod archive failed: {}", curl_easy_strerror(result));
- return std::optional<fs::path>();
}
+
+ return {downloadPath, success};
}
bool ModDownloader::IsModLegit(fs::path modPath, std::string_view expectedChecksum)
@@ -399,11 +400,9 @@ int GetModArchiveSize(unzFile file, unz_global_info64 info)
return totalSize;
}
-void ModDownloader::ExtractMod(fs::path modPath, VerifiedModPlatform platform)
+void ModDownloader::ExtractMod(fs::path modPath, fs::path destinationPath, VerifiedModPlatform platform)
{
unzFile file;
- std::string name;
- fs::path modDirectory;
file = unzOpen(modPath.generic_string().c_str());
ScopeGuard cleanup(
@@ -445,11 +444,6 @@ void ModDownloader::ExtractMod(fs::path modPath, VerifiedModPlatform platform)
return;
}
- // Mod directory name (removing the ".zip" fom the archive name)
- name = modPath.filename().string();
- name = name.substr(0, name.length() - 4);
- modDirectory = GetRemoteModFolderPath() / name;
-
for (int i = 0; i < gi.number_entry; i++)
{
char zipFilename[256];
@@ -459,7 +453,7 @@ void ModDownloader::ExtractMod(fs::path modPath, VerifiedModPlatform platform)
// Extract file
{
std::error_code ec;
- fs::path fileDestination = modDirectory / zipFilename;
+ fs::path fileDestination = destinationPath / zipFilename;
spdlog::info("=> {}", fileDestination.generic_string());
// Create parent directory if needed
@@ -589,6 +583,9 @@ void ModDownloader::ExtractMod(fs::path modPath, VerifiedModPlatform platform)
}
}
}
+
+ // Mod extraction went fine
+ modState.state = DONE;
}
void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
@@ -603,11 +600,14 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
std::thread requestThread(
[this, modName, modVersion]()
{
+ std::string name;
fs::path archiveLocation;
+ fs::path modDirectory;
ScopeGuard cleanup(
[&]
{
+ // Remove downloaded archive
try
{
remove(archiveLocation);
@@ -617,14 +617,31 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
spdlog::error("Error while removing downloaded archive: {}", a.what());
}
+ // Remove mod if auto-download process failed
+ if (modState.state != DONE)
+ {
+ try
+ {
+ remove_all(modDirectory);
+ }
+ catch (const std::exception& e)
+ {
+ spdlog::error("Error while removing downloaded mod: {}", e.what());
+ }
+ }
+
spdlog::info("Done cleaning after downloading {}.", modName);
});
// Download mod archive
VerifiedModVersion fullVersion = verifiedMods[modName].versions[modVersion];
std::string expectedHash = fullVersion.checksum;
- std::optional<fs::path> fetchingResult = FetchModFromDistantStore(std::string_view(modName), fullVersion);
- if (!fetchingResult.has_value())
+
+ const std::tuple<fs::path, bool> downloadResult = FetchModFromDistantStore(std::string_view(modName), fullVersion);
+ archiveLocation = get<0>(downloadResult);
+ bool downloadSuccessful = get<1>(downloadResult);
+
+ if (!downloadSuccessful)
{
spdlog::error("Something went wrong while fetching archive, aborting.");
if (modState.state != ABORTED)
@@ -633,7 +650,7 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
}
return;
}
- archiveLocation = fetchingResult.value();
+
if (!IsModLegit(archiveLocation, std::string_view(expectedHash)))
{
spdlog::warn("Archive hash does not match expected checksum, aborting.");
@@ -641,9 +658,13 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
return;
}
+ // Mod directory name (removing the ".zip" fom the archive name)
+ name = archiveLocation.filename().string();
+ name = name.substr(0, name.length() - 4);
+ modDirectory = GetRemoteModFolderPath() / name;
+
// Extract downloaded mod archive
- ExtractMod(archiveLocation, fullVersion.platform);
- modState.state = DONE;
+ ExtractMod(archiveLocation, modDirectory, fullVersion.platform);
});
requestThread.detach();