mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-19 19:43:23 +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 };
|
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
|
#define KWSYS_ST_BUFFER 4096
|
||||||
|
|
||||||
bool SystemTools::FilesDiffer(std::string const& source,
|
bool SystemTools::FilesDiffer(std::string const& source,
|
||||||
@@ -2583,15 +2625,31 @@ SystemTools::CopyStatus SystemTools::CopyFileAlways(
|
|||||||
return status;
|
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,
|
SystemTools::CopyStatus SystemTools::CopyAFile(std::string const& source,
|
||||||
std::string const& destination,
|
std::string const& destination,
|
||||||
bool always)
|
bool always)
|
||||||
{
|
{
|
||||||
if (always) {
|
return SystemTools::CopyAFile(source, destination,
|
||||||
return SystemTools::CopyFileAlways(source, destination);
|
always ? CopyWhen::Always
|
||||||
} else {
|
: CopyWhen::OnlyIfDifferent);
|
||||||
return SystemTools::CopyFileIfDifferent(source, destination);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2599,7 +2657,8 @@ SystemTools::CopyStatus SystemTools::CopyAFile(std::string const& source,
|
|||||||
* "destination".
|
* "destination".
|
||||||
*/
|
*/
|
||||||
Status SystemTools::CopyADirectory(std::string const& source,
|
Status SystemTools::CopyADirectory(std::string const& source,
|
||||||
std::string const& destination, bool always)
|
std::string const& destination,
|
||||||
|
SystemTools::CopyWhen when)
|
||||||
{
|
{
|
||||||
Status status;
|
Status status;
|
||||||
Directory dir;
|
Directory dir;
|
||||||
@@ -2622,12 +2681,12 @@ Status SystemTools::CopyADirectory(std::string const& source,
|
|||||||
std::string fullDestPath = destination;
|
std::string fullDestPath = destination;
|
||||||
fullDestPath += "/";
|
fullDestPath += "/";
|
||||||
fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
|
fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
|
||||||
status = SystemTools::CopyADirectory(fullPath, fullDestPath, always);
|
status = SystemTools::CopyADirectory(fullPath, fullDestPath, when);
|
||||||
if (!status.IsSuccess()) {
|
if (!status.IsSuccess()) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
status = SystemTools::CopyAFile(fullPath, destination, always);
|
status = SystemTools::CopyAFile(fullPath, destination, when);
|
||||||
if (!status.IsSuccess()) {
|
if (!status.IsSuccess()) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -2638,6 +2697,14 @@ Status SystemTools::CopyADirectory(std::string const& source,
|
|||||||
return status;
|
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
|
// return size of file; also returns zero if no file exists
|
||||||
unsigned long SystemTools::FileLength(std::string const& filename)
|
unsigned long SystemTools::FileLength(std::string const& filename)
|
||||||
{
|
{
|
||||||
|
@@ -577,6 +577,13 @@ public:
|
|||||||
static CopyStatus CopyFileIfDifferent(std::string const& source,
|
static CopyStatus CopyFileIfDifferent(std::string const& source,
|
||||||
std::string const& destination);
|
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
|
* Compare the contents of two files. Return true if different
|
||||||
*/
|
*/
|
||||||
@@ -658,24 +665,34 @@ public:
|
|||||||
static CopyStatus CopyFileAlways(std::string const& source,
|
static CopyStatus CopyFileAlways(std::string const& source,
|
||||||
std::string const& destination);
|
std::string const& destination);
|
||||||
|
|
||||||
|
enum class CopyWhen
|
||||||
|
{
|
||||||
|
Always,
|
||||||
|
OnlyIfDifferent,
|
||||||
|
OnlyIfNewer,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy a file. If the "always" argument is true the file is always
|
* Copy a file with specified copy behavior.
|
||||||
* copied. If it is false, the file is copied only if it is new or
|
|
||||||
* has changed.
|
|
||||||
*/
|
*/
|
||||||
static CopyStatus CopyAFile(std::string const& source,
|
static CopyStatus CopyAFile(std::string const& source,
|
||||||
std::string const& destination,
|
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
|
* Copy content directory to another directory with all files and
|
||||||
* subdirectories. If the "always" argument is true all files are
|
* subdirectories. The "when" argument controls when files are copied:
|
||||||
* always copied. If it is false, only files that have changed or
|
* Always: all files are always copied.
|
||||||
* are new are 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,
|
static Status CopyADirectory(std::string const& source,
|
||||||
std::string const& destination,
|
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
|
* Remove a file
|
||||||
|
@@ -1160,6 +1160,94 @@ static bool CheckCopyFileIfDifferent()
|
|||||||
return ret;
|
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()
|
static bool CheckURLParsing()
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
@@ -1271,6 +1359,8 @@ int testSystemTools(int, char*[])
|
|||||||
|
|
||||||
res &= CheckCopyFileIfDifferent();
|
res &= CheckCopyFileIfDifferent();
|
||||||
|
|
||||||
|
res &= CheckCopyFileIfNewer();
|
||||||
|
|
||||||
res &= CheckURLParsing();
|
res &= CheckURLParsing();
|
||||||
|
|
||||||
res &= CheckSplitString();
|
res &= CheckSplitString();
|
||||||
|
Reference in New Issue
Block a user