mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-18 17:31:57 +08:00
Merge branch 'upstream-KWSys' into update-kwsys
# By KWSys Upstream * upstream-KWSys: KWSys 2025-07-24 (bf2d9893)
This commit is contained in:
@@ -2247,6 +2247,48 @@ SystemTools::CopyStatus SystemTools::CopyFileIfDifferent(
|
||||
return CopyStatus{ Status::Success(), CopyStatus::NoPath };
|
||||
}
|
||||
|
||||
SystemTools::CopyStatus SystemTools::CopyFileIfNewer(
|
||||
std::string const& source, std::string const& destination)
|
||||
{
|
||||
// special check for a destination that is a directory
|
||||
// FileTimeCompare does not handle file to directory compare
|
||||
if (SystemTools::FileIsDirectory(destination)) {
|
||||
std::string const new_destination = FileInDir(source, destination);
|
||||
if (!SystemTools::ComparePath(new_destination, destination)) {
|
||||
return SystemTools::CopyFileIfNewer(source, new_destination);
|
||||
}
|
||||
// If source and destination are the same path, don't copy
|
||||
return CopyStatus{ Status::Success(), CopyStatus::NoPath };
|
||||
}
|
||||
|
||||
// source and destination are files so do a copy if source is newer
|
||||
// Check if source file exists first
|
||||
if (!SystemTools::FileExists(source)) {
|
||||
return CopyStatus{ Status::POSIX_errno(), CopyStatus::SourcePath };
|
||||
}
|
||||
// If destination doesn't exist, always copy
|
||||
if (!SystemTools::FileExists(destination)) {
|
||||
return SystemTools::CopyFileAlways(source, destination);
|
||||
}
|
||||
// Check if source is newer than destination
|
||||
int timeResult;
|
||||
Status timeStatus =
|
||||
SystemTools::FileTimeCompare(source, destination, &timeResult);
|
||||
if (timeStatus.IsSuccess()) {
|
||||
if (timeResult > 0) {
|
||||
// Source is newer, copy it
|
||||
return SystemTools::CopyFileAlways(source, destination);
|
||||
} else {
|
||||
// Source is not newer, no need to copy
|
||||
return CopyStatus{ Status::Success(), CopyStatus::NoPath };
|
||||
}
|
||||
} else {
|
||||
// Time comparison failed, be conservative and copy to ensure updates are
|
||||
// not missed
|
||||
return SystemTools::CopyFileAlways(source, destination);
|
||||
}
|
||||
}
|
||||
|
||||
#define KWSYS_ST_BUFFER 4096
|
||||
|
||||
bool SystemTools::FilesDiffer(std::string const& source,
|
||||
@@ -2583,15 +2625,31 @@ SystemTools::CopyStatus SystemTools::CopyFileAlways(
|
||||
return status;
|
||||
}
|
||||
|
||||
SystemTools::CopyStatus SystemTools::CopyAFile(std::string const& source,
|
||||
std::string const& destination,
|
||||
SystemTools::CopyWhen when)
|
||||
{
|
||||
switch (when) {
|
||||
case SystemTools::CopyWhen::Always:
|
||||
return SystemTools::CopyFileAlways(source, destination);
|
||||
case SystemTools::CopyWhen::OnlyIfDifferent:
|
||||
return SystemTools::CopyFileIfDifferent(source, destination);
|
||||
case SystemTools::CopyWhen::OnlyIfNewer:
|
||||
return SystemTools::CopyFileIfNewer(source, destination);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Should not reach here
|
||||
return CopyStatus{ Status::POSIX_errno(), CopyStatus::NoPath };
|
||||
}
|
||||
|
||||
SystemTools::CopyStatus SystemTools::CopyAFile(std::string const& source,
|
||||
std::string const& destination,
|
||||
bool always)
|
||||
{
|
||||
if (always) {
|
||||
return SystemTools::CopyFileAlways(source, destination);
|
||||
} else {
|
||||
return SystemTools::CopyFileIfDifferent(source, destination);
|
||||
}
|
||||
return SystemTools::CopyAFile(source, destination,
|
||||
always ? CopyWhen::Always
|
||||
: CopyWhen::OnlyIfDifferent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2599,7 +2657,8 @@ SystemTools::CopyStatus SystemTools::CopyAFile(std::string const& source,
|
||||
* "destination".
|
||||
*/
|
||||
Status SystemTools::CopyADirectory(std::string const& source,
|
||||
std::string const& destination, bool always)
|
||||
std::string const& destination,
|
||||
SystemTools::CopyWhen when)
|
||||
{
|
||||
Status status;
|
||||
Directory dir;
|
||||
@@ -2622,12 +2681,12 @@ Status SystemTools::CopyADirectory(std::string const& source,
|
||||
std::string fullDestPath = destination;
|
||||
fullDestPath += "/";
|
||||
fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
|
||||
status = SystemTools::CopyADirectory(fullPath, fullDestPath, always);
|
||||
status = SystemTools::CopyADirectory(fullPath, fullDestPath, when);
|
||||
if (!status.IsSuccess()) {
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
status = SystemTools::CopyAFile(fullPath, destination, always);
|
||||
status = SystemTools::CopyAFile(fullPath, destination, when);
|
||||
if (!status.IsSuccess()) {
|
||||
return status;
|
||||
}
|
||||
@@ -2638,6 +2697,14 @@ Status SystemTools::CopyADirectory(std::string const& source,
|
||||
return status;
|
||||
}
|
||||
|
||||
Status SystemTools::CopyADirectory(std::string const& source,
|
||||
std::string const& destination, bool always)
|
||||
{
|
||||
return SystemTools::CopyADirectory(source, destination,
|
||||
always ? CopyWhen::Always
|
||||
: CopyWhen::OnlyIfDifferent);
|
||||
}
|
||||
|
||||
// return size of file; also returns zero if no file exists
|
||||
unsigned long SystemTools::FileLength(std::string const& filename)
|
||||
{
|
||||
|
@@ -577,6 +577,13 @@ public:
|
||||
static CopyStatus CopyFileIfDifferent(std::string const& source,
|
||||
std::string const& destination);
|
||||
|
||||
/**
|
||||
* Copy the source file to the destination file only
|
||||
* if the source file is newer than the destination file.
|
||||
*/
|
||||
static CopyStatus CopyFileIfNewer(std::string const& source,
|
||||
std::string const& destination);
|
||||
|
||||
/**
|
||||
* Compare the contents of two files. Return true if different
|
||||
*/
|
||||
@@ -658,24 +665,34 @@ public:
|
||||
static CopyStatus CopyFileAlways(std::string const& source,
|
||||
std::string const& destination);
|
||||
|
||||
enum class CopyWhen
|
||||
{
|
||||
Always,
|
||||
OnlyIfDifferent,
|
||||
OnlyIfNewer,
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy a file. If the "always" argument is true the file is always
|
||||
* copied. If it is false, the file is copied only if it is new or
|
||||
* has changed.
|
||||
* Copy a file with specified copy behavior.
|
||||
*/
|
||||
static CopyStatus CopyAFile(std::string const& source,
|
||||
std::string const& destination,
|
||||
bool always = true);
|
||||
CopyWhen when = CopyWhen::Always);
|
||||
static CopyStatus CopyAFile(std::string const& source,
|
||||
std::string const& destination, bool always);
|
||||
|
||||
/**
|
||||
* Copy content directory to another directory with all files and
|
||||
* subdirectories. If the "always" argument is true all files are
|
||||
* always copied. If it is false, only files that have changed or
|
||||
* are new are copied.
|
||||
* subdirectories. The "when" argument controls when files are copied:
|
||||
* Always: all files are always copied.
|
||||
* OnlyIfDifferent: only files that have changed are copied.
|
||||
* OnlyIfNewer: only files that are newer than the destination are copied.
|
||||
*/
|
||||
static Status CopyADirectory(std::string const& source,
|
||||
std::string const& destination,
|
||||
bool always = true);
|
||||
CopyWhen when = CopyWhen::Always);
|
||||
static Status CopyADirectory(std::string const& source,
|
||||
std::string const& destination, bool always);
|
||||
|
||||
/**
|
||||
* Remove a file
|
||||
|
@@ -1160,6 +1160,94 @@ static bool CheckCopyFileIfDifferent()
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool CheckCopyFileIfNewer()
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
// Prepare "older" files.
|
||||
if (!writeFile("older_source.txt", "old content")) {
|
||||
return false;
|
||||
}
|
||||
if (!writeFile("older_dest.txt", "old content")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Small delay to ensure different timestamps
|
||||
#if defined(_WIN32)
|
||||
Sleep(1125); // Sleep for 1.125 seconds on Windows
|
||||
#else
|
||||
usleep(1125000); // Sleep for 1.125 seconds on Unix
|
||||
#endif
|
||||
|
||||
// Prepare "newer" files.
|
||||
if (!writeFile("newer_source.txt", "test content")) {
|
||||
return false;
|
||||
}
|
||||
if (!writeFile("newer_source2.txt", "newer content")) {
|
||||
return false;
|
||||
}
|
||||
if (!writeFile("newer_dest2.txt", "new content")) {
|
||||
return false;
|
||||
}
|
||||
if (!kwsys::SystemTools::MakeDirectory("newer_dir_a") ||
|
||||
!kwsys::SystemTools::MakeDirectory("newer_dir_b")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test case 1: Copy when destination doesn't exist
|
||||
if (!kwsys::SystemTools::CopyFileIfNewer("newer_source.txt",
|
||||
"newer_dest1.txt")) {
|
||||
std::cerr << "CopyFileIfNewer() failed when destination doesn't exist."
|
||||
<< std::endl;
|
||||
ret = false;
|
||||
} else {
|
||||
std::string dest_content = readFile("newer_dest1.txt");
|
||||
if (dest_content != "test content") {
|
||||
std::cerr << "CopyFileIfNewer() incorrect content when destination "
|
||||
"doesn't exist."
|
||||
<< std::endl;
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test case 2: Don't copy when source is older
|
||||
auto copy_result =
|
||||
kwsys::SystemTools::CopyFileIfNewer("older_source.txt", "newer_dest2.txt");
|
||||
if (!copy_result) {
|
||||
std::cerr << "CopyFileIfNewer() failed when source is older." << std::endl;
|
||||
ret = false;
|
||||
} else {
|
||||
std::string dest_content = readFile("newer_dest2.txt");
|
||||
if (dest_content != "new content") {
|
||||
std::cerr
|
||||
<< "CopyFileIfNewer() should not have copied when source is older."
|
||||
<< std::endl;
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test case 3: Copy when source is newer
|
||||
if (!kwsys::SystemTools::CopyFileIfNewer("newer_source2.txt",
|
||||
"older_dest.txt")) {
|
||||
std::cerr << "CopyFileIfNewer() failed when source is newer." << std::endl;
|
||||
ret = false;
|
||||
} else {
|
||||
std::string dest_content = readFile("older_dest.txt");
|
||||
if (dest_content != "newer content") {
|
||||
std::cerr << "CopyFileIfNewer() incorrect content when source is newer."
|
||||
<< std::endl;
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test case 4: Directory to directory copy
|
||||
if (!kwsys::SystemTools::CopyFileIfNewer("newer_dir_a/", "newer_dir_b")) {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool CheckURLParsing()
|
||||
{
|
||||
bool ret = true;
|
||||
@@ -1271,6 +1359,8 @@ int testSystemTools(int, char*[])
|
||||
|
||||
res &= CheckCopyFileIfDifferent();
|
||||
|
||||
res &= CheckCopyFileIfNewer();
|
||||
|
||||
res &= CheckURLParsing();
|
||||
|
||||
res &= CheckSplitString();
|
||||
|
Reference in New Issue
Block a user