diff -r 93272c0f9a80 -r 63e6243b880c updaterevision/updaterevision.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/updaterevision/updaterevision.c Thu Feb 06 20:43:22 2014 +0200 @@ -0,0 +1,136 @@ +/* updaterevision.c + * + * Public domain. This program uses git commands command to get + * various bits of repository status for a particular directory + * and writes it into a header file so that it can be used for a + * project's versioning. + */ + +#define _CRT_SECURE_NO_DEPRECATE + +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#define popen _popen +#define pclose _pclose +#endif + +// Used to strip newline characters from lines read by fgets. +void stripnl(char *str) +{ + if (*str != '\0') + { + size_t len = strlen(str); + if (str[len - 1] == '\n') + { + str[len - 1] = '\0'; + } + } +} + +int main(int argc, char **argv) +{ + char vertag[64], lastlog[64], lasthash[64], *hash = NULL; + FILE *stream = NULL; + int gotrev = 0, needupdate = 1; + + vertag[0] = '\0'; + lastlog[0] = '\0'; + + if (argc != 2) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + // Use git describe --tags to get a version string. If we are sitting directly + // on a tag, it returns that tag. Otherwise it returns --. + // Use git log to get the time of the latest commit in ISO 8601 format and its full hash. + stream = popen("git describe --tags && git log -1 --format=%ai*%H", "r"); + + if (NULL != stream) + { + if (fgets(vertag, sizeof vertag, stream) == vertag && + fgets(lastlog, sizeof lastlog, stream) == lastlog) + { + stripnl(vertag); + stripnl(lastlog); + gotrev = 1; + } + + pclose(stream); + } + + if (gotrev) + { + hash = strchr(lastlog, '*'); + if (hash != NULL) + { + *hash = '\0'; + hash++; + } + } + if (hash == NULL) + { + fprintf(stderr, "Failed to get commit info: %s\n", strerror(errno)); + strcpy(vertag, ""); + lastlog[0] = '\0'; + lastlog[1] = '0'; + lastlog[2] = '\0'; + hash = lastlog + 1; + } + + stream = fopen (argv[1], "r"); + if (stream != NULL) + { + if (!gotrev) + { // If we didn't get a revision but the file does exist, leave it alone. + fclose (stream); + return 0; + } + // Read the revision that's in this file already. If it's the same as + // what we've got, then we don't need to modify it and can avoid rebuilding + // dependant files. + if (fgets(lasthash, sizeof lasthash, stream) == lasthash) + { + stripnl(lasthash); + if (strcmp(hash, lasthash + 3) == 0) + { + needupdate = 0; + } + } + fclose (stream); + } + + if (needupdate) + { + stream = fopen (argv[1], "w"); + if (stream == NULL) + { + return 1; + } + fprintf(stream, +"// %s\n" +"//\n" +"// This file was automatically generated by the\n" +"// updaterevision tool. Do not edit by hand.\n" +"\n" +"#define GIT_DESCRIPTION \"%s\"\n" +"#define GIT_HASH \"%s\"\n" +"#define GIT_TIME \"%s\"\n", + hash, vertag, hash, lastlog); + fclose(stream); + fprintf(stderr, "%s updated to commit %s.\n", argv[1], vertag); + } + else + { + fprintf (stderr, "%s is up to date at commit %s.\n", argv[1], vertag); + } + + return 0; +}