From 4ffdd564eb32be6147cb8610bbf6c0b5496fc56a Mon Sep 17 00:00:00 2001 From: Domen Vrankar Date: Sun, 4 Sep 2016 21:13:24 +0200 Subject: [PATCH] CPack/DEB: Add option to select archive type Add a `CPACK_DEBIAN_ARCHIVE_TYPE` option that can be used to select an archive type that supports long file names. Closes: #14332 --- Help/release/dev/cpack-deb-long-filenames.rst | 6 ++++ Modules/CPackDeb.cmake | 33 ++++++++++++++++++- Source/CPack/cmCPackDebGenerator.cxx | 12 +++++-- .../DEB/LONG_FILENAMES-ExpectedFiles.cmake | 5 +++ .../DEB/LONG_FILENAMES-Prerequirements.cmake | 7 ++++ .../DEB/LONG_FILENAMES-VerifyResult.cmake | 26 +++++++++++++++ .../CPack/DEB/LONG_FILENAMES-specifics.cmake | 3 ++ .../RunCMake/CPack/DEB/Prerequirements.cmake | 7 ++++ Tests/RunCMake/CPack/LONG_FILENAMES.cmake | 10 ++++++ Tests/RunCMake/CPack/RunCMakeTest.cmake | 1 + 10 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 Help/release/dev/cpack-deb-long-filenames.rst create mode 100644 Tests/RunCMake/CPack/DEB/LONG_FILENAMES-ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/DEB/LONG_FILENAMES-Prerequirements.cmake create mode 100644 Tests/RunCMake/CPack/DEB/LONG_FILENAMES-VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/DEB/LONG_FILENAMES-specifics.cmake create mode 100644 Tests/RunCMake/CPack/LONG_FILENAMES.cmake diff --git a/Help/release/dev/cpack-deb-long-filenames.rst b/Help/release/dev/cpack-deb-long-filenames.rst new file mode 100644 index 000000000..6113eafa0 --- /dev/null +++ b/Help/release/dev/cpack-deb-long-filenames.rst @@ -0,0 +1,6 @@ +cpack-deb-long-filenames +------------------------ + +* The :module:`CPackDeb` module learned to support long file names + when archive format is set to GNU tar. + See :variable:`CPACK_DEBIAN_ARCHIVE_TYPE` diff --git a/Modules/CPackDeb.cmake b/Modules/CPackDeb.cmake index c9678d629..1a7b92379 100644 --- a/Modules/CPackDeb.cmake +++ b/Modules/CPackDeb.cmake @@ -177,6 +177,24 @@ # # See https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections # +# .. variable:: CPACK_DEBIAN_ARCHIVE_TYPE +# +# The archive format used for creating the Debian package. +# +# * Mandatory : YES +# * Default : "paxr" +# +# Possible values are: +# +# - paxr +# - gnutar +# +# .. note:: +# +# Default pax archive format is the most portable format and generates +# packages that do not treat sparse files specially. +# GNU tar format on the other hand supports longer filenames. +# # .. variable:: CPACK_DEBIAN_COMPRESSION_TYPE # # The compression used for creating the Debian package. @@ -842,12 +860,24 @@ function(cpack_deb_prepare_package_vars) set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") endif() + if(CPACK_DEBIAN_ARCHIVE_TYPE) + set(archive_types_ "paxr;gnutar") + cmake_policy(PUSH) + cmake_policy(SET CMP0057 NEW) + if(NOT CPACK_DEBIAN_ARCHIVE_TYPE IN_LIST archive_types_) + message(FATAL_ERROR "CPACK_DEBIAN_ARCHIVE_TYPE set to unsupported" + "type ${CPACK_DEBIAN_ARCHIVE_TYPE}") + endif() + cmake_policy(POP) + else() + set(CPACK_DEBIAN_ARCHIVE_TYPE "paxr") + endif() + # Compression: (recommended) if(NOT CPACK_DEBIAN_COMPRESSION_TYPE) set(CPACK_DEBIAN_COMPRESSION_TYPE "gzip") endif() - # Recommends: # You should set: CPACK_DEBIAN_PACKAGE_RECOMMENDS @@ -1000,6 +1030,7 @@ function(cpack_deb_prepare_package_vars) set(GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_DEBIAN_PACKAGE_MAINTAINER}" PARENT_SCOPE) set(GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_DEBIAN_PACKAGE_DESCRIPTION}" PARENT_SCOPE) set(GEN_CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}" PARENT_SCOPE) + set(GEN_CPACK_DEBIAN_ARCHIVE_TYPE "${CPACK_DEBIAN_ARCHIVE_TYPE}" PARENT_SCOPE) set(GEN_CPACK_DEBIAN_COMPRESSION_TYPE "${CPACK_DEBIAN_COMPRESSION_TYPE}" PARENT_SCOPE) set(GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS "${CPACK_DEBIAN_PACKAGE_RECOMMENDS}" PARENT_SCOPE) set(GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS "${CPACK_DEBIAN_PACKAGE_SUGGESTS}" PARENT_SCOPE) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 1f3ac5155..b90959855 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -419,6 +419,12 @@ int cmCPackDebGenerator::createDeb() << debian_compression_type << std::endl); } + const char* debian_archive_type = + this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"); + if (!debian_archive_type) { + debian_archive_type = "paxr"; + } + std::string filename_data_tar = strGenWDIR + "/data.tar" + compression_suffix; @@ -431,7 +437,8 @@ int cmCPackDebGenerator::createDeb() << filename_data_tar << "\" for writing" << std::endl); return 0; } - cmArchiveWrite data_tar(fileStream_data_tar, tar_compression_type, "paxr"); + cmArchiveWrite data_tar(fileStream_data_tar, tar_compression_type, + debian_archive_type); // uid/gid should be the one of the root user, and this root user has // always uid/gid equal to 0. @@ -535,7 +542,8 @@ int cmCPackDebGenerator::createDeb() return 0; } cmArchiveWrite control_tar(fileStream_control_tar, - cmArchiveWrite::CompressGZip, "paxr"); + cmArchiveWrite::CompressGZip, + debian_archive_type); // sets permissions and uid/gid for the files control_tar.SetUIDAndGID(0u, 0u); diff --git a/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-ExpectedFiles.cmake b/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-ExpectedFiles.cmake new file mode 100644 index 000000000..dd72cf7bb --- /dev/null +++ b/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-ExpectedFiles.cmake @@ -0,0 +1,5 @@ +set(whitespaces_ "[\t\n\r ]*") + +set(EXPECTED_FILES_COUNT "1") +set(EXPECTED_FILE_1 "long_filenames_0.1.1-1_*.deb") +set(EXPECTED_FILE_CONTENT_1 "^.*/usr/${whitespaces_}.*/usr/foo/${whitespaces_}.*/usr/foo/llllllllll_oooooooooo_nnnnnnnnnn_gggggggggg_ffffffffff_iiiiiiiiii_llllllllll_eeeeeeeeee_nnnnnnnnnn_aaaaaaaaaa_mmmmmmmmmm_eeeeeeeeee.txt$") diff --git a/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-Prerequirements.cmake b/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-Prerequirements.cmake new file mode 100644 index 000000000..0c1d77ea6 --- /dev/null +++ b/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-Prerequirements.cmake @@ -0,0 +1,7 @@ +function(get_test_prerequirements found_var) + find_program(FAKEROOT_EXECUTABLE NAMES fakeroot) + + if(FAKEROOT_EXECUTABLE) + set(${found_var} true PARENT_SCOPE) + endif() +endfunction() diff --git a/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-VerifyResult.cmake b/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-VerifyResult.cmake new file mode 100644 index 000000000..0452343c0 --- /dev/null +++ b/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-VerifyResult.cmake @@ -0,0 +1,26 @@ +# create structure required by non root dpkg install +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/root_dir") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir/updates") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir/info") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir/available" "") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir/status" "") + +# some programs used by fakeroot require sbin in path so we should not +# leave this to chance (programs: ldconfig and start-stop-daemon) +set(ENV{PATH} "$ENV{PATH}:/usr/local/sbin:/usr/sbin:/sbin") + +execute_process(COMMAND ${FAKEROOT_EXECUTABLE} ${DPKG_EXECUTABLE} + -i --force-not-root --root=${CMAKE_CURRENT_BINARY_DIR}/root_dir + --admindir=${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir + --log=${CMAKE_CURRENT_BINARY_DIR}/root_dir/dpkg.log + ${FOUND_FILE_1} + RESULT_VARIABLE install_result_ + ERROR_VARIABLE install_error_ + OUTPUT_QUIET + ) + +if(install_result_) + message(FATAL_ERROR "LONG_FILENAMES package error - result:" + " '${install_result_}'; text: '${install_error_}'") +endif() diff --git a/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-specifics.cmake b/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-specifics.cmake new file mode 100644 index 000000000..39a6be498 --- /dev/null +++ b/Tests/RunCMake/CPack/DEB/LONG_FILENAMES-specifics.cmake @@ -0,0 +1,3 @@ +set(CPACK_PACKAGE_CONTACT "someone") +set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT") +set(CPACK_DEBIAN_ARCHIVE_TYPE "gnutar") diff --git a/Tests/RunCMake/CPack/DEB/Prerequirements.cmake b/Tests/RunCMake/CPack/DEB/Prerequirements.cmake index 197b99d5d..cb9a27745 100644 --- a/Tests/RunCMake/CPack/DEB/Prerequirements.cmake +++ b/Tests/RunCMake/CPack/DEB/Prerequirements.cmake @@ -5,4 +5,11 @@ function(get_test_prerequirements found_var config_file) file(WRITE "${config_file}" "set(DPKG_EXECUTABLE \"${DPKG_EXECUTABLE}\")") set(${found_var} true PARENT_SCOPE) endif() + + # optional tool for some tests + find_program(FAKEROOT_EXECUTABLE fakeroot) + if(FAKEROOT_EXECUTABLE) + file(APPEND "${config_file}" + "\nset(FAKEROOT_EXECUTABLE \"${FAKEROOT_EXECUTABLE}\")") + endif() endfunction() diff --git a/Tests/RunCMake/CPack/LONG_FILENAMES.cmake b/Tests/RunCMake/CPack/LONG_FILENAMES.cmake new file mode 100644 index 000000000..3242aef77 --- /dev/null +++ b/Tests/RunCMake/CPack/LONG_FILENAMES.cmake @@ -0,0 +1,10 @@ +set(LONG_FILENAME + "${CMAKE_CURRENT_BINARY_DIR}/llllllllll_oooooooooo_nnnnnnnnnn_gggggggggg_ffffffffff_iiiiiiiiii_llllllllll_eeeeeeeeee_nnnnnnnnnn_aaaaaaaaaa_mmmmmmmmmm_eeeeeeeeee.txt") + +file(WRITE + "${LONG_FILENAME}" + "long_filename_test") + +install(FILES ${LONG_FILENAME} DESTINATION foo) + +set(CPACK_PACKAGE_NAME "long_filenames") diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 44586d7a2..a3029cfd8 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -17,3 +17,4 @@ run_cpack_test(INSTALL_SCRIPTS "RPM" false) run_cpack_test(DEB_GENERATE_SHLIBS "DEB" true) run_cpack_test(DEB_GENERATE_SHLIBS_LDCONFIG "DEB" true) run_cpack_test(DEBUGINFO "RPM" true) +run_cpack_test(LONG_FILENAMES "DEB" false)