diff options
-rw-r--r-- | Source/cmFileCommand.cxx | 63 | ||||
-rw-r--r-- | Source/cmSystemTools.cxx | 64 | ||||
-rw-r--r-- | Source/cmSystemTools.h | 5 |
3 files changed, 114 insertions, 18 deletions
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 9330bb4..3a31a3f 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -17,9 +17,11 @@ #include "cmFileCommand.h" #include "cmake.h" #include "cmHexFileConverter.h" +#include "cmFileTimeComparison.h" #include <sys/types.h> #include <sys/stat.h> + #include <cmsys/Directory.hxx> #include <cmsys/Glob.hxx> #include <cmsys/RegularExpression.hxx> @@ -716,6 +718,7 @@ struct cmFileInstaller private: cmFileCommand* FileCommand; cmMakefile* Makefile; + cmFileTimeComparison FileTimes; public: // The length of the destdir setting. @@ -807,11 +810,6 @@ private: bool cmFileInstaller::InstallSymlink(const char* fromFile, const char* toFile, bool always) { - // Inform the user about this file installation. - std::string message = "Installing "; - message += toFile; - this->Makefile->DisplayStatus(message.c_str(), -1); - // Read the original symlink. std::string symlinkTarget; if(!cmSystemTools::ReadSymlink(fromFile, symlinkTarget)) @@ -825,6 +823,7 @@ bool cmFileInstaller::InstallSymlink(const char* fromFile, const char* toFile, // Compare the symlink value to that at the destination if not // always installing. + bool copy = true; if(!always) { std::string oldSymlinkTarget; @@ -832,22 +831,30 @@ bool cmFileInstaller::InstallSymlink(const char* fromFile, const char* toFile, { if(symlinkTarget == oldSymlinkTarget) { - return true; + copy = false; } } } - // Remove the destination file so we can always create the symlink. - cmSystemTools::RemoveFile(toFile); + // Inform the user about this file installation. + std::string message = (copy? "Installing: " : "Up-to-date: "); + message += toFile; + this->Makefile->DisplayStatus(message.c_str(), -1); - // Create the symlink. - if(!cmSystemTools::CreateSymlink(symlinkTarget.c_str(), toFile)) + if(copy) { - cmOStringStream e; - e << "INSTALL cannot duplicate symlink \"" << fromFile - << "\" at \"" << toFile << "\"."; - this->FileCommand->SetError(e.str().c_str()); - return false; + // Remove the destination file so we can always create the symlink. + cmSystemTools::RemoveFile(toFile); + + // Create the symlink. + if(!cmSystemTools::CreateSymlink(symlinkTarget.c_str(), toFile)) + { + cmOStringStream e; + e << "INSTALL cannot duplicate symlink \"" << fromFile + << "\" at \"" << toFile << "\"."; + this->FileCommand->SetError(e.str().c_str()); + return false; + } } // Add the file to the manifest. @@ -875,13 +882,27 @@ bool cmFileInstaller::InstallFile(const char* fromFile, const char* toFile, return this->InstallSymlink(fromFile, toFile, always); } + // Determine whether we will copy the file. + bool copy = true; + if(!always) + { + // If both files exist and "fromFile" is not newer than "toFile" + // do not copy. + int timeResult; + if(this->FileTimes.FileTimeCompare(fromFile, toFile, &timeResult) && + timeResult <= 0) + { + copy = false; + } + } + // Inform the user about this file installation. - std::string message = "Installing "; + std::string message = (copy? "Installing: " : "Up-to-date: "); message += toFile; this->Makefile->DisplayStatus(message.c_str(), -1); // Copy the file. - if(!cmSystemTools::CopyAFile(fromFile, toFile, always)) + if(copy && !cmSystemTools::CopyAFile(fromFile, toFile, true)) { cmOStringStream e; e << "INSTALL cannot copy file \"" << fromFile @@ -893,6 +914,12 @@ bool cmFileInstaller::InstallFile(const char* fromFile, const char* toFile, // Add the file to the manifest. this->ManifestAppend(toFile); + // Set the file modification time of the destination file. + if(copy && !always) + { + cmSystemTools::CopyFileTime(fromFile, toFile); + } + // Set permissions of the destination file. mode_t permissions = (match_properties.Permissions? match_properties.Permissions : this->FilePermissions); @@ -934,7 +961,7 @@ bool cmFileInstaller::InstallDirectory(const char* source, } // Inform the user about this directory installation. - std::string message = "Installing "; + std::string message = "Installing: "; message += destination; this->Makefile->DisplayStatus(message.c_str(), -1); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 04d6885..1c2ecc9 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -32,6 +32,7 @@ #endif #if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__)) +# define CM_SYSTEM_TOOLS_WINDOWS #include <string.h> #include <windows.h> #include <direct.h> @@ -41,6 +42,7 @@ #include <sys/types.h> #include <fcntl.h> #include <unistd.h> +#include <utime.h> #endif #include <sys/stat.h> @@ -66,6 +68,26 @@ extern char** environ; # endif #endif +#ifdef CM_SYSTEM_TOOLS_WINDOWS +class cmSystemToolsWindowsHandle +{ +public: + cmSystemToolsWindowsHandle(HANDLE h): handle_(h) {} + ~cmSystemToolsWindowsHandle() + { + if(this->handle_ != INVALID_HANDLE_VALUE) + { + CloseHandle(this->handle_); + } + } + operator bool() const { return this->handle_ != INVALID_HANDLE_VALUE; } + operator !() const { return this->handle_ == INVALID_HANDLE_VALUE; } + operator HANDLE() const { return this->handle_; } +private: + HANDLE handle_; +}; +#endif + bool cmSystemTools::s_RunCommandHideConsole = false; bool cmSystemTools::s_DisableRunCommandOutput = false; bool cmSystemTools::s_ErrorOccured = false; @@ -2006,3 +2028,45 @@ void cmSystemTools::DoNotInheritStdPipes() } #endif } + +//---------------------------------------------------------------------------- +bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + cmSystemToolsWindowsHandle hFrom = + CreateFile(fromFile, GENERIC_READ, FILE_SHARE_READ, 0, + OPEN_EXISTING, 0, 0); + cmSystemToolsWindowsHandle hTo = + CreateFile(toFile, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); + if(!hFrom || !hTo) + { + return false; + } + FILETIME timeCreation; + FILETIME timeLastAccess; + FILETIME timeLastWrite; + if(!GetFileTime(hFrom, &timeCreation, &timeLastAccess, &timeLastWrite)) + { + return false; + } + if(!SetFileTime(hFrom, &timeCreation, &timeLastAccess, &timeLastWrite)) + { + return false; + } +#else + struct stat fromStat; + if(stat(fromFile, &fromStat) < 0) + { + return false; + } + + struct utimbuf buf; + buf.actime = fromStat.st_atime; + buf.modtime = fromStat.st_mtime; + if(utime(toFile, &buf) < 0) + { + return false; + } +#endif + return true; +} diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index ed95bdf..9007537 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -345,6 +345,11 @@ public: // if you want to be able to kill child processes and // not get stuck waiting for all the output on the pipes. static void DoNotInheritStdPipes(); + + /** Copy the file create/access/modify times from the file named by + the first argument to that named by the second. */ + static bool CopyFileTime(const char* fromFile, const char* toFile); + private: static bool s_ForceUnixPaths; static bool s_RunCommandHideConsole; |