Merge topic 'file-COPY_FILE-subcommand'

088444211e file: add `COPY_FILE` subcommand
100016e9cb cmSystemTools: add utilities to copy a file with error handling

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !5885
This commit is contained in:
Brad King
2021-03-11 13:13:21 +00:00
committed by Kitware Robot
35 changed files with 334 additions and 0 deletions
+92
View File
@@ -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 },
+46
View File
@@ -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)
{
+18
View File
@@ -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,