Improve error message behavior on installer for invalid sources. (#77)

This commit is contained in:
Darío 2025-01-16 12:13:14 -03:00 committed by GitHub
parent 5f9fdcf934
commit 5c98a34084
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 51 additions and 15 deletions

View file

@ -7,10 +7,12 @@
struct DirectoryFileSystem : VirtualFileSystem struct DirectoryFileSystem : VirtualFileSystem
{ {
std::filesystem::path directoryPath; std::filesystem::path directoryPath;
std::string name;
DirectoryFileSystem(const std::filesystem::path &directoryPath) DirectoryFileSystem(const std::filesystem::path &directoryPath)
{ {
this->directoryPath = directoryPath; this->directoryPath = directoryPath;
name = (const char *)(directoryPath.filename().u8string().data());
} }
bool load(const std::string &path, uint8_t *fileData, size_t fileDataMaxByteCount) const override bool load(const std::string &path, uint8_t *fileData, size_t fileDataMaxByteCount) const override
@ -51,6 +53,11 @@ struct DirectoryFileSystem : VirtualFileSystem
return std::filesystem::exists(directoryPath / std::filesystem::path(std::u8string_view((const char8_t *)(path.c_str())))); return std::filesystem::exists(directoryPath / std::filesystem::path(std::u8string_view((const char8_t *)(path.c_str()))));
} }
const std::string &getName() const override
{
return name;
}
static std::unique_ptr<VirtualFileSystem> create(const std::filesystem::path &directoryPath) static std::unique_ptr<VirtualFileSystem> create(const std::filesystem::path &directoryPath)
{ {
if (std::filesystem::exists(directoryPath)) if (std::filesystem::exists(directoryPath))

View file

@ -73,14 +73,14 @@ static bool copyFile(const FilePair &pair, const uint64_t *fileHashes, VirtualFi
if (!sourceVfs.exists(filename)) if (!sourceVfs.exists(filename))
{ {
journal.lastResult = Journal::Result::FileMissing; journal.lastResult = Journal::Result::FileMissing;
journal.lastErrorMessage = fmt::format("File {} does not exist in the file system.", filename); journal.lastErrorMessage = fmt::format("File {} does not exist in {}.", filename, sourceVfs.getName());
return false; return false;
} }
if (!sourceVfs.load(filename, fileData)) if (!sourceVfs.load(filename, fileData))
{ {
journal.lastResult = Journal::Result::FileReadFailed; journal.lastResult = Journal::Result::FileReadFailed;
journal.lastErrorMessage = fmt::format("Failed to read file {} from the file system.", filename); journal.lastErrorMessage = fmt::format("Failed to read file {} from {}.", filename, sourceVfs.getName());
return false; return false;
} }
@ -96,7 +96,7 @@ static bool copyFile(const FilePair &pair, const uint64_t *fileHashes, VirtualFi
if (!fileHashFound) if (!fileHashFound)
{ {
journal.lastResult = Journal::Result::FileHashFailed; journal.lastResult = Journal::Result::FileHashFailed;
journal.lastErrorMessage = fmt::format("File {} from the file system did not match any of the known hashes.", filename); journal.lastErrorMessage = fmt::format("File {} from {} did not match any of the known hashes.", filename, sourceVfs.getName());
return false; return false;
} }
} }
@ -150,7 +150,7 @@ static DLC detectDLC(const std::filesystem::path &sourcePath, VirtualFileSystem
if (!sourceVfs.load(DLCValidationFile, dlcXmlBytes)) if (!sourceVfs.load(DLCValidationFile, dlcXmlBytes))
{ {
journal.lastResult = Journal::Result::FileMissing; journal.lastResult = Journal::Result::FileMissing;
journal.lastErrorMessage = fmt::format("File {} does not exist in the file system.", DLCValidationFile); journal.lastErrorMessage = fmt::format("File {} does not exist in {}.", DLCValidationFile, sourceVfs.getName());
return DLC::Unknown; return DLC::Unknown;
} }
@ -164,7 +164,7 @@ static DLC detectDLC(const std::filesystem::path &sourcePath, VirtualFileSystem
if (typeStartLocation == nullptr || typeEndLocation == nullptr) if (typeStartLocation == nullptr || typeEndLocation == nullptr)
{ {
journal.lastResult = Journal::Result::DLCParsingFailed; journal.lastResult = Journal::Result::DLCParsingFailed;
journal.lastErrorMessage = "Failed to find DLC type for " + fromPath(sourcePath) + "."; journal.lastErrorMessage = fmt::format("Failed to find DLC type for {}.", sourceVfs.getName());
return DLC::Unknown; return DLC::Unknown;
} }
@ -173,7 +173,7 @@ static DLC detectDLC(const std::filesystem::path &sourcePath, VirtualFileSystem
if (typeNumberCount != 1) if (typeNumberCount != 1)
{ {
journal.lastResult = Journal::Result::UnknownDLCType; journal.lastResult = Journal::Result::UnknownDLCType;
journal.lastErrorMessage = "DLC type for " + fromPath(sourcePath) + " is unknown."; journal.lastErrorMessage = fmt::format("DLC type for {} is unknown.", sourceVfs.getName());
return DLC::Unknown; return DLC::Unknown;
} }
@ -193,7 +193,7 @@ static DLC detectDLC(const std::filesystem::path &sourcePath, VirtualFileSystem
return DLC::EmpireCityAdabat; return DLC::EmpireCityAdabat;
default: default:
journal.lastResult = Journal::Result::UnknownDLCType; journal.lastResult = Journal::Result::UnknownDLCType;
journal.lastErrorMessage = "DLC type for " + fromPath(sourcePath) + " is unknown."; journal.lastErrorMessage = fmt::format("DLC type for {} is unknown.", sourceVfs.getName());
return DLC::Unknown; return DLC::Unknown;
} }
} }
@ -246,7 +246,7 @@ bool Installer::computeTotalSize(std::span<const FilePair> filePairs, const uint
if (!sourceVfs.exists(filename)) if (!sourceVfs.exists(filename))
{ {
journal.lastResult = Journal::Result::FileMissing; journal.lastResult = Journal::Result::FileMissing;
journal.lastErrorMessage = fmt::format("File {} does not exist in the file system.", filename); journal.lastErrorMessage = fmt::format("File {} does not exist in {}.", filename, sourceVfs.getName());
return false; return false;
} }
@ -300,7 +300,7 @@ bool Installer::copyFiles(std::span<const FilePair> filePairs, const uint64_t *f
else else
{ {
journal.lastResult = Journal::Result::ValidationFileMissing; journal.lastResult = Journal::Result::ValidationFileMissing;
journal.lastErrorMessage = fmt::format("Unable to find validation file {} in file system.", validationFile); journal.lastErrorMessage = fmt::format("Unable to find validation file {} in {}.", validationFile, sourceVfs.getName());
return false; return false;
} }
@ -317,7 +317,7 @@ bool Installer::parseContent(const std::filesystem::path &sourcePath, std::uniqu
else else
{ {
journal.lastResult = Journal::Result::VirtualFileSystemFailed; journal.lastResult = Journal::Result::VirtualFileSystemFailed;
journal.lastErrorMessage = "Unable to open file system at " + fromPath(sourcePath); journal.lastErrorMessage = "Unable to open " + fromPath(sourcePath);
return false; return false;
} }
} }

View file

@ -21,6 +21,8 @@ ISOFileSystem::ISOFileSystem(const std::filesystem::path &isoPath)
return; return;
} }
name = (const char *)(isoPath.filename().u8string().data());
// Find root sector. // Find root sector.
const uint8_t *mappedFileData = mappedFile.data(); const uint8_t *mappedFileData = mappedFile.data();
uint32_t gameOffset = 0; uint32_t gameOffset = 0;
@ -173,6 +175,11 @@ bool ISOFileSystem::exists(const std::string &path) const
return fileMap.find(path) != fileMap.end(); return fileMap.find(path) != fileMap.end();
} }
const std::string &ISOFileSystem::getName() const
{
return name;
}
bool ISOFileSystem::empty() const bool ISOFileSystem::empty() const
{ {
return !mappedFile.isOpen(); return !mappedFile.isOpen();

View file

@ -22,11 +22,13 @@ struct ISOFileSystem : VirtualFileSystem
{ {
MemoryMappedFile mappedFile; MemoryMappedFile mappedFile;
std::map<std::string, std::tuple<size_t, size_t>> fileMap; std::map<std::string, std::tuple<size_t, size_t>> fileMap;
std::string name;
ISOFileSystem(const std::filesystem::path &isoPath); ISOFileSystem(const std::filesystem::path &isoPath);
bool load(const std::string &path, uint8_t *fileData, size_t fileDataMaxByteCount) const override; bool load(const std::string &path, uint8_t *fileData, size_t fileDataMaxByteCount) const override;
size_t getSize(const std::string &path) const override; size_t getSize(const std::string &path) const override;
bool exists(const std::string &path) const override; bool exists(const std::string &path) const override;
const std::string &getName() const override;
bool empty() const; bool empty() const;
static std::unique_ptr<ISOFileSystem> create(const std::filesystem::path &isoPath); static std::unique_ptr<ISOFileSystem> create(const std::filesystem::path &isoPath);

View file

@ -8,6 +8,7 @@ struct VirtualFileSystem {
virtual bool load(const std::string &path, uint8_t *fileData, size_t fileDataMaxByteCount) const = 0; virtual bool load(const std::string &path, uint8_t *fileData, size_t fileDataMaxByteCount) const = 0;
virtual size_t getSize(const std::string &path) const = 0; virtual size_t getSize(const std::string &path) const = 0;
virtual bool exists(const std::string &path) const = 0; virtual bool exists(const std::string &path) const = 0;
virtual const std::string &getName() const = 0;
// Concrete implementation shortcut. // Concrete implementation shortcut.
bool load(const std::string &path, std::vector<uint8_t> &fileData) bool load(const std::string &path, std::vector<uint8_t> &fileData)

View file

@ -269,6 +269,8 @@ XContentFileSystem::XContentFileSystem(const std::filesystem::path &contentPath)
return; return;
} }
name = (const char *)(contentPath.filename().u8string().data());
const uint8_t *rootMappedFileData = rootMappedFile.data(); const uint8_t *rootMappedFileData = rootMappedFile.data();
if (sizeof(XContentContainerHeader) > rootMappedFile.size()) if (sizeof(XContentContainerHeader) > rootMappedFile.size())
{ {
@ -607,6 +609,11 @@ bool XContentFileSystem::exists(const std::string &path) const
return fileMap.find(path) != fileMap.end(); return fileMap.find(path) != fileMap.end();
} }
const std::string &XContentFileSystem::getName() const
{
return name;
}
bool XContentFileSystem::empty() const bool XContentFileSystem::empty() const
{ {
return mappedFiles.empty(); return mappedFiles.empty();

View file

@ -49,11 +49,13 @@ struct XContentFileSystem : VirtualFileSystem
std::vector<MemoryMappedFile> mappedFiles; std::vector<MemoryMappedFile> mappedFiles;
uint64_t baseOffset = 0; uint64_t baseOffset = 0;
std::map<std::string, File> fileMap; std::map<std::string, File> fileMap;
std::string name;
XContentFileSystem(const std::filesystem::path &contentPath); XContentFileSystem(const std::filesystem::path &contentPath);
bool load(const std::string &path, uint8_t *fileData, size_t fileDataMaxByteCount) const override; bool load(const std::string &path, uint8_t *fileData, size_t fileDataMaxByteCount) const override;
size_t getSize(const std::string &path) const override; size_t getSize(const std::string &path) const override;
bool exists(const std::string &path) const override; bool exists(const std::string &path) const override;
const std::string &getName() const override;
bool empty() const; bool empty() const;
static std::unique_ptr<XContentFileSystem> create(const std::filesystem::path &contentPath); static std::unique_ptr<XContentFileSystem> create(const std::filesystem::path &contentPath);

View file

@ -1123,7 +1123,7 @@ static void InstallerStart()
g_installerThread = std::make_unique<std::thread>(InstallerThread); g_installerThread = std::make_unique<std::thread>(InstallerThread);
} }
static bool InstallerParseSources() static bool InstallerParseSources(std::string &errorMessage)
{ {
std::error_code spaceErrorCode; std::error_code spaceErrorCode;
std::filesystem::space_info spaceInfo = std::filesystem::space(g_installPath, spaceErrorCode); std::filesystem::space_info spaceInfo = std::filesystem::space(g_installPath, spaceErrorCode);
@ -1136,14 +1136,17 @@ static bool InstallerParseSources()
installerInput.gameSource = g_gameSourcePath; installerInput.gameSource = g_gameSourcePath;
installerInput.updateSource = g_updateSourcePath; installerInput.updateSource = g_updateSourcePath;
for (std::filesystem::path &path : g_dlcSourcePaths) { for (std::filesystem::path &path : g_dlcSourcePaths)
{
if (!path.empty()) if (!path.empty())
{ {
installerInput.dlcSources.push_back(path); installerInput.dlcSources.push_back(path);
} }
} }
return Installer::parseSources(installerInput, g_installerJournal, g_installerSources); bool sourcesParsed = Installer::parseSources(installerInput, g_installerJournal, g_installerSources);
errorMessage = g_installerJournal.lastErrorMessage;
return sourcesParsed;
} }
static void DrawNextButton() static void DrawNextButton()
@ -1195,10 +1198,17 @@ static void DrawNextButton()
} }
bool dlcInstallerMode = g_gameSourcePath.empty(); bool dlcInstallerMode = g_gameSourcePath.empty();
if (!InstallerParseSources()) std::string sourcesErrorMessage;
if (!InstallerParseSources(sourcesErrorMessage))
{ {
// Some of the sources that were provided to the installer are not valid. Restart the file selection process. // Some of the sources that were provided to the installer are not valid. Restart the file selection process.
g_currentMessagePrompt = Localise("Installer_Message_InvalidFiles"); std::stringstream stringStream;
stringStream << Localise("Installer_Message_InvalidFiles");
if (!sourcesErrorMessage.empty()) {
stringStream << std::endl << std::endl << sourcesErrorMessage;
}
g_currentMessagePrompt = stringStream.str();
g_currentMessagePromptConfirmation = false; g_currentMessagePromptConfirmation = false;
g_currentPage = dlcInstallerMode ? WizardPage::SelectDLC : WizardPage::SelectGameAndUpdate; g_currentPage = dlcInstallerMode ? WizardPage::SelectDLC : WizardPage::SelectGameAndUpdate;
} }