summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/command/file.rst8
-rw-r--r--Help/release/dev/file-RENAME.rst3
-rw-r--r--Source/cmFileCommand.cxx17
-rw-r--r--Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt1
-rw-r--r--Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake9
-rw-r--r--Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt1
-rw-r--r--Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt13
-rw-r--r--Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake5
-rw-r--r--Tests/RunCMake/file/RENAME-file-replace.cmake9
-rw-r--r--Tests/RunCMake/file/RunCMakeTest.cmake3
10 files changed, 64 insertions, 5 deletions
diff --git a/Help/command/file.rst b/Help/command/file.rst
index b28e206..9cde90c 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -666,7 +666,8 @@ Examples of recursive globbing include::
.. code-block:: cmake
file(RENAME <oldname> <newname>
- [RESULT <result>])
+ [RESULT <result>]
+ [NO_REPLACE])
Move a file or directory within a filesystem from ``<oldname>`` to
``<newname>``, replacing the destination atomically.
@@ -677,6 +678,11 @@ The options are:
Set ``<result>`` variable to ``0`` on success or an error message otherwise.
If ``RESULT`` is not specified and the operation fails, an error is emitted.
+``NO_REPLACE``
+ If the ``<newname>`` path already exists, do not replace it.
+ If ``RESULT <result>`` is used, the result variable will be
+ set to ``NO_REPLACE``. Otherwise, an error is emitted.
+
.. _REMOVE:
.. _REMOVE_RECURSE:
diff --git a/Help/release/dev/file-RENAME.rst b/Help/release/dev/file-RENAME.rst
index 6cde036..6c1314d 100644
--- a/Help/release/dev/file-RENAME.rst
+++ b/Help/release/dev/file-RENAME.rst
@@ -2,4 +2,5 @@ file-RENAME
-----------
* The :command:`file(RENAME)` command learned to optionally capture
- failure in a result variable.
+ failure in a result variable. It also gained a ``NO_REPLACE``
+ option to fail if the destination exists.
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index ab954f2..065b845 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -1333,11 +1333,13 @@ bool HandleRename(std::vector<std::string> const& args,
struct Arguments
{
+ bool NoReplace = false;
std::string Result;
};
- static auto const parser =
- cmArgumentParser<Arguments>{}.Bind("RESULT"_s, &Arguments::Result);
+ static auto const parser = cmArgumentParser<Arguments>{}
+ .Bind("NO_REPLACE"_s, &Arguments::NoReplace)
+ .Bind("RESULT"_s, &Arguments::Result);
std::vector<std::string> unconsumedArgs;
Arguments const arguments =
@@ -1349,13 +1351,22 @@ bool HandleRename(std::vector<std::string> const& args,
std::string err;
switch (cmSystemTools::RenameFile(oldname, newname,
- cmSystemTools::Replace::Yes, &err)) {
+ arguments.NoReplace
+ ? cmSystemTools::Replace::No
+ : cmSystemTools::Replace::Yes,
+ &err)) {
case cmSystemTools::RenameResult::Success:
if (!arguments.Result.empty()) {
status.GetMakefile().AddDefinition(arguments.Result, "0");
}
return true;
case cmSystemTools::RenameResult::NoReplace:
+ if (!arguments.Result.empty()) {
+ err = "NO_REPLACE";
+ } else {
+ err = "path not replaced";
+ }
+ CM_FALLTHROUGH;
case cmSystemTools::RenameResult::Failure:
if (!arguments.Result.empty()) {
status.GetMakefile().AddDefinition(arguments.Result, err);
diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt
new file mode 100644
index 0000000..a116330
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt
@@ -0,0 +1 @@
+^-- file\(RENAME\) failed with result: NO_REPLACE$
diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake
new file mode 100644
index 0000000..1ff4178
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake
@@ -0,0 +1,9 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "a")
+file(WRITE "${newname}" "b")
+file(RENAME "${oldname}" "${newname}" NO_REPLACE RESULT result)
+message(STATUS "file(RENAME) failed with result: ${result}")
+if(NOT EXISTS "${oldname}")
+ message(FATAL_ERROR "The old name does not still exist:\n ${oldname}")
+endif()
diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt
new file mode 100644
index 0000000..dd7294c
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt
@@ -0,0 +1,13 @@
+^CMake Error at [^
+]*/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake:[0-9] \(file\):
+ file RENAME failed to rename
+
+ [^
+]*/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-build/input
+
+ to
+
+ [^
+]*/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-build/output
+
+ because: path not replaced$
diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake
new file mode 100644
index 0000000..c05dd63
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake
@@ -0,0 +1,5 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "a")
+file(WRITE "${newname}" "b")
+file(RENAME "${oldname}" "${newname}" NO_REPLACE)
diff --git a/Tests/RunCMake/file/RENAME-file-replace.cmake b/Tests/RunCMake/file/RENAME-file-replace.cmake
new file mode 100644
index 0000000..efbfaed
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-replace.cmake
@@ -0,0 +1,9 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "a")
+file(WRITE "${newname}" "b")
+file(RENAME "${oldname}" "${newname}")
+file(READ "${newname}" new)
+if(NOT "${new}" STREQUAL "a")
+ message(FATAL_ERROR "New name:\n ${newname}\ndoes not contain expected content 'a'.")
+endif()
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake
index d9e4cfe..f74832c 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -50,9 +50,12 @@ run_cmake(SIZE-error-does-not-exist)
run_cmake(REMOVE-empty)
+run_cmake_script(RENAME-file-replace)
run_cmake_script(RENAME-file-to-file)
run_cmake_script(RENAME-file-to-dir-capture)
run_cmake_script(RENAME-file-to-dir-fail)
+run_cmake_script(RENAME-file-NO_REPLACE-capture)
+run_cmake_script(RENAME-file-NO_REPLACE-fail)
run_cmake_script(RENAME-arg-missing)
run_cmake_script(RENAME-arg-unknown)