This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, master has been updated
       via  4ec2b999414495ae58871755307ea17f391f7910 (commit)
       via  c8e217e0a70f8f445e2c593f44e1105c959fb9d7 (commit)
      from  2b8e5a3ba772d6df6e56a28d8645127008636b03 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4ec2b999414495ae58871755307ea17f391f7910
commit 4ec2b999414495ae58871755307ea17f391f7910
Merge: 2b8e5a3 c8e217e
Author:     Brad King <brad.k...@kitware.com>
AuthorDate: Fri May 24 14:41:43 2019 +0000
Commit:     Kitware Robot <kwro...@kitware.com>
CommitDate: Fri May 24 10:43:14 2019 -0400

    Merge topic 'selective-tar-extracting-and-listing'
    
    c8e217e0a7 cmake: tar: Allow selective extracting and listing of archives
    
    Acked-by: Kitware Robot <kwro...@kitware.com>
    Merge-request: !3342


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c8e217e0a70f8f445e2c593f44e1105c959fb9d7
commit c8e217e0a70f8f445e2c593f44e1105c959fb9d7
Author:     Bartosz Kosiorek <gan...@poczta.onet.pl>
AuthorDate: Wed May 22 21:29:08 2019 +0200
Commit:     Brad King <brad.k...@kitware.com>
CommitDate: Thu May 23 10:08:22 2019 -0400

    cmake: tar: Allow selective extracting and listing of archives

diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index df0d4c5..97c65e7 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -528,16 +528,22 @@ Available commands are:
 ``sleep <number>...``
   Sleep for given number of seconds.
 
-``tar [cxt][vf][zjJ] file.tar [<options>] [--] [<file>...]``
+``tar [cxt][vf][zjJ] file.tar [<options>] [--] [<pathname>...]``
   Create or extract a tar or zip archive.  Options are:
 
   ``c``
     Create a new archive containing the specified files.
-    If used, the <file> argument is mandatory.
+    If used, the ``<pathname>...`` argument is mandatory.
   ``x``
     Extract to disk from the archive.
+    The ``<pathname>...`` argument could be used to extract only selected files
+    or directories.
+    When extracting selected files or directories, you must provide their exact
+    names including the path, as printed by list (``-t``).
   ``t``
-    List archive contents to stdout.
+    List archive contents.
+    The ``<pathname>...`` argument could be used to list only selected files
+    or directories.
   ``v``
     Produce verbose output.
   ``z``
diff --git a/Help/release/dev/cmake-e-tar-extract-specific-files.rst 
b/Help/release/dev/cmake-e-tar-extract-specific-files.rst
new file mode 100644
index 0000000..4ab3eab
--- /dev/null
+++ b/Help/release/dev/cmake-e-tar-extract-specific-files.rst
@@ -0,0 +1,8 @@
+cmake-e-tar-extract-specific-files
+----------------------------------
+
+* The :manual:`cmake(1)` ``-E tar`` tool allow for extract (``-x``) or list
+  (``-t``) only specific files or directories.  To select pathnames append
+  a space-separated list of file names or directories.
+  When extracting selected files or directories, you must provide their exact
+  pathname, as printed by list (``-t``)
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 6359d60..d00d4d0 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1757,7 +1757,9 @@ bool copy_data(struct archive* ar, struct archive* aw)
 #  endif
 }
 
-bool extract_tar(const char* outFileName, bool verbose, bool extract)
+bool extract_tar(const char* outFileName,
+                 const std::vector<std::string>& files, bool verbose,
+                 bool extract)
 {
   cmLocaleRAII localeRAII;
   static_cast<void>(localeRAII);
@@ -1766,6 +1768,21 @@ bool extract_tar(const char* outFileName, bool verbose, 
bool extract)
   archive_read_support_filter_all(a);
   archive_read_support_format_all(a);
   struct archive_entry* entry;
+
+  struct archive* matching = archive_match_new();
+  if (matching == nullptr) {
+    cmSystemTools::Error("Out of memory");
+    return false;
+  }
+
+  for (const auto& filename : files) {
+    if (archive_match_include_pattern(matching, filename.c_str()) !=
+        ARCHIVE_OK) {
+      cmSystemTools::Error("Failed to add to inclusion list: " + filename);
+      return false;
+    }
+  }
+
   int r = cm_archive_read_open_file(a, outFileName, 10240);
   if (r) {
     ArchiveError("Problem with archive_read_open_file(): ", a);
@@ -1782,6 +1799,11 @@ bool extract_tar(const char* outFileName, bool verbose, 
bool extract)
       ArchiveError("Problem with archive_read_next_header(): ", a);
       break;
     }
+
+    if (archive_match_excluded(matching, entry)) {
+      continue;
+    }
+
     if (verbose) {
       if (extract) {
         cmSystemTools::Stdout("x ");
@@ -1827,6 +1849,27 @@ bool extract_tar(const char* outFileName, bool verbose, 
bool extract)
       }
     }
   }
+
+  bool error_occured = false;
+  if (matching != nullptr) {
+    const char* p;
+    int ar;
+
+    while ((ar = archive_match_path_unmatched_inclusions_next(matching, &p)) ==
+           ARCHIVE_OK) {
+      cmSystemTools::Error("tar: " + std::string(p) +
+                           ": Not found in archive");
+      error_occured = true;
+    }
+    if (error_occured) {
+      return false;
+    }
+    if (ar == ARCHIVE_FATAL) {
+      cmSystemTools::Error("tar: Out of memory");
+      return false;
+    }
+  }
+  archive_match_free(matching);
   archive_write_free(ext);
   archive_read_close(a);
   archive_read_free(a);
@@ -1835,23 +1878,29 @@ bool extract_tar(const char* outFileName, bool verbose, 
bool extract)
 }
 #endif
 
-bool cmSystemTools::ExtractTar(const char* outFileName, bool verbose)
+bool cmSystemTools::ExtractTar(const char* outFileName,
+                               const std::vector<std::string>& files,
+                               bool verbose)
 {
 #if defined(CMAKE_BUILD_WITH_CMAKE)
-  return extract_tar(outFileName, verbose, true);
+  return extract_tar(outFileName, files, verbose, true);
 #else
   (void)outFileName;
+  (void)files;
   (void)verbose;
   return false;
 #endif
 }
 
-bool cmSystemTools::ListTar(const char* outFileName, bool verbose)
+bool cmSystemTools::ListTar(const char* outFileName,
+                            const std::vector<std::string>& files,
+                            bool verbose)
 {
 #if defined(CMAKE_BUILD_WITH_CMAKE)
-  return extract_tar(outFileName, verbose, false);
+  return extract_tar(outFileName, files, verbose, false);
 #else
   (void)outFileName;
+  (void)files;
   (void)verbose;
   return false;
 #endif
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 80c6ee3..09a4d13 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -450,13 +450,15 @@ public:
     TarCompressNone
   };
 
-  static bool ListTar(const char* outFileName, bool verbose);
+  static bool ListTar(const char* outFileName,
+                      const std::vector<std::string>& files, bool verbose);
   static bool CreateTar(const char* outFileName,
                         const std::vector<std::string>& files,
                         cmTarCompression compressType, bool verbose,
                         std::string const& mtime = std::string(),
                         std::string const& format = std::string());
-  static bool ExtractTar(const char* inFileName, bool verbose);
+  static bool ExtractTar(const char* inFileName,
+                         const std::vector<std::string>& files, bool verbose);
   // This should be called first thing in main
   // it will keep child processes from inheriting the
   // stdin and stdout of this process.  This is important
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 3c75957..bcf7b2f 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -1127,7 +1127,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> 
const& args)
         return 1;
       }
       if (action == cmSystemTools::TarActionList) {
-        if (!cmSystemTools::ListTar(outFile.c_str(), verbose)) {
+        if (!cmSystemTools::ListTar(outFile.c_str(), files, verbose)) {
           cmSystemTools::Error("Problem listing tar: " + outFile);
           return 1;
         }
@@ -1142,7 +1142,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> 
const& args)
           return 1;
         }
       } else if (action == cmSystemTools::TarActionExtract) {
-        if (!cmSystemTools::ExtractTar(outFile.c_str(), verbose)) {
+        if (!cmSystemTools::ExtractTar(outFile.c_str(), files, verbose)) {
           cmSystemTools::Error("Problem extracting tar: " + outFile);
           return 1;
         }
diff --git a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake 
b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake
index 5deb110..4d1b396 100644
--- a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake
@@ -30,3 +30,6 @@ run_cmake(pax-xz)
 run_cmake(paxr)
 run_cmake(paxr-bz2)
 run_cmake(zip)
+
+# Extracting only selected files or directories
+run_cmake(zip-filtered)
diff --git a/Tests/RunCMake/CommandLineTar/roundtrip.cmake 
b/Tests/RunCMake/CommandLineTar/roundtrip.cmake
index dc1c885..fa63d12 100644
--- a/Tests/RunCMake/CommandLineTar/roundtrip.cmake
+++ b/Tests/RunCMake/CommandLineTar/roundtrip.cmake
@@ -47,7 +47,11 @@ file(REMOVE_RECURSE ${FULL_DECOMPRESS_DIR})
 file(MAKE_DIRECTORY ${FULL_DECOMPRESS_DIR})
 
 run_tar(${CMAKE_CURRENT_BINARY_DIR} ${COMPRESSION_FLAGS} ${FULL_OUTPUT_NAME} 
${COMPRESSION_OPTIONS} ${COMPRESS_DIR})
-run_tar(${FULL_DECOMPRESS_DIR} ${DECOMPRESSION_FLAGS} ${FULL_OUTPUT_NAME} 
${DECOMPRESSION_OPTIONS})
+run_tar(${FULL_DECOMPRESS_DIR} ${DECOMPRESSION_FLAGS} ${FULL_OUTPUT_NAME} 
${DECOMPRESSION_OPTIONS} -- ${DECOMPRESSION_PATHNAMES})
+
+if(CUSTOM_CHECK_FILES)
+  set(CHECK_FILES ${CUSTOM_CHECK_FILES})
+endif()
 
 foreach(file ${CHECK_FILES})
   set(input ${FULL_COMPRESS_DIR}/${file})
@@ -69,6 +73,14 @@ foreach(file ${CHECK_FILES})
   endif()
 endforeach()
 
+foreach(file ${NOT_EXISTING_FILES_CHECK})
+  set(output ${FULL_DECOMPRESS_DIR}/${COMPRESS_DIR}/${file})
+
+  if(EXISTS ${output})
+     message(SEND_ERROR "File ${output} exists but it shouldn't")
+  endif()
+endforeach()
+
 function(check_magic EXPECTED)
   file(READ ${FULL_OUTPUT_NAME} ACTUAL
     ${ARGN}
diff --git a/Tests/RunCMake/CommandLineTar/zip-filtered.cmake 
b/Tests/RunCMake/CommandLineTar/zip-filtered.cmake
new file mode 100644
index 0000000..c13210e
--- /dev/null
+++ b/Tests/RunCMake/CommandLineTar/zip-filtered.cmake
@@ -0,0 +1,28 @@
+set(OUTPUT_NAME "test.zip")
+
+set(COMPRESSION_FLAGS cvf)
+set(COMPRESSION_OPTIONS --format=zip)
+
+set(DECOMPRESSION_FLAGS xvf)
+set(LIST_ARCHIVE TRUE)
+set(DECOMPRESSION_PATHNAMES
+  compress_dir/f1.txt # Decompress only file
+  compress_dir/d1     # and whole directory
+)
+
+set(CUSTOM_CHECK_FILES
+  "f1.txt"
+  "d1/f1.txt"
+)
+
+# This files shouldn't exists
+set(NOT_EXISTING_FILES_CHECK
+  "d 2/f1.txt"
+  "d + 3/f1.txt"
+  "d_4/f1.txt"
+  "d-4/f1.txt"
+)
+
+include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
+
+check_magic("504b0304" LIMIT 4 HEX)

-----------------------------------------------------------------------

Summary of changes:
 Help/manual/cmake.1.rst                            | 12 +++--
 .../dev/cmake-e-tar-extract-specific-files.rst     |  8 +++
 Source/cmSystemTools.cxx                           | 59 ++++++++++++++++++++--
 Source/cmSystemTools.h                             |  6 ++-
 Source/cmcmd.cxx                                   |  4 +-
 Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake   |  3 ++
 Tests/RunCMake/CommandLineTar/roundtrip.cmake      | 14 ++++-
 Tests/RunCMake/CommandLineTar/zip-filtered.cmake   | 28 ++++++++++
 8 files changed, 121 insertions(+), 13 deletions(-)
 create mode 100644 Help/release/dev/cmake-e-tar-extract-specific-files.rst
 create mode 100644 Tests/RunCMake/CommandLineTar/zip-filtered.cmake


hooks/post-receive
-- 
CMake
_______________________________________________
Cmake-commits mailing list
Cmake-commits@cmake.org
https://cmake.org/mailman/listinfo/cmake-commits

Reply via email to