Browse Source

Merge topic 'cat_cmd_20557'

a625f30785 cmake -E: add cat command.

Acked-by: Kitware Robot <[email protected]>
Merge-request: !4600
Kyle Edwards 5 năm trước cách đây
mục cha
commit
5f20e85412

+ 3 - 0
Help/manual/cmake.1.rst

@@ -554,6 +554,9 @@ Available commands are:
   ``serverMode``
     ``true`` if cmake supports server-mode and ``false`` otherwise.
 
+``cat <files>...``
+  Concatenate files and print on the standard output.
+
 ``chdir <dir> <cmd> [<arg>...]``
   Change the current working directory and run a command.
 

+ 5 - 0
Help/release/dev/command-line-cat.rst

@@ -0,0 +1,5 @@
+Command-Line
+------------
+* :manual:`cmake(1)` gained a ``cat`` command line
+  option that can be used to concatenate files and print them
+  on standard output.

+ 35 - 0
Source/cmcmd.cxx

@@ -90,6 +90,7 @@ void CMakeCommandUsage(const char* 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"
     << "  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"
@@ -180,6 +181,13 @@ static bool cmTarFilesFrom(std::string const& file,
   return true;
 }
 
+static void cmCatFile(const std::string& fileToAppend)
+{
+  cmsys::ifstream source(fileToAppend.c_str(),
+                         (std::ios::binary | std::ios::in));
+  std::cout << source.rdbuf();
+}
+
 static bool cmRemoveDirectory(const std::string& dir, bool recursive = true)
 {
   if (cmSystemTools::FileIsSymlink(dir)) {
@@ -927,6 +935,33 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
       return HashSumFile(args, cmCryptoHash::AlgoSHA512);
     }
 
+    // Command to concat files into one
+    if (args[1] == "cat" && args.size() >= 3) {
+      int return_value = 0;
+      for (auto const& arg : cmMakeRange(args).advance(2)) {
+        if (cmHasLiteralPrefix(arg, "-")) {
+          if (arg != "--") {
+            cmSystemTools::Error(arg + ": option not handled");
+            return_value = 1;
+          }
+        } else if (!cmSystemTools::TestFileAccess(arg,
+                                                  cmsys::TEST_FILE_READ) &&
+                   cmSystemTools::TestFileAccess(arg, cmsys::TEST_FILE_OK)) {
+          cmSystemTools::Error(arg + ": permission denied (ignoring)");
+          return_value = 1;
+        } else if (cmSystemTools::FileIsDirectory(arg)) {
+          cmSystemTools::Error(arg + ": is a directory (ignoring)");
+          return_value = 1;
+        } else if (!cmSystemTools::FileExists(arg)) {
+          cmSystemTools::Error(arg + ": no such file or directory (ignoring)");
+          return_value = 1;
+        } else {
+          cmCatFile(arg);
+        }
+      }
+      return return_value;
+    }
+
     // Command to change directory and run a program.
     if (args[1] == "chdir" && args.size() >= 4) {
       std::string const& directory = args[2];

+ 1 - 0
Tests/RunCMake/CommandLine/E_cat_directory-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLine/E_cat_directory-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: .* is a directory

+ 3 - 0
Tests/RunCMake/CommandLine/E_cat_good_cat-stdout.txt

@@ -0,0 +1,3 @@
+first file to append
+second file to append
+àéùç - 한국어

+ 1 - 0
Tests/RunCMake/CommandLine/E_cat_non_existing_file-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLine/E_cat_non_existing_file-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: .*: no such file or directory \(ignoring\)

+ 1 - 0
Tests/RunCMake/CommandLine/E_cat_non_readable_file-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLine/E_cat_non_readable_file-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: .*: permission denied \(ignoring\)

+ 1 - 0
Tests/RunCMake/CommandLine/E_cat_option_not_handled-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLine/E_cat_option_not_handled-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: -f: option not handled

+ 38 - 0
Tests/RunCMake/CommandLine/RunCMakeTest.cmake

@@ -459,6 +459,44 @@ if(NOT WIN32 AND NOT CYGWIN)
 endif()
 unset(out)
 
+# cat tests
+set(out ${RunCMake_BINARY_DIR}/cat_tests)
+file(REMOVE_RECURSE "${out}")
+file(MAKE_DIRECTORY ${out})
+run_cmake_command(E_cat_non_existing_file
+  ${CMAKE_COMMAND} -E cat ${out}/non-existing-file.txt)
+
+if(UNIX)
+  # test non readable file only if not root
+  execute_process(
+    COMMAND id -u $ENV{USER}
+    OUTPUT_VARIABLE uid
+    OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+  if(NOT "${uid}" STREQUAL "0")
+    # Create non readable file
+    set(inside_folder "${out}/in")
+    file(MAKE_DIRECTORY ${inside_folder})
+    file(WRITE "${inside_folder}/non_readable_file.txt" "first file to append\n")
+    file(COPY "${inside_folder}/non_readable_file.txt" DESTINATION "${out}" FILE_PERMISSIONS OWNER_WRITE)
+    run_cmake_command(E_cat_non_readable_file
+      ${CMAKE_COMMAND} -E cat "${out}/non_readable_file.txt")
+  endif()
+endif()
+
+run_cmake_command(E_cat_option_not_handled
+  ${CMAKE_COMMAND} -E cat -f)
+
+run_cmake_command(E_cat_directory
+  ${CMAKE_COMMAND} -E cat ${out})
+
+file(WRITE "${out}/first_file.txt" "first file to append\n")
+file(WRITE "${out}/second_file.txt" "second file to append\n")
+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}/unicode_file.txt")
+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)