diff --git a/installer/Component.cpp b/installer/Component.cpp index 0504ffb50e..aa77c49a09 100644 --- a/installer/Component.cpp +++ b/installer/Component.cpp @@ -33,7 +33,7 @@ Component::Component(const nlohmann::json& json, const std::string& directory, component = parent + "_" + directory; } JsonHelper::handle(json, "Files", [&](const auto& file) { - files.emplace_back(file, component); + files.emplace_back(file, component, directory); }); JsonHelper::handle(json, "Registry", [&](const auto& registry) { registries.emplace_back(registry, component); @@ -99,3 +99,11 @@ std::vector Component::getServiceInstalls() const { std::vector Component::getShortcuts() const { return shortcuts; } + +std::string Component::getComponentName() const { + return component; +} + +std::string Component::getDirectory() const { + return directory; +} diff --git a/installer/Component.h b/installer/Component.h index a6da3cb878..0c4c4a8dc0 100644 --- a/installer/Component.h +++ b/installer/Component.h @@ -45,6 +45,8 @@ class Component : public Record { std::vector getServiceControls() const; std::vector getServiceInstalls() const; std::vector getShortcuts() const; + std::string getComponentName() const; + std::string getDirectory() const; private: std::string component{}; std::string componentId{}; diff --git a/installer/File.cpp b/installer/File.cpp index fb17a04f1b..d632f5b32c 100644 --- a/installer/File.cpp +++ b/installer/File.cpp @@ -21,15 +21,17 @@ #include "MsiHelper.h" #include "JsonHelper.h" -File::File(const nlohmann::json& json, const std::string& component) : - component(component) { +File::File(const nlohmann::json& json, const std::string& component, + const std::string& directory) : + component(component), directory(directory) { JsonHelper::get(json, "FilePath", filepath); JsonHelper::get(json, "IsFont", isFont); } MSIHANDLE File::getRecord() const { - return MsiHelper::MsiRecordSet({ getFileId(), component, filename, - filesize, version, language, attributes, sequence }); + return MsiHelper::MsiRecordSet({ getFileId(), component, + filename_short + "|" + filename_long, filesize, version, language, + attributes, sequence }); } std::filesystem::path File::getFilepath() const { @@ -75,10 +77,26 @@ void File::setFilepath(const std::filesystem::path& p) { filepath = p; } -void File::setFileName(const std::string& n) { - filename = n; +void File::setShortFileName(const std::string& n) { + filename_short = n; +} + +void File::setLongFileName(const std::string& n) { + filename_long = n; +} + +std::string File::getShortFileName() const { + return filename_short; +} + +std::string File::getLongFileName() const { + return filename_long; } bool File::isVersioned() const noexcept { return !version.empty(); } + +std::string File::getDirectory() const { + return directory; +} diff --git a/installer/File.h b/installer/File.h index 5ee986023f..604af0c696 100644 --- a/installer/File.h +++ b/installer/File.h @@ -23,7 +23,8 @@ class File : public Record { public: - explicit File(const nlohmann::json& json, const std::string& component); + explicit File(const nlohmann::json& json, const std::string& component, + const std::string& directory); ~File() = default; MSIHANDLE getRecord() const override; std::filesystem::path getFilepath() const; @@ -35,11 +36,16 @@ class File : public Record { void setAttributes(int a) noexcept; void setSequence(int s) noexcept; void setFilepath(const std::filesystem::path& p); - void setFileName(const std::string& n); + void setShortFileName(const std::string& n); + void setLongFileName(const std::string& n); + std::string getShortFileName() const; + std::string getLongFileName() const; bool isVersioned() const noexcept; + std::string getDirectory() const; private: std::string component{}; - std::string filename{}; + std::string filename_short{}; + std::string filename_long{}; int filesize = MSI_NULL_INTEGER; std::string version{}; std::string language{}; @@ -47,4 +53,5 @@ class File : public Record { int sequence = MSI_NULL_INTEGER; std::filesystem::path filepath{}; bool isFont = false; + std::string directory{}; }; diff --git a/installer/FileTable.cpp b/installer/FileTable.cpp index d1e88276f6..e2c081a304 100644 --- a/installer/FileTable.cpp +++ b/installer/FileTable.cpp @@ -120,25 +120,47 @@ std::filesystem::path FileTable::GetAbsolutePath( return root_path / p; } -std::string FileTable::GetFileName(const std::filesystem::path& filePath) { - char shortName[MAX_PATH]; - auto fileName = filePath.filename().string(); - std::cout << "Get short file name for " << fileName << std::endl; - if (GetShortPathName(filePath.string().c_str(), shortName, MAX_PATH) - != 0) { - std::cout << "Short file name for " << fileName << " is " << shortName - << std::endl; - const auto converted = - std::filesystem::path(shortName).filename().string(); - if (converted != fileName) { - return converted + "|" + fileName; - } +std::tuple FileTable::GetFileName( + const std::filesystem::path& filePath, const std::string& directory) { + auto extension = filePath.extension().string(); + if (extension.size() > 4) { + extension = extension.substr(0, 4); } - else { - std::cerr << "Failed to get short path name for " << filePath << - ": " << GetLastError() << std::endl; + std::transform(extension.begin(), extension.end(), extension.begin(), + ::toupper); + auto name = filePath.filename().stem().string(); + std::transform(name.begin(), name.end(), name.begin(), ::toupper); + auto i = 0; + const auto filename_long = name; + while (true) { + auto suffix_len = 1; + auto t = i; + while (t /= 10) { + suffix_len++; + } + ++suffix_len; + if (suffix_len > 6) { + suffix_len = 6; + } + if (filename_long.size() > 8) { + name = filename_long.substr(0, 8 - suffix_len) + "~" + + std::to_string(++i); + std::transform(name.begin(), name.end(), name.begin(), ::toupper); + } + auto found = false; + for (const auto& file : files) { + if (file.getDirectory() == directory && + file.getShortFileName() == name + extension) { + found = true; + break; + } + } + if (!found) { + break; + } } - return fileName; + + return { name + extension, filePath.filename().string() }; } FileTable::FileTable(const std::vector& directories, @@ -167,7 +189,11 @@ FileTable::FileTable(const std::vector& directories, } file.setFilesize(static_cast( GetFileSize(file.getFilepath().string()))); - file.setFileName(GetFileName(file.getFilepath())); + auto [filename_short, filename_long] = + GetFileName(file.getFilepath(), + component.getDirectory()); + file.setShortFileName(filename_short); + file.setLongFileName(filename_long); files.push_back(file); } } diff --git a/installer/FileTable.h b/installer/FileTable.h index dbeec6355f..41dccbe5fe 100644 --- a/installer/FileTable.h +++ b/installer/FileTable.h @@ -37,7 +37,8 @@ class FileTable : public Generator { size_t GetFileSize(const std::string& filePath); std::filesystem::path GetAbsolutePath( const std::filesystem::path& filePath); - std::string GetFileName(const std::filesystem::path& filePath); + std::tuple GetFileName( + const std::filesystem::path& filePath, const std::string& directory); std::vector files{}; std::filesystem::path root_path{}; std::filesystem::path output_path{}; diff --git a/tests/msi_validation.py b/tests/msi_validation.py index a408387d4b..8dc3738b54 100644 --- a/tests/msi_validation.py +++ b/tests/msi_validation.py @@ -57,7 +57,7 @@ def main(): if error_found: print("Validation failed") - sys.exit(0) + sys.exit(1) print("Validation succeeded") sys.exit(0)