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
This commit is contained in:
Kasper Laudrup 2022-03-15 19:27:54 +01:00
parent f692cba34b
commit 0b7fd783f8
9 changed files with 69 additions and 12 deletions

View File

@ -1227,7 +1227,8 @@ the ``MTIME`` option.
[DESTINATION <dir>]
[PATTERNS <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.

View File

@ -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

View File

@ -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.

View File

@ -3507,6 +3507,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
bool ListOnly = false;
std::string Destination;
std::vector<std::string> Patterns;
bool Touch = false;
};
static auto const parser = cmArgumentParser<Arguments>{}
@ -3514,7 +3515,8 @@ bool HandleArchiveExtractCommand(std::vector<std::string> 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<std::string> unrecognizedArguments;
std::vector<std::string> keywordsMissingValues;
@ -3577,8 +3579,11 @@ bool HandleArchiveExtractCommand(std::vector<std::string> 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;

View File

@ -1821,6 +1821,7 @@ bool copy_data(struct archive* ar, struct archive* aw)
bool extract_tar(const std::string& outFileName,
const std::vector<std::string>& 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<std::string>& 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;

View File

@ -417,6 +417,12 @@ public:
TarCompressNone
};
enum class cmTarExtractTimestamps
{
Yes,
No
};
static bool ListTar(const std::string& outFileName,
const std::vector<std::string>& 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<std::string>& files, bool verbose);
const std::vector<std::string>& 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

View File

@ -1368,6 +1368,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
std::vector<std::string> 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<std::string> 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<std::string> 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;
}

View File

@ -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)

View File

@ -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()