Jelajahi Sumber

Merge topic 'cmake-E-create_hardlink'

2fad00940d cmake: Add -E create_hardlink

Acked-by: Kitware Robot <[email protected]>
Merge-request: !5015
Brad King 5 tahun lalu
induk
melakukan
c7b7547d8d

+ 7 - 0
Help/manual/cmake.1.rst

@@ -598,6 +598,13 @@ Available commands are:
   .. note::
     Path to where ``<new>`` symbolic link will be created has to exist beforehand.
 
+``create_hardlink <old> <new>``
+  Create a hard link ``<new>`` naming ``<old>``.
+
+  .. note::
+    Path to where ``<new>`` hard link will be created has to exist beforehand.
+    ``<old>`` has to exist beforehand.
+
 ``echo [<string>...]``
   Displays arguments as text.
 

+ 5 - 0
Help/release/dev/cmake-E-create_hardlink.rst

@@ -0,0 +1,5 @@
+cmake-E-create_hardlink
+-----------------------
+
+* The :manual:`cmake(1)` gained a ``-E create_hardlink`` command-line tool
+  that can be used to create hardlinks between files.

+ 29 - 0
Source/cmcmd.cxx

@@ -126,6 +126,7 @@ void CMakeCommandUsage(const char* program)
     << "  touch <file>...           - touch a <file>.\n"
     << "  touch_nocreate <file>...  - touch a <file> but do not create it.\n"
     << "  create_symlink old new    - create a symbolic link new -> old\n"
+    << "  create_hardlink old new   - create a hard link new -> old\n"
     << "  true                      - do nothing with an exit code of 0\n"
     << "  false                     - do nothing with an exit code of 1\n"
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -1034,6 +1035,34 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
       return 0;
     }
 
+    // Command to create a hard link.  Fails on platforms not
+    // supporting them.
+    if (args[1] == "create_hardlink" && args.size() == 4) {
+      const char* SouceFileName = args[2].c_str();
+      const char* destinationFileName = args[3].c_str();
+
+      if (!cmSystemTools::FileExists(SouceFileName)) {
+        std::cerr << "failed to create hard link because source path '"
+                  << SouceFileName << "' does not exist \n";
+        return 1;
+      }
+
+      if ((cmSystemTools::FileExists(destinationFileName) ||
+           cmSystemTools::FileIsSymlink(destinationFileName)) &&
+          !cmSystemTools::RemoveFile(destinationFileName)) {
+        std::string emsg = cmSystemTools::GetLastSystemError();
+        std::cerr << "failed to create hard link '" << destinationFileName
+                  << "' because existing path cannot be removed: " << emsg
+                  << "\n";
+        return 1;
+      }
+
+      if (!cmSystemTools::CreateLink(args[2], args[3])) {
+        return 1;
+      }
+      return 0;
+    }
+
     // Command to do nothing with an exit code of 0.
     if (args[1] == "true") {
       return 0;

+ 1 - 0
Tests/RunCMake/CommandLine/E_create_hardlink-no-arg-result.txt

@@ -0,0 +1 @@
+1

+ 3 - 0
Tests/RunCMake/CommandLine/E_create_hardlink-no-arg-stderr.txt

@@ -0,0 +1,3 @@
+^CMake Error: cmake version .*
+Usage: .* -E <command> \[arguments\.\.\.\]
+Available commands:

+ 1 - 0
Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: failed to create link .* no such file or directory

+ 1 - 0
Tests/RunCMake/CommandLine/E_create_hardlink-non-existent-source-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLine/E_create_hardlink-non-existent-source-stderr.txt

@@ -0,0 +1 @@
+^failed to create hard link because source path .* does not exist

+ 3 - 0
Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake

@@ -0,0 +1,3 @@
+if(${actual_stderr_var} MATCHES "operation not permitted")
+  unset(msg)
+endif()

+ 1 - 0
Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-stderr.txt

@@ -0,0 +1 @@
+^failed to create hard link because source path .* does not exist

+ 36 - 0
Tests/RunCMake/CommandLine/RunCMakeTest.cmake

@@ -348,6 +348,42 @@ run_cmake_command(E_create_symlink-no-replace-dir
   ${CMAKE_COMMAND} -E create_symlink T .
   )
 
+#create hard link tests
+run_cmake_command(E_create_hardlink-no-arg
+  ${CMAKE_COMMAND} -E create_hardlink
+  )
+
+set(dir ${RunCMake_BINARY_DIR}/hardlink_tests)
+file(REMOVE_RECURSE "${dir}")
+file(MAKE_DIRECTORY ${dir})
+
+run_cmake_command(E_create_hardlink-non-existent-source
+  ${CMAKE_COMMAND} -E create_hardlink ${dir}/I_dont_exist ${dir}/link
+  )
+
+file(TOUCH ${dir}/1)
+
+run_cmake_command(E_create_hardlink-ok
+  ${CMAKE_COMMAND} -E create_hardlink ${dir}/1 ${dir}/1-link
+  )
+
+run_cmake_command(E_create_hardlink-no-directory
+  ${CMAKE_COMMAND} -E create_hardlink ${dir}/1 ${dir}/a/1-link
+  )
+
+#On Windows, if the user does not have sufficient privileges
+#don't fail this test
+set(RunCMake_DEFAULT_stderr "(operation not permitted)?")
+run_cmake_command(E_create_hardlink-unresolved-symlink-prereq
+  ${CMAKE_COMMAND} -E create_symlink ${dir}/1 ${dir}/1-symlink
+  )
+file(REMOVE ${dir}/1)
+
+run_cmake_command(E_create_hardlink-unresolved-symlink
+  ${CMAKE_COMMAND} -E create_hardlink ${dir}/1-symlink ${dir}/1s-link
+  )
+unset(RunCMake_DEFAULT_stderr)
+
 set(in ${RunCMake_SOURCE_DIR}/copy_input)
 set(out ${RunCMake_BINARY_DIR}/copy_output)
 file(REMOVE_RECURSE "${out}")