parent
f8107e7c6b
commit
8d9069e5b6
@ -848,17 +848,21 @@ Available commands are:
|
||||
|
||||
.. program:: cmake-E
|
||||
|
||||
.. option:: copy <file>... <destination>
|
||||
.. option:: copy <file>... <destination>, copy -t <destination> <file>...
|
||||
|
||||
Copy files to ``<destination>`` (either file or directory).
|
||||
If multiple files are specified, the ``<destination>`` must be
|
||||
directory and it must exist. Wildcards are not supported.
|
||||
``copy`` does follow symlinks. That means it does not copy symlinks,
|
||||
but the files or directories it point to.
|
||||
If multiple files are specified, or if ``-t`` is specified, the
|
||||
``<destination>`` must be directory and it must exist. If ``-t`` is not
|
||||
specified, the last argument is assumed to be the ``<destination>``.
|
||||
Wildcards are not supported. ``copy`` does follow symlinks. That means it
|
||||
does not copy symlinks, but the files or directories it point to.
|
||||
|
||||
.. versionadded:: 3.5
|
||||
Support for multiple input files.
|
||||
|
||||
.. versionadded:: 3.26
|
||||
Support for ``-t`` argument.
|
||||
|
||||
.. option:: copy_directory <dir>... <destination>
|
||||
|
||||
Copy content of ``<dir>...`` directories to ``<destination>`` directory.
|
||||
|
4
Help/release/dev/cmake-E-copy-t-arg.rst
Normal file
4
Help/release/dev/cmake-E-copy-t-arg.rst
Normal file
@ -0,0 +1,4 @@
|
||||
cmake-E-copy-t-arg
|
||||
------------------
|
||||
|
||||
* The :option:`cmake -E copy <cmake-E copy>` argument now supports a ``-t`` argument.
|
@ -2,6 +2,8 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include <cm/optional>
|
||||
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
@ -250,6 +252,15 @@ private:
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
static std::function<bool(const std::string&, CallState...)>
|
||||
generateSetToValue(cm::optional<std::string>& value1)
|
||||
{
|
||||
return [&value1](const std::string& arg, CallState&&...) -> bool {
|
||||
value1 = arg;
|
||||
return true;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
std::string extract_single_value(std::string const& input,
|
||||
|
@ -2,11 +2,15 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmcmd.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cmext/algorithm>
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "cmCommandLineArgument.h"
|
||||
#include "cmConsoleBuf.h"
|
||||
#include "cmDuration.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
@ -640,20 +644,59 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
|
||||
if (args.size() > 1) {
|
||||
// Copy file
|
||||
if (args[1] == "copy" && args.size() > 3) {
|
||||
using CommandArgument =
|
||||
cmCommandLineArgument<bool(const std::string& value)>;
|
||||
|
||||
cm::optional<std::string> targetArg;
|
||||
std::vector<CommandArgument> argParsers{
|
||||
{ "-t", CommandArgument::Values::One,
|
||||
CommandArgument::setToValue(targetArg) },
|
||||
};
|
||||
|
||||
std::vector<std::string> files;
|
||||
for (decltype(args.size()) i = 2; i < args.size(); i++) {
|
||||
const std::string& arg = args[i];
|
||||
bool matched = false;
|
||||
for (auto const& m : argParsers) {
|
||||
if (m.matches(arg)) {
|
||||
matched = true;
|
||||
if (m.parse(arg, i, args)) {
|
||||
break;
|
||||
}
|
||||
return 1; // failed to parse
|
||||
}
|
||||
}
|
||||
if (!matched) {
|
||||
files.push_back(arg);
|
||||
}
|
||||
}
|
||||
|
||||
// If multiple source files specified,
|
||||
// then destination must be directory
|
||||
if ((args.size() > 4) &&
|
||||
(!cmSystemTools::FileIsDirectory(args.back()))) {
|
||||
std::cerr << "Error: Target (for copy command) \"" << args.back()
|
||||
if (files.size() > 2 && !targetArg) {
|
||||
targetArg = files.back();
|
||||
files.pop_back();
|
||||
}
|
||||
if (targetArg && (!cmSystemTools::FileIsDirectory(*targetArg))) {
|
||||
std::cerr << "Error: Target (for copy command) \"" << *targetArg
|
||||
<< "\" is not a directory.\n";
|
||||
return 1;
|
||||
}
|
||||
if (!targetArg) {
|
||||
if (files.size() < 2) {
|
||||
std::cerr
|
||||
<< "Error: No files or target specified (for copy command).\n";
|
||||
return 1;
|
||||
}
|
||||
targetArg = files.back();
|
||||
files.pop_back();
|
||||
}
|
||||
// If error occurs we want to continue copying next files.
|
||||
bool return_value = false;
|
||||
for (auto const& arg : cmMakeRange(args).advance(2).retreat(1)) {
|
||||
if (!cmsys::SystemTools::CopyFileAlways(arg, args.back())) {
|
||||
std::cerr << "Error copying file \"" << arg << "\" to \""
|
||||
<< args.back() << "\".\n";
|
||||
for (auto const& file : files) {
|
||||
if (!cmsys::SystemTools::CopyFileAlways(file, *targetArg)) {
|
||||
std::cerr << "Error copying file \"" << file << "\" to \""
|
||||
<< *targetArg << "\".\n";
|
||||
return_value = true;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1 @@
|
||||
^Error: Target \(for copy command\).* is not a directory.$
|
@ -574,6 +574,12 @@ 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-t-argument
|
||||
${CMAKE_COMMAND} -E copy ${in}/f1.txt -t ${out} ${in}/f3.txt)
|
||||
run_cmake_command(E_copy-t-argument-target-is-file
|
||||
${CMAKE_COMMAND} -E copy ${in}/f1.txt -t ${out}/f1.txt ${in}/f3.txt)
|
||||
run_cmake_command(E_copy-t-argument-no-source-files
|
||||
${CMAKE_COMMAND} -E copy -t ${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
|
||||
|
Loading…
Reference in New Issue
Block a user