summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAsit Dhal <dhal.asitk@gmail.com>2020-09-20 02:29:53 (GMT)
committerAsit Dhal <dhal.asitk@gmail.com>2020-10-01 15:07:44 (GMT)
commit116a427eb1aa7e603a80a50486c08cd0dd16d7dd (patch)
treec0a83c7d054b77110fcc77af694d63a6ef0672d7
parent47b569a85852f716b05ede538e9940392407316c (diff)
downloadCMake-116a427eb1aa7e603a80a50486c08cd0dd16d7dd.zip
CMake-116a427eb1aa7e603a80a50486c08cd0dd16d7dd.tar.gz
CMake-116a427eb1aa7e603a80a50486c08cd0dd16d7dd.tar.bz2
execute_process: add options for fatal errors on subprocess failure
Fixes: #19930
-rw-r--r--Help/command/execute_process.rst8
-rw-r--r--Help/release/dev/execute-process-command-error-is-fatal.rst5
-rw-r--r--Source/cmExecuteProcessCommand.cxx58
-rw-r--r--Tests/RunCMake/execute_process/AnyCommandError-result.txt1
-rw-r--r--Tests/RunCMake/execute_process/AnyCommandError-stderr.txt2
-rw-r--r--Tests/RunCMake/execute_process/AnyCommandError.cmake8
-rw-r--r--Tests/RunCMake/execute_process/CommandError-result.txt1
-rw-r--r--Tests/RunCMake/execute_process/CommandError-stderr.txt2
-rw-r--r--Tests/RunCMake/execute_process/CommandError.cmake3
-rw-r--r--Tests/RunCMake/execute_process/LastCommandError-result.txt1
-rw-r--r--Tests/RunCMake/execute_process/LastCommandError-stderr.txt2
-rw-r--r--Tests/RunCMake/execute_process/LastCommandError.cmake8
-rw-r--r--Tests/RunCMake/execute_process/RunCMakeTest.cmake4
13 files changed, 101 insertions, 2 deletions
diff --git a/Help/command/execute_process.rst b/Help/command/execute_process.rst
index b32025f..a6f141a 100644
--- a/Help/command/execute_process.rst
+++ b/Help/command/execute_process.rst
@@ -23,7 +23,8 @@ Execute one or more child processes.
[ERROR_STRIP_TRAILING_WHITESPACE]
[ENCODING <name>]
[ECHO_OUTPUT_VARIABLE]
- [ECHO_ERROR_VARIABLE])
+ [ECHO_ERROR_VARIABLE]
+ [COMMAND_ERROR_IS_FATAL <ANY|LAST>])
Runs the given sequence of one or more commands.
@@ -116,6 +117,11 @@ Options:
This is analogous to the ``tee`` Unix command.
+``COMMAND_ERROR_IS_FATAL <ANY|LAST>``
+ ``COMMAND_ERROR_IS_FATAL ANY`` option stops processing if any command fails.
+ ``COMMAND_ERROR_IS_FATAL LAST`` option stops processing if the last command
+ in the command list fails.
+
If more than one ``OUTPUT_*`` or ``ERROR_*`` option is given for the
same pipe the precedence is not specified.
If no ``OUTPUT_*`` or ``ERROR_*`` options are given the output will
diff --git a/Help/release/dev/execute-process-command-error-is-fatal.rst b/Help/release/dev/execute-process-command-error-is-fatal.rst
new file mode 100644
index 0000000..fbc54bf
--- /dev/null
+++ b/Help/release/dev/execute-process-command-error-is-fatal.rst
@@ -0,0 +1,5 @@
+execute-process-command-error-is-fatal
+--------------------------------------
+
+* The :command:`execute_process` command gained a ``COMMAND_ERROR_IS_FATAL``
+ option to specify a fatal error.
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 9c53bdf..14147e0 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -7,8 +7,10 @@
#include <cstdio>
#include <iostream>
#include <memory>
+#include <sstream>
#include <vector>
+#include <cm/string_view>
#include <cmext/algorithm>
#include <cmext/string_view>
@@ -63,6 +65,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
bool EchoOutputVariable = false;
bool EchoErrorVariable = false;
std::string Encoding;
+ std::string CommandErrorIsFatal;
};
static auto const parser =
@@ -86,7 +89,8 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
&Arguments::ErrorStripTrailingWhitespace)
.Bind("ENCODING"_s, &Arguments::Encoding)
.Bind("ECHO_OUTPUT_VARIABLE"_s, &Arguments::EchoOutputVariable)
- .Bind("ECHO_ERROR_VARIABLE"_s, &Arguments::EchoErrorVariable);
+ .Bind("ECHO_ERROR_VARIABLE"_s, &Arguments::EchoErrorVariable)
+ .Bind("COMMAND_ERROR_IS_FATAL"_s, &Arguments::CommandErrorIsFatal);
std::vector<std::string> unparsedArguments;
std::vector<std::string> keywordsMissingValue;
@@ -131,6 +135,14 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
return false;
}
}
+
+ if (!arguments.CommandErrorIsFatal.empty()) {
+ if (arguments.CommandErrorIsFatal != "ANY"_s &&
+ arguments.CommandErrorIsFatal != "LAST"_s) {
+ status.SetError("COMMAND_ERROR_IS_FATAL option can be ANY or LAST");
+ return false;
+ }
+ }
// Create a process instance.
std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp_ptr(
cmsysProcess_New(), cmsysProcess_Delete);
@@ -363,6 +375,50 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
}
}
+ if (arguments.CommandErrorIsFatal == "ANY"_s) {
+ if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
+ std::vector<int> failedIndexes;
+ for (int i = 0; i < static_cast<int>(arguments.Commands.size()); ++i) {
+ if (cmsysProcess_GetStateByIndex(cp, i) ==
+ kwsysProcess_StateByIndex_Exited) {
+ int exitCode = cmsysProcess_GetExitValueByIndex(cp, i);
+ if (exitCode) {
+ failedIndexes.push_back(i);
+ }
+ }
+ }
+ if (!failedIndexes.empty()) {
+ std::ostringstream oss;
+ oss << "failed command indexes: ";
+ for (auto i = 0u; i < failedIndexes.size(); i++) {
+ if (i == failedIndexes.size() - 1) {
+ oss << failedIndexes[i] + 1;
+ } else {
+ oss << failedIndexes[i] + 1 << ", ";
+ }
+ }
+ status.SetError(oss.str());
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ }
+ }
+
+ if (arguments.CommandErrorIsFatal == "LAST"_s) {
+ if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
+ int lastIndex = static_cast<int>(arguments.Commands.size() - 1);
+ if (cmsysProcess_GetStateByIndex(cp, lastIndex) ==
+ kwsysProcess_StateByIndex_Exited) {
+ int exitCode = cmsysProcess_GetExitValueByIndex(cp, lastIndex);
+ if (exitCode) {
+ status.SetError("last command failed");
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ }
+ }
+ }
+
return true;
}
diff --git a/Tests/RunCMake/execute_process/AnyCommandError-result.txt b/Tests/RunCMake/execute_process/AnyCommandError-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/execute_process/AnyCommandError-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/execute_process/AnyCommandError-stderr.txt b/Tests/RunCMake/execute_process/AnyCommandError-stderr.txt
new file mode 100644
index 0000000..0380562
--- /dev/null
+++ b/Tests/RunCMake/execute_process/AnyCommandError-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error at .*AnyCommandError.cmake:1 \(execute_process\):
+ execute_process failed command indexes: 2, 3, 4
diff --git a/Tests/RunCMake/execute_process/AnyCommandError.cmake b/Tests/RunCMake/execute_process/AnyCommandError.cmake
new file mode 100644
index 0000000..f8ec385
--- /dev/null
+++ b/Tests/RunCMake/execute_process/AnyCommandError.cmake
@@ -0,0 +1,8 @@
+execute_process(COMMAND ${CMAKE_COMMAND} -E true
+ COMMAND ${CMAKE_COMMAND} -E false
+ COMMAND ${CMAKE_COMMAND} -E false
+ COMMAND ${CMAKE_COMMAND} -E false
+ COMMAND ${CMAKE_COMMAND} -E true
+ COMMAND ${CMAKE_COMMAND} -E true
+ COMMAND_ERROR_IS_FATAL ANY
+)
diff --git a/Tests/RunCMake/execute_process/CommandError-result.txt b/Tests/RunCMake/execute_process/CommandError-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/execute_process/CommandError-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/execute_process/CommandError-stderr.txt b/Tests/RunCMake/execute_process/CommandError-stderr.txt
new file mode 100644
index 0000000..c28f3a3
--- /dev/null
+++ b/Tests/RunCMake/execute_process/CommandError-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error at .*CommandError.cmake:1 \(execute_process\):
+ execute_process COMMAND_ERROR_IS_FATAL option can be ANY or LAST
diff --git a/Tests/RunCMake/execute_process/CommandError.cmake b/Tests/RunCMake/execute_process/CommandError.cmake
new file mode 100644
index 0000000..da58928
--- /dev/null
+++ b/Tests/RunCMake/execute_process/CommandError.cmake
@@ -0,0 +1,3 @@
+execute_process(COMMAND ${CMAKE_COMMAND} -E true
+ COMMAND_ERROR_IS_FATAL ALL
+)
diff --git a/Tests/RunCMake/execute_process/LastCommandError-result.txt b/Tests/RunCMake/execute_process/LastCommandError-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/execute_process/LastCommandError-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/execute_process/LastCommandError-stderr.txt b/Tests/RunCMake/execute_process/LastCommandError-stderr.txt
new file mode 100644
index 0000000..ff191b3
--- /dev/null
+++ b/Tests/RunCMake/execute_process/LastCommandError-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error at .*LastCommandError.cmake:1 \(execute_process\):
+ execute_process last command failed
diff --git a/Tests/RunCMake/execute_process/LastCommandError.cmake b/Tests/RunCMake/execute_process/LastCommandError.cmake
new file mode 100644
index 0000000..6116a5c
--- /dev/null
+++ b/Tests/RunCMake/execute_process/LastCommandError.cmake
@@ -0,0 +1,8 @@
+execute_process(COMMAND ${CMAKE_COMMAND} -E true
+ COMMAND ${CMAKE_COMMAND} -E false
+ COMMAND ${CMAKE_COMMAND} -E false
+ COMMAND ${CMAKE_COMMAND} -E false
+ COMMAND ${CMAKE_COMMAND} -E true
+ COMMAND ${CMAKE_COMMAND} -E false
+ COMMAND_ERROR_IS_FATAL LAST
+)
diff --git a/Tests/RunCMake/execute_process/RunCMakeTest.cmake b/Tests/RunCMake/execute_process/RunCMakeTest.cmake
index 89ad6b2..f4c3d19 100644
--- a/Tests/RunCMake/execute_process/RunCMakeTest.cmake
+++ b/Tests/RunCMake/execute_process/RunCMakeTest.cmake
@@ -26,3 +26,7 @@ run_cmake_command(EchoCommand3 ${CMAKE_COMMAND}
${RunCMake_SOURCE_DIR}/EchoCommand.cmake)
run_cmake_command(EchoVariable ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/EchoVariable.cmake)
+
+run_cmake_command(AnyCommandError ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/AnyCommandError.cmake)
+run_cmake_command(LastCommandError ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/LastCommandError.cmake)
+run_cmake_command(CommandError ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/CommandError.cmake)