diff options
author | Brad King <brad.king@kitware.com> | 2021-03-03 20:54:14 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2021-03-04 13:44:06 (GMT) |
commit | c61292726cd3018ec502f8d59e62352c8dce62d3 (patch) | |
tree | 66f8d89ec3c3329453622e37abacb6dc22c852b2 | |
parent | 0c2dc345047135cac824ffc222bfb0c26f6c23be (diff) | |
download | CMake-c61292726cd3018ec502f8d59e62352c8dce62d3.zip CMake-c61292726cd3018ec502f8d59e62352c8dce62d3.tar.gz CMake-c61292726cd3018ec502f8d59e62352c8dce62d3.tar.bz2 |
file(RENAME): Add option to capture error message on failure
-rw-r--r-- | Help/command/file.rst | 11 | ||||
-rw-r--r-- | Help/release/dev/file-RENAME.rst | 5 | ||||
-rw-r--r-- | Source/cmFileCommand.cxx | 41 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-arg-missing-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-arg-missing-stderr.txt | 3 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-arg-missing.cmake | 1 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-arg-unknown-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt | 5 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-arg-unknown.cmake | 1 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake | 9 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-to-dir-fail-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt | 13 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake | 5 | ||||
-rw-r--r-- | Tests/RunCMake/file/RENAME-file-to-file.cmake | 10 | ||||
-rw-r--r-- | Tests/RunCMake/file/RunCMakeTest.cmake | 6 |
16 files changed, 105 insertions, 9 deletions
diff --git a/Help/command/file.rst b/Help/command/file.rst index 3db605d..b28e206 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -38,7 +38,7 @@ Synopsis `Filesystem`_ file({`GLOB`_ | `GLOB_RECURSE`_} <out-var> [...] [<globbing-expr>...]) - file(`RENAME`_ <oldname> <newname>) + file(`RENAME`_ <oldname> <newname> [...]) file({`REMOVE`_ | `REMOVE_RECURSE`_ } [<files>...]) file(`MAKE_DIRECTORY`_ [<dir>...]) file({`COPY`_ | `INSTALL`_} <file>... DESTINATION <dir> [...]) @@ -665,11 +665,18 @@ Examples of recursive globbing include:: .. code-block:: cmake - file(RENAME <oldname> <newname>) + file(RENAME <oldname> <newname> + [RESULT <result>]) Move a file or directory within a filesystem from ``<oldname>`` to ``<newname>``, replacing the destination atomically. +The options are: + +``RESULT <result>`` + 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. + .. _REMOVE: .. _REMOVE_RECURSE: diff --git a/Help/release/dev/file-RENAME.rst b/Help/release/dev/file-RENAME.rst new file mode 100644 index 0000000..6cde036 --- /dev/null +++ b/Help/release/dev/file-RENAME.rst @@ -0,0 +1,5 @@ +file-RENAME +----------- + +* The :command:`file(RENAME)` command learned to optionally capture + failure in a result variable. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index f674833..6243bb2 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1313,8 +1313,9 @@ bool HandleRelativePathCommand(std::vector<std::string> const& args, bool HandleRename(std::vector<std::string> const& args, cmExecutionStatus& status) { - if (args.size() != 3) { - status.SetError("RENAME given incorrect number of arguments."); + if (args.size() < 3) { + status.SetError("RENAME must be called with at least two additional " + "arguments"); return false; } @@ -1330,13 +1331,39 @@ bool HandleRename(std::vector<std::string> const& args, cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]); } - if (!cmSystemTools::RenameFile(oldname, newname)) { - std::string err = cmSystemTools::GetLastSystemError(); - status.SetError(cmStrCat("RENAME failed to rename\n ", oldname, - "\nto\n ", newname, "\nbecause: ", err, "\n")); + struct Arguments + { + std::string Result; + }; + + static auto const parser = + cmArgumentParser<Arguments>{}.Bind("RESULT"_s, &Arguments::Result); + + std::vector<std::string> unconsumedArgs; + Arguments const arguments = + parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs); + if (!unconsumedArgs.empty()) { + status.SetError("RENAME unknown argument:\n " + unconsumedArgs.front()); return false; } - return true; + + std::string err; + switch (cmSystemTools::RenameFile(oldname, newname, &err)) { + case cmSystemTools::RenameResult::Success: + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, "0"); + } + return true; + case cmSystemTools::RenameResult::Failure: + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, err); + return true; + } + break; + } + status.SetError(cmStrCat("RENAME failed to rename\n ", oldname, "\nto\n ", + newname, "\nbecause: ", err, "\n")); + return false; } bool HandleRemoveImpl(std::vector<std::string> const& args, bool recurse, diff --git a/Tests/RunCMake/file/RENAME-arg-missing-result.txt b/Tests/RunCMake/file/RENAME-arg-missing-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-missing-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/RENAME-arg-missing-stderr.txt b/Tests/RunCMake/file/RENAME-arg-missing-stderr.txt new file mode 100644 index 0000000..98d2961 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-missing-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/RENAME-arg-missing.cmake:1 \(file\): + file RENAME must be called with at least two additional arguments$ diff --git a/Tests/RunCMake/file/RENAME-arg-missing.cmake b/Tests/RunCMake/file/RENAME-arg-missing.cmake new file mode 100644 index 0000000..2358ce9 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-missing.cmake @@ -0,0 +1 @@ +file(RENAME "old") diff --git a/Tests/RunCMake/file/RENAME-arg-unknown-result.txt b/Tests/RunCMake/file/RENAME-arg-unknown-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-unknown-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt b/Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt new file mode 100644 index 0000000..16edb25 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/RENAME-arg-unknown.cmake:1 \(file\): + file RENAME unknown argument: + + unknown$ diff --git a/Tests/RunCMake/file/RENAME-arg-unknown.cmake b/Tests/RunCMake/file/RENAME-arg-unknown.cmake new file mode 100644 index 0000000..3110f70 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-unknown.cmake @@ -0,0 +1 @@ +file(RENAME "old" "new" unknown) diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt b/Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt new file mode 100644 index 0000000..0276a5f --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt @@ -0,0 +1 @@ +^-- file\(RENAME\) failed with result: [A-Za-z] diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake b/Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake new file mode 100644 index 0000000..4f817e8 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake @@ -0,0 +1,9 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +file(MAKE_DIRECTORY "${newname}") +file(RENAME "${oldname}" "${newname}" 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-to-dir-fail-result.txt b/Tests/RunCMake/file/RENAME-file-to-dir-fail-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-dir-fail-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt b/Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt new file mode 100644 index 0000000..e4dbc38 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt @@ -0,0 +1,13 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake:[0-9] \(file\): + file RENAME failed to rename + + [^ +]*/Tests/RunCMake/file/RENAME-file-to-dir-fail-build/input + + to + + [^ +]*/Tests/RunCMake/file/RENAME-file-to-dir-fail-build/output + + because: [A-Za-z] diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake b/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake new file mode 100644 index 0000000..61fa644 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake @@ -0,0 +1,5 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +file(MAKE_DIRECTORY "${newname}") +file(RENAME "${oldname}" "${newname}") diff --git a/Tests/RunCMake/file/RENAME-file-to-file.cmake b/Tests/RunCMake/file/RENAME-file-to-file.cmake new file mode 100644 index 0000000..dbc411be --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-file.cmake @@ -0,0 +1,10 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +file(RENAME "${oldname}" "${newname}") +if(EXISTS "${oldname}") + message(FATAL_ERROR "The old name still exists:\n ${oldname}") +endif() +if(NOT EXISTS "${newname}") + message(FATAL_ERROR "The new name does not exist:\n ${newname}") +endif() diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 22813eb..d9e4cfe 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -50,6 +50,12 @@ run_cmake(SIZE-error-does-not-exist) run_cmake(REMOVE-empty) +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-arg-missing) +run_cmake_script(RENAME-arg-unknown) + # tests are valid both for GLOB and GLOB_RECURSE run_cmake(GLOB-sort-dedup) run_cmake(GLOB-error-LIST_DIRECTORIES-not-boolean) |