Hello.

Here is the patch with tests.
________________________________________
From: Brad King <brad.k...@kitware.com>
Sent: Thursday, December 3, 2015 7:07 PM
To: Bartosz Kosiorek
Cc: cmake-developers@cmake.org
Subject: Re: [cmake-developers] [PATCH] Extend copy and copy_if_different 
commands with support multiple files

On 12/03/2015 12:31 PM, Bartosz Kosiorek wrote:
> When I'm trying to run test with wildcard:
> run_cmake_command(E_copy-wildcard-source-files-target-is-directory 
> ${CMAKE_COMMAND} -E copy
>                   ${RunCMake_copy_TEST_SOURCE_DIR}/directory1/*
>                   ${RunCMake_copy_TEST_BINARY_DIR})
>
> I've got an error:

The command is not running through a shell in that case so there is
no step that expands the wildcard.  This feature is not about wildcard
expansion, but about multiple inputs to the copy.  They can be
spelled out explicitly in the command invocation, or passed through
a variable containing a list populated by file(GLOB).

-Brad

From 8225688074386ac8633bad5e6f9fdb4a7caf9775 Mon Sep 17 00:00:00 2001
From: "Bartosz Kosiorek bartosz.kosio...@tomtom.com"
 <bartosz.kosio...@tomtom.com>
Date: Thu, 3 Dec 2015 00:43:37 +0100
Subject: [PATCH 1/2] Extend copy and copy_if_different command with support
 multiple files

This patch allows to use multiple files in command copy and copy_if_different.
Input files could be merged with wildcards.
If multipile input files were provided, then destination must be directory.
If only one input file was provided, then destination could be either
file or directory. This path is starting point for fixing bug 15703
---
 Help/manual/cmake.1.rst | 12 ++++----
 Source/cmcmd.cxx        | 73 +++++++++++++++++++++++++++++++++++--------------
 2 files changed, 58 insertions(+), 27 deletions(-)

diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index dac16bf..086f259 100644
--- a/Help/manual/cmake.1.rst
+++ b/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.
@@ -193,10 +193,10 @@ Available commands are:
 ``make_directory <dir>``
   Create a directory.
 
-``md5sum [<file>...]``
+``md5sum <file>...``
   Compute md5sum of files.
 
-``remove [-f] [<file>...]``
+``remove [-f] <file>...``
   Remove the file(s), use ``-f`` to force it.
 
 ``remove_directory <dir>``
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 21b126b..0dc5a9a 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -52,25 +52,25 @@ void CMakeCommandUsage(const char* program)
   // If you add new commands, change here,
   // and in cmakemain.cxx in the options table
   errorStream
-    << "Usage: " << program << " -E [command] [arguments ...]\n"
+    << "Usage: " << program << " -E <command> [arguments...]\n"
     << "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 "
+    << "  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"
     << "                            - run command in a modified environment\n"
     << "  environment               - display the current environment\n"
     << "  make_directory dir        - create a directory\n"
-    << "  md5sum file1 [...]        - compute md5sum of files\n"
-    << "  remove [-f] file1 file2 ... - remove the file(s), use -f to force "
+    << "  md5sum <file>...          - compute md5sum of files\n"
+    << "  remove [-f] <file>...     - remove the file(s), use -f to force "
        "it\n"
     << "  remove_directory dir      - remove a directory and its contents\n"
     << "  rename oldname newname    - rename a file or directory "
@@ -78,7 +78,7 @@ void CMakeCommandUsage(const char* program)
     << "  tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]\n"
     << "                            - create or extract a tar or zip archive\n"
     << "  sleep <number>...         - sleep for given number of seconds\n"
-    << "  time command [args] ...   - run command and return elapsed time\n"
+    << "  time command [args...]    - run command and return elapsed time\n"
     << "  touch file                - touch a file.\n"
     << "  touch_nocreate file       - touch a file but do not create it.\n"
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -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
-- 
2.5.0

From 3774ba18d8e193b68685c84f4ccb0b0e4ea2b5a9 Mon Sep 17 00:00:00 2001
From: "Bartosz Kosiorek bartosz.kosio...@tomtom.com"
 <bartosz.kosio...@tomtom.com>
Date: Thu, 3 Dec 2015 21:29:30 +0100
Subject: [PATCH 2/2] Add unit tests for "copy" and "copy_if_different"
 commands

---
 ...source-directory-target-is-directory-result.txt |  1 +
 ...source-directory-target-is-directory-stderr.txt |  0
 .../CommandLine/E_copy-one-source-file-result.txt  |  1 +
 .../CommandLine/E_copy-one-source-file-stderr.txt  |  1 +
 ...ree-source-files-target-is-directory-result.txt |  1 +
 ...ree-source-files-target-is-directory-stderr.txt |  0
 ...py-three-source-files-target-is-file-result.txt |  1 +
 ...py-three-source-files-target-is-file-stderr.txt |  1 +
 ...bad-source-files-target-is-directory-result.txt |  1 +
 ...bad-source-files-target-is-directory-stderr.txt |  1 +
 ...source-directory-target-is-directory-result.txt |  1 +
 ...source-directory-target-is-directory-stderr.txt |  0
 ...ree-source-files-target-is-directory-result.txt |  1 +
 ...ree-source-files-target-is-directory-stderr.txt |  0
 ...nt-three-source-files-target-is-file-result.txt |  1 +
 ...nt-three-source-files-target-is-file-stderr.txt |  1 +
 Tests/RunCMake/CommandLine/RunCMakeTest.cmake      | 44 ++++++++++++++++++++++
 .../CommandLine/test_copy_command_dir/file1.txt    |  0
 .../CommandLine/test_copy_command_dir/file2.txt    |  0
 .../CommandLine/test_copy_command_dir/file3.txt    |  0
 20 files changed, 56 insertions(+)
 create mode 100644 Tests/RunCMake/CommandLine/E_copy-one-source-directory-target-is-directory-result.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy-one-source-directory-target-is-directory-stderr.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy-one-source-file-result.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy-one-source-file-stderr.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-directory-result.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-directory-stderr.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-result.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-stderr.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy-two-good-and-one-bad-source-files-target-is-directory-result.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy-two-good-and-one-bad-source-files-target-is-directory-stderr.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy_if_different-one-source-directory-target-is-directory-result.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy_if_different-one-source-directory-target-is-directory-stderr.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-directory-result.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-directory-stderr.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-result.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-stderr.txt
 create mode 100644 Tests/RunCMake/CommandLine/test_copy_command_dir/file1.txt
 create mode 100644 Tests/RunCMake/CommandLine/test_copy_command_dir/file2.txt
 create mode 100644 Tests/RunCMake/CommandLine/test_copy_command_dir/file3.txt

diff --git a/Tests/RunCMake/CommandLine/E_copy-one-source-directory-target-is-directory-result.txt b/Tests/RunCMake/CommandLine/E_copy-one-source-directory-target-is-directory-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy-one-source-directory-target-is-directory-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/E_copy-one-source-directory-target-is-directory-stderr.txt b/Tests/RunCMake/CommandLine/E_copy-one-source-directory-target-is-directory-stderr.txt
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/RunCMake/CommandLine/E_copy-one-source-file-result.txt b/Tests/RunCMake/CommandLine/E_copy-one-source-file-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy-one-source-file-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_copy-one-source-file-stderr.txt b/Tests/RunCMake/CommandLine/E_copy-one-source-file-stderr.txt
new file mode 100644
index 0000000..9a9301d
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy-one-source-file-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: .*
diff --git a/Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-directory-result.txt b/Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-directory-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-directory-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-directory-stderr.txt b/Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-directory-stderr.txt
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-result.txt b/Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-stderr.txt b/Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-stderr.txt
new file mode 100644
index 0000000..2e23d0a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy-three-source-files-target-is-file-stderr.txt
@@ -0,0 +1 @@
+^Error: Target \(copy\).* is not a directory.$
diff --git a/Tests/RunCMake/CommandLine/E_copy-two-good-and-one-bad-source-files-target-is-directory-result.txt b/Tests/RunCMake/CommandLine/E_copy-two-good-and-one-bad-source-files-target-is-directory-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy-two-good-and-one-bad-source-files-target-is-directory-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_copy-two-good-and-one-bad-source-files-target-is-directory-stderr.txt b/Tests/RunCMake/CommandLine/E_copy-two-good-and-one-bad-source-files-target-is-directory-stderr.txt
new file mode 100644
index 0000000..2d0d986
--- /dev/null
+++ b/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 .*
diff --git a/Tests/RunCMake/CommandLine/E_copy_if_different-one-source-directory-target-is-directory-result.txt b/Tests/RunCMake/CommandLine/E_copy_if_different-one-source-directory-target-is-directory-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy_if_different-one-source-directory-target-is-directory-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/E_copy_if_different-one-source-directory-target-is-directory-stderr.txt b/Tests/RunCMake/CommandLine/E_copy_if_different-one-source-directory-target-is-directory-stderr.txt
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-directory-result.txt b/Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-directory-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-directory-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-directory-stderr.txt b/Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-directory-stderr.txt
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-result.txt b/Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-stderr.txt b/Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-stderr.txt
new file mode 100644
index 0000000..fe20f8c
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_copy_if_different-three-source-files-target-is-file-stderr.txt
@@ -0,0 +1 @@
+^Error: Target \(copy_if_different\).* is not a directory.$
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 6b4b384..1fffa46 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -101,6 +101,50 @@ if(UNIX)
     )
 endif()
 
+set(RunCMake_copy_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/test_copy_command_dir)
+set(RunCMake_copy_TEST_SOURCE_DIR ${RunCMake_SOURCE_DIR}/test_copy_command_dir)
+run_cmake_command(E_copy-one-source-file ${CMAKE_COMMAND} -E copy
+  ${RunCMake_copy_TEST_BINARY_DIR}/file1.txt)
+run_cmake_command(E_copy-one-source-directory-target-is-directory
+  ${CMAKE_COMMAND} -E copy
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file1.txt
+  ${RunCMake_copy_TEST_BINARY_DIR})
+run_cmake_command(E_copy-three-source-files-target-is-directory
+  ${CMAKE_COMMAND} -E copy
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file1.txt
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file2.txt
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file3.txt
+  ${RunCMake_copy_TEST_BINARY_DIR})
+run_cmake_command(E_copy-three-source-files-target-is-file
+  ${CMAKE_COMMAND} -E copy
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file1.txt
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file2.txt
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file3.txt
+  ${RunCMake_copy_TEST_BINARY_DIR}/file1.txt)
+run_cmake_command(E_copy-two-good-and-one-bad-source-files-target-is-directory
+  ${CMAKE_COMMAND} -E copy
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file1.txt
+  ${RunCMake_copy_TEST_SOURCE_DIR}/not_existing_file.bad
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file3.txt
+  ${RunCMake_copy_TEST_BINARY_DIR})
+
+run_cmake_command(E_copy_if_different-one-source-directory-target-is-directory
+  ${CMAKE_COMMAND} -E copy_if_different
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file1.txt
+  ${RunCMake_copy_TEST_BINARY_DIR})
+run_cmake_command(E_copy_if_different-three-source-files-target-is-directory
+  ${CMAKE_COMMAND} -E copy_if_different
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file1.txt
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file2.txt
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file3.txt
+  ${RunCMake_copy_TEST_BINARY_DIR})
+run_cmake_command(E_copy_if_different-three-source-files-target-is-file
+  ${CMAKE_COMMAND} -E copy_if_different
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file1.txt
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file2.txt
+  ${RunCMake_copy_TEST_SOURCE_DIR}/file3.txt
+  ${RunCMake_copy_TEST_BINARY_DIR}/file1.txt)
+
 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)
diff --git a/Tests/RunCMake/CommandLine/test_copy_command_dir/file1.txt b/Tests/RunCMake/CommandLine/test_copy_command_dir/file1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/RunCMake/CommandLine/test_copy_command_dir/file2.txt b/Tests/RunCMake/CommandLine/test_copy_command_dir/file2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/RunCMake/CommandLine/test_copy_command_dir/file3.txt b/Tests/RunCMake/CommandLine/test_copy_command_dir/file3.txt
new file mode 100644
index 0000000..e69de29
-- 
2.5.0

-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake-developers

Reply via email to