Browse Source

Merge topic 'file-archive-workdir'

d8a9aabd24 file(ARCHIVE_CREATE): add WORKING_DIRECTORY option
d65b5a8e03 Help: Format file(ARCHIVE*) options as definition lists

Acked-by: Kitware Robot <[email protected]>
Merge-request: !9803
Brad King 1 year ago
parent
commit
b91ea1b368

+ 58 - 35
Help/command/file.rst

@@ -901,8 +901,9 @@ Archiving
     PATHS <paths>...
     [FORMAT <format>]
     [COMPRESSION <compression>
-     [COMPRESSION_LEVEL <compression-level>]]
+    [COMPRESSION_LEVEL <compression-level>]]
     [MTIME <mtime>]
+    [WORKING_DIRECTORY <dir>]
     [VERBOSE])
   :target: ARCHIVE_CREATE
   :break: verbatim
@@ -913,40 +914,55 @@ Archiving
   listed in ``<paths>``.  Note that ``<paths>`` must list actual files or
   directories; wildcards are not supported.
 
-  Use the ``FORMAT`` option to specify the archive format.  Supported values
-  for ``<format>`` are ``7zip``, ``gnutar``, ``pax``, ``paxr``, ``raw`` and
-  ``zip``.  If ``FORMAT`` is not given, the default format is ``paxr``.
+  The options are:
 
-  Some archive formats allow the type of compression to be specified.
-  The ``7zip`` and ``zip`` archive formats already imply a specific type of
-  compression.  The other formats use no compression by default, but can be
-  directed to do so with the ``COMPRESSION`` option.  Valid values for
-  ``<compression>`` are ``None``, ``BZip2``, ``GZip``, ``XZ``, and ``Zstd``.
+  ``FORMAT <format>``
+    Specify the archive format.  Supported values for ``<format>`` are
+    ``7zip``, ``gnutar``, ``pax``, ``paxr``, ``raw`` and ``zip``.
+    If ``FORMAT`` is not given, the default format is ``paxr``.
+
+  ``COMPRESSION <compression>``
+    Some archive formats allow the type of compression to be specified.
+    The ``7zip`` and ``zip`` archive formats already imply a specific type of
+    compression.  The other formats use no compression by default, but can be
+    directed to do so with the ``COMPRESSION`` option.  Valid values for
+    ``<compression>`` are ``None``, ``BZip2``, ``GZip``, ``XZ``, and ``Zstd``.
+
+    .. note::
+      With ``FORMAT`` set to ``raw``, only one file will be compressed
+      with the compression type specified by ``COMPRESSION``.
+
+  ``COMPRESSION_LEVEL <compression-level>``
+    .. versionadded:: 3.19
 
-  .. versionadded:: 3.19
     The compression level can be specified with the ``COMPRESSION_LEVEL``
     option.  The ``<compression-level>`` should be between 0-9, with the
     default being 0.  The ``COMPRESSION`` option must be present when
     ``COMPRESSION_LEVEL`` is given.
 
-  .. versionadded:: 3.26
-    The ``<compression-level>`` of the ``Zstd`` algorithm can be set
-    between 0-19.
+    .. versionadded:: 3.26
+      The ``<compression-level>`` of the ``Zstd`` algorithm can be set
+      between 0-19.
 
-  .. note::
-    With ``FORMAT`` set to ``raw``, only one file will be compressed with the
-    compression type specified by ``COMPRESSION``.
+  ``MTIME <mtime>``
+    Specify the modification time recorded in tarball entries.
+
+  ``WORKING_DIRECTORY <dir>``
+    .. versionadded:: 3.31
 
-  The ``VERBOSE`` option enables verbose output for the archive operation.
+    Specify the directory in which the archive creation operation will
+    be executed.  Paths in the ``<paths>`` argument can be relative to
+    this directory.  If this option is not provided, the current working
+    directory will be used by default.
 
-  To specify the modification time recorded in tarball entries, use
-  the ``MTIME`` option.
+  ``VERBOSE``
+    Enable verbose output from the archive operation.
 
 .. signature::
   file(ARCHIVE_EXTRACT
     INPUT <archive>
     [DESTINATION <dir>]
-    [PATTERNS <patterns>...]
+    [PATTERNS <pattern>...]
     [LIST_ONLY]
     [VERBOSE]
     [TOUCH])
@@ -956,17 +972,30 @@ Archiving
 
   Extracts or lists the content of the specified ``<archive>``.
 
-  The directory where the content of the archive will be extracted to can
-  be specified using the ``DESTINATION`` option.  If the directory does not
-  exist, it will be created.  If ``DESTINATION`` is not given, the current
-  binary directory will be used.
+  The options are:
+
+  ``DESTINATION <dir>``
+    Specify the directory under which the content of the archive will be
+    extracted.  If the directory does not exist, it will be created.
+    If ``DESTINATION`` is not given, the current binary directory will
+    be used.
+
+  ``PATTERNS <pattern>...``
+    Extract/list only files and directories that match one of the given
+    patterns.  Wildcards are supported.  If the ``PATTERNS`` option is
+    not given, the entire archive will be listed or extracted.
+
+  ``LIST_ONLY``
+    List the files in the archive rather than extract them.
 
-  If required, you may select which files and directories to list or extract
-  from the archive using the specified ``<patterns>``.  Wildcards are
-  supported.  If the ``PATTERNS`` option is not given, the entire archive will
-  be listed or extracted.
+  ``TOUCH``
+    .. versionadded:: 3.24
 
-  ``LIST_ONLY`` will list the files in the archive rather than extract them.
+    Give extracted files a current local timestamp instead of extracting
+    file timestamps from the archive.
+
+  ``VERBOSE``
+    Enable verbose output from the extraction operation.
 
   .. note::
     The working directory for this subcommand is the ``DESTINATION`` directory
@@ -975,12 +1004,6 @@ Archiving
     ``INPUT`` archives as they are unlikely to be extracted where a relative
     path works.
 
-  .. versionadded:: 3.24
-    The ``TOUCH`` option gives extracted files a current local
-    timestamp instead of extracting file timestamps from the archive.
-
-  With ``VERBOSE``, the command will produce verbose output.
-
 Handling Runtime Binaries
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 

+ 5 - 0
Help/release/dev/file-archive-workdir.rst

@@ -0,0 +1,5 @@
+file-archive-workdir
+--------------------
+
+* The :command:`file(ARCHIVE_CREATE)` command gained a ``WORKING_DIRECTORY``
+  option to specify a working directory for the archiving process.

+ 2 - 2
Source/cmCTest.cxx

@@ -1646,8 +1646,8 @@ std::string cmCTest::Base64GzipEncodeFile(std::string const& file)
   std::vector<std::string> files;
   files.push_back(file);
 
-  if (!cmSystemTools::CreateTar(tarFile, files, cmSystemTools::TarCompressGZip,
-                                false)) {
+  if (!cmSystemTools::CreateTar(tarFile, files, {},
+                                cmSystemTools::TarCompressGZip, false)) {
     cmCTestLog(this, ERROR_MESSAGE,
                "Error creating tar while "
                "encoding file: "

+ 4 - 1
Source/cmFileCommand.cxx

@@ -3607,6 +3607,7 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
     // accepted without one and treated as if an empty value were given.
     // Fixing this would require a policy.
     ArgumentParser::Maybe<std::string> MTime;
+    std::string WorkingDirectory;
     bool Verbose = false;
     // "PATHS" requires at least one value, but use a custom check below.
     ArgumentParser::MaybeEmpty<std::vector<std::string>> Paths;
@@ -3619,6 +3620,7 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
       .Bind("COMPRESSION"_s, &Arguments::Compression)
       .Bind("COMPRESSION_LEVEL"_s, &Arguments::CompressionLevel)
       .Bind("MTIME"_s, &Arguments::MTime)
+      .Bind("WORKING_DIRECTORY"_s, &Arguments::WorkingDirectory)
       .Bind("VERBOSE"_s, &Arguments::Verbose)
       .Bind("PATHS"_s, &Arguments::Paths);
 
@@ -3718,7 +3720,8 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
     return false;
   }
 
-  if (!cmSystemTools::CreateTar(parsedArgs.Output, parsedArgs.Paths, compress,
+  if (!cmSystemTools::CreateTar(parsedArgs.Output, parsedArgs.Paths,
+                                parsedArgs.WorkingDirectory, compress,
                                 parsedArgs.Verbose, parsedArgs.MTime,
                                 parsedArgs.Format, compressionLevel)) {
     status.SetError(cmStrCat("failed to compress: ", parsedArgs.Output));

+ 8 - 1
Source/cmSystemTools.cxx

@@ -36,6 +36,7 @@
 #include "cmUVProcessChain.h"
 #include "cmUVStream.h"
 #include "cmValue.h"
+#include "cmWorkingDirectory.h"
 
 #if !defined(CMAKE_BOOTSTRAP)
 #  include <cm3p/archive.h>
@@ -1867,12 +1868,18 @@ bool cmSystemTools::IsPathToMacOSSharedLibrary(const std::string& path)
 
 bool cmSystemTools::CreateTar(const std::string& outFileName,
                               const std::vector<std::string>& files,
+                              const std::string& workingDirectory,
                               cmTarCompression compressType, bool verbose,
                               std::string const& mtime,
                               std::string const& format, int compressionLevel)
 {
 #if !defined(CMAKE_BOOTSTRAP)
-  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+  cmWorkingDirectory workdir(cmSystemTools::GetCurrentWorkingDirectory());
+  if (!workingDirectory.empty()) {
+    workdir.SetDirectory(workingDirectory);
+  }
+
+  const std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
   cmsys::ofstream fout(outFileName.c_str(), std::ios::out | std::ios::binary);
   if (!fout) {
     std::string e = cmStrCat("Cannot open output file \"", outFileName,

+ 1 - 0
Source/cmSystemTools.h

@@ -497,6 +497,7 @@ public:
                       const std::vector<std::string>& files, bool verbose);
   static bool CreateTar(const std::string& outFileName,
                         const std::vector<std::string>& files,
+                        const std::string& workingDirectory,
                         cmTarCompression compressType, bool verbose,
                         std::string const& mtime = std::string(),
                         std::string const& format = std::string(),

+ 2 - 2
Source/cmcmd.cxx

@@ -1550,8 +1550,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
         if (files.empty()) {
           std::cerr << "tar: No files or directories specified\n";
         }
-        if (!cmSystemTools::CreateTar(outFile, files, compress, verbose, mtime,
-                                      format)) {
+        if (!cmSystemTools::CreateTar(outFile, files, {}, compress, verbose,
+                                      mtime, format)) {
           cmSystemTools::Error("Problem creating tar: " + outFile);
           return 1;
         }

+ 2 - 0
Tests/RunCMake/File_Archive/RunCMakeTest.cmake

@@ -10,6 +10,8 @@ run_cmake(paxr)
 run_cmake(paxr-bz2)
 run_cmake(zip)
 
+run_cmake(working-directory)
+
 # Extracting only selected files or directories
 run_cmake(zip-filtered)
 

+ 4 - 3
Tests/RunCMake/File_Archive/roundtrip.cmake

@@ -39,8 +39,9 @@ file(ARCHIVE_CREATE
   OUTPUT ${FULL_OUTPUT_NAME}
   FORMAT "${ARCHIVE_FORMAT}"
   COMPRESSION "${COMPRESSION_TYPE}"
+  WORKING_DIRECTORY "${WORKING_DIRECTORY}"
   VERBOSE
-  PATHS ${COMPRESS_DIR})
+  PATHS ${FULL_COMPRESS_DIR})
 
 file(ARCHIVE_EXTRACT
   INPUT ${FULL_OUTPUT_NAME}
@@ -54,10 +55,10 @@ endif()
 
 foreach(file ${CHECK_FILES})
   set(input ${FULL_COMPRESS_DIR}/${file})
-  set(output ${FULL_DECOMPRESS_DIR}/${COMPRESS_DIR}/${file})
+  set(output ${FULL_DECOMPRESS_DIR}/${CUSTOM_OUTPUT_DIRECTORY}/${COMPRESS_DIR}/${file})
 
   if(NOT EXISTS ${input})
-    message(SEND_ERROR "Cannot find input file ${output}")
+    message(SEND_ERROR "Cannot find input file ${input}")
   endif()
 
   if(NOT EXISTS ${output})

+ 12 - 0
Tests/RunCMake/File_Archive/working-directory.cmake

@@ -0,0 +1,12 @@
+set(OUTPUT_NAME "test.zip")
+
+set(ARCHIVE_FORMAT zip)
+
+get_filename_component(CURRENT_FILE_NAME ${CMAKE_CURRENT_LIST_FILE} NAME_WE)
+set(CUSTOM_OUTPUT_DIRECTORY "${CURRENT_FILE_NAME}-build")
+
+set(WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../")
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)