aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--primedev/mods/autodownload/moddownloader.cpp57
-rw-r--r--primedev/mods/autodownload/moddownloader.h14
2 files changed, 46 insertions, 25 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();
diff --git a/primedev/mods/autodownload/moddownloader.h b/primedev/mods/autodownload/moddownloader.h
index 2ac72a48..f8c0c664 100644
--- a/primedev/mods/autodownload/moddownloader.h
+++ b/primedev/mods/autodownload/moddownloader.h
@@ -43,14 +43,12 @@ private:
* input mod name as mod dependency string if bypass flag is set up; fetched
* archive is then stored in a temporary location.
*
- * If something went wrong during archive download, this will return an empty
- * optional object.
*
* @param modName name of the mod to be downloaded
* @param modVersion version of the mod to be downloaded
- * @returns location of the downloaded archive
+ * @returns tuple containing location of the downloaded archive and whether download completed successfully
*/
- std::optional<fs::path> FetchModFromDistantStore(std::string_view modName, VerifiedModVersion modVersion);
+ std::tuple<fs::path, bool> FetchModFromDistantStore(std::string_view modName, VerifiedModVersion modVersion);
/**
* Tells if a mod archive has not been corrupted.
@@ -69,14 +67,16 @@ private:
/**
* Extracts a mod archive to the game folder.
*
- * This extracts a downloaded mod archive from its original location to the
- * current game profile; the install folder is defined by the platform parameter.
+ * This extracts a downloaded mod archive from its original location, `modPath`,
+ * to the specified `destinationPath`; the way to decompress the archive is
+ * defined by the `platform` parameter.
*
* @param modPath location of the downloaded archive
+ * @param destinationPath destination of the extraction
* @param platform origin of the downloaded archive
* @returns nothing
*/
- void ExtractMod(fs::path modPath, VerifiedModPlatform platform);
+ void ExtractMod(fs::path modPath, fs::path destinationPath, VerifiedModPlatform platform);
public:
ModDownloader();