This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, master has been updated
       via  3bd8ed22e8017e5490b8e758f486433b005ace30 (commit)
       via  e3ff7ced630808e2e74f0853a720bc90d3f35abb (commit)
      from  8ada05980f1a12a2673f78f4ea7bab9df6b9d987 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3bd8ed22e8017e5490b8e758f486433b005ace30
commit 3bd8ed22e8017e5490b8e758f486433b005ace30
Merge: 8ada059 e3ff7ce
Author:     Marc Chevrier <marc.chevr...@gmail.com>
AuthorDate: Sat May 18 08:25:16 2019 +0000
Commit:     Kitware Robot <kwro...@kitware.com>
CommitDate: Sat May 18 04:25:39 2019 -0400

    Merge topic 'file-install-follow-symlink-chain'
    
    e3ff7ced63 file(INSTALL): Add FOLLOW_SYMLINK_CHAIN argument
    
    Acked-by: Kitware Robot <kwro...@kitware.com>
    Acked-by: Brad King <brad.k...@kitware.com>
    Merge-request: !3332


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e3ff7ced630808e2e74f0853a720bc90d3f35abb
commit e3ff7ced630808e2e74f0853a720bc90d3f35abb
Author:     Kyle Edwards <kyle.edwa...@kitware.com>
AuthorDate: Thu May 16 15:23:14 2019 -0400
Commit:     Kyle Edwards <kyle.edwa...@kitware.com>
CommitDate: Thu May 16 15:25:33 2019 -0400

    file(INSTALL): Add FOLLOW_SYMLINK_CHAIN argument

diff --git a/Help/command/file.rst b/Help/command/file.rst
index 465e567..0664e7c 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -311,6 +311,7 @@ Create the given directories and their parents as needed.
        [FILE_PERMISSIONS <permissions>...]
        [DIRECTORY_PERMISSIONS <permissions>...]
        [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
+       [FOLLOW_SYMLINK_CHAIN]
        [FILES_MATCHING]
        [[PATTERN <pattern> | REGEX <regex>]
         [EXCLUDE] [PERMISSIONS <permissions>...]] [...])
@@ -324,6 +325,32 @@ at the destination with the same timestamp.  Copying 
preserves input
 permissions unless explicit permissions or ``NO_SOURCE_PERMISSIONS``
 are given (default is ``USE_SOURCE_PERMISSIONS``).
 
+If ``FOLLOW_SYMLINK_CHAIN`` is specified, ``COPY`` will recursively resolve
+the symlinks at the paths given until a real file is found, and install
+a corresponding symlink in the destination for each symlink encountered. For
+each symlink that is installed, the resolution is stripped of the directory,
+leaving only the filename, meaning that the new symlink points to a file in
+the same directory as the symlink. This feature is useful on some Unix systems,
+where libraries are installed as a chain of symlinks with version numbers, with
+less specific versions pointing to more specific versions.
+``FOLLOW_SYMLINK_CHAIN`` will install all of these symlinks and the library
+itself into the destination directory. For example, if you have the following
+directory structure:
+
+* ``/opt/foo/lib/libfoo.so.1.2.3``
+* ``/opt/foo/lib/libfoo.so.1.2 -> libfoo.so.1.2.3``
+* ``/opt/foo/lib/libfoo.so.1 -> libfoo.so.1.2``
+* ``/opt/foo/lib/libfoo.so -> libfoo.so.1``
+
+and you do:
+
+.. code-block:: cmake
+
+  file(COPY /opt/foo/lib/libfoo.so DESTINATION lib FOLLOW_SYMLINK_CHAIN)
+
+This will install all of the symlinks and ``libfoo.so.1.2.3`` itself into
+``lib``.
+
 See the :command:`install(DIRECTORY)` command for documentation of
 permissions, ``FILES_MATCHING``, ``PATTERN``, ``REGEX``, and
 ``EXCLUDE`` options.  Copying directories preserves the structure
diff --git a/Help/release/dev/file-install-follow-symlink-chain.rst 
b/Help/release/dev/file-install-follow-symlink-chain.rst
new file mode 100644
index 0000000..8d22512
--- /dev/null
+++ b/Help/release/dev/file-install-follow-symlink-chain.rst
@@ -0,0 +1,6 @@
+file-install-follow-symlink-chain
+---------------------------------
+
+* The :command:`file(INSTALL)` command learned a new argument,
+  ``FOLLOW_SYMLINK_CHAIN``, which can be used to recursively resolve and
+  install symlinks.
diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx
index 8913e6d..972cd6e 100644
--- a/Source/cmFileCopier.cxx
+++ b/Source/cmFileCopier.cxx
@@ -31,6 +31,7 @@ cmFileCopier::cmFileCopier(cmFileCommand* command, const 
char* name)
   , UseGivenPermissionsFile(false)
   , UseGivenPermissionsDir(false)
   , UseSourcePermissions(true)
+  , FollowSymlinkChain(false)
   , Doing(DoingNone)
 {
 }
@@ -249,6 +250,9 @@ bool cmFileCopier::CheckKeyword(std::string const& arg)
     this->Doing = DoingPattern;
   } else if (arg == "REGEX") {
     this->Doing = DoingRegex;
+  } else if (arg == "FOLLOW_SYMLINK_CHAIN") {
+    this->FollowSymlinkChain = true;
+    this->Doing = DoingNone;
   } else if (arg == "EXCLUDE") {
     // Add this property to the current match rule.
     if (this->CurrentMatchRule) {
@@ -464,16 +468,69 @@ bool cmFileCopier::Install(const std::string& fromFile,
   if (cmSystemTools::SameFile(fromFile, toFile)) {
     return true;
   }
-  if (cmSystemTools::FileIsSymlink(fromFile)) {
-    return this->InstallSymlink(fromFile, toFile);
+
+  std::string newFromFile = fromFile;
+  std::string newToFile = toFile;
+
+  if (this->FollowSymlinkChain &&
+      !this->InstallSymlinkChain(newFromFile, newToFile)) {
+    return false;
   }
-  if (cmSystemTools::FileIsDirectory(fromFile)) {
-    return this->InstallDirectory(fromFile, toFile, match_properties);
+
+  if (cmSystemTools::FileIsSymlink(newFromFile)) {
+    return this->InstallSymlink(newFromFile, newToFile);
   }
-  if (cmSystemTools::FileExists(fromFile)) {
-    return this->InstallFile(fromFile, toFile, match_properties);
+  if (cmSystemTools::FileIsDirectory(newFromFile)) {
+    return this->InstallDirectory(newFromFile, newToFile, match_properties);
   }
-  return this->ReportMissing(fromFile);
+  if (cmSystemTools::FileExists(newFromFile)) {
+    return this->InstallFile(newFromFile, newToFile, match_properties);
+  }
+  return this->ReportMissing(newFromFile);
+}
+
+bool cmFileCopier::InstallSymlinkChain(std::string& fromFile,
+                                       std::string& toFile)
+{
+  std::string newFromFile;
+  std::string toFilePath = cmSystemTools::GetFilenamePath(toFile);
+  while (cmSystemTools::ReadSymlink(fromFile, newFromFile)) {
+    if (!cmSystemTools::FileIsFullPath(newFromFile)) {
+      std::string fromFilePath = cmSystemTools::GetFilenamePath(fromFile);
+      newFromFile = fromFilePath + "/" + newFromFile;
+    }
+
+    std::string symlinkTarget = cmSystemTools::GetFilenameName(newFromFile);
+
+    bool copy = true;
+    if (!this->Always) {
+      std::string oldSymlinkTarget;
+      if (cmSystemTools::ReadSymlink(toFile, oldSymlinkTarget)) {
+        if (symlinkTarget == oldSymlinkTarget) {
+          copy = false;
+        }
+      }
+    }
+
+    this->ReportCopy(toFile, TypeLink, copy);
+
+    if (copy) {
+      cmSystemTools::RemoveFile(toFile);
+      cmSystemTools::MakeDirectory(toFilePath);
+
+      if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) {
+        std::ostringstream e;
+        e << this->Name << " cannot create symlink \"" << toFile << "\".";
+        this->FileCommand->SetError(e.str());
+        return false;
+      }
+    }
+
+    fromFile = newFromFile;
+    toFile = toFilePath + "/" + symlinkTarget;
+  }
+
+  return true;
 }
 
 bool cmFileCopier::InstallSymlink(const std::string& fromFile,
diff --git a/Source/cmFileCopier.h b/Source/cmFileCopier.h
index 003b8f6..a79a60b 100644
--- a/Source/cmFileCopier.h
+++ b/Source/cmFileCopier.h
@@ -64,6 +64,7 @@ protected:
   // Translate an argument to a permissions bit.
   bool CheckPermissions(std::string const& arg, mode_t& permissions);
 
+  bool InstallSymlinkChain(std::string& fromFile, std::string& toFile);
   bool InstallSymlink(const std::string& fromFile, const std::string& toFile);
   bool InstallFile(const std::string& fromFile, const std::string& toFile,
                    MatchProperties match_properties);
@@ -86,6 +87,7 @@ protected:
   bool UseGivenPermissionsFile;
   bool UseGivenPermissionsDir;
   bool UseSourcePermissions;
+  bool FollowSymlinkChain;
   std::string Destination;
   std::string FilesFromDir;
   std::vector<std::string> Files;
diff --git a/Tests/RunCMake/file/INSTALL-FOLLOW_SYMLINK_CHAIN.cmake 
b/Tests/RunCMake/file/INSTALL-FOLLOW_SYMLINK_CHAIN.cmake
new file mode 100644
index 0000000..d8a12eb
--- /dev/null
+++ b/Tests/RunCMake/file/INSTALL-FOLLOW_SYMLINK_CHAIN.cmake
@@ -0,0 +1,168 @@
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/dest1")
+
+file(TOUCH "${CMAKE_BINARY_DIR}/file1.txt")
+file(CREATE_LINK file1.txt "${CMAKE_BINARY_DIR}/file1.txt.sym" SYMBOLIC)
+file(TOUCH "${CMAKE_BINARY_DIR}/dest1/file1.txt.sym")
+
+file(TOUCH "${CMAKE_BINARY_DIR}/file2.txt")
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/file2")
+file(CREATE_LINK ../file2.txt "${CMAKE_BINARY_DIR}/file2/file2.txt.sym" 
SYMBOLIC)
+
+file(TOUCH "${CMAKE_BINARY_DIR}/file3.txt")
+file(CREATE_LINK "${CMAKE_BINARY_DIR}/file3.txt" 
"${CMAKE_BINARY_DIR}/file3.txt.sym" SYMBOLIC)
+
+file(TOUCH "${CMAKE_BINARY_DIR}/file4.txt")
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/file4")
+file(CREATE_LINK "${CMAKE_BINARY_DIR}/file4.txt" 
"${CMAKE_BINARY_DIR}/file4/file4.txt.sym" SYMBOLIC)
+
+file(TOUCH "${CMAKE_BINARY_DIR}/file5.txt")
+
+file(TOUCH "${CMAKE_BINARY_DIR}/file6.txt")
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/file6/file6")
+file(CREATE_LINK file6.txt "${CMAKE_BINARY_DIR}/file6.txt.sym.1" SYMBOLIC)
+file(CREATE_LINK ../file6.txt.sym.1 
"${CMAKE_BINARY_DIR}/file6/file6.txt.sym.2" SYMBOLIC)
+file(CREATE_LINK "${CMAKE_BINARY_DIR}/file6/file6.txt.sym.2" 
"${CMAKE_BINARY_DIR}/file6/file6/file6.txt.sym.3" SYMBOLIC)
+file(CREATE_LINK file6.txt.sym.3 
"${CMAKE_BINARY_DIR}/file6/file6/file6.txt.sym.4" SYMBOLIC)
+
+file(TOUCH "${CMAKE_BINARY_DIR}/file7.txt")
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/file7")
+
+file(TOUCH "${CMAKE_BINARY_DIR}/file8.txt")
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/file8")
+file(CREATE_LINK "${CMAKE_BINARY_DIR}/file8/../file8.txt" 
"${CMAKE_BINARY_DIR}/file8/file8.txt.sym" SYMBOLIC)
+
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/file9")
+file(TOUCH "${CMAKE_BINARY_DIR}/file9/file9.txt")
+file(CREATE_LINK "${CMAKE_BINARY_DIR}/file9" "${CMAKE_BINARY_DIR}/file9.sym" 
SYMBOLIC)
+
+file(TOUCH "${CMAKE_BINARY_DIR}/file10.txt")
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/file10")
+file(CREATE_LINK "." "${CMAKE_BINARY_DIR}/file10/file10" SYMBOLIC)
+file(CREATE_LINK "${CMAKE_BINARY_DIR}/file10/file10/../file10.txt" 
"${CMAKE_BINARY_DIR}/file10/file10.txt.sym" SYMBOLIC)
+
+file(INSTALL
+  "${CMAKE_BINARY_DIR}/file1.txt.sym"
+  DESTINATION "${CMAKE_BINARY_DIR}/dest1"
+  FOLLOW_SYMLINK_CHAIN
+  )
+
+file(INSTALL
+  "${CMAKE_BINARY_DIR}/file1.txt.sym"
+  "${CMAKE_BINARY_DIR}/file2/file2.txt.sym"
+  "${CMAKE_BINARY_DIR}/file3.txt.sym"
+  "${CMAKE_BINARY_DIR}/file4/file4.txt.sym"
+  "${CMAKE_BINARY_DIR}/file5.txt"
+  "${CMAKE_BINARY_DIR}/file6/file6/file6.txt.sym.4"
+  "${CMAKE_BINARY_DIR}/file8/file8.txt.sym"
+  "${CMAKE_BINARY_DIR}/file7/../file7.txt"
+  "${CMAKE_BINARY_DIR}/file8.txt"
+  "${CMAKE_BINARY_DIR}/file9.sym/file9.txt"
+  "${CMAKE_BINARY_DIR}/file10/file10/file10.txt.sym"
+  DESTINATION "${CMAKE_BINARY_DIR}/dest2"
+  FOLLOW_SYMLINK_CHAIN
+  )
+
+set(resolved_file1.txt.sym file1.txt)
+set(resolved_file10.txt.sym file10.txt)
+set(resolved_file2.txt.sym file2.txt)
+set(resolved_file3.txt.sym file3.txt)
+set(resolved_file4.txt.sym file4.txt)
+set(resolved_file6.txt.sym.1 file6.txt)
+set(resolved_file6.txt.sym.2 file6.txt.sym.1)
+set(resolved_file6.txt.sym.3 file6.txt.sym.2)
+set(resolved_file6.txt.sym.4 file6.txt.sym.3)
+set(resolved_file8.txt.sym file8.txt)
+set(syms)
+foreach(f
+  file1.txt
+  file1.txt.sym
+  file10.txt
+  file10.txt.sym
+  file2.txt
+  file2.txt.sym
+  file3.txt
+  file3.txt.sym
+  file4.txt
+  file4.txt.sym
+  file5.txt
+  file6.txt
+  file6.txt.sym.1
+  file6.txt.sym.2
+  file6.txt.sym.3
+  file6.txt.sym.4
+  file7.txt
+  file8.txt
+  file8.txt.sym
+  file9.txt
+  )
+  string(REPLACE "." "\\." r "${f}")
+  list(APPEND syms 
"[^;]*/Tests/RunCMake/file/INSTALL-FOLLOW_SYMLINK_CHAIN-build/dest2/${r}")
+  set(filename "${CMAKE_BINARY_DIR}/dest2/${f}")
+  if(DEFINED resolved_${f})
+    file(READ_SYMLINK "${filename}" resolved)
+    if(NOT resolved STREQUAL "${resolved_${f}}")
+      message(SEND_ERROR "Expected symlink resolution for ${f}: 
${resolved_${f}}\nActual resolution: ${resolved}")
+    endif()
+  elseif(NOT EXISTS "${filename}" OR IS_SYMLINK "${filename}" OR IS_DIRECTORY 
"${filename}")
+    message(SEND_ERROR "${f} should be a regular file")
+  endif()
+endforeach()
+
+file(GLOB_RECURSE actual_syms LIST_DIRECTORIES true 
"${CMAKE_BINARY_DIR}/dest2/*")
+if(NOT actual_syms MATCHES "^${syms}$")
+  message(SEND_ERROR "Expected files:\n\n  ^${syms}$\n\nActual files:\n\n  
${actual_syms}")
+endif()
+
+file(INSTALL
+  "${CMAKE_BINARY_DIR}/file1.txt.sym"
+  "${CMAKE_BINARY_DIR}/file2/file2.txt.sym"
+  "${CMAKE_BINARY_DIR}/file3.txt.sym"
+  "${CMAKE_BINARY_DIR}/file4/file4.txt.sym"
+  "${CMAKE_BINARY_DIR}/file5.txt"
+  "${CMAKE_BINARY_DIR}/file6/file6/file6.txt.sym.4"
+  "${CMAKE_BINARY_DIR}/file8/file8.txt.sym"
+  "${CMAKE_BINARY_DIR}/file7/../file7.txt"
+  "${CMAKE_BINARY_DIR}/file8.txt"
+  "${CMAKE_BINARY_DIR}/file9.sym/file9.txt"
+  "${CMAKE_BINARY_DIR}/file10/file10/file10.txt.sym"
+  DESTINATION "${CMAKE_BINARY_DIR}/dest3"
+  )
+
+set(resolved_file1.txt.sym [[^file1\.txt$]])
+set(resolved_file10.txt.sym 
[[/Tests/RunCMake/file/INSTALL-FOLLOW_SYMLINK_CHAIN-build/file10/file10/\.\./file10\.txt$]])
+set(resolved_file2.txt.sym [[^\.\./file2\.txt$]])
+set(resolved_file3.txt.sym 
[[/Tests/RunCMake/file/INSTALL-FOLLOW_SYMLINK_CHAIN-build/file3\.txt$]])
+set(resolved_file4.txt.sym 
[[/Tests/RunCMake/file/INSTALL-FOLLOW_SYMLINK_CHAIN-build/file4\.txt$]])
+set(resolved_file6.txt.sym.4 [[^file6\.txt\.sym\.3$]])
+set(resolved_file8.txt.sym 
[[/Tests/RunCMake/file/INSTALL-FOLLOW_SYMLINK_CHAIN-build/file8/\.\./file8\.txt$]])
+set(syms)
+foreach(f
+  file1.txt.sym
+  file10.txt.sym
+  file2.txt.sym
+  file3.txt.sym
+  file4.txt.sym
+  file5.txt
+  file6.txt.sym.4
+  file7.txt
+  file8.txt
+  file8.txt.sym
+  file9.txt
+  )
+  string(REPLACE "." "\\." r "${f}")
+  list(APPEND syms 
"[^;]*/Tests/RunCMake/file/INSTALL-FOLLOW_SYMLINK_CHAIN-build/dest3/${r}")
+  set(filename "${CMAKE_BINARY_DIR}/dest3/${f}")
+  if(DEFINED resolved_${f})
+    file(READ_SYMLINK "${filename}" resolved)
+    if(NOT resolved MATCHES "${resolved_${f}}")
+      message(SEND_ERROR "Expected symlink resolution for ${f}: 
${resolved_${f}}\nActual resolution: ${resolved}")
+    endif()
+  elseif(NOT EXISTS "${filename}" OR IS_SYMLINK "${filename}" OR IS_DIRECTORY 
"${filename}")
+    message(SEND_ERROR "${f} should be a regular file")
+  endif()
+endforeach()
+
+file(GLOB_RECURSE actual_syms LIST_DIRECTORIES true 
"${CMAKE_BINARY_DIR}/dest3/*")
+if(NOT actual_syms MATCHES "^${syms}$")
+  message(SEND_ERROR "Expected files:\n\n  ^${syms}$\n\nActual files:\n\n  
${actual_syms}")
+endif()
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake 
b/Tests/RunCMake/file/RunCMakeTest.cmake
index 128e8f3..996d1c5 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -64,6 +64,7 @@ if(NOT WIN32 OR CYGWIN)
   run_cmake(READ_SYMLINK)
   run_cmake(READ_SYMLINK-noexist)
   run_cmake(READ_SYMLINK-notsymlink)
+  run_cmake(INSTALL-FOLLOW_SYMLINK_CHAIN)
 endif()
 
 if(RunCMake_GENERATOR STREQUAL "Ninja")

-----------------------------------------------------------------------

Summary of changes:
 Help/command/file.rst                              |  27 ++++
 .../dev/file-install-follow-symlink-chain.rst      |   6 +
 Source/cmFileCopier.cxx                            |  71 ++++++++-
 Source/cmFileCopier.h                              |   2 +
 .../file/INSTALL-FOLLOW_SYMLINK_CHAIN.cmake        | 168 +++++++++++++++++++++
 Tests/RunCMake/file/RunCMakeTest.cmake             |   1 +
 6 files changed, 268 insertions(+), 7 deletions(-)
 create mode 100644 Help/release/dev/file-install-follow-symlink-chain.rst
 create mode 100644 Tests/RunCMake/file/INSTALL-FOLLOW_SYMLINK_CHAIN.cmake


hooks/post-receive
-- 
CMake
_______________________________________________
Cmake-commits mailing list
Cmake-commits@cmake.org
https://cmake.org/mailman/listinfo/cmake-commits

Reply via email to