From f692cba34b758f5c308c3fd659c438ce022a0a80 Mon Sep 17 00:00:00 2001 From: Kasper Laudrup Date: Sun, 13 Mar 2022 19:16:25 +0100 Subject: Tests: Add test for 'cmake -E tar --mtime' option Add a test for ensuring the `--mtime` option works as expected. --- Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake | 3 +++ Tests/RunCMake/CommandLineTar/mtime-tests.cmake | 9 +++++++++ Tests/RunCMake/CommandLineTar/set-mtime.cmake | 11 +++++++++++ 3 files changed, 23 insertions(+) create mode 100644 Tests/RunCMake/CommandLineTar/mtime-tests.cmake create mode 100644 Tests/RunCMake/CommandLineTar/set-mtime.cmake diff --git a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake index a64af95..079a535 100644 --- a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake @@ -34,3 +34,6 @@ run_cmake(zip) # Extracting only selected files or directories run_cmake(zip-filtered) + +# Use the --mtime option to set the mtime when creating archive +run_cmake(set-mtime) diff --git a/Tests/RunCMake/CommandLineTar/mtime-tests.cmake b/Tests/RunCMake/CommandLineTar/mtime-tests.cmake new file mode 100644 index 0000000..8b4f098 --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/mtime-tests.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "test.tar") + +set(ARCHIVE_MTIME "1970-01-01UTC") +set(ARCHIVE_MTIME_RFC3339 "1970-01-01T00:00:00Z") + +set(COMPRESSION_FLAGS cvf) +set(COMPRESSION_OPTIONS --mtime=${ARCHIVE_MTIME}) + +set(DECOMPRESSION_FLAGS xvf) diff --git a/Tests/RunCMake/CommandLineTar/set-mtime.cmake b/Tests/RunCMake/CommandLineTar/set-mtime.cmake new file mode 100644 index 0000000..333cc88 --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/set-mtime.cmake @@ -0,0 +1,11 @@ +include(${CMAKE_CURRENT_LIST_DIR}/mtime-tests.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +foreach(file ${CHECK_FILES}) + file(TIMESTAMP ${FULL_DECOMPRESS_DIR}/${COMPRESS_DIR}/${file} MTIME UTC) + if(NOT MTIME STREQUAL ARCHIVE_MTIME_RFC3339) + message(FATAL_ERROR + "Extracted timestamp ${MTIME} does not match expected ${ARCHIVE_MTIME_RFC3339}") + endif() +endforeach() -- cgit v0.12 From 0b7fd783f82639ba129e62edeac0de6594542708 Mon Sep 17 00:00:00 2001 From: Kasper Laudrup Date: Tue, 15 Mar 2022 19:27:54 +0100 Subject: cmake -E tar: Add --touch option Similar to GNU tar add a --touch option to the tar extract command to skip extracting the timestamps from the files in the archive effectively touching them as if they were just created. Issue: #22746 --- Help/command/file.rst | 7 ++++++- Help/manual/cmake.1.rst | 6 ++++++ Help/release/dev/cmake-E-tar-touch.rst | 6 ++++++ Source/cmFileCommand.cxx | 11 ++++++++--- Source/cmSystemTools.cxx | 18 ++++++++++++------ Source/cmSystemTools.h | 10 +++++++++- Source/cmcmd.cxx | 7 ++++++- Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake | 3 +++ Tests/RunCMake/CommandLineTar/touch-mtime.cmake | 13 +++++++++++++ 9 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 Help/release/dev/cmake-E-tar-touch.rst create mode 100644 Tests/RunCMake/CommandLineTar/touch-mtime.cmake diff --git a/Help/command/file.rst b/Help/command/file.rst index 2769577..3374d2d 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -1227,7 +1227,8 @@ the ``MTIME`` option. [DESTINATION ] [PATTERNS ...] [LIST_ONLY] - [VERBOSE]) + [VERBOSE] + [TOUCH]) .. versionadded:: 3.18 @@ -1245,4 +1246,8 @@ extracted. ``LIST_ONLY`` will list the files in the archive rather than extract them. +.. 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. diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index e93cbe5..3febc9e 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -948,6 +948,12 @@ Available commands are: Specify modification time recorded in tarball entries. + ``--touch`` + .. versionadded:: 3.24 + + Use current local timestamp instead of extracting file timestamps + from the archive. + ``--`` .. versionadded:: 3.1 diff --git a/Help/release/dev/cmake-E-tar-touch.rst b/Help/release/dev/cmake-E-tar-touch.rst new file mode 100644 index 0000000..6d1338d --- /dev/null +++ b/Help/release/dev/cmake-E-tar-touch.rst @@ -0,0 +1,6 @@ +cmake-E-tar-touch +----------------- + +* The :manual:`cmake(1)` ``-E tar`` command gained the ``--touch`` option + to keep the current local timestamp instead of extracting file timestamps + from the archive. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 09e5015..e4728ac 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -3507,6 +3507,7 @@ bool HandleArchiveExtractCommand(std::vector const& args, bool ListOnly = false; std::string Destination; std::vector Patterns; + bool Touch = false; }; static auto const parser = cmArgumentParser{} @@ -3514,7 +3515,8 @@ bool HandleArchiveExtractCommand(std::vector const& args, .Bind("VERBOSE"_s, &Arguments::Verbose) .Bind("LIST_ONLY"_s, &Arguments::ListOnly) .Bind("DESTINATION"_s, &Arguments::Destination) - .Bind("PATTERNS"_s, &Arguments::Patterns); + .Bind("PATTERNS"_s, &Arguments::Patterns) + .Bind("TOUCH"_s, &Arguments::Touch); std::vector unrecognizedArguments; std::vector keywordsMissingValues; @@ -3577,8 +3579,11 @@ bool HandleArchiveExtractCommand(std::vector const& args, return false; } - if (!cmSystemTools::ExtractTar(inFile, parsedArgs.Patterns, - parsedArgs.Verbose)) { + if (!cmSystemTools::ExtractTar( + inFile, parsedArgs.Patterns, + parsedArgs.Touch ? cmSystemTools::cmTarExtractTimestamps::No + : cmSystemTools::cmTarExtractTimestamps::Yes, + parsedArgs.Verbose)) { status.SetError(cmStrCat("failed to extract: ", inFile)); cmSystemTools::SetFatalErrorOccured(); return false; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index a5dfa4c..cb32172 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1821,6 +1821,7 @@ bool copy_data(struct archive* ar, struct archive* aw) bool extract_tar(const std::string& outFileName, const std::vector& files, bool verbose, + cmSystemTools::cmTarExtractTimestamps extractTimestamps, bool extract) { cmLocaleRAII localeRAII; @@ -1879,10 +1880,12 @@ bool extract_tar(const std::string& outFileName, cmSystemTools::Stdout("\n"); } if (extract) { - r = archive_write_disk_set_options(ext, ARCHIVE_EXTRACT_TIME); - if (r != ARCHIVE_OK) { - ArchiveError("Problem with archive_write_disk_set_options(): ", ext); - break; + if (extractTimestamps == cmSystemTools::cmTarExtractTimestamps::Yes) { + r = archive_write_disk_set_options(ext, ARCHIVE_EXTRACT_TIME); + if (r != ARCHIVE_OK) { + ArchiveError("Problem with archive_write_disk_set_options(): ", ext); + break; + } } r = archive_write_header(ext, entry); @@ -1942,13 +1945,15 @@ bool extract_tar(const std::string& outFileName, bool cmSystemTools::ExtractTar(const std::string& outFileName, const std::vector& files, + cmTarExtractTimestamps extractTimestamps, bool verbose) { #if !defined(CMAKE_BOOTSTRAP) - return extract_tar(outFileName, files, verbose, true); + return extract_tar(outFileName, files, verbose, extractTimestamps, true); #else (void)outFileName; (void)files; + (void)extractTimestamps; (void)verbose; return false; #endif @@ -1959,7 +1964,8 @@ bool cmSystemTools::ListTar(const std::string& outFileName, bool verbose) { #if !defined(CMAKE_BOOTSTRAP) - return extract_tar(outFileName, files, verbose, false); + return extract_tar(outFileName, files, verbose, cmTarExtractTimestamps::Yes, + false); #else (void)outFileName; (void)files; diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 19dabe8..c17ecbd 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -417,6 +417,12 @@ public: TarCompressNone }; + enum class cmTarExtractTimestamps + { + Yes, + No + }; + static bool ListTar(const std::string& outFileName, const std::vector& files, bool verbose); static bool CreateTar(const std::string& outFileName, @@ -426,7 +432,9 @@ public: std::string const& format = std::string(), int compressionLevel = 0); static bool ExtractTar(const std::string& inFileName, - const std::vector& files, bool verbose); + const std::vector& files, + cmTarExtractTimestamps extractTimestamps, + 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 f1c1bdc..df740c9 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1368,6 +1368,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, std::vector files; std::string mtime; std::string format; + cmSystemTools::cmTarExtractTimestamps extractTimestamps = + cmSystemTools::cmTarExtractTimestamps::Yes; cmSystemTools::cmTarCompression compress = cmSystemTools::TarCompressNone; int nCompress = 0; @@ -1393,6 +1395,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, format); return 1; } + } else if (arg == "--touch") { + extractTimestamps = cmSystemTools::cmTarExtractTimestamps::No; } else { cmSystemTools::Error("Unknown option to -E tar: " + arg); return 1; @@ -1464,7 +1468,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, return 1; } } else if (action == cmSystemTools::TarActionExtract) { - if (!cmSystemTools::ExtractTar(outFile, files, verbose)) { + if (!cmSystemTools::ExtractTar(outFile, files, extractTimestamps, + verbose)) { cmSystemTools::Error("Problem extracting tar: " + outFile); return 1; } diff --git a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake index 079a535..a487f37 100644 --- a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake @@ -37,3 +37,6 @@ run_cmake(zip-filtered) # Use the --mtime option to set the mtime when creating archive run_cmake(set-mtime) + +# Use the --touch option to avoid extracting the mtime +run_cmake(touch-mtime) diff --git a/Tests/RunCMake/CommandLineTar/touch-mtime.cmake b/Tests/RunCMake/CommandLineTar/touch-mtime.cmake new file mode 100644 index 0000000..c9e3524 --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/touch-mtime.cmake @@ -0,0 +1,13 @@ +include(${CMAKE_CURRENT_LIST_DIR}/mtime-tests.cmake) + +set(DECOMPRESSION_OPTIONS --touch) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +foreach(file ${CHECK_FILES}) + file(TIMESTAMP ${FULL_DECOMPRESS_DIR}/${COMPRESS_DIR}/${file} MTIME UTC) + if(MTIME STREQUAL ARCHIVE_MTIME_RFC3339) + message(FATAL_ERROR + "File has unexpected timestamp ${MTIME}") + endif() +endforeach() -- cgit v0.12