Browse Source

Merge topic 'update-kwsys'

ea46bc69d5 Merge branch 'upstream-KWSys' into update-kwsys
278ce30d07 KWSys 2025-07-24 (bf2d9893)
ce54396676 cmFileCopier: Remove explicit default argument

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !10959
master
Brad King 3 days ago
committed by Kitware Robot
parent
commit
f60e3852af
  1. 2
      Source/cmFileCopier.cxx
  2. 83
      Source/kwsys/SystemTools.cxx
  3. 33
      Source/kwsys/SystemTools.hxx.in
  4. 90
      Source/kwsys/testSystemTools.cxx

2
Source/cmFileCopier.cxx

@ -618,7 +618,7 @@ bool cmFileCopier::InstallFile(std::string const& fromFile,
// Copy the file.
if (copy) {
auto copy_status = cmSystemTools::CopyAFile(fromFile, toFile, true);
auto copy_status = cmSystemTools::CopyAFile(fromFile, toFile);
if (!copy_status) {
std::ostringstream e;
e << this->Name << " cannot copy file \"" << fromFile << "\" to \""

83
Source/kwsys/SystemTools.cxx

@ -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,
@ -2585,13 +2627,29 @@ SystemTools::CopyStatus SystemTools::CopyFileAlways(
SystemTools::CopyStatus SystemTools::CopyAFile(std::string const& source,
std::string const& destination,
bool always)
SystemTools::CopyWhen when)
{
if (always) {
return SystemTools::CopyFileAlways(source, destination);
} else {
return SystemTools::CopyFileIfDifferent(source, destination);
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)
{
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)
{

33
Source/kwsys/SystemTools.hxx.in

@ -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

90
Source/kwsys/testSystemTools.cxx

@ -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();

Loading…
Cancel
Save