diff options
Diffstat (limited to 'Source')
| -rw-r--r-- | Source/cmFileCommand.cxx | 8 | ||||
| -rw-r--r-- | Source/cmSystemTools.cxx | 19 | ||||
| -rw-r--r-- | Source/cmSystemTools.h | 6 |
3 files changed, 31 insertions, 2 deletions
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 85f528d..cdd0408 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1408,12 +1408,14 @@ bool HandleCopyFile(std::vector<std::string> const& args, struct Arguments { + bool InputMayBeRecent = false; bool OnlyIfDifferent = false; std::string Result; }; static auto const parser = cmArgumentParser<Arguments>{} + .Bind("INPUT_MAY_BE_RECENT"_s, &Arguments::InputMayBeRecent) .Bind("ONLY_IF_DIFFERENT"_s, &Arguments::OnlyIfDifferent) .Bind("RESULT"_s, &Arguments::Result); @@ -1456,9 +1458,13 @@ bool HandleCopyFile(std::vector<std::string> const& args, } else { when = cmSystemTools::CopyWhen::Always; } + cmSystemTools::CopyInputRecent const inputRecent = arguments.InputMayBeRecent + ? cmSystemTools::CopyInputRecent::Yes + : cmSystemTools::CopyInputRecent::No; std::string err; - if (cmSystemTools::CopySingleFile(oldname, newname, when, &err) == + if (cmSystemTools::CopySingleFile(oldname, newname, when, inputRecent, + &err) == cmSystemTools::CopyResult::Success) { if (!arguments.Result.empty()) { status.GetMakefile().AddDefinition(arguments.Result, "0"); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 75b7668..f94c4d3 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1113,7 +1113,7 @@ bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname, cmSystemTools::CopyResult cmSystemTools::CopySingleFile( std::string const& oldname, std::string const& newname, CopyWhen when, - std::string* err) + CopyInputRecent inputRecent, std::string* err) { switch (when) { case CopyWhen::Always: @@ -1137,7 +1137,24 @@ cmSystemTools::CopyResult cmSystemTools::CopySingleFile( status = cmsys::SystemTools::CloneFileContent(oldname, newname); if (!status) { // if cloning did not succeed, fall back to blockwise copy +#ifdef _WIN32 + if (inputRecent == CopyInputRecent::Yes) { + // Windows sometimes locks a file immediately after creation. + // Retry a few times. + WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry(); + while ((status = + cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname), + status.Path == cmsys::SystemTools::CopyStatus::SourcePath && + status.GetPOSIX() == EACCES && --retry.Count)) { + cmSystemTools::Delay(retry.Delay); + } + } else { + status = cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname); + } +#else + static_cast<void>(inputRecent); status = cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname); +#endif } if (!status) { if (err) { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index f2b3dd2..09f2bf0 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -149,6 +149,11 @@ public: Always, OnlyIfDifferent, }; + enum class CopyInputRecent + { + No, + Yes, + }; enum class CopyResult { Success, @@ -179,6 +184,7 @@ public: /** Copy a file. */ static CopyResult CopySingleFile(std::string const& oldname, std::string const& newname, CopyWhen when, + CopyInputRecent inputRecent, std::string* err = nullptr); enum class Replace |
