diff options
-rw-r--r-- | Help/manual/cmake.1.rst | 21 | ||||
-rw-r--r-- | Help/release/dev/cmcmd-end-of-options-delimiter.rst | 7 | ||||
-rw-r--r-- | Source/cmcmd.cxx | 23 | ||||
-rw-r--r-- | Tests/RunCMake/CMakeLists.txt | 3 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/E_cat-with-double-dash-stdout.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/E_cat-without-double-dash-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/E_cat-without-double-dash-stderr.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/E_env-with-double-dash-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/E_env-without-double-dash-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/E_env-without-double-dash-stderr.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 18 |
11 files changed, 65 insertions, 13 deletions
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index c2b4d68..6383faf 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -646,11 +646,17 @@ Available commands are: ``true`` if cmake supports server-mode and ``false`` otherwise. Always false since CMake 3.20. -``cat <files>...`` +``cat [--] <files>...`` .. versionadded:: 3.18 Concatenate files and print on the standard output. + .. versionadded:: 3.24 + Added support for the double dash argument ``--``. This basic implementation + of ``cat`` does not support any options, so using a option starting with + ``-`` will result in an error. Use ``--`` to indicate the end of options, in + case a file starts with ``-``. + ``chdir <dir> <cmd> [<arg>...]`` Change the current working directory and run a command. @@ -719,11 +725,16 @@ Available commands are: ``echo_append [<string>...]`` Displays arguments as text but no new line. -``env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]...`` +``env [--unset=NAME ...] [NAME=VALUE ...] [--] <command> [<arg>...]`` .. versionadded:: 3.1 Run command in a modified environment. + .. versionadded:: 3.24 + Added support for the double dash argument ``--``. Use ``--`` to stop + interpreting options/environment variables and treat the next argument as + the command, even if it start with ``-`` or contains a ``=``. + ``environment`` Display the current environment variables. @@ -816,16 +827,16 @@ Available commands are: Rename a file or directory (on one volume). If file with the ``<newname>`` name already exists, then it will be silently replaced. -``rm [-rRf] <file> <dir>...`` +``rm [-rRf] [--] <file|dir>...`` .. versionadded:: 3.17 Remove the files ``<file>`` or directories ``<dir>``. - Use ``-r`` or ``-R`` to remove directories and their contents recursively. If any of the listed files/directories do not exist, the command returns a non-zero exit code, but no message is logged. The ``-f`` option changes the behavior to return a zero exit code (i.e. success) in such - situations instead. + situations instead. Use ``--`` to stop interpreting options and treat all + remaining arguments as paths, even if they start with ``-``. ``server`` Launch :manual:`cmake-server(7)` mode. diff --git a/Help/release/dev/cmcmd-end-of-options-delimiter.rst b/Help/release/dev/cmcmd-end-of-options-delimiter.rst new file mode 100644 index 0000000..bc9cc21 --- /dev/null +++ b/Help/release/dev/cmcmd-end-of-options-delimiter.rst @@ -0,0 +1,7 @@ +cmcmd-end-of-options-delimiter +------------------------------ + +* The :manual:`cmake(1)` ``-E`` commands ``cat`` and ``env`` learned to respect + a double dash (``--``) argument that acts as a delimiter indicating the end of + options. Any following arguments are treated as operands/positional arguments, + even if they begin with a dash ``-`` character. diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 32c01e5..ba61a83 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -97,7 +97,8 @@ void CMakeCommandUsage(std::string const& program) << "Available commands: \n" << " capabilities - Report capabilities built into cmake " "in JSON format\n" - << " cat <files>... - concat the files and print them to the standard output\n" + << " cat [--] <files>... - concat the files and print them to the " + "standard output\n" << " chdir dir cmd [args...] - run command in a given directory\n" << " compare_files [--ignore-eol] file1 file2\n" << " - check if file1 is same as file2\n" @@ -110,7 +111,7 @@ void CMakeCommandUsage(std::string const& program) << " echo [<string>...] - displays arguments as text\n" << " echo_append [<string>...] - displays arguments as text but no new " "line\n" - << " env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]...\n" + << " env [--unset=NAME ...] [NAME=VALUE ...] [--] <command> [<arg>...]\n" << " - run command in a modified environment\n" << " environment - display the current environment\n" << " make_directory <dir>... - create parent and <dir> directories\n" @@ -125,8 +126,9 @@ void CMakeCommandUsage(std::string const& program) << " remove_directory <dir>... - remove directories and their contents (deprecated: use rm instead)\n" << " rename oldname newname - rename a file or directory " "(on one volume)\n" - << " rm [-rRf] <file/dir>... - remove files or directories, use -f to " - "force it, r or R to remove directories and their contents recursively\n" + << " rm [-rRf] [--] <file/dir>... - remove files or directories, use -f " + "to force it, r or R to remove directories and their contents " + "recursively\n" << " sleep <number>... - sleep for given number of seconds\n" << " tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]\n" << " - create or extract a tar or zip archive\n" @@ -793,6 +795,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, auto ae = args.cend(); for (; ai != ae; ++ai) { std::string const& a = *ai; + if (a == "--") { + // Stop parsing options/environment variables; the next argument + // should be the command. + ++ai; + break; + } if (cmHasLiteralPrefix(a, "--unset=")) { // Unset environment variable. cmSystemTools::UnPutEnv(a.substr(8)); @@ -1051,9 +1059,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, // Command to concat files into one if (args[1] == "cat" && args.size() >= 3) { int return_value = 0; + bool doing_options = true; for (auto const& arg : cmMakeRange(args).advance(2)) { - if (cmHasLiteralPrefix(arg, "-")) { - if (arg != "--") { + if (doing_options && cmHasLiteralPrefix(arg, "-")) { + if (arg == "--") { + doing_options = false; + } else { cmSystemTools::Error(arg + ": option not handled"); return_value = 1; } diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 1d7e632..144f842 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -703,7 +703,8 @@ endif() add_executable(pseudo_llvm-rc pseudo_llvm-rc.c) add_RunCMake_test(CommandLine -DLLVM_RC=$<TARGET_FILE:pseudo_llvm-rc> -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} - -DCYGWIN=${CYGWIN} -DMSYS=${MSYS} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}) + -DCYGWIN=${CYGWIN} -DMSYS=${MSYS} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + -DEXIT_CODE_EXE=$<TARGET_FILE:exit_code>) add_RunCMake_test(CommandLineTar) if(CMAKE_PLATFORM_NO_VERSIONED_SONAME OR (NOT CMAKE_SHARED_LIBRARY_SONAME_FLAG AND NOT CMAKE_SHARED_LIBRARY_SONAME_C_FLAG)) diff --git a/Tests/RunCMake/CommandLine/E_cat-with-double-dash-stdout.txt b/Tests/RunCMake/CommandLine/E_cat-with-double-dash-stdout.txt new file mode 100644 index 0000000..e5939d0 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_cat-with-double-dash-stdout.txt @@ -0,0 +1 @@ +file starting with dash, not an option diff --git a/Tests/RunCMake/CommandLine/E_cat-without-double-dash-result.txt b/Tests/RunCMake/CommandLine/E_cat-without-double-dash-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_cat-without-double-dash-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_cat-without-double-dash-stderr.txt b/Tests/RunCMake/CommandLine/E_cat-without-double-dash-stderr.txt new file mode 100644 index 0000000..051f678 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_cat-without-double-dash-stderr.txt @@ -0,0 +1 @@ +^CMake Error: -file-starting-with-dash.txt: option not handled$ diff --git a/Tests/RunCMake/CommandLine/E_env-with-double-dash-result.txt b/Tests/RunCMake/CommandLine/E_env-with-double-dash-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-with-double-dash-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_env-without-double-dash-result.txt b/Tests/RunCMake/CommandLine/E_env-without-double-dash-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-without-double-dash-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_env-without-double-dash-stderr.txt b/Tests/RunCMake/CommandLine/E_env-without-double-dash-stderr.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-without-double-dash-stderr.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 033fbe6..50815a8 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -676,17 +676,33 @@ file(WRITE "${out}/empty_file.txt" "") file(WRITE "${out}/unicode_file.txt" "àéùç - 한국어") # Korean in Korean run_cmake_command(E_cat_good_cat ${CMAKE_COMMAND} -E cat "${out}/first_file.txt" "${out}/second_file.txt" "${out}/empty_file.txt" "${out}/unicode_file.txt") -unset(out) run_cmake_command(E_cat_good_binary_cat ${CMAKE_COMMAND} -E cat "${RunCMake_SOURCE_DIR}/E_cat_binary_files/binary.obj" "${RunCMake_SOURCE_DIR}/E_cat_binary_files/binary.obj") +# To test whether the double dash (--) works, we need to control the working directory +# in order to be able to pass a relative path that starts with a dash. +file(WRITE "${out}/-file-starting-with-dash.txt" "file starting with dash, not an option\n") +set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${out}") +run_cmake_command(E_cat-with-double-dash ${CMAKE_COMMAND} -E cat -- "-file-starting-with-dash.txt") +run_cmake_command(E_cat-without-double-dash ${CMAKE_COMMAND} -E cat "-file-starting-with-dash.txt") +unset(RunCMake_TEST_COMMAND_WORKING_DIRECTORY) +unset(out) + run_cmake_command(E_env-no-command0 ${CMAKE_COMMAND} -E env) run_cmake_command(E_env-no-command1 ${CMAKE_COMMAND} -E env TEST_ENV=1) run_cmake_command(E_env-bad-arg1 ${CMAKE_COMMAND} -E env -bad-arg1) run_cmake_command(E_env-set ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-set.cmake) run_cmake_command(E_env-unset ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -E env --unset=TEST_ENV ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-unset.cmake) +# To test whether the double dash (--) works for the env command, we need a command that e.g. contains an equals sign (=) +# and would normally be interpreted as an NAME=VALUE environment variable. +# Ensuring such a command is done by simply copying the trivial exit_code executable with a different name. +cmake_path(GET EXIT_CODE_EXE FILENAME exit_code) +file(COPY_FILE "${EXIT_CODE_EXE}" "${RunCMake_BINARY_DIR}/env=${exit_code}") +run_cmake_command(E_env-with-double-dash ${CMAKE_COMMAND} -E env TEST_ENV=1 -- "${RunCMake_BINARY_DIR}/env=${exit_code}" zero_exit) +run_cmake_command(E_env-without-double-dash ${CMAKE_COMMAND} -E env TEST_ENV=1 "${RunCMake_BINARY_DIR}/env=${exit_code}" zero_exit) + run_cmake_command(E_md5sum-dir ${CMAKE_COMMAND} -E md5sum .) run_cmake_command(E_sha1sum-dir ${CMAKE_COMMAND} -E sha1sum .) run_cmake_command(E_sha224sum-dir ${CMAKE_COMMAND} -E sha224sum .) |