Ver código fonte

Merge topic 'cpack-several-checksums'

bc1c295b95 CPack: Add support for multiple checksums per package

Acked-by: Kitware Robot <[email protected]>
Merge-request: !11141
Brad King 1 mês atrás
pai
commit
bf1841534c

+ 4 - 0
Help/release/dev/cpack-several-checksums.rst

@@ -0,0 +1,4 @@
+cpack-several-checksums
+-----------------------
+
+* :variable:`CPACK_PACKAGE_CHECKSUM` now supports multiple values.

+ 5 - 2
Modules/CPack.cmake

@@ -204,8 +204,8 @@ installers.  The most commonly-used variables are:
 
   .. versionadded:: 3.7
 
-  An algorithm that will be used to generate an additional file with the
-  checksum of the package.  The output file name will be:
+  One or multiple algorithms that will be used to generate additional files with
+  the checksum of the package.  The output file names will be:
 
   .. code-block:: cmake
 
@@ -214,6 +214,9 @@ installers.  The most commonly-used variables are:
   Supported algorithms are those listed by the
   :ref:`string(\<HASH\>) <Supported Hash Algorithms>` command.
 
+  .. versionchanged:: 4.2
+    The variable accepts a list of algorithms.
+
 .. variable:: CPACK_PROJECT_CONFIG_FILE
 
   CPack-time project CPack configuration file.  This file is included at cpack

+ 56 - 13
Source/CPack/cmCPackGenerator.cxx

@@ -3,6 +3,7 @@
 #include "cmCPackGenerator.h"
 
 #include <algorithm>
+#include <iterator>
 #include <memory>
 #include <utility>
 
@@ -174,14 +175,42 @@ int cmCPackGenerator::PrepareNames()
     return 0;
   }
 
-  // Check algorithm for calculating the checksum of the package.
-  cmValue algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM");
-  if (algoSignature) {
-    if (!cmCryptoHash::New(*algoSignature)) {
-      cmCPackLogger(cmCPackLog::LOG_ERROR,
-                    "Cannot recognize algorithm: " << algoSignature
-                                                   << std::endl);
-      return 0;
+  // Check algorithms for calculating the checksum of the package.
+  cmValue algoSignatures = this->GetOption("CPACK_PACKAGE_CHECKSUM");
+  if (cmNonempty(algoSignatures)) {
+    cmList algoList{ algoSignatures };
+    // Workout unique algorithms and duplicates for diagnostic purposes
+    algoList.sort();
+    // Store a copy since std::unique modifies the sequence
+    cmList const sortedAlgoList = algoList;
+    auto const newEnd = std::unique(algoList.begin(), algoList.end());
+
+    if (newEnd != algoList.end()) {
+      cmList duplicatesAlgoList;
+
+      std::set_difference(sortedAlgoList.begin(), sortedAlgoList.end(),
+                          algoList.begin(), newEnd,
+                          std::back_inserter(duplicatesAlgoList));
+      // Make sure to output duplicates a single time even if these appear more
+      // than two times. Exploit the already sorted sequence to determine the
+      // unique elements.
+      duplicatesAlgoList.erase(
+        std::unique(duplicatesAlgoList.begin(), duplicatesAlgoList.end()),
+        duplicatesAlgoList.end());
+
+      cmCPackLogger(cmCPackLog::LOG_WARNING,
+                    "Algorithm specified multiple times: "
+                      << duplicatesAlgoList.join(", ") << std::endl);
+    }
+
+    algoList.erase(newEnd, algoList.end());
+
+    for (std::string const& algo : algoList) {
+      if (!cmCryptoHash::New(algo)) {
+        cmCPackLogger(cmCPackLog::LOG_ERROR,
+                      "Cannot recognize algorithm: " << algo << std::endl);
+        return 0;
+      }
     }
   }
 
@@ -1200,8 +1229,22 @@ int cmCPackGenerator::DoPackage()
   }
 
   /* Prepare checksum algorithm*/
-  cmValue algo = this->GetOption("CPACK_PACKAGE_CHECKSUM");
-  std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(*algo);
+  cmValue algoSignatures = this->GetOption("CPACK_PACKAGE_CHECKSUM");
+  std::vector<std::unique_ptr<cmCryptoHash>> crypto;
+
+  if (cmNonempty(algoSignatures)) {
+    cmList algoList{ algoSignatures };
+    // Keep unique algorithms since generating the same checksum multiple times
+    // is not meaningful.
+    algoList.remove_duplicates();
+    crypto.reserve(algoList.size());
+
+    for (std::string const& algo : algoList) {
+      if (std::unique_ptr<cmCryptoHash> hash = cmCryptoHash::New(algo)) {
+        crypto.push_back(std::move(hash));
+      }
+    }
+  }
 
   /*
    * Copy the generated packages to final destination
@@ -1218,9 +1261,9 @@ int cmCPackGenerator::DoPackage()
     if (!this->CopyPackageFile(pkgFileName, filename)) {
       return 0;
     }
-    /* Generate checksum file */
-    if (crypto) {
-      if (!this->GenerateChecksumFile(*crypto, filename)) {
+    /* Generate checksum files */
+    for (std::unique_ptr<cmCryptoHash> const& hash : crypto) {
+      if (!this->GenerateChecksumFile(*hash, filename)) {
         return 0;
       }
     }

+ 1 - 0
Tests/RunCMake/CPack/RunCMakeTest.cmake

@@ -41,6 +41,7 @@ run_cpack_test_package_target(MINIMAL "RPM.MINIMAL;DEB.MINIMAL;7Z;TBZ2;TGZ;TXZ;T
 run_cpack_test_package_target(THREADED_ALL "TXZ;DEB" false "MONOLITHIC;COMPONENT")
 run_cpack_test_package_target(THREADED "TXZ;DEB" false "MONOLITHIC;COMPONENT")
 run_cpack_test_subtests(PACKAGE_CHECKSUM "invalid;MD5;SHA1;SHA224;SHA256;SHA384;SHA512" "TGZ" false "MONOLITHIC")
+run_cpack_test(PACKAGE_CHECKSUM_MULTIPLE "TGZ" false "MONOLITHIC")
 run_cpack_test(PARTIALLY_RELOCATABLE_WARNING "RPM.PARTIALLY_RELOCATABLE_WARNING" false "COMPONENT")
 run_cpack_test(PER_COMPONENT_FIELDS "RPM.PER_COMPONENT_FIELDS;DEB.PER_COMPONENT_FIELDS" false "COMPONENT")
 run_cpack_test_subtests(SINGLE_DEBUGINFO "no_main_component" "RPM.SINGLE_DEBUGINFO" true "CUSTOM")

+ 2 - 0
Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM_MULTIPLE/ExpectedFiles.cmake

@@ -0,0 +1,2 @@
+set(EXPECTED_FILES_COUNT "1")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")

+ 14 - 0
Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM_MULTIPLE/VerifyResult.cmake

@@ -0,0 +1,14 @@
+set(hash_algos MD5 SHA1 SHA224 SHA256 SHA384 SHA512)
+
+file(GLOB PACKAGE RELATIVE "${bin_dir}" "*.tar.gz")
+
+foreach(algo IN LISTS hash_algos)
+  string(TOLOWER ${algo} CHECKSUM_EXTENSION)
+  file(STRINGS ${PACKAGE}.${CHECKSUM_EXTENSION} CHSUM_VALUE)
+  file(${algo} ${PACKAGE} expected_value)
+  set(expected_value "${expected_value}  ${PACKAGE}")
+
+  if(NOT expected_value STREQUAL CHSUM_VALUE)
+    message(FATAL_ERROR "Generated checksum is not valid! Expected [${expected_value}] Got [${CHSUM_VALUE}]")
+  endif()
+endforeach()

+ 2 - 0
Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM_MULTIPLE/test.cmake

@@ -0,0 +1,2 @@
+install(FILES CMakeLists.txt DESTINATION foo)
+set(CPACK_PACKAGE_CHECKSUM MD5 SHA1 SHA224 SHA256 SHA384 SHA512)