mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-09 07:11:05 -06:00
cmSystemTools: Add RenameFile option to not replace destination
This commit is contained in:
@@ -1348,12 +1348,14 @@ bool HandleRename(std::vector<std::string> const& args,
|
||||
}
|
||||
|
||||
std::string err;
|
||||
switch (cmSystemTools::RenameFile(oldname, newname, &err)) {
|
||||
switch (cmSystemTools::RenameFile(oldname, newname,
|
||||
cmSystemTools::Replace::Yes, &err)) {
|
||||
case cmSystemTools::RenameResult::Success:
|
||||
if (!arguments.Result.empty()) {
|
||||
status.GetMakefile().AddDefinition(arguments.Result, "0");
|
||||
}
|
||||
return true;
|
||||
case cmSystemTools::RenameResult::NoReplace:
|
||||
case cmSystemTools::RenameResult::Failure:
|
||||
if (!arguments.Result.empty()) {
|
||||
status.GetMakefile().AddDefinition(arguments.Result, err);
|
||||
|
||||
@@ -973,14 +973,19 @@ void cmSystemTools::InitializeLibUV()
|
||||
|
||||
#ifdef _WIN32
|
||||
namespace {
|
||||
bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname)
|
||||
bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname,
|
||||
cmSystemTools::Replace replace)
|
||||
{
|
||||
// Not only ignore any previous error, but clear any memory of it.
|
||||
SetLastError(0);
|
||||
|
||||
// Use MOVEFILE_REPLACE_EXISTING to replace an existing destination file.
|
||||
return MoveFileExW(oldname.c_str(), newname.c_str(),
|
||||
MOVEFILE_REPLACE_EXISTING);
|
||||
DWORD flags = 0;
|
||||
if (replace == cmSystemTools::Replace::Yes) {
|
||||
// Use MOVEFILE_REPLACE_EXISTING to replace an existing destination file.
|
||||
flags = flags | MOVEFILE_REPLACE_EXISTING;
|
||||
}
|
||||
|
||||
return MoveFileExW(oldname.c_str(), newname.c_str(), flags);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -988,12 +993,13 @@ bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname)
|
||||
bool cmSystemTools::RenameFile(const std::string& oldname,
|
||||
const std::string& newname)
|
||||
{
|
||||
return cmSystemTools::RenameFile(oldname, newname, nullptr) ==
|
||||
return cmSystemTools::RenameFile(oldname, newname, Replace::Yes) ==
|
||||
RenameResult::Success;
|
||||
}
|
||||
|
||||
cmSystemTools::RenameResult cmSystemTools::RenameFile(
|
||||
std::string const& oldname, std::string const& newname, std::string* err)
|
||||
std::string const& oldname, std::string const& newname, Replace replace,
|
||||
std::string* err)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
# ifndef INVALID_FILE_ATTRIBUTES
|
||||
@@ -1016,7 +1022,7 @@ cmSystemTools::RenameResult cmSystemTools::RenameFile(
|
||||
oldname_wstr, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
|
||||
|
||||
DWORD move_last_error = 0;
|
||||
while (!cmMoveFile(oldname_wstr, newname_wstr) && --retry.Count) {
|
||||
while (!cmMoveFile(oldname_wstr, newname_wstr, replace) && --retry.Count) {
|
||||
move_last_error = GetLastError();
|
||||
|
||||
// There was no error ==> the operation is not yet complete.
|
||||
@@ -1032,6 +1038,9 @@ cmSystemTools::RenameResult cmSystemTools::RenameFile(
|
||||
// 3) Windows Explorer has an associated directory already opened.
|
||||
if (move_last_error != ERROR_ACCESS_DENIED &&
|
||||
move_last_error != ERROR_SHARING_VIOLATION) {
|
||||
if (replace == Replace::No && move_last_error == ERROR_ALREADY_EXISTS) {
|
||||
return RenameResult::NoReplace;
|
||||
}
|
||||
ReportError(err);
|
||||
return RenameResult::Failure;
|
||||
}
|
||||
@@ -1060,10 +1069,23 @@ cmSystemTools::RenameResult cmSystemTools::RenameFile(
|
||||
if (retry.Count > 0) {
|
||||
return RenameResult::Success;
|
||||
}
|
||||
if (replace == Replace::No && GetLastError() == ERROR_ALREADY_EXISTS) {
|
||||
return RenameResult::NoReplace;
|
||||
}
|
||||
ReportError(err);
|
||||
return RenameResult::Failure;
|
||||
#else
|
||||
/* On UNIX we have an OS-provided call to do this atomically. */
|
||||
// On UNIX we have OS-provided calls to create 'newname' atomically.
|
||||
if (replace == Replace::No) {
|
||||
if (link(oldname.c_str(), newname.c_str()) == 0) {
|
||||
return RenameResult::Success;
|
||||
}
|
||||
if (errno == EEXIST) {
|
||||
return RenameResult::NoReplace;
|
||||
}
|
||||
ReportError(err);
|
||||
return RenameResult::Failure;
|
||||
}
|
||||
if (rename(oldname.c_str(), newname.c_str()) == 0) {
|
||||
return RenameResult::Success;
|
||||
}
|
||||
|
||||
@@ -128,9 +128,15 @@ public:
|
||||
static bool SimpleGlob(const std::string& glob,
|
||||
std::vector<std::string>& files, int type = 0);
|
||||
|
||||
enum class Replace
|
||||
{
|
||||
Yes,
|
||||
No,
|
||||
};
|
||||
enum class RenameResult
|
||||
{
|
||||
Success,
|
||||
NoReplace,
|
||||
Failure,
|
||||
};
|
||||
|
||||
@@ -139,7 +145,8 @@ public:
|
||||
static bool RenameFile(const std::string& oldname,
|
||||
const std::string& newname);
|
||||
static RenameResult RenameFile(std::string const& oldname,
|
||||
std::string const& newname, std::string* err);
|
||||
std::string const& newname, Replace replace,
|
||||
std::string* err = nullptr);
|
||||
|
||||
//! Rename a file if contents are different, delete the source otherwise
|
||||
static void MoveFileIfDifferent(const std::string& source,
|
||||
|
||||
Reference in New Issue
Block a user