From d8a9aabd24a471ab82f3742e7d38754bdd47a480 Mon Sep 17 00:00:00 2001 From: Yuri Witte Date: Thu, 5 Sep 2024 05:06:04 -0300 Subject: [PATCH] file(ARCHIVE_CREATE): add WORKING_DIRECTORY option Fixes: #25260 Issue: #21653 --- Help/command/file.rst | 9 +++++++++ Help/release/dev/file-archive-workdir.rst | 5 +++++ Source/cmCTest.cxx | 4 ++-- Source/cmFileCommand.cxx | 5 ++++- Source/cmSystemTools.cxx | 9 ++++++++- Source/cmSystemTools.h | 1 + Source/cmcmd.cxx | 4 ++-- Tests/RunCMake/File_Archive/RunCMakeTest.cmake | 2 ++ Tests/RunCMake/File_Archive/roundtrip.cmake | 7 ++++--- Tests/RunCMake/File_Archive/working-directory.cmake | 12 ++++++++++++ 10 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 Help/release/dev/file-archive-workdir.rst create mode 100644 Tests/RunCMake/File_Archive/working-directory.cmake diff --git a/Help/command/file.rst b/Help/command/file.rst index b7d3413ca5..315762ebe6 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -903,6 +903,7 @@ Archiving [COMPRESSION [COMPRESSION_LEVEL ]] [MTIME ] + [WORKING_DIRECTORY ] [VERBOSE]) :target: ARCHIVE_CREATE :break: verbatim @@ -946,6 +947,14 @@ Archiving ``MTIME `` Specify the modification time recorded in tarball entries. + ``WORKING_DIRECTORY `` + .. versionadded:: 3.31 + + Specify the directory in which the archive creation operation will + be executed. Paths in the ```` argument can be relative to + this directory. If this option is not provided, the current working + directory will be used by default. + ``VERBOSE`` Enable verbose output from the archive operation. diff --git a/Help/release/dev/file-archive-workdir.rst b/Help/release/dev/file-archive-workdir.rst new file mode 100644 index 0000000000..baf4a22013 --- /dev/null +++ b/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. diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index f6f6553ad9..8f2eb850d0 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -1646,8 +1646,8 @@ std::string cmCTest::Base64GzipEncodeFile(std::string const& file) std::vector 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: " diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index f5cd6e8689..cefa35e0b5 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -3607,6 +3607,7 @@ bool HandleArchiveCreateCommand(std::vector const& args, // accepted without one and treated as if an empty value were given. // Fixing this would require a policy. ArgumentParser::Maybe MTime; + std::string WorkingDirectory; bool Verbose = false; // "PATHS" requires at least one value, but use a custom check below. ArgumentParser::MaybeEmpty> Paths; @@ -3619,6 +3620,7 @@ bool HandleArchiveCreateCommand(std::vector 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 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)); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 474aafdb9d..5ad0439c9e 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -36,6 +36,7 @@ #include "cmUVProcessChain.h" #include "cmUVStream.h" #include "cmValue.h" +#include "cmWorkingDirectory.h" #if !defined(CMAKE_BOOTSTRAP) # include @@ -1867,12 +1868,18 @@ bool cmSystemTools::IsPathToMacOSSharedLibrary(const std::string& path) bool cmSystemTools::CreateTar(const std::string& outFileName, const std::vector& 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, diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index d0b604610c..0531f63b84 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -497,6 +497,7 @@ public: const std::vector& files, bool verbose); static bool CreateTar(const std::string& outFileName, const std::vector& files, + const std::string& workingDirectory, cmTarCompression compressType, bool verbose, std::string const& mtime = std::string(), std::string const& format = std::string(), diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 22381bc100..c82cb32da8 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1550,8 +1550,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector 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; } diff --git a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake index dad0dd36c3..c50476c550 100644 --- a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake +++ b/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) diff --git a/Tests/RunCMake/File_Archive/roundtrip.cmake b/Tests/RunCMake/File_Archive/roundtrip.cmake index 404925663c..bb9b25b34f 100644 --- a/Tests/RunCMake/File_Archive/roundtrip.cmake +++ b/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}) diff --git a/Tests/RunCMake/File_Archive/working-directory.cmake b/Tests/RunCMake/File_Archive/working-directory.cmake new file mode 100644 index 0000000000..18efd343fe --- /dev/null +++ b/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)