diff --git a/Help/command/file.rst b/Help/command/file.rst index d70639d7a6..f1e818534b 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -915,6 +915,7 @@ Archiving [FORMAT ] [COMPRESSION [COMPRESSION_LEVEL ]] + [ENCODING ] [MTIME ] [THREADS ] [WORKING_DIRECTORY ] @@ -1006,6 +1007,39 @@ Archiving formats too. The ``Zstd`` algorithm compression level can be set between 0-19, except for ``zip`` format. + ``ENCODING `` + .. versionadded:: 4.4 + + Specify the pathname character encoding used in the archive. + + The ```` may be one of: + + ``UTF-8`` + Archive pathnames are encoded as UTF-8. + + In CMake 4.4 and below, this is the default. + See policy :policy:`CMP0213` for CMake 4.3 and below compatibility + details. + + ``OEM`` + On Windows platforms, pathnames are encoded as using the original + equipment manufacturer (OEM) code page. On non-Windows platforms, + pathnames are encoded according to the current locale. + + In CMake 4.3 and below, the ``OEM`` encoding (current locale) + was always used. + + ``UTF-16LE``, ``UTF-16BE`` + Archive pathnames are encoded as UTF-16 little-endian or big-endian. + + ``...`` + Any encoding name supported by ``iconv`` on the current platform. + On Windows, code page names may be specified. + + .. note:: + ``7zip`` archives always encode paths as ``UTF-16LE``, + so this option is silently ignored for that format. + ``MTIME `` Specify the modification time recorded in tarball entries. @@ -1032,6 +1066,7 @@ Archiving file(ARCHIVE_EXTRACT INPUT [DESTINATION ] + [ENCODING ] [PATTERNS ...] [LIST_ONLY] [VERBOSE] @@ -1050,6 +1085,41 @@ Archiving If ``DESTINATION`` is not given, the current binary directory will be used. + ``ENCODING `` + .. versionadded:: 4.4 + + Specify the pathname character encoding used in the archive. + + The ```` may be one of: + + ``UTF-8`` + Archive pathnames are encoded as UTF-8. + + In CMake 4.3 and below, this is the default + if the :policy:`CMP0213` is ``NEW``. + + ``OEM`` + On Windows platforms, pathnames are encoded as using the original + equipment manufacturer (OEM) code page. On non-Windows platforms, + pathnames are encoded according to the current locale. + + In CMake 4.3 and below, the ``OEM`` encoding (current locale) + was always used. + + In CMake 4.4 and above, the ``OEM`` encoding (current locale) + is only used if the :policy:`CMP0213` is not ``NEW``. + + ``UTF-16LE``, ``UTF-16BE`` + Archive pathnames are encoded as UTF-16 little-endian or big-endian. + + ``...`` + Any encoding name supported by ``iconv`` on the current platform. + On Windows, code page names may be specified. + + .. note:: + ``7zip`` archives always encode paths as ``UTF-16LE``, + so this option is silently ignored for that format. + ``PATTERNS ...`` Extract/list only files and directories that match one of the given patterns. Wildcards are supported. If the ``PATTERNS`` option is diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 761963b751..b8f120cefe 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -100,6 +100,7 @@ Policies Introduced by CMake 4.4 .. toctree:: :maxdepth: 1 + CMP0213: file(ARCHIVE_{CREATE,EXTRACT}) encode archive paths as UTF-8 by default. CMP0212: add_custom_command DEPENDS does not strip .exe suffixes. CMP0211: A file may belong to at most one file set in a target. diff --git a/Help/policy/CMP0213.rst b/Help/policy/CMP0213.rst new file mode 100644 index 0000000000..d8a8e25c9e --- /dev/null +++ b/Help/policy/CMP0213.rst @@ -0,0 +1,22 @@ +CMP0213 +------- + +.. versionadded:: 4.4 + +:command:`file(ARCHIVE_CREATE)` and :command:`file(ARCHIVE_EXTRACT)` +encode archive paths as UTF-8 by default. + +CMake 4.3 and below always used the ``OEM`` (current locale) encoding for archive +paths. CMake 4.4 offer the ``ENCODING`` option, but prefer to use ``UTF-8`` +by default. This policy provides compatibility for projects that have not +been updated to specify the encoding or accept the new default. + +The ``OLD`` behavior for this policy is to use the current locale as the +default encoding, which is also known as an ``OEM`` encoding. +The ``NEW`` behavior uses ``UTF-8`` as the default encoding. + +.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.4 +.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn +.. include:: include/STANDARD_ADVICE.rst + +.. include:: include/DEPRECATED.rst diff --git a/Help/release/dev/file-archive-encoding.rst b/Help/release/dev/file-archive-encoding.rst new file mode 100644 index 0000000000..3275c4c227 --- /dev/null +++ b/Help/release/dev/file-archive-encoding.rst @@ -0,0 +1,7 @@ +file-archive-encoding +--------------------- + +* The :command:`file(ARCHIVE_CREATE)` and :command:`file(ARCHIVE_EXTRACT)` + commands accepts an ``ENCODING`` option to specify the encoding of the + archive pathnames. The default is now ``UTF-8``. + See policy :policy:`CMP0213`. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 8eedc3c375..eec0ffd047 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -3678,6 +3678,7 @@ bool HandleArchiveCreateCommand(std::vector const& args, std::string Format; std::string Compression; std::string CompressionLevel; + std::string Encoding; // "MTIME" should require one value, but it has long been accidentally // accepted without one and treated as if an empty value were given. // Fixing this would require a policy. @@ -3695,6 +3696,7 @@ bool HandleArchiveCreateCommand(std::vector const& args, .Bind("FORMAT"_s, &Arguments::Format) .Bind("COMPRESSION"_s, &Arguments::Compression) .Bind("COMPRESSION_LEVEL"_s, &Arguments::CompressionLevel) + .Bind("ENCODING"_s, &Arguments::Encoding) .Bind("MTIME"_s, &Arguments::MTime) .Bind("THREADS"_s, &Arguments::Threads) .Bind("WORKING_DIRECTORY"_s, &Arguments::WorkingDirectory) @@ -3822,9 +3824,18 @@ bool HandleArchiveCreateCommand(std::vector const& args, return false; } + if (parsedArgs.Encoding.empty()) { + if (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0213) == + cmPolicies::NEW) { + parsedArgs.Encoding = "UTF-8"; + } else { + parsedArgs.Encoding = "OEM"; + } + } + if (!cmSystemTools::CreateTar( parsedArgs.Output, parsedArgs.Paths, parsedArgs.WorkingDirectory, - compress, "OEM", parsedArgs.Verbose, parsedArgs.MTime, + compress, parsedArgs.Encoding, parsedArgs.Verbose, parsedArgs.MTime, parsedArgs.Format, compressionLevel, threads)) { status.SetError(cmStrCat("failed to compress: ", parsedArgs.Output)); cmSystemTools::SetFatalErrorOccurred(); @@ -3840,6 +3851,7 @@ bool HandleArchiveExtractCommand(std::vector const& args, struct Arguments : public ArgumentParser::ParseResult { std::string Input; + std::string Encoding; bool Verbose = false; bool ListOnly = false; std::string Destination; @@ -3849,6 +3861,7 @@ bool HandleArchiveExtractCommand(std::vector const& args, static auto const parser = cmArgumentParser{} .Bind("INPUT"_s, &Arguments::Input) + .Bind("ENCODING"_s, &Arguments::Encoding) .Bind("VERBOSE"_s, &Arguments::Verbose) .Bind("LIST_ONLY"_s, &Arguments::ListOnly) .Bind("DESTINATION"_s, &Arguments::Destination) @@ -3872,9 +3885,18 @@ bool HandleArchiveExtractCommand(std::vector const& args, std::string inFile = parsedArgs.Input; + if (parsedArgs.Encoding.empty()) { + if (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0213) == + cmPolicies::NEW) { + parsedArgs.Encoding = "UTF-8"; + } else { + parsedArgs.Encoding = "OEM"; + } + } + if (parsedArgs.ListOnly) { - if (!cmSystemTools::ListTar(inFile, parsedArgs.Patterns, "OEM", - parsedArgs.Verbose)) { + if (!cmSystemTools::ListTar(inFile, parsedArgs.Patterns, + parsedArgs.Encoding, parsedArgs.Verbose)) { status.SetError(cmStrCat("failed to list: ", inFile)); cmSystemTools::SetFatalErrorOccurred(); return false; @@ -3911,7 +3933,7 @@ bool HandleArchiveExtractCommand(std::vector const& args, inFile, parsedArgs.Patterns, parsedArgs.Touch ? cmSystemTools::cmTarExtractTimestamps::No : cmSystemTools::cmTarExtractTimestamps::Yes, - "OEM", parsedArgs.Verbose)) { + parsedArgs.Encoding, parsedArgs.Verbose)) { status.SetError(cmStrCat("failed to extract:\n ", inFile)); cmSystemTools::SetFatalErrorOccurred(); return false; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 5b0fc00f14..a9ddf9ec97 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -635,7 +635,11 @@ class cmMakefile; WARN) \ SELECT(POLICY, CMP0212, \ "add_custom_command DEPENDS does not strip .exe suffixes.", 4, 4, 0, \ - WARN) + WARN) \ + SELECT(POLICY, CMP0213, \ + "file(ARCHIVE_{CREATE,EXTRACT}) encode archive paths as UTF-8 by " \ + "default.", \ + 4, 4, 0, WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index d684cd3054..cff9f764fb 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -1016,7 +1016,11 @@ endif() add_RunCMake_test(LinkLibrariesProcessing) add_RunCMake_test(LinkLibrariesStrategy) add_RunCMake_test(LinkFlags -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}) -add_RunCMake_test(File_Archive -DPython_EXECUTABLE=${Python_EXECUTABLE}) +if(DEFINED CMake_TEST_LOCALE_CHARSET) + list(APPEND File_Archive_ARGS -DCMake_TEST_LOCALE_CHARSET=${CMake_TEST_LOCALE_CHARSET}) +endif() +list(APPEND File_Archive_ARGS -DPython_EXECUTABLE=${Python_EXECUTABLE}) +add_RunCMake_test(File_Archive) add_RunCMake_test(File_Configure) add_RunCMake_test(File_Generate) add_RunCMake_test(ExportWithoutLanguage) diff --git a/Tests/RunCMake/File_Archive/CMP0213-NEW.cmake b/Tests/RunCMake/File_Archive/CMP0213-NEW.cmake new file mode 100644 index 0000000000..bf126fe6d0 --- /dev/null +++ b/Tests/RunCMake/File_Archive/CMP0213-NEW.cmake @@ -0,0 +1,10 @@ +set(OUTPUT_NAME "test.zip") + +cmake_policy(SET CMP0213 NEW) + +set(ARCHIVE_FORMAT zip) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("504b0304" LIMIT 4 HEX) diff --git a/Tests/RunCMake/File_Archive/CMP0213-OLD-fails-result.txt b/Tests/RunCMake/File_Archive/CMP0213-OLD-fails-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/File_Archive/CMP0213-OLD-fails-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Archive/CMP0213-OLD-fails-stderr.txt b/Tests/RunCMake/File_Archive/CMP0213-OLD-fails-stderr.txt new file mode 100644 index 0000000000..1976196306 --- /dev/null +++ b/Tests/RunCMake/File_Archive/CMP0213-OLD-fails-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error: archive_write_header: Can't translate [Pp]athname( '[^']*\.txt')? to [^ +]* +CMake Error at roundtrip\.cmake:[0-9]+ \(file\): + file failed to compress: diff --git a/Tests/RunCMake/File_Archive/CMP0213-OLD-fails.cmake b/Tests/RunCMake/File_Archive/CMP0213-OLD-fails.cmake new file mode 100644 index 0000000000..bf5dafae19 --- /dev/null +++ b/Tests/RunCMake/File_Archive/CMP0213-OLD-fails.cmake @@ -0,0 +1,11 @@ +set(OUTPUT_NAME "bad.zip") + +cmake_policy(SET CMP0213 OLD) + +set(ARCHIVE_FORMAT zip) +set(ENCODING OEM) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("504b0304" LIMIT 4 HEX) diff --git a/Tests/RunCMake/File_Archive/CMP0213-OLD.cmake b/Tests/RunCMake/File_Archive/CMP0213-OLD.cmake new file mode 100644 index 0000000000..6829cf127c --- /dev/null +++ b/Tests/RunCMake/File_Archive/CMP0213-OLD.cmake @@ -0,0 +1,10 @@ +set(OUTPUT_NAME "test.zip") + +cmake_policy(SET CMP0213 OLD) + +set(ARCHIVE_FORMAT zip) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("504b0304" LIMIT 4 HEX) diff --git a/Tests/RunCMake/File_Archive/CMP0213-WARN-fails-result.txt b/Tests/RunCMake/File_Archive/CMP0213-WARN-fails-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/File_Archive/CMP0213-WARN-fails-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Archive/CMP0213-WARN-fails-stderr.txt b/Tests/RunCMake/File_Archive/CMP0213-WARN-fails-stderr.txt new file mode 100644 index 0000000000..1976196306 --- /dev/null +++ b/Tests/RunCMake/File_Archive/CMP0213-WARN-fails-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error: archive_write_header: Can't translate [Pp]athname( '[^']*\.txt')? to [^ +]* +CMake Error at roundtrip\.cmake:[0-9]+ \(file\): + file failed to compress: diff --git a/Tests/RunCMake/File_Archive/CMP0213-WARN-fails.cmake b/Tests/RunCMake/File_Archive/CMP0213-WARN-fails.cmake new file mode 100644 index 0000000000..30b22606ca --- /dev/null +++ b/Tests/RunCMake/File_Archive/CMP0213-WARN-fails.cmake @@ -0,0 +1,11 @@ +set(OUTPUT_NAME "bad.zip") + +# No need to set CMP0213 - WARN is default + +set(ARCHIVE_FORMAT zip) +set(ENCODING OEM) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("504b0304" LIMIT 4 HEX) diff --git a/Tests/RunCMake/File_Archive/CMP0213-WARN.cmake b/Tests/RunCMake/File_Archive/CMP0213-WARN.cmake new file mode 100644 index 0000000000..795c980bff --- /dev/null +++ b/Tests/RunCMake/File_Archive/CMP0213-WARN.cmake @@ -0,0 +1,10 @@ +set(OUTPUT_NAME "test.zip") + +# No need to set CMP0213 - WARN is default + +set(ARCHIVE_FORMAT zip) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("504b0304" LIMIT 4 HEX) diff --git a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake index 0602db1a01..aadfffa607 100644 --- a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake +++ b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake @@ -30,6 +30,41 @@ run_cmake(threads-gz) run_cmake(threads-xz) run_cmake(threads-zstd) +# Encoding tests. These rely on UTF-8 encoding of our test sources. +if(NOT DEFINED CMake_TEST_LOCALE_CHARSET) + cmake_host_system_information(RESULT CMake_TEST_LOCALE_CHARSET QUERY LOCALE_CHARSET) + message(STATUS "Detected LOCALE_CHARSET '${CMake_TEST_LOCALE_CHARSET}'") +endif() + +if(CMake_TEST_LOCALE_CHARSET STREQUAL "UTF-8") + if(CMAKE_HOST_WIN32) + # The OEM encoding cannot represent our UTF-8 test paths. + run_cmake(encoding-oem-gnutar-fails) + run_cmake(encoding-oem-zip-fails) + run_cmake(CMP0213-OLD-fails) + run_cmake(CMP0213-WARN-fails) + else() + run_cmake(encoding-oem-gnutar) + run_cmake(encoding-oem-zip) + run_cmake(CMP0213-OLD) + run_cmake(CMP0213-WARN) + endif() + + run_cmake(CMP0213-NEW) + + run_cmake(encoding-oem-7zip) + run_cmake(encoding-oem-pax) + run_cmake(encoding-oem-paxr) + + run_cmake(encoding-utf-8-7zip) + run_cmake(encoding-utf-8-gnutar) + run_cmake(encoding-utf-8-pax) + run_cmake(encoding-utf-8-paxr) + run_cmake(encoding-utf-8-zip) +else() + message(STATUS "encoding-* - SKIPPED due to non-UTF-8 locale") +endif() + # Extracting only selected files or directories run_cmake(zip-filtered) diff --git a/Tests/RunCMake/File_Archive/encoding-oem-7zip.cmake b/Tests/RunCMake/File_Archive/encoding-oem-7zip.cmake new file mode 100644 index 0000000000..f0e73d2fbe --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-oem-7zip.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "test.7z") + +set(ARCHIVE_FORMAT 7zip) +set(ENCODING OEM) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("377abcaf271c" LIMIT 6 HEX) diff --git a/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails-result.txt b/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails-stderr.txt b/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails-stderr.txt new file mode 100644 index 0000000000..1976196306 --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error: archive_write_header: Can't translate [Pp]athname( '[^']*\.txt')? to [^ +]* +CMake Error at roundtrip\.cmake:[0-9]+ \(file\): + file failed to compress: diff --git a/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails.cmake b/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails.cmake new file mode 100644 index 0000000000..63508bef4e --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-oem-gnutar-fails.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "bad.tar") + +set(ARCHIVE_FORMAT gnutar) +set(ENCODING OEM) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX) diff --git a/Tests/RunCMake/File_Archive/encoding-oem-gnutar.cmake b/Tests/RunCMake/File_Archive/encoding-oem-gnutar.cmake new file mode 100644 index 0000000000..3f67fefcd6 --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-oem-gnutar.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "test.tar") + +set(ARCHIVE_FORMAT gnutar) +set(ENCODING OEM) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX) diff --git a/Tests/RunCMake/File_Archive/encoding-oem-pax.cmake b/Tests/RunCMake/File_Archive/encoding-oem-pax.cmake new file mode 100644 index 0000000000..ade4a86d4c --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-oem-pax.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "test.tar") + +set(ARCHIVE_FORMAT pax) +set(ENCODING OEM) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX) diff --git a/Tests/RunCMake/File_Archive/encoding-oem-paxr.cmake b/Tests/RunCMake/File_Archive/encoding-oem-paxr.cmake new file mode 100644 index 0000000000..010e10f40f --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-oem-paxr.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "test.tar") + +set(ARCHIVE_FORMAT paxr) +set(ENCODING OEM) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX) diff --git a/Tests/RunCMake/File_Archive/encoding-oem-zip-fails-result.txt b/Tests/RunCMake/File_Archive/encoding-oem-zip-fails-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-oem-zip-fails-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Archive/encoding-oem-zip-fails-stderr.txt b/Tests/RunCMake/File_Archive/encoding-oem-zip-fails-stderr.txt new file mode 100644 index 0000000000..1976196306 --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-oem-zip-fails-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error: archive_write_header: Can't translate [Pp]athname( '[^']*\.txt')? to [^ +]* +CMake Error at roundtrip\.cmake:[0-9]+ \(file\): + file failed to compress: diff --git a/Tests/RunCMake/File_Archive/encoding-oem-zip-fails.cmake b/Tests/RunCMake/File_Archive/encoding-oem-zip-fails.cmake new file mode 100644 index 0000000000..fd48639706 --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-oem-zip-fails.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "bad.zip") + +set(ARCHIVE_FORMAT zip) +set(ENCODING OEM) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("504b0304" LIMIT 4 HEX) diff --git a/Tests/RunCMake/File_Archive/encoding-oem-zip.cmake b/Tests/RunCMake/File_Archive/encoding-oem-zip.cmake new file mode 100644 index 0000000000..3e1bc3d5e0 --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-oem-zip.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "test.zip") + +set(ARCHIVE_FORMAT zip) +set(ENCODING OEM) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("504b0304" LIMIT 4 HEX) diff --git a/Tests/RunCMake/File_Archive/encoding-utf-8-7zip.cmake b/Tests/RunCMake/File_Archive/encoding-utf-8-7zip.cmake new file mode 100644 index 0000000000..8fba09fbd2 --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-utf-8-7zip.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "test.7z") + +set(ARCHIVE_FORMAT 7zip) +set(ENCODING UTF-8) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("377abcaf271c" LIMIT 6 HEX) diff --git a/Tests/RunCMake/File_Archive/encoding-utf-8-gnutar.cmake b/Tests/RunCMake/File_Archive/encoding-utf-8-gnutar.cmake new file mode 100644 index 0000000000..2a25ffc4c9 --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-utf-8-gnutar.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "test.tar") + +set(ARCHIVE_FORMAT gnutar) +set(ENCODING UTF-8) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX) diff --git a/Tests/RunCMake/File_Archive/encoding-utf-8-pax.cmake b/Tests/RunCMake/File_Archive/encoding-utf-8-pax.cmake new file mode 100644 index 0000000000..7c813e116d --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-utf-8-pax.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "test.tar") + +set(ARCHIVE_FORMAT pax) +set(ENCODING UTF-8) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX) diff --git a/Tests/RunCMake/File_Archive/encoding-utf-8-paxr.cmake b/Tests/RunCMake/File_Archive/encoding-utf-8-paxr.cmake new file mode 100644 index 0000000000..26ff3cdcef --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-utf-8-paxr.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "test.tar") + +set(ARCHIVE_FORMAT paxr) +set(ENCODING UTF-8) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX) diff --git a/Tests/RunCMake/File_Archive/encoding-utf-8-zip.cmake b/Tests/RunCMake/File_Archive/encoding-utf-8-zip.cmake new file mode 100644 index 0000000000..b71cc41740 --- /dev/null +++ b/Tests/RunCMake/File_Archive/encoding-utf-8-zip.cmake @@ -0,0 +1,9 @@ +set(OUTPUT_NAME "test.zip") + +set(ARCHIVE_FORMAT zip) +set(ENCODING UTF-8) +include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("504b0304" LIMIT 4 HEX) diff --git a/Tests/RunCMake/File_Archive/roundtrip.cmake b/Tests/RunCMake/File_Archive/roundtrip.cmake index 5b70b61af2..d0bbd5c951 100644 --- a/Tests/RunCMake/File_Archive/roundtrip.cmake +++ b/Tests/RunCMake/File_Archive/roundtrip.cmake @@ -20,6 +20,7 @@ set(CHECK_FILES "d_4/f1.txt" "d-4/f1.txt" "My Special Directory/f1.txt" + ${COMPRESSION_ADDITIONAL_FILE_NAMES} ) foreach(file ${CHECK_FILES}) @@ -35,16 +36,23 @@ file(REMOVE ${FULL_OUTPUT_NAME}) file(REMOVE_RECURSE ${FULL_DECOMPRESS_DIR}) file(MAKE_DIRECTORY ${FULL_DECOMPRESS_DIR}) +set(ENCODING_OPTIONS "") +if (ENCODING) + set(ENCODING_OPTIONS ENCODING "${ENCODING}") +endif() + file(ARCHIVE_CREATE OUTPUT ${FULL_OUTPUT_NAME} FORMAT "${ARCHIVE_FORMAT}" COMPRESSION "${COMPRESSION_TYPE}" WORKING_DIRECTORY "${WORKING_DIRECTORY}" + ${ENCODING_OPTIONS} VERBOSE PATHS ${FULL_COMPRESS_DIR}) file(ARCHIVE_EXTRACT INPUT ${FULL_OUTPUT_NAME} + ${ENCODING_OPTIONS} ${DECOMPRESSION_OPTIONS} DESTINATION ${FULL_DECOMPRESS_DIR} VERBOSE) diff --git a/Tests/RunCMake/File_Archive/utf-8-paths.cmake b/Tests/RunCMake/File_Archive/utf-8-paths.cmake new file mode 100644 index 0000000000..af85ffac87 --- /dev/null +++ b/Tests/RunCMake/File_Archive/utf-8-paths.cmake @@ -0,0 +1,10 @@ +list(APPEND COMPRESSION_ADDITIONAL_FILE_NAMES + "arabic-نَسِيج.txt" + "armenian-Բարեւ ձեզ.txt" + "chinese-质地.txt" + "cyrillic-привет.txt" + "greek-Γεια.txt" + "hungarian-hűtő.txt" + "japanese-テクスチャ.txt" + "korean-조직.txt" +)