summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSibi Siddharthan <sibisiddharthan.github@gmail.com>2020-07-14 16:24:04 (GMT)
committerSibi Siddharthan <sibisiddharthan.github@gmail.com>2020-07-15 14:52:04 (GMT)
commit2fad00940d7ed3c5928bda5b671bdcf08ce53bb8 (patch)
tree16ed66550694ac2eb00aadfc95098b3c30b8236d
parent2da778664d3e99ada4e67a5a1b9d377f92a9f75f (diff)
downloadCMake-2fad00940d7ed3c5928bda5b671bdcf08ce53bb8.zip
CMake-2fad00940d7ed3c5928bda5b671bdcf08ce53bb8.tar.gz
CMake-2fad00940d7ed3c5928bda5b671bdcf08ce53bb8.tar.bz2
cmake: Add -E create_hardlink
Fixes: #20950 Signed-off-by: Sibi Siddharthan <sibisiddharthan.github@gmail.com>
-rw-r--r--Help/manual/cmake.1.rst7
-rw-r--r--Help/release/dev/cmake-E-create_hardlink.rst5
-rw-r--r--Source/cmcmd.cxx29
-rw-r--r--Tests/RunCMake/CommandLine/E_create_hardlink-no-arg-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_create_hardlink-no-arg-stderr.txt3
-rw-r--r--Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_create_hardlink-non-existent-source-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_create_hardlink-non-existent-source-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake3
-rw-r--r--Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake36
13 files changed, 90 insertions, 0 deletions
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index d5fe34c..544f6ea 100644
--- a/Help/manual/cmake.1.rst
+++ b/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.
diff --git a/Help/release/dev/cmake-E-create_hardlink.rst b/Help/release/dev/cmake-E-create_hardlink.rst
new file mode 100644
index 0000000..66cdc87
--- /dev/null
+++ b/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.
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 49e8a4f..1a5fea1 100644
--- a/Source/cmcmd.cxx
+++ b/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;
diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-no-arg-result.txt b/Tests/RunCMake/CommandLine/E_create_hardlink-no-arg-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_create_hardlink-no-arg-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-no-arg-stderr.txt b/Tests/RunCMake/CommandLine/E_create_hardlink-no-arg-stderr.txt
new file mode 100644
index 0000000..50d9b03
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_create_hardlink-no-arg-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: cmake version .*
+Usage: .* -E <command> \[arguments\.\.\.\]
+Available commands:
diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-result.txt b/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt b/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt
new file mode 100644
index 0000000..21e60ee
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: failed to create link .* no such file or directory
diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-non-existent-source-result.txt b/Tests/RunCMake/CommandLine/E_create_hardlink-non-existent-source-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_create_hardlink-non-existent-source-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-non-existent-source-stderr.txt b/Tests/RunCMake/CommandLine/E_create_hardlink-non-existent-source-stderr.txt
new file mode 100644
index 0000000..a334571
--- /dev/null
+++ b/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
diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake b/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake
new file mode 100644
index 0000000..5b97aec
--- /dev/null
+++ b/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()
diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-result.txt b/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-stderr.txt b/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-stderr.txt
new file mode 100644
index 0000000..a334571
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-stderr.txt
@@ -0,0 +1 @@
+^failed to create hard link because source path .* does not exist
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 6d69945..b20e683 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/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}")