diff options
author | David Cole <david.cole@kitware.com> | 2012-12-11 18:43:50 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2012-12-11 18:43:50 (GMT) |
commit | b575eadcdaf55fa4fe9a9d2dd8cb5e530365eae9 (patch) | |
tree | db0dc28738603f9e5612c0afce5f60f43b6f05b6 /Source | |
parent | d73c4057edeca78fcefbcaf9fd3768e2c0e19e07 (diff) | |
parent | 12d87c04253bd203a9b8a510b1772291527d441c (diff) | |
download | CMake-b575eadcdaf55fa4fe9a9d2dd8cb5e530365eae9.zip CMake-b575eadcdaf55fa4fe9a9d2dd8cb5e530365eae9.tar.gz CMake-b575eadcdaf55fa4fe9a9d2dd8cb5e530365eae9.tar.bz2 |
Merge topic 'add-timestamp-subcommands'
12d87c0 CMake: Fix dashboard build errors and warnings
e28ce24 CMake: Fix dashboard test failure
354ecc1 CMake: Fix dashboard warnings
d842d90 CMake: Stylistic changes and documentation tweaks
711e2b3 CMake: Add TIMESTAMP subcommand to string and file commands
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmBootstrapCommands.cxx | 1 | ||||
-rw-r--r-- | Source/cmFileCommand.cxx | 57 | ||||
-rw-r--r-- | Source/cmFileCommand.h | 9 | ||||
-rw-r--r-- | Source/cmStringCommand.cxx | 54 | ||||
-rw-r--r-- | Source/cmStringCommand.h | 30 | ||||
-rw-r--r-- | Source/cmTimestamp.cxx | 134 | ||||
-rw-r--r-- | Source/cmTimestamp.h | 40 |
7 files changed, 324 insertions, 1 deletions
diff --git a/Source/cmBootstrapCommands.cxx b/Source/cmBootstrapCommands.cxx index 9097a74..e3a2ad4 100644 --- a/Source/cmBootstrapCommands.cxx +++ b/Source/cmBootstrapCommands.cxx @@ -89,6 +89,7 @@ #include "cmStringCommand.cxx" #include "cmSubdirCommand.cxx" #include "cmTargetLinkLibrariesCommand.cxx" +#include "cmTimestamp.cxx" #include "cmTryCompileCommand.cxx" #include "cmTryRunCommand.cxx" #include "cmUnsetCommand.cxx" diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index b877f3c..0cdbb82 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -17,6 +17,8 @@ #include "cmFileTimeComparison.h" #include "cmCryptoHash.h" +#include "cmTimestamp.h" + #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cm_curl.h" #endif @@ -161,6 +163,10 @@ bool cmFileCommand { return this->HandleCMakePathCommand(args, true); } + else if ( subCommand == "TIMESTAMP" ) + { + return this->HandleTimestampCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e.c_str()); @@ -3241,3 +3247,54 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) return false; #endif } + +//---------------------------------------------------------------------------- +bool cmFileCommand::HandleTimestampCommand( + std::vector<std::string> const& args) +{ + if(args.size() < 3) + { + this->SetError("sub-command TIMESTAMP requires at least two arguments."); + return false; + } + else if(args.size() > 5) + { + this->SetError("sub-command TIMESTAMP takes at most four arguments."); + return false; + } + + unsigned int argsIndex = 1; + + const std::string& filename = args[argsIndex++]; + + const std::string& outputVariable = args[argsIndex++]; + + std::string formatString; + if(args.size() > argsIndex && args[argsIndex] != "UTC") + { + formatString = args[argsIndex++]; + } + + bool utcFlag = false; + if(args.size() > argsIndex) + { + if(args[argsIndex] == "UTC") + { + utcFlag = true; + } + else + { + std::string e = " TIMESTAMP sub-command does not recognize option " + + args[argsIndex] + "."; + this->SetError(e.c_str()); + return false; + } + } + + cmTimestamp timestamp; + std::string result = timestamp.FileModificationTime( + filename.c_str(), formatString, utcFlag); + this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str()); + + return true; +} diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index a0862ec..5973fa7 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -87,6 +87,7 @@ public: " [TLS_VERIFY on|off] [TLS_CAINFO file])\n" " file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n" " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n" + " file(TIMESTAMP filename variable [<format string>] [UTC])\n" "WRITE will write a message into a file called 'filename'. It " "overwrites the file if it already exists, and creates the file " "if it does not exist. (If the file is a build input, use " @@ -200,6 +201,12 @@ public: "If SHOW_PROGRESS is specified, progress information will be printed " "as status messages until the operation is complete." "\n" + "TIMESTAMP will write a string representation of " + "the modification time of filename to variable.\n" + "Should the command be unable to obtain a timestamp " + "variable will be set to the empty string \"\".\n" + "See documentation of the string TIMESTAMP sub-command for more details." + "\n" "The file() command also provides COPY and INSTALL signatures:\n" " file(<COPY|INSTALL> files... DESTINATION <dir>\n" " [FILE_PERMISSIONS permissions...]\n" @@ -260,6 +267,8 @@ protected: bool HandleInstallCommand(std::vector<std::string> const& args); bool HandleDownloadCommand(std::vector<std::string> const& args); bool HandleUploadCommand(std::vector<std::string> const& args); + + bool HandleTimestampCommand(std::vector<std::string> const& args); }; diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 0193dc9..e49edd8 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -19,6 +19,8 @@ #include <ctype.h> #include <time.h> +#include <cmTimestamp.h> + //---------------------------------------------------------------------------- bool cmStringCommand ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) @@ -87,6 +89,10 @@ bool cmStringCommand { return this->HandleFindCommand(args); } + else if(subCommand == "TIMESTAMP") + { + return this->HandleTimestampCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e.c_str()); @@ -879,3 +885,51 @@ bool cmStringCommand this->Makefile->AddDefinition(variableName.c_str(), &*result.begin()); return true; } + +//---------------------------------------------------------------------------- +bool cmStringCommand +::HandleTimestampCommand(std::vector<std::string> const& args) +{ + if(args.size() < 2) + { + this->SetError("sub-command TIMESTAMP requires at least one argument."); + return false; + } + else if(args.size() > 4) + { + this->SetError("sub-command TIMESTAMP takes at most three arguments."); + return false; + } + + unsigned int argsIndex = 1; + + const std::string &outputVariable = args[argsIndex++]; + + std::string formatString; + if(args.size() > argsIndex && args[argsIndex] != "UTC") + { + formatString = args[argsIndex++]; + } + + bool utcFlag = false; + if(args.size() > argsIndex) + { + if(args[argsIndex] == "UTC") + { + utcFlag = true; + } + else + { + std::string e = " TIMESTAMP sub-command does not recognize option " + + args[argsIndex] + "."; + this->SetError(e.c_str()); + return false; + } + } + + cmTimestamp timestamp; + std::string result = timestamp.CurrentTime(formatString, utcFlag); + this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str()); + + return true; +} diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index 728b1bc..4423a90 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -93,6 +93,7 @@ public: " string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>]\n" " [RANDOM_SEED <seed>] <output variable>)\n" " string(FIND <string> <substring> <output variable> [REVERSE])\n" + " string(TIMESTAMP <output variable> [<format string>] [UTC])\n" "REGEX MATCH will match the regular expression once and store the " "match in the output variable.\n" "REGEX MATCHALL will match the regular expression as many times as " @@ -142,7 +143,33 @@ public: " () Saves a matched subexpression, which can be referenced \n" " in the REGEX REPLACE operation. Additionally it is saved\n" " by all regular expression-related commands, including \n" - " e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9)."; + " e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9).\n" + "TIMESTAMP will write a string representation of " + "the current date and/or time to the output variable.\n" + "Should the command be unable to obtain a timestamp " + "the output variable will be set to the empty string \"\".\n" + "The optional UTC flag requests the current date/time " + "representation to be in Coordinated Universal Time (UTC) " + "rather than local time.\n" + "The optional <format string> may contain the following " + "format specifiers: \n" + " %d The day of the current month (01-31).\n" + " %H The hour on a 24-hour clock (00-23).\n" + " %I The hour on a 12-hour clock (01-12).\n" + " %j The day of the current year (001-366).\n" + " %m The month of the current year (01-12).\n" + " %M The minute of the current hour (00-59).\n" + " %S The second of the current minute.\n" + " 60 represents a leap second. (00-60)\n" + " %U The week number of the current year (00-53).\n" + " %w The day of the current week. 0 is Sunday. (0-6)\n" + " %y The last two digits of the current year (00-99)\n" + " %Y The current year. \n" + "Unknown format specifiers will be ignored " + "and copied to the output as-is.\n" + "If no explicit <format string> is given it will default to:\n" + " %Y-%m-%dT%H:%M:%S for local time.\n" + " %Y-%m-%dT%H:%M:%SZ for UTC."; } cmTypeMacro(cmStringCommand, cmCommand); @@ -165,6 +192,7 @@ protected: bool HandleStripCommand(std::vector<std::string> const& args); bool HandleRandomCommand(std::vector<std::string> const& args); bool HandleFindCommand(std::vector<std::string> const& args); + bool HandleTimestampCommand(std::vector<std::string> const& args); class RegexReplacement { diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx new file mode 100644 index 0000000..ac26503 --- /dev/null +++ b/Source/cmTimestamp.cxx @@ -0,0 +1,134 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmTimestamp.h" + +#include <cstring> + +#include <sys/types.h> +#include <sys/stat.h> + +//---------------------------------------------------------------------------- +std::string cmTimestamp::CurrentTime( + const std::string& formatString, bool utcFlag) +{ + time_t currentTimeT = time(0); + if(currentTimeT == time_t(-1)) + { + return std::string(); + } + + return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag); +} + +//---------------------------------------------------------------------------- +std::string cmTimestamp::FileModificationTime(const char* path, + const std::string& formatString, bool utcFlag) +{ + struct stat info; + memset(&info, 0, sizeof(info)); + + if(stat(path, &info) != 0) + { + return std::string(); + } + + return CreateTimestampFromTimeT(info.st_mtime, formatString, utcFlag); +} + +//---------------------------------------------------------------------------- +std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT, + std::string formatString, bool utcFlag) +{ + if(formatString.empty()) + { + formatString = "%Y-%m-%dT%H:%M:%S"; + if(utcFlag) + { + formatString += "Z"; + } + } + + struct tm timeStruct; + memset(&timeStruct, 0, sizeof(timeStruct)); + + struct tm* ptr = (struct tm*) 0; + if(utcFlag) + { + ptr = gmtime(&timeT); + } + else + { + ptr = localtime(&timeT); + } + + if(ptr == 0) + { + return std::string(); + } + + timeStruct = *ptr; + + std::string result; + for(std::string::size_type i = 0; i < formatString.size(); ++i) + { + char c1 = formatString[i]; + char c2 = (i+1 < formatString.size()) ? + formatString[i+1] : static_cast<char>(0); + + if(c1 == '%' && c2 != 0) + { + result += AddTimestampComponent(c2, timeStruct); + ++i; + } + else + { + result += c1; + } + } + + return result; +} + +//---------------------------------------------------------------------------- +std::string cmTimestamp::AddTimestampComponent( + char flag, struct tm& timeStruct) +{ + std::string formatString = "%"; + formatString += flag; + + switch(flag) + { + case 'd': + case 'H': + case 'I': + case 'j': + case 'm': + case 'M': + case 'S': + case 'U': + case 'w': + case 'y': + case 'Y': + break; + default: + { + return formatString; + } + } + + char buffer[16]; + + size_t size = strftime(buffer, sizeof(buffer), + formatString.c_str(), &timeStruct); + + return std::string(buffer, size); +} diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h new file mode 100644 index 0000000..24c1869 --- /dev/null +++ b/Source/cmTimestamp.h @@ -0,0 +1,40 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmTimestamp_h +#define cmTimestamp_h + +#include <string> +#include <time.h> + +/** \class cmTimestamp + * \brief Utility class to generate sting representation of a timestamp + * + */ +class cmTimestamp +{ +public: + cmTimestamp() {} + + std::string CurrentTime(const std::string& formatString, bool utcFlag); + + std::string FileModificationTime(const char* path, + const std::string& formatString, bool utcFlag); + +private: + std::string CreateTimestampFromTimeT(time_t timeT, + std::string formatString, bool utcFlag); + + std::string AddTimestampComponent(char flag, struct tm& timeStruct); +}; + + +#endif |