Kaynağa Gözat

cmake: Teach -E copy[_if_different] to support multiple files (#15703)

If multiple input files are provided then the destination must be a
directory.  If only one input file is provided then destination may be
either a file or directory.
Bartosz Kosiorek 10 yıl önce
ebeveyn
işleme
384ae5514e
23 değiştirilmiş dosya ile 90 ekleme ve 19 silme
  1. 4 4
      Help/manual/cmake.1.rst
  2. 5 0
      Help/release/dev/cmake-E-copy-multiple-inputs.rst
  3. 46 15
      Source/cmcmd.cxx
  4. 1 0
      Tests/RunCMake/CommandLine/E_copy-one-source-directory-target-is-directory-result.txt
  5. 0 0
      Tests/RunCMake/CommandLine/E_copy-one-source-directory-target-is-directory-stderr.txt
  6. 1 0
      Tests/RunCMake/CommandLine/E_copy-one-source-file-result.txt
  7. 1 0
      Tests/RunCMake/CommandLine/E_copy-one-source-file-stderr.txt
  8. 1 0
      Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-directory-result.txt
  9. 0 0
      Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-directory-stderr.txt
  10. 1 0
      Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-result.txt
  11. 1 0
      Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-stderr.txt
  12. 1 0
      Tests/RunCMake/CommandLine/E_copy-two-good-and-one-bad-source-files-target-is-directory-result.txt
  13. 1 0
      Tests/RunCMake/CommandLine/E_copy-two-good-and-one-bad-source-files-target-is-directory-stderr.txt
  14. 1 0
      Tests/RunCMake/CommandLine/E_copy_if_different-one-source-directory-target-is-directory-result.txt
  15. 0 0
      Tests/RunCMake/CommandLine/E_copy_if_different-one-source-directory-target-is-directory-stderr.txt
  16. 1 0
      Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-directory-result.txt
  17. 0 0
      Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-directory-stderr.txt
  18. 1 0
      Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-result.txt
  19. 1 0
      Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-stderr.txt
  20. 23 0
      Tests/RunCMake/CommandLine/RunCMakeTest.cmake
  21. 0 0
      Tests/RunCMake/CommandLine/copy_input/f1.txt
  22. 0 0
      Tests/RunCMake/CommandLine/copy_input/f2.txt
  23. 0 0
      Tests/RunCMake/CommandLine/copy_input/f3.txt

+ 4 - 4
Help/manual/cmake.1.rst

@@ -169,14 +169,14 @@ Available commands are:
 ``compare_files <file1> <file2>``
   Check if file1 is same as file2.
 
-``copy <file> <destination>``
-  Copy file to destination (either file or directory).
+``copy <file>... <destination>``
+  Copy files to 'destination' (either file or directory).
 
 ``copy_directory <source> <destination>``
   Copy directory 'source' content to directory 'destination'.
 
-``copy_if_different <in-file> <out-file>``
-  Copy file if input has changed.
+``copy_if_different <file>... <destination>``
+  Copy files if input has changed. Destination could be file or directory.
 
 ``echo [<string>...]``
   Displays arguments as text.

+ 5 - 0
Help/release/dev/cmake-E-copy-multiple-inputs.rst

@@ -0,0 +1,5 @@
+cmake-E-copy-multiple-inputs
+----------------------------
+
+* The :manual:`cmake(1)` ``-E copy`` and ``-E copy_if_different`` command-line
+  tools learned to support copying multiple input files to a directory.

+ 46 - 15
Source/cmcmd.cxx

@@ -56,11 +56,11 @@ void CMakeCommandUsage(const char* program)
     << "Available commands: \n"
     << "  chdir dir cmd [args]...   - run command in a given directory\n"
     << "  compare_files file1 file2 - check if file1 is same as file2\n"
-    << "  copy file destination     - copy file to destination (either file "
-       "or directory)\n"
+    << "  copy <file>... destination  - copy files to destination "
+       "(either file or directory)\n"
     << "  copy_directory source destination   - copy directory 'source' "
        "content to directory 'destination'\n"
-    << "  copy_if_different in-file out-file  - copy file if input has "
+    << "  copy_if_different <file>... destination  - copy files if it has "
        "changed\n"
     << "  echo [<string>...]        - displays arguments as text\n"
     << "  echo_append [<string>...] - displays arguments as text but no new "
@@ -149,29 +149,60 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
   if (args.size() > 1)
     {
     // Copy file
-    if (args[1] == "copy" && args.size() == 4)
+    if (args[1] == "copy" && args.size() > 3)
       {
-      if(!cmSystemTools::cmCopyFile(args[2].c_str(), args[3].c_str()))
+      // If multiple source files specified,
+      // then destination must be directory
+      if ((args.size() > 4) &&
+          (!cmSystemTools::FileIsDirectory(args[args.size() - 1])))
         {
-        std::cerr << "Error copying file \"" << args[2]
-                  << "\" to \"" << args[3] << "\".\n";
+        std::cerr << "Error: Target (for copy command) \""
+                  << args[args.size() - 1]
+                  << "\" is not a directory.\n";
         return 1;
         }
-      return 0;
+      // If error occurs we want to continue copying next files.
+      bool return_value = 0;
+      for (std::string::size_type cc = 2; cc < args.size() - 1; cc ++)
+        {
+        if(!cmSystemTools::cmCopyFile(args[cc].c_str(),
+            args[args.size() - 1].c_str()))
+          {
+          std::cerr << "Error copying file \"" << args[cc]
+                    << "\" to \"" << args[args.size() - 1] << "\".\n";
+          return_value = 1;
+          }
+        }
+      return return_value;
       }
 
     // Copy file if different.
-    if (args[1] == "copy_if_different" && args.size() == 4)
+    if (args[1] == "copy_if_different" && args.size() > 3)
       {
-      if(!cmSystemTools::CopyFileIfDifferent(args[2].c_str(),
-          args[3].c_str()))
+      // If multiple source files specified,
+      // then destination must be directory
+      if ((args.size() > 4) &&
+          (!cmSystemTools::FileIsDirectory(args[args.size() - 1])))
         {
-        std::cerr << "Error copying file (if different) from \""
-                  << args[2] << "\" to \"" << args[3]
-                  << "\".\n";
+        std::cerr << "Error: Target (for copy_if_different command) \""
+                  << args[args.size() - 1]
+                  << "\" is not a directory.\n";
         return 1;
         }
-      return 0;
+      // If error occurs we want to continue copying next files.
+      bool return_value = 0;
+      for (std::string::size_type cc = 2; cc < args.size() - 1; cc ++)
+        {
+        if(!cmSystemTools::CopyFileIfDifferent(args[cc].c_str(),
+            args[args.size() - 1].c_str()))
+          {
+          std::cerr << "Error copying file (if different) from \""
+                     << args[cc] << "\" to \"" << args[args.size() - 1]
+                     << "\".\n";
+          return_value = 1;
+          }
+        }
+      return return_value;
       }
 
     // Copy directory content

+ 1 - 0
Tests/RunCMake/CommandLine/E_copy-one-source-directory-target-is-directory-result.txt

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

+ 0 - 0
Tests/RunCMake/CommandLine/E_copy-one-source-directory-target-is-directory-stderr.txt


+ 1 - 0
Tests/RunCMake/CommandLine/E_copy-one-source-file-result.txt

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

+ 1 - 0
Tests/RunCMake/CommandLine/E_copy-one-source-file-stderr.txt

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

+ 1 - 0
Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-directory-result.txt

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

+ 0 - 0
Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-directory-stderr.txt


+ 1 - 0
Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-result.txt

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

+ 1 - 0
Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-stderr.txt

@@ -0,0 +1 @@
+^Error: Target \(for copy command\).* is not a directory.$

+ 1 - 0
Tests/RunCMake/CommandLine/E_copy-two-good-and-one-bad-source-files-target-is-directory-result.txt

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

+ 1 - 0
Tests/RunCMake/CommandLine/E_copy-two-good-and-one-bad-source-files-target-is-directory-stderr.txt

@@ -0,0 +1 @@
+^Error copying file .*not_existing_file.bad\" to .*

+ 1 - 0
Tests/RunCMake/CommandLine/E_copy_if_different-one-source-directory-target-is-directory-result.txt

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

+ 0 - 0
Tests/RunCMake/CommandLine/E_copy_if_different-one-source-directory-target-is-directory-stderr.txt


+ 1 - 0
Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-directory-result.txt

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

+ 0 - 0
Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-directory-stderr.txt


+ 1 - 0
Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-result.txt

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

+ 1 - 0
Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-stderr.txt

@@ -0,0 +1 @@
+^Error: Target \(for copy_if_different command\).* is not a directory.$

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

@@ -101,6 +101,29 @@ if(UNIX)
     )
 endif()
 
+set(in ${RunCMake_SOURCE_DIR}/copy_input)
+set(out ${RunCMake_BINARY_DIR}/copy_output)
+file(REMOVE_RECURSE "${out}")
+file(MAKE_DIRECTORY ${out})
+run_cmake_command(E_copy-one-source-file
+  ${CMAKE_COMMAND} -E copy ${out}/f1.txt)
+run_cmake_command(E_copy-one-source-directory-target-is-directory
+  ${CMAKE_COMMAND} -E copy ${in}/f1.txt ${out})
+run_cmake_command(E_copy-three-source-files-target-is-directory
+  ${CMAKE_COMMAND} -E copy ${in}/f1.txt ${in}/f2.txt ${in}/f3.txt ${out})
+run_cmake_command(E_copy-three-source-files-target-is-file
+  ${CMAKE_COMMAND} -E copy ${in}/f1.txt ${in}/f2.txt ${in}/f3.txt ${out}/f1.txt)
+run_cmake_command(E_copy-two-good-and-one-bad-source-files-target-is-directory
+  ${CMAKE_COMMAND} -E copy ${in}/f1.txt ${in}/not_existing_file.bad ${in}/f3.txt ${out})
+run_cmake_command(E_copy_if_different-one-source-directory-target-is-directory
+  ${CMAKE_COMMAND} -E copy_if_different ${in}/f1.txt ${out})
+run_cmake_command(E_copy_if_different-three-source-files-target-is-directory
+  ${CMAKE_COMMAND} -E copy_if_different ${in}/f1.txt ${in}/f2.txt ${in}/f3.txt ${out})
+run_cmake_command(E_copy_if_different-three-source-files-target-is-file
+  ${CMAKE_COMMAND} -E copy_if_different ${in}/f1.txt ${in}/f2.txt ${in}/f3.txt ${out}/f1.txt)
+unset(in)
+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)

+ 0 - 0
Tests/RunCMake/CommandLine/copy_input/f1.txt


+ 0 - 0
Tests/RunCMake/CommandLine/copy_input/f2.txt


+ 0 - 0
Tests/RunCMake/CommandLine/copy_input/f3.txt