From 9e67ad47a99b549ee02bd48ad2d1ae438f9f3181 Mon Sep 17 00:00:00 2001 From: Deniz Bahadir Date: Wed, 1 May 2024 19:20:32 +0200 Subject: cmLocalGenerator: Support arbitrary component name when installing The generated `cmake_install.cmake` script no longer blindly tries to create files `install_manifest_.txt` that partly consists of the verbatim name of a component, which might contain characters that are not supported on the platform / filesystem. Instead, if the component's name contains a (possibly) problematic character its MD5 hash will be used: `install_manifest_.txt` --- Source/cmLocalGenerator.cxx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index ffd41d2..22daa0e 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -717,8 +717,15 @@ void cmLocalGenerator::GenerateInstallRules() /* clang-format off */ fout << "if(CMAKE_INSTALL_COMPONENT)\n" - " set(CMAKE_INSTALL_MANIFEST \"install_manifest_" + " if(CMAKE_INSTALL_COMPONENT MATCHES \"^[a-zA-Z0-9_.+-]+$\")\n" + " set(CMAKE_INSTALL_MANIFEST \"install_manifest_" "${CMAKE_INSTALL_COMPONENT}.txt\")\n" + " else()\n" + " string(MD5 CMAKE_INST_COMP_HASH \"${CMAKE_INSTALL_COMPONENT}\")\n" + " set(CMAKE_INSTALL_MANIFEST \"install_manifest_" + "${CMAKE_INST_COMP_HASH}.txt\")\n" + " unset(CMAKE_INST_COMP_HASH)\n" + " endif()\n" "else()\n" " set(CMAKE_INSTALL_MANIFEST \"install_manifest.txt\")\n" "endif()\n" -- cgit v0.12 From a1af593291efecb5204eb7aa745468dc2a1bf1a7 Mon Sep 17 00:00:00 2001 From: Deniz Bahadir Date: Wed, 1 May 2024 19:20:32 +0200 Subject: CPack: Support arbitrary component name when packaging CPack no longer blindly tries to create temporary packaging (sub)directories that contain the verbatim name of a component, which might contain characters that are not supported on the platform / filesystem. Instead, if the component's name contains a (possibly) problematic character its MD5 hash will be used for that temporary packaging (sub)directory. Likewise, if the component's name resembles a reserved device name (e.g. "COM1" on Windows) then the temporary packaging (sub)directory will get this name prefixed with an underscore. Similar, if it ends in a dot (on Windows) then the temporary packaging (sub)directory will get this name suffixed with an underscore. Fixes: #23612 --- Modules/Internal/CPack/CPackRPM.cmake | 2 +- Source/CPack/IFW/cmCPackIFWGenerator.cxx | 18 +++++++++- Source/CPack/IFW/cmCPackIFWGenerator.h | 2 ++ Source/CPack/cmCPackArchiveGenerator.cxx | 9 +---- Source/CPack/cmCPackDebGenerator.cxx | 18 ++++++++-- Source/CPack/cmCPackDebGenerator.h | 2 ++ Source/CPack/cmCPackDragNDropGenerator.cxx | 22 ++++++++---- Source/CPack/cmCPackDragNDropGenerator.h | 2 ++ Source/CPack/cmCPackGenerator.cxx | 56 ++++++++++++++++++++++++++++-- Source/CPack/cmCPackGenerator.h | 22 ++++++++++++ Source/CPack/cmCPackRPMGenerator.cxx | 48 +++++++++++++++++++++---- Source/CPack/cmCPackRPMGenerator.h | 4 +++ 12 files changed, 176 insertions(+), 29 deletions(-) diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake index 23fb823..4998d71 100644 --- a/Modules/Internal/CPack/CPackRPM.cmake +++ b/Modules/Internal/CPack/CPackRPM.cmake @@ -916,7 +916,7 @@ function(cpack_rpm_generate_package) CPACK_RPM_MAIN_COMPONENT_UPPER) if(NOT CPACK_RPM_MAIN_COMPONENT_UPPER STREQUAL CPACK_RPM_PACKAGE_COMPONENT_UPPER) - string(APPEND CPACK_RPM_PACKAGE_NAME "-${CPACK_RPM_PACKAGE_COMPONENT}") + string(APPEND CPACK_RPM_PACKAGE_NAME "-${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}") cpack_rpm_variable_fallback("CPACK_RPM_PACKAGE_NAME" "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_NAME" diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index b3e5fe4..7c82668 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -461,7 +461,7 @@ int cmCPackIFWGenerator::InitializeInternal() return this->Superclass::InitializeInternal(); } -std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix( +std::string cmCPackIFWGenerator::GetComponentInstallSuffix( const std::string& componentName) { const std::string prefix = "packages/"; @@ -475,6 +475,22 @@ std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix( this->GetComponentPackageName(&this->Components[componentName]) + suffix; } +std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix( + const std::string& componentName) +{ + const std::string prefix = "packages/"; + const std::string suffix = "/data"; + + if (this->componentPackageMethod == this->ONE_PACKAGE) { + return cmStrCat(prefix, this->GetRootPackageName(), suffix); + } + + return prefix + + this->GetSanitizedDirOrFileName( + this->GetComponentPackageName(&this->Components[componentName])) + + suffix; +} + cmCPackComponent* cmCPackIFWGenerator::GetComponent( const std::string& projectName, const std::string& componentName) { diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h index 86b4993..e125be0 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.h +++ b/Source/CPack/IFW/cmCPackIFWGenerator.h @@ -67,6 +67,8 @@ protected: */ const char* GetOutputExtension() override; + std::string GetComponentInstallSuffix( + const std::string& componentName) override; std::string GetComponentInstallDirNameSuffix( const std::string& componentName) override; diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index b7b6785..8bd3aa0 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -234,7 +234,7 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( " - packaging component: " << component->Name << std::endl); // Add the files of this component to the archive std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); - localToplevel += "/" + component->Name; + localToplevel += "/" + this->GetSanitizedDirOrFileName(component->Name); // Change to local toplevel cmWorkingDirectory workdir(localToplevel); if (workdir.Failed()) { @@ -357,11 +357,7 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup) << comp.second.Name << "> does not belong to any group, package it separately." << std::endl); - std::string localToplevel( - this->GetOption("CPACK_TEMPORARY_DIRECTORY")); std::string packageFileName = std::string(this->toplevel); - - localToplevel += "/" + comp.first; packageFileName += "/" + this->GetArchiveComponentFileName(comp.first, false); @@ -379,10 +375,7 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup) // We build 1 package per component else { for (auto& comp : this->Components) { - std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); std::string packageFileName = std::string(this->toplevel); - - localToplevel += "/" + comp.first; packageFileName += "/" + this->GetArchiveComponentFileName(comp.first, false); diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 7693891..31191a9 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -536,6 +536,11 @@ int cmCPackDebGenerator::InitializeInternal() int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, std::string const& packageName) { + // Determine the sanitized packaging directory-name that can be used on the + // file-system. + std::string sanitizedPkgDirName = + this->GetSanitizedDirOrFileName(packageName); + // Begin the archive for this pack std::string localToplevel(initialTopLevel); std::string packageFileName( @@ -543,7 +548,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, std::string outputFileName(*this->GetOption("CPACK_PACKAGE_FILE_NAME") + "-" + packageName + this->GetOutputExtension()); - localToplevel += "/" + packageName; + localToplevel += "/" + sanitizedPkgDirName; /* replace the TEMP DIRECTORY with the component one */ this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel); packageFileName += "/" + outputFileName; @@ -554,7 +559,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, // Tell CPackDeb.cmake the name of the component GROUP. this->SetOption("CPACK_DEB_PACKAGE_COMPONENT", packageName); // Tell CPackDeb.cmake the path where the component is. - std::string component_path = cmStrCat('/', packageName); + std::string component_path = cmStrCat('/', sanitizedPkgDirName); this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH", component_path); if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -894,7 +899,7 @@ bool cmCPackDebGenerator::SupportsComponentInstallation() const return this->IsOn("CPACK_DEB_COMPONENT_INSTALL"); } -std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix( +std::string cmCPackDebGenerator::GetComponentInstallSuffix( const std::string& componentName) { if (this->componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) { @@ -913,3 +918,10 @@ std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix( } return componentName; } + +std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix( + const std::string& componentName) +{ + return this->GetSanitizedDirOrFileName( + this->GetComponentInstallSuffix(componentName)); +} diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h index 11561a4..2a8c194 100644 --- a/Source/CPack/cmCPackDebGenerator.h +++ b/Source/CPack/cmCPackDebGenerator.h @@ -59,6 +59,8 @@ protected: int PackageFiles() override; const char* GetOutputExtension() override { return ".deb"; } bool SupportsComponentInstallation() const override; + std::string GetComponentInstallSuffix( + const std::string& componentName) override; std::string GetComponentInstallDirNameSuffix( const std::string& componentName) override; diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index b4cada3..4c518ac 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -182,13 +182,14 @@ int cmCPackDragNDropGenerator::PackageFiles() } // component install - std::vector package_files; + std::vector> package_files; std::map::iterator compIt; for (compIt = this->Components.begin(); compIt != this->Components.end(); ++compIt) { - std::string name = GetComponentInstallDirNameSuffix(compIt->first); - package_files.push_back(name); + std::string dirName = GetComponentInstallDirNameSuffix(compIt->first); + std::string fileName = GetComponentInstallSuffix(compIt->first); + package_files.emplace_back(fileName, dirName); } std::sort(package_files.begin(), package_files.end()); package_files.erase(std::unique(package_files.begin(), package_files.end()), @@ -198,15 +199,15 @@ int cmCPackDragNDropGenerator::PackageFiles() packageFileNames.clear(); for (auto const& package_file : package_files) { std::string full_package_name = cmStrCat(toplevel, '/'); - if (package_file == "ALL_IN_ONE"_s) { + if (package_file.first == "ALL_IN_ONE"_s) { full_package_name += this->GetOption("CPACK_PACKAGE_FILE_NAME"); } else { - full_package_name += package_file; + full_package_name += package_file.first; } full_package_name += GetOutputExtension(); packageFileNames.push_back(full_package_name); - std::string src_dir = cmStrCat(toplevel, '/', package_file); + std::string src_dir = cmStrCat(toplevel, '/', package_file.second); if (0 == this->CreateDMG(src_dir, full_package_name)) { return 0; @@ -707,7 +708,7 @@ bool cmCPackDragNDropGenerator::SupportsComponentInstallation() const return true; } -std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix( +std::string cmCPackDragNDropGenerator::GetComponentInstallSuffix( const std::string& componentName) { // we want to group components together that go in the same dmg package @@ -747,6 +748,13 @@ std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix( return GetComponentPackageFileName(package_file_name, componentName, false); } +std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix( + const std::string& componentName) +{ + return this->GetSanitizedDirOrFileName( + this->GetComponentInstallSuffix(componentName)); +} + void cmCPackDragNDropGenerator::WriteRezXML(std::string const& file, RezDoc const& rez) { diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h index 6089ae5..249f73e 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.h +++ b/Source/CPack/cmCPackDragNDropGenerator.h @@ -35,6 +35,8 @@ protected: bool CreateEmptyFile(std::ostringstream& target, size_t size); bool RunCommand(std::string const& command, std::string* output = nullptr); + std::string GetComponentInstallSuffix( + const std::string& componentName) override; std::string GetComponentInstallDirNameSuffix( const std::string& componentName) override; diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 4a5580c..03b8766 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -761,6 +761,7 @@ int cmCPackGenerator::InstallCMakeProject( // instead of the default // one install directory for each component. tempInstallDirectory += this->GetComponentInstallDirNameSuffix(component); + if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) { tempInstallDirectory += "/"; tempInstallDirectory += *this->GetOption("CPACK_PACKAGE_FILE_NAME"); @@ -965,7 +966,7 @@ int cmCPackGenerator::InstallCMakeProject( if (componentInstall) { std::string absoluteDestFileComponent = std::string("CPACK_ABSOLUTE_DESTINATION_FILES") + "_" + - this->GetComponentInstallDirNameSuffix(component); + this->GetComponentInstallSuffix(component); if (nullptr != this->GetOption(absoluteDestFileComponent)) { std::string absoluteDestFilesListComponent = cmStrCat(this->GetOption(absoluteDestFileComponent), ';', *d); @@ -1544,11 +1545,62 @@ int cmCPackGenerator::PrepareGroupingKind() return 1; } -std::string cmCPackGenerator::GetComponentInstallDirNameSuffix( +std::string cmCPackGenerator::GetSanitizedDirOrFileName( + const std::string& name, bool isFullName) const +{ + if (isFullName) { +#ifdef _WIN32 + // Given name matches a reserved name (on Windows)? + // Then return it prepended with an underscore. + cmsys::RegularExpression reserved_pattern("^(" + "[Cc][Oo][Nn]|" + "[Pp][Rr][Nn]|" + "[Aa][Uu][Xx]|" + "[Nn][Uu][Ll]|" + "[Cc][Oo][Mm][1-9]|" + "[Ll][Pp][Tt][1-9]" + ")([.].+)?"); + if (reserved_pattern.find(name)) { + return "_" + name; + } + // Given name ends in a dot (on Windows)? + // Then return it appended with an underscore. + if (name.back() == '.') { + return name + '_'; + } +#endif + } + +#ifndef _WIN32 + constexpr const char* prohibited_chars = "<>\"/\\|?*`"; +#else + // Note: Windows also excludes the colon. + constexpr const char* prohibited_chars = "<>\"/\\|?*`:"; +#endif + // Given name contains non-supported character? + // Then return its MD5 hash. + if (name.find_first_of(prohibited_chars) != std::string::npos) { + cmCryptoHash hasher(cmCryptoHash::AlgoMD5); + return hasher.HashString(name); + } + + // Otherwise return unmodified. + return name; +} + +std::string cmCPackGenerator::GetComponentInstallSuffix( const std::string& componentName) { return componentName; } + +std::string cmCPackGenerator::GetComponentInstallDirNameSuffix( + const std::string& componentName) +{ + return this->GetSanitizedDirOrFileName( + this->GetComponentInstallSuffix(componentName)); +} + std::string cmCPackGenerator::GetComponentPackageFileName( const std::string& initialPackageFileName, const std::string& groupOrComponentName, bool isGroupName) diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index c9af776..980ab8f 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -145,6 +145,18 @@ protected: virtual int PrepareGroupingKind(); /** + * Ensures that the given name only contains characters that can cleanly be + * used as directory or file name and returns this sanitized name. Possibly, + * this name might be replaced by its hash. + * @param[in] name the name for a directory or file that shall be sanitized. + * @param[in] isFullName true if the result is used as the full name for a + * directory or file. (Defaults to true.) + * @return the sanitized name. + */ + virtual std::string GetSanitizedDirOrFileName(const std::string& name, + bool isFullName = true) const; + + /** * Some CPack generators may prefer to have * CPack install all components belonging to the same * [component] group to be install in the same directory. @@ -154,6 +166,16 @@ protected: * @return the name suffix the generator wants for the specified component * default is "componentName" */ + virtual std::string GetComponentInstallSuffix( + const std::string& componentName); + + /** + * The value that GetComponentInstallSuffix returns, but sanitized. + * @param[in] componentName the name of the component to be installed + * @return the name suffix the generator wants for the specified component + * (but sanitized, so that it can be used on the file-system). + * default is "componentName". + */ virtual std::string GetComponentInstallDirNameSuffix( const std::string& componentName); diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx index 3d4d05e..8dfb159 100644 --- a/Source/CPack/cmCPackRPMGenerator.cxx +++ b/Source/CPack/cmCPackRPMGenerator.cxx @@ -12,6 +12,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" +#include "cmCryptoHash.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -62,7 +63,15 @@ void cmCPackRPMGenerator::AddGeneratedPackageNames() int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel, std::string const& packageName) { - int retval = 1; + // Determine the sanitized package name that can be used in file-names on + // the file-system. + std::string sanitizedPkgNameSuffix = + this->GetSanitizedDirOrFileName(packageName, false); + // Determine the sanitized packaging directory-name that can be used on the + // file-system. + std::string sanitizedPkgDirName = + this->GetSanitizedDirOrFileName(packageName); + // Begin the archive for this pack std::string localToplevel(initialToplevel); std::string packageFileName( @@ -72,7 +81,7 @@ int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel, this->GetOption("CPACK_PACKAGE_FILE_NAME"), packageName, true) + this->GetOutputExtension()); - localToplevel += "/" + packageName; + localToplevel += "/" + sanitizedPkgDirName; /* replace the TEMP DIRECTORY with the component one */ this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel); packageFileName += "/" + outputFileName; @@ -82,16 +91,34 @@ int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel, this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", packageFileName); // Tell CPackRPM.cmake the name of the component NAME. this->SetOption("CPACK_RPM_PACKAGE_COMPONENT", packageName); + // Tell CPackRPM.cmake the suffix for the component NAME. + this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_NAME", + sanitizedPkgNameSuffix); // Tell CPackRPM.cmake the path where the component is. - std::string component_path = cmStrCat('/', packageName); + std::string component_path = cmStrCat('/', sanitizedPkgDirName); this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH", component_path); if (!this->ReadListFile("Internal/CPack/CPackRPM.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackRPM.cmake" << std::endl); - retval = 0; + return 0; } - return retval; + return 1; +} + +std::string cmCPackRPMGenerator::GetSanitizedDirOrFileName( + const std::string& name, bool isFullName) const +{ + auto sanitizedName = + this->cmCPackGenerator::GetSanitizedDirOrFileName(name, isFullName); + if (sanitizedName == name && !isFullName) { + // Make sure to also sanitize if name contains a colon (':'). + if (name.find_first_of(':') != std::string::npos) { + cmCryptoHash hasher(cmCryptoHash::AlgoMD5); + return hasher.HashString(name); + } + } + return sanitizedName; } int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup) @@ -417,7 +444,7 @@ bool cmCPackRPMGenerator::SupportsComponentInstallation() const return this->IsOn("CPACK_RPM_COMPONENT_INSTALL"); } -std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix( +std::string cmCPackRPMGenerator::GetComponentInstallSuffix( const std::string& componentName) { if (this->componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) { @@ -432,7 +459,14 @@ std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix( std::string groupVar = "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP"; if (nullptr != this->GetOption(groupVar)) { - return std::string(this->GetOption(groupVar)); + return *this->GetOption(groupVar); } return componentName; } + +std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix( + const std::string& componentName) +{ + return this->GetSanitizedDirOrFileName( + this->GetComponentInstallSuffix(componentName)); +} diff --git a/Source/CPack/cmCPackRPMGenerator.h b/Source/CPack/cmCPackRPMGenerator.h index 886afb1..0e23503 100644 --- a/Source/CPack/cmCPackRPMGenerator.h +++ b/Source/CPack/cmCPackRPMGenerator.h @@ -61,7 +61,11 @@ protected: */ int PackageComponentsAllInOne(const std::string& compInstDirName); const char* GetOutputExtension() override { return ".rpm"; } + std::string GetSanitizedDirOrFileName(const std::string& name, + bool isFullName = true) const override; bool SupportsComponentInstallation() const override; + std::string GetComponentInstallSuffix( + const std::string& componentName) override; std::string GetComponentInstallDirNameSuffix( const std::string& componentName) override; -- cgit v0.12 From d7e2fede0351f4438548ea135ebf3058cb46ebda Mon Sep 17 00:00:00 2001 From: Deniz Bahadir Date: Wed, 1 May 2024 19:20:32 +0200 Subject: CPack: Add tests for component containing problematic characters --- Tests/RunCMake/CMakeLists.txt | 2 ++ .../CPack/DEB/packaging_GROUP_default.cmake | 1 + Tests/RunCMake/CPack/RunCMakeTest.cmake | 2 ++ .../ExpectedFiles.cmake | 42 ++++++++++++++++++++++ .../tests/COMPONENT_WITH_SPECIAL_CHARS/test.cmake | 34 ++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 Tests/RunCMake/CPack/DEB/packaging_GROUP_default.cmake create mode 100644 Tests/RunCMake/CPack/tests/COMPONENT_WITH_SPECIAL_CHARS/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/COMPONENT_WITH_SPECIAL_CHARS/test.cmake diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 005bd17..192675e 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -1047,6 +1047,7 @@ set(cpack_tests DEB.DEB_PACKAGE_VERSION_BACK_COMPATIBILITY DEB.DEB_DESCRIPTION DEB.PROJECT_META + DEB.COMPONENT_WITH_SPECIAL_CHARS RPM.AUTO_SUFFIXES RPM.CUSTOM_BINARY_SPEC_FILE @@ -1069,6 +1070,7 @@ set(cpack_tests RPM.SYMLINKS RPM.USER_FILELIST RPM.PROJECT_META + RPM.COMPONENT_WITH_SPECIAL_CHARS 7Z TBZ2 diff --git a/Tests/RunCMake/CPack/DEB/packaging_GROUP_default.cmake b/Tests/RunCMake/CPack/DEB/packaging_GROUP_default.cmake new file mode 100644 index 0000000..8821ab9 --- /dev/null +++ b/Tests/RunCMake/CPack/DEB/packaging_GROUP_default.cmake @@ -0,0 +1 @@ +set(CPACK_PACKAGE_CONTACT "someone") diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 258f6a6..5d32404 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -71,3 +71,5 @@ run_cpack_test_subtests( run_cpack_test(PROJECT_META "RPM.PROJECT_META;DEB.PROJECT_META" false "MONOLITHIC;COMPONENT") run_cpack_test_package_target(PRE_POST_SCRIPTS "ZIP" false "MONOLITHIC;COMPONENT") run_cpack_test_subtests(DUPLICATE_FILE "success;conflict_file;conflict_symlink" "TGZ" false "COMPONENT;GROUP") +run_cpack_test(COMPONENT_WITH_SPECIAL_CHARS "RPM.COMPONENT_WITH_SPECIAL_CHARS;DEB.COMPONENT_WITH_SPECIAL_CHARS;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ" false "MONOLITHIC;COMPONENT;GROUP") +run_cpack_test_package_target(COMPONENT_WITH_SPECIAL_CHARS "RPM.COMPONENT_WITH_SPECIAL_CHARS;DEB.COMPONENT_WITH_SPECIAL_CHARS;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ" false "MONOLITHIC;COMPONENT;GROUP") diff --git a/Tests/RunCMake/CPack/tests/COMPONENT_WITH_SPECIAL_CHARS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/COMPONENT_WITH_SPECIAL_CHARS/ExpectedFiles.cmake new file mode 100644 index 0000000..0eb250d --- /dev/null +++ b/Tests/RunCMake/CPack/tests/COMPONENT_WITH_SPECIAL_CHARS/ExpectedFiles.cmake @@ -0,0 +1,42 @@ +if(PACKAGING_TYPE STREQUAL "MONOLITHIC") + set(EXPECTED_FILES_COUNT "1") + set(EXPECTED_FILE_CONTENT_1_LIST + "/foo1" + "/foo1/CMakeLists.txt" + "/foo2" + "/foo2/CMakeLists.txt" + "/foo3" + "/foo3/CMakeLists.txt" + ) +elseif(PACKAGING_TYPE STREQUAL "COMPONENT") + set(EXPECTED_FILES_COUNT "3") + set(EXPECTED_FILE_1 "*-comp1.test1.*") + set(EXPECTED_FILE_CONTENT_1_LIST + "/foo1" + "/foo1/CMakeLists.txt" + ) + set(EXPECTED_FILE_2 "*-component2.*") + set(EXPECTED_FILE_CONTENT_2_LIST + "/foo2" + "/foo2/CMakeLists.txt" + ) + set(EXPECTED_FILE_3 "*-component3.*") + set(EXPECTED_FILE_CONTENT_3_LIST + "/foo3" + "/foo3/CMakeLists.txt" + ) +elseif(PACKAGING_TYPE STREQUAL "GROUP") + set(EXPECTED_FILES_COUNT "2") + set(EXPECTED_FILE_1 "*-group1.*") + set(EXPECTED_FILE_CONTENT_1_LIST + "/foo1" + "/foo1/CMakeLists.txt" + "/foo2" + "/foo2/CMakeLists.txt" + ) + set(EXPECTED_FILE_2 "*-group2.*") + set(EXPECTED_FILE_CONTENT_2_LIST + "/foo3" + "/foo3/CMakeLists.txt" + ) +endif() diff --git a/Tests/RunCMake/CPack/tests/COMPONENT_WITH_SPECIAL_CHARS/test.cmake b/Tests/RunCMake/CPack/tests/COMPONENT_WITH_SPECIAL_CHARS/test.cmake new file mode 100644 index 0000000..b905cc3 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/COMPONENT_WITH_SPECIAL_CHARS/test.cmake @@ -0,0 +1,34 @@ +install(FILES CMakeLists.txt DESTINATION foo1 COMPONENT comp1.test1) +install(FILES CMakeLists.txt DESTINATION foo2 COMPONENT comp2::test2) +install(FILES CMakeLists.txt DESTINATION foo3 COMPONENT comp3/test3) + +if(PACKAGING_TYPE STREQUAL "COMPONENT") + foreach(gen IN ITEMS ARCHIVE DEBIAN RPM) + set(CPACK_${gen}_COMP2::TEST2_FILE_NAME "component_with_special_chars-0.1.1-${CMAKE_SYSTEM_NAME}-component2") + set(CPACK_${gen}_COMP3/TEST3_FILE_NAME "component_with_special_chars-0.1.1-${CMAKE_SYSTEM_NAME}-component3") + endforeach() +elseif(PACKAGING_TYPE STREQUAL "GROUP") + set(CPACK_COMPONENTS_GROUPING ONE_PER_GROUP) + foreach(gen IN ITEMS ARCHIVE DEB RPM) + set(CPACK_${gen}_COMPONENT_INSTALL ON) + endforeach() + include(CPackComponent) + + cpack_add_component_group(group1 DISPLAY_NAME "Group 1") + cpack_add_component_group(group2 DISPLAY_NAME "Group 2") + cpack_add_component(comp1.test1 + DISPLAY_NAME "Group 1" + DESCRIPTION "Component for Group 1" + GROUP group1 + ) + cpack_add_component(comp2::test2 + DISPLAY_NAME "Group 1" + DESCRIPTION "Component for Group 1" + GROUP group1 + ) + cpack_add_component(comp3/test3 + DISPLAY_NAME "Group 2" + DESCRIPTION "Component for Group 2" + GROUP group2 + ) +endif() -- cgit v0.12