فهرست منبع

cli tar: support compression level

Fixes #27422
AJIOB 2 ماه پیش
والد
کامیت
d4d2a6a19d
22فایلهای تغییر یافته به همراه140 افزوده شده و 2 حذف شده
  1. 11 0
      Help/manual/cmake.1.rst
  2. 5 0
      Help/release/dev/cli-tar-compression-level.rst
  3. 1 0
      Help/release/dev/cli-tar-multithread.rst
  4. 56 1
      Source/cmcmd.cxx
  5. 13 0
      Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake
  6. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-bz2-result.txt
  7. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-bz2-stderr.txt
  8. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-gz-result.txt
  9. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-gz-stderr.txt
  10. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-no-compression-result.txt
  11. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-no-compression-stderr.txt
  12. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-not-a-number-result.txt
  13. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-not-a-number-stderr.txt
  14. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-xz-result.txt
  15. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-xz-stderr.txt
  16. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-zstd-result.txt
  17. 1 0
      Tests/RunCMake/CommandLineTar/bad-compression-level-zstd-stderr.txt
  18. 10 0
      Tests/RunCMake/CommandLineTar/compression-level-bz2.cmake
  19. 10 0
      Tests/RunCMake/CommandLineTar/compression-level-gz.cmake
  20. 10 0
      Tests/RunCMake/CommandLineTar/compression-level-xz.cmake
  21. 11 0
      Tests/RunCMake/CommandLineTar/compression-level-zstd.cmake
  22. 1 1
      Tests/RunCMake/File_Archive/RunCMakeTest.cmake

+ 11 - 0
Help/manual/cmake.1.rst

@@ -1497,6 +1497,17 @@ Available commands are:
 
 
     Specify modification time recorded in tarball entries.
     Specify modification time recorded in tarball entries.
 
 
+  .. option:: --cmake-tar-compression-level=<compression-level>
+
+    .. versionadded:: 4.3
+
+    The ``<compression-level>`` should be between ``0`` and ``9``, with the
+    default being ``0``.  The compression algorithm must be selected when
+    the ``--cmake-tar-compression-level`` option is given.
+
+    The ``<compression-level>`` of the ``Zstd`` algorithm can be set
+    between ``0`` and ``19``.
+
   .. option:: --cmake-tar-threads=<number>
   .. option:: --cmake-tar-threads=<number>
 
 
     .. versionadded:: 4.3
     .. versionadded:: 4.3

+ 5 - 0
Help/release/dev/cli-tar-compression-level.rst

@@ -0,0 +1,5 @@
+cli-tar-compression-level
+-------------------------
+
+* The :manual:`cmake(1)` ``-E tar`` tool supports specifying compression level
+  via ``--cmake-tar-compression-level`` option

+ 1 - 0
Help/release/dev/cli-tar-multithread.rst

@@ -2,5 +2,6 @@ cli-tar-multithread
 -------------------
 -------------------
 
 
 * The :manual:`cmake(1)` ``-E tar`` tool supports multithreading operations
 * The :manual:`cmake(1)` ``-E tar`` tool supports multithreading operations
+  via ``--cmake-tar-threads`` option
 * The :command:`file(ARCHIVE_CREATE)` command supports multithreading via the
 * The :command:`file(ARCHIVE_CREATE)` command supports multithreading via the
   ``THREADS`` option
   ``THREADS`` option

+ 56 - 1
Source/cmcmd.cxx

@@ -1584,6 +1584,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
       std::string mtime;
       std::string mtime;
       std::string format;
       std::string format;
       int numThreads = 1;
       int numThreads = 1;
+      int compressionLevel = 0;
+      bool compressionLevelFlagPassed = false;
       cmSystemTools::cmTarExtractTimestamps extractTimestamps =
       cmSystemTools::cmTarExtractTimestamps extractTimestamps =
         cmSystemTools::cmTarExtractTimestamps::Yes;
         cmSystemTools::cmTarExtractTimestamps::Yes;
       cmSystemTools::cmTarCompression compress =
       cmSystemTools::cmTarCompression compress =
@@ -1627,6 +1629,34 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
             }
             }
 
 
             numThreads = static_cast<decltype(numThreads)>(numThreadsLong);
             numThreads = static_cast<decltype(numThreads)>(numThreadsLong);
+          } else if (cmHasLiteralPrefix(arg,
+                                        "--cmake-tar-compression-level=")) {
+            std::string const& compressionLevelStr = arg.substr(30);
+            long compressionLevelLong = 0;
+            if (!cmStrToLong(compressionLevelStr, &compressionLevelLong)) {
+              cmSystemTools::Error(
+                cmStrCat("Invalid --cmake-tar-compression-level value: '",
+                         compressionLevelStr, "' - not a number"));
+              return 1;
+            }
+            if (compressionLevelLong >
+                std::numeric_limits<decltype(compressionLevel)>::max()) {
+              cmSystemTools::Error(
+                cmStrCat("Invalid --cmake-tar-compression-level value: '",
+                         compressionLevelStr, "' - too large"));
+              return 1;
+            }
+            if (compressionLevelLong <
+                std::numeric_limits<decltype(compressionLevel)>::min()) {
+              cmSystemTools::Error(
+                cmStrCat("Invalid --cmake-tar-compression-level value: '",
+                         compressionLevelStr, "' - too small"));
+              return 1;
+            }
+
+            compressionLevel =
+              static_cast<decltype(compressionLevel)>(compressionLevelLong);
+            compressionLevelFlagPassed = true;
           } else if (cmHasLiteralPrefix(arg, "--files-from=")) {
           } else if (cmHasLiteralPrefix(arg, "--files-from=")) {
             std::string const& files_from = arg.substr(13);
             std::string const& files_from = arg.substr(13);
             if (!cmTarFilesFrom(files_from, files)) {
             if (!cmTarFilesFrom(files_from, files)) {
@@ -1697,6 +1727,30 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
                              "at most one flag of z, j, or J may be used");
                              "at most one flag of z, j, or J may be used");
         return 1;
         return 1;
       }
       }
+      if (compressionLevelFlagPassed) {
+        if (nCompress == 0) {
+          cmSystemTools::Error("Can not use --cmake-tar-compression-level "
+                               "without compression algorithm selection");
+          return 1;
+        }
+
+        constexpr int minCompressionLevel = 0;
+        int maxCompressionLevel = 9;
+        if (compress == cmSystemTools::TarCompressZstd) {
+          maxCompressionLevel = 19;
+        }
+
+        if (compressionLevel < minCompressionLevel ||
+            compressionLevel > maxCompressionLevel) {
+          cmSystemTools::Error(
+            cmStrCat("Compression level must be between ",
+                     std::to_string(minCompressionLevel), " and ",
+                     std::to_string(maxCompressionLevel), ". Got ",
+                     std::to_string(compressionLevel)));
+          return 1;
+        }
+      }
+
       if (action == cmSystemTools::TarActionList) {
       if (action == cmSystemTools::TarActionList) {
         if (!cmSystemTools::ListTar(outFile, files, verbose)) {
         if (!cmSystemTools::ListTar(outFile, files, verbose)) {
           cmSystemTools::Error("Problem listing tar: " + outFile);
           cmSystemTools::Error("Problem listing tar: " + outFile);
@@ -1707,7 +1761,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
           std::cerr << "tar: No files or directories specified\n";
           std::cerr << "tar: No files or directories specified\n";
         }
         }
         if (!cmSystemTools::CreateTar(outFile, files, {}, compress, verbose,
         if (!cmSystemTools::CreateTar(outFile, files, {}, compress, verbose,
-                                      mtime, format, 0, numThreads)) {
+                                      mtime, format, compressionLevel,
+                                      numThreads)) {
           cmSystemTools::Error("Problem creating tar: " + outFile);
           cmSystemTools::Error("Problem creating tar: " + outFile);
           return 1;
           return 1;
         }
         }

+ 13 - 0
Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake

@@ -43,6 +43,19 @@ run_cmake(threads-xz)
 run_cmake(threads-zstd)
 run_cmake(threads-zstd)
 run_cmake(threads-zip)
 run_cmake(threads-zip)
 
 
+# Check the --cmake-tar-compression-level option
+external_command_test(bad-compression-level-no-compression  tar cvf bad.tar --cmake-tar-compression-level=1 .)
+external_command_test(bad-compression-level-not-a-number  tar cvjf bad.tar --cmake-tar-compression-level=nan .)
+external_command_test(bad-compression-level-bz2  tar cvjf bad.tar --cmake-tar-compression-level=10 .)
+external_command_test(bad-compression-level-gz  tar cvzf bad.tar --cmake-tar-compression-level=10 .)
+external_command_test(bad-compression-level-xz  tar cvJf bad.tar --cmake-tar-compression-level=10 .)
+external_command_test(bad-compression-level-zstd  tar cvf bad.tar --zstd --cmake-tar-compression-level=20 .)
+
+run_cmake(compression-level-bz2)
+run_cmake(compression-level-gz)
+run_cmake(compression-level-xz)
+run_cmake(compression-level-zstd)
+
 # Extracting only selected files or directories
 # Extracting only selected files or directories
 run_cmake(zip-filtered)
 run_cmake(zip-filtered)
 
 

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-bz2-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-bz2-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: Compression level must be between 0 and 9. Got 10$

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-gz-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-gz-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: Compression level must be between 0 and 9. Got 10$

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-no-compression-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-no-compression-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: Can not use --cmake-tar-compression-level without compression algorithm selection$

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-not-a-number-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-not-a-number-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: Invalid --cmake-tar-compression-level value: 'nan' - not a number$

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-xz-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-xz-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: Compression level must be between 0 and 9. Got 10$

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-zstd-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLineTar/bad-compression-level-zstd-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: Compression level must be between 0 and 19. Got 20$

+ 10 - 0
Tests/RunCMake/CommandLineTar/compression-level-bz2.cmake

@@ -0,0 +1,10 @@
+set(OUTPUT_NAME "test.tar.bz2")
+
+set(COMPRESSION_FLAGS cvjf)
+set(COMPRESSION_OPTIONS --cmake-tar-threads=9)
+
+set(DECOMPRESSION_FLAGS xvjf)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("425a68" LIMIT 3 HEX)

+ 10 - 0
Tests/RunCMake/CommandLineTar/compression-level-gz.cmake

@@ -0,0 +1,10 @@
+set(OUTPUT_NAME "test.tar.gz")
+
+set(COMPRESSION_FLAGS -cvzf)
+set(COMPRESSION_OPTIONS --cmake-tar-compression-level=9)
+
+set(DECOMPRESSION_FLAGS -xvzf)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("1f8b" LIMIT 2 HEX)

+ 10 - 0
Tests/RunCMake/CommandLineTar/compression-level-xz.cmake

@@ -0,0 +1,10 @@
+set(OUTPUT_NAME "test.tar.xz")
+
+set(COMPRESSION_FLAGS cvJf)
+set(COMPRESSION_OPTIONS --cmake-tar-compression-level=9)
+
+set(DECOMPRESSION_FLAGS xvJf)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("fd377a585a00" LIMIT 6 HEX)

+ 11 - 0
Tests/RunCMake/CommandLineTar/compression-level-zstd.cmake

@@ -0,0 +1,11 @@
+set(OUTPUT_NAME "test.tar.zstd")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --zstd --cmake-tar-compression-level=19)
+
+set(DECOMPRESSION_FLAGS xvf)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+# libarchive 3.8.2 enables a checksum feature; older versions do not.
+check_magic("^28b52ffd0[04][56]8$" LIMIT 6 HEX)

+ 1 - 1
Tests/RunCMake/File_Archive/RunCMakeTest.cmake

@@ -14,7 +14,7 @@ run_cmake(zip)
 
 
 run_cmake(working-directory)
 run_cmake(working-directory)
 
 
-# Check the --cmake-tar-threads option
+# Check the THREADS option
 run_cmake(argument-validation-threads)
 run_cmake(argument-validation-threads)
 run_cmake(threads-bz2)
 run_cmake(threads-bz2)
 run_cmake(threads-gz)
 run_cmake(threads-gz)