mirror of
https://github.com/Kitware/CMake.git
synced 2026-04-24 07:08:38 -05:00
Merge topic 'file-COPY_FILE-subcommand'
088444211efile: add `COPY_FILE` subcommand100016e9cbcmSystemTools: add utilities to copy a file with error handling Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !5885
This commit is contained in:
@@ -1379,6 +1379,97 @@ bool HandleRename(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HandleCopyFile(std::vector<std::string> const& args,
|
||||
cmExecutionStatus& status)
|
||||
{
|
||||
if (args.size() < 3) {
|
||||
status.SetError("COPY_FILE must be called with at least two additional "
|
||||
"arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute full path for old and new names.
|
||||
std::string oldname = args[1];
|
||||
if (!cmsys::SystemTools::FileIsFullPath(oldname)) {
|
||||
oldname =
|
||||
cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]);
|
||||
}
|
||||
std::string newname = args[2];
|
||||
if (!cmsys::SystemTools::FileIsFullPath(newname)) {
|
||||
newname =
|
||||
cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]);
|
||||
}
|
||||
|
||||
struct Arguments
|
||||
{
|
||||
bool OnlyIfDifferent = false;
|
||||
std::string Result;
|
||||
};
|
||||
|
||||
static auto const parser =
|
||||
cmArgumentParser<Arguments>{}
|
||||
.Bind("ONLY_IF_DIFFERENT"_s, &Arguments::OnlyIfDifferent)
|
||||
.Bind("RESULT"_s, &Arguments::Result);
|
||||
|
||||
std::vector<std::string> unconsumedArgs;
|
||||
Arguments const arguments =
|
||||
parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs);
|
||||
if (!unconsumedArgs.empty()) {
|
||||
status.SetError("COPY_FILE unknown argument:\n " +
|
||||
unconsumedArgs.front());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
if (cmsys::SystemTools::FileIsDirectory(oldname)) {
|
||||
if (!arguments.Result.empty()) {
|
||||
status.GetMakefile().AddDefinition(arguments.Result,
|
||||
"cannot copy a directory");
|
||||
} else {
|
||||
status.SetError(
|
||||
cmStrCat("COPY_FILE cannot copy a directory\n ", oldname));
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (cmsys::SystemTools::FileIsDirectory(newname)) {
|
||||
if (!arguments.Result.empty()) {
|
||||
status.GetMakefile().AddDefinition(arguments.Result,
|
||||
"cannot copy to a directory");
|
||||
} else {
|
||||
status.SetError(
|
||||
cmStrCat("COPY_FILE cannot copy to a directory\n ", newname));
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
cmSystemTools::CopyWhen when;
|
||||
if (arguments.OnlyIfDifferent) {
|
||||
when = cmSystemTools::CopyWhen::OnlyIfDifferent;
|
||||
} else {
|
||||
when = cmSystemTools::CopyWhen::Always;
|
||||
}
|
||||
|
||||
std::string err;
|
||||
if (cmSystemTools::CopySingleFile(oldname, newname, when, &err) ==
|
||||
cmSystemTools::CopyResult::Success) {
|
||||
if (!arguments.Result.empty()) {
|
||||
status.GetMakefile().AddDefinition(arguments.Result, "0");
|
||||
}
|
||||
} else {
|
||||
if (!arguments.Result.empty()) {
|
||||
status.GetMakefile().AddDefinition(arguments.Result, err);
|
||||
} else {
|
||||
status.SetError(cmStrCat("COPY_FILE failed to copy\n ", oldname,
|
||||
"\nto\n ", newname, "\nbecause: ", err, "\n"));
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool HandleRemoveImpl(std::vector<std::string> const& args, bool recurse,
|
||||
cmExecutionStatus& status)
|
||||
{
|
||||
@@ -3609,6 +3700,7 @@ bool cmFileCommand(std::vector<std::string> const& args,
|
||||
{ "GLOB_RECURSE"_s, HandleGlobRecurseCommand },
|
||||
{ "MAKE_DIRECTORY"_s, HandleMakeDirectoryCommand },
|
||||
{ "RENAME"_s, HandleRename },
|
||||
{ "COPY_FILE"_s, HandleCopyFile },
|
||||
{ "REMOVE"_s, HandleRemove },
|
||||
{ "REMOVE_RECURSE"_s, HandleRemoveRecurse },
|
||||
{ "COPY"_s, HandleCopyCommand },
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
# include <unistd.h>
|
||||
|
||||
# include <sys/time.h>
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && \
|
||||
@@ -990,6 +991,51 @@ bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname,
|
||||
}
|
||||
#endif
|
||||
|
||||
bool cmSystemTools::CopySingleFile(const std::string& oldname,
|
||||
const std::string& newname)
|
||||
{
|
||||
return cmSystemTools::CopySingleFile(oldname, newname, CopyWhen::Always) ==
|
||||
CopyResult::Success;
|
||||
}
|
||||
|
||||
cmSystemTools::CopyResult cmSystemTools::CopySingleFile(
|
||||
std::string const& oldname, std::string const& newname, CopyWhen when,
|
||||
std::string* err)
|
||||
{
|
||||
switch (when) {
|
||||
case CopyWhen::Always:
|
||||
break;
|
||||
case CopyWhen::OnlyIfDifferent:
|
||||
if (!FilesDiffer(oldname, newname)) {
|
||||
return CopyResult::Success;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
mode_t perm = 0;
|
||||
bool perms = SystemTools::GetPermissions(oldname, perm);
|
||||
|
||||
// If files are the same do not copy
|
||||
if (SystemTools::SameFile(oldname, newname)) {
|
||||
return CopyResult::Success;
|
||||
}
|
||||
|
||||
if (!cmsys::SystemTools::CloneFileContent(oldname, newname)) {
|
||||
// if cloning did not succeed, fall back to blockwise copy
|
||||
if (!cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname)) {
|
||||
ReportError(err);
|
||||
return CopyResult::Failure;
|
||||
}
|
||||
}
|
||||
if (perms) {
|
||||
if (!SystemTools::SetPermissions(newname, perm)) {
|
||||
ReportError(err);
|
||||
return CopyResult::Failure;
|
||||
}
|
||||
}
|
||||
return CopyResult::Success;
|
||||
}
|
||||
|
||||
bool cmSystemTools::RenameFile(const std::string& oldname,
|
||||
const std::string& newname)
|
||||
{
|
||||
|
||||
@@ -128,6 +128,24 @@ public:
|
||||
static bool SimpleGlob(const std::string& glob,
|
||||
std::vector<std::string>& files, int type = 0);
|
||||
|
||||
enum class CopyWhen
|
||||
{
|
||||
Always,
|
||||
OnlyIfDifferent,
|
||||
};
|
||||
enum class CopyResult
|
||||
{
|
||||
Success,
|
||||
Failure,
|
||||
};
|
||||
|
||||
/** Copy a file. */
|
||||
static bool CopySingleFile(const std::string& oldname,
|
||||
const std::string& newname);
|
||||
static CopyResult CopySingleFile(std::string const& oldname,
|
||||
std::string const& newname, CopyWhen when,
|
||||
std::string* err = nullptr);
|
||||
|
||||
enum class Replace
|
||||
{
|
||||
Yes,
|
||||
|
||||
Reference in New Issue
Block a user