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
{
std::filesystem::path directoryPath;
std::string name;
DirectoryFileSystem(const std::filesystem::path &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
@ -51,6 +53,11 @@ struct DirectoryFileSystem : VirtualFileSystem
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)
{
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))
{
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;
}
if (!sourceVfs.load(filename, fileData))
{
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;
}
@ -96,7 +96,7 @@ static bool copyFile(const FilePair &pair, const uint64_t *fileHashes, VirtualFi
if (!fileHashFound)
{
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;
}
}
@ -150,7 +150,7 @@ static DLC detectDLC(const std::filesystem::path &sourcePath, VirtualFileSystem
if (!sourceVfs.load(DLCValidationFile, dlcXmlBytes))
{
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;
}
@ -164,7 +164,7 @@ static DLC detectDLC(const std::filesystem::path &sourcePath, VirtualFileSystem
if (typeStartLocation == nullptr || typeEndLocation == nullptr)
{
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;
}
@ -173,7 +173,7 @@ static DLC detectDLC(const std::filesystem::path &sourcePath, VirtualFileSystem
if (typeNumberCount != 1)
{
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;
}
@ -193,7 +193,7 @@ static DLC detectDLC(const std::filesystem::path &sourcePath, VirtualFileSystem
return DLC::EmpireCityAdabat;
default:
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;
}
}
@ -246,7 +246,7 @@ bool Installer::computeTotalSize(std::span<const FilePair> filePairs, const uint
if (!sourceVfs.exists(filename))
{
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;
}
@ -300,7 +300,7 @@ bool Installer::copyFiles(std::span<const FilePair> filePairs, const uint64_t *f
else
{
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;
}
@ -317,7 +317,7 @@ bool Installer::parseContent(const std::filesystem::path &sourcePath, std::uniqu
else
{
journal.lastResult = Journal::Result::VirtualFileSystemFailed;
journal.lastErrorMessage = "Unable to open file system at " + fromPath(sourcePath);
journal.lastErrorMessage = "Unable to open " + fromPath(sourcePath);
return false;
}
}

View file

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

View file

@ -22,11 +22,13 @@ struct ISOFileSystem : VirtualFileSystem
{
MemoryMappedFile mappedFile;
std::map<std::string, std::tuple<size_t, size_t>> fileMap;
std::string name;
ISOFileSystem(const std::filesystem::path &isoPath);
bool load(const std::string &path, uint8_t *fileData, size_t fileDataMaxByteCount) const override;
size_t getSize(const std::string &path) const override;
bool exists(const std::string &path) const override;
const std::string &getName() const override;
bool empty() const;
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 size_t getSize(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.
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;
}
name = (const char *)(contentPath.filename().u8string().data());
const uint8_t *rootMappedFileData = rootMappedFile.data();
if (sizeof(XContentContainerHeader) > rootMappedFile.size())
{
@ -607,6 +609,11 @@ bool XContentFileSystem::exists(const std::string &path) const
return fileMap.find(path) != fileMap.end();
}
const std::string &XContentFileSystem::getName() const
{
return name;
}
bool XContentFileSystem::empty() const
{
return mappedFiles.empty();

View file

@ -49,11 +49,13 @@ struct XContentFileSystem : VirtualFileSystem
std::vector<MemoryMappedFile> mappedFiles;
uint64_t baseOffset = 0;
std::map<std::string, File> fileMap;
std::string name;
XContentFileSystem(const std::filesystem::path &contentPath);
bool load(const std::string &path, uint8_t *fileData, size_t fileDataMaxByteCount) const override;
size_t getSize(const std::string &path) const override;
bool exists(const std::string &path) const override;
const std::string &getName() const override;
bool empty() const;
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);
}
static bool InstallerParseSources()
static bool InstallerParseSources(std::string &errorMessage)
{
std::error_code spaceErrorCode;
std::filesystem::space_info spaceInfo = std::filesystem::space(g_installPath, spaceErrorCode);
@ -1136,14 +1136,17 @@ static bool InstallerParseSources()
installerInput.gameSource = g_gameSourcePath;
installerInput.updateSource = g_updateSourcePath;
for (std::filesystem::path &path : g_dlcSourcePaths) {
for (std::filesystem::path &path : g_dlcSourcePaths)
{
if (!path.empty())
{
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()
@ -1195,10 +1198,17 @@ static void DrawNextButton()
}
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.
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_currentPage = dlcInstallerMode ? WizardPage::SelectDLC : WizardPage::SelectGameAndUpdate;
}