diff options
-rw-r--r-- | Help/command/file.rst | 8 | ||||
-rw-r--r-- | Help/release/dev/file-RENAME.rst | 3 | ||||
-rw-r--r-- | Source/cmFileCommand.cxx | 17 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake | 9 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt | 13 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake | 5 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-replace.cmake | 9 | ||||
-rw-r--r-- | Tests/RunCMake/file/RunCMakeTest.cmake | 3 |
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) |