summaryrefslogtreecommitdiffstats
path: root/Source/cmFileCommand.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmFileCommand.cxx')
-rw-r--r--Source/cmFileCommand.cxx146
1 files changed, 139 insertions, 7 deletions
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 4a28238..a06ed48 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -1313,8 +1313,9 @@ bool HandleRelativePathCommand(std::vector<std::string> const& args,
bool HandleRename(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- if (args.size() != 3) {
- status.SetError("RENAME given incorrect number of arguments.");
+ if (args.size() < 3) {
+ status.SetError("RENAME must be called with at least two additional "
+ "arguments");
return false;
}
@@ -1330,13 +1331,143 @@ bool HandleRename(std::vector<std::string> const& args,
cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]);
}
- if (!cmSystemTools::RenameFile(oldname, newname)) {
- std::string err = cmSystemTools::GetLastSystemError();
- status.SetError(cmStrCat("RENAME failed to rename\n ", oldname,
- "\nto\n ", newname, "\nbecause: ", err, "\n"));
+ struct Arguments
+ {
+ bool NoReplace = false;
+ std::string Result;
+ };
+
+ static auto const parser = cmArgumentParser<Arguments>{}
+ .Bind("NO_REPLACE"_s, &Arguments::NoReplace)
+ .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("RENAME unknown argument:\n " + unconsumedArgs.front());
return false;
}
- return true;
+
+ std::string err;
+ switch (cmSystemTools::RenameFile(oldname, newname,
+ arguments.NoReplace
+ ? cmSystemTools::Replace::No
+ : cmSystemTools::Replace::Yes,
+ &err)) {
+ case cmSystemTools::RenameResult::Success:
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, "0");
+ }
+ return true;
+ case cmSystemTools::RenameResult::NoReplace:
+ if (!arguments.Result.empty()) {
+ err = "NO_REPLACE";
+ } else {
+ err = "path not replaced";
+ }
+ CM_FALLTHROUGH;
+ case cmSystemTools::RenameResult::Failure:
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, err);
+ return true;
+ }
+ break;
+ }
+ status.SetError(cmStrCat("RENAME failed to rename\n ", oldname, "\nto\n ",
+ newname, "\nbecause: ", err, "\n"));
+ 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,
@@ -3569,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 },