diff options
author | Ben Boeckel <ben.boeckel@kitware.com> | 2021-03-04 16:50:10 (GMT) |
---|---|---|
committer | Ben Boeckel <ben.boeckel@kitware.com> | 2021-03-10 15:43:18 (GMT) |
commit | 088444211e942a3587f4af5ef76c3654f2562364 (patch) | |
tree | fa5bd94beead2050d900e7c2341dc27899b2733e /Source/cmFileCommand.cxx | |
parent | 100016e9cb31aad7b642a9733409c7294cd6652f (diff) | |
download | CMake-088444211e942a3587f4af5ef76c3654f2562364.zip CMake-088444211e942a3587f4af5ef76c3654f2562364.tar.gz CMake-088444211e942a3587f4af5ef76c3654f2562364.tar.bz2 |
file: add `COPY_FILE` subcommand
The `file(COPY)` subcommand is overloaded and busy for such a simple
operation. Instead, make a simpler subcommand with error handling
support.
Diffstat (limited to 'Source/cmFileCommand.cxx')
-rw-r--r-- | Source/cmFileCommand.cxx | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 065b845..1c73d0d 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -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 }, |