diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | datever.c | 126 |
2 files changed, 93 insertions, 36 deletions
@@ -1,4 +1,4 @@ -CFLAGS=-Wall -Wextra -Wpedantic -O3 +CFLAGS=-Wall -Wextra -Wpedantic -O3 -std=c99 -D_POSIX_C_SOURCE=200809L CFLAGS+=`pkg-config --cflags libgit2` LDLIBS+=`pkg-config --libs libgit2` @@ -10,4 +10,5 @@ clean: rm -f datever +.POSIX: .PHONY: all clean @@ -1,11 +1,24 @@ #include <stdio.h> -#include <string.h> #include <time.h> #include <git2.h> +struct datever +{ + int year; + int month; + int day; + int revision; +}; + + static int must(const char* msg, int err); +static struct datever find_latest(git_repository* repo); +static struct datever datever_init(); +static struct datever datever_from_time(time_t time); +static int datever_is_valid(const struct datever* ver); +static int datever_compare(const struct datever* lhs, const struct datever* rhs); int @@ -14,52 +27,95 @@ main() git_libgit2_init(); git_repository* repo = NULL; must("open repository", git_repository_open_ext(&repo, NULL, GIT_REPOSITORY_OPEN_FROM_ENV, NULL)); + const struct datever ver = find_latest(repo); + printf("%d%02d%02d.%d\n", ver.year, ver.month, ver.day, ver.revision); +} + + +/// If [[err]] is considered erroneous, print [[msg]] and the last libgit2 error to standard error and then terminate +/// current process. +int +must(const char* const msg, const int err) +{ + if (0 > err) { + const git_error* const e = git_error_last(); + if (NULL != msg) + dprintf(2, "%s: ", msg); + dprintf(2, "%s\n", e->message); + exit(1); + } + return err; +} + + +struct datever +find_latest(git_repository* const repo) +{ git_revwalk* walker = NULL; must("walk revisions", git_revwalk_new(&walker, repo)); must("find HEAD", git_revwalk_push_head(walker)); git_oid oid; - char prev[37]; - prev[0] = 0; - char date[37]; - int count = 0; + git_commit* commit; + struct datever prev = datever_init(); + struct datever ver = datever_init(); while (0 == git_revwalk_next(&oid, walker)) { - git_commit* commit; must("find commit", git_commit_lookup(&commit, repo, &oid)); - const git_time_t gt = git_commit_time(commit); - const struct tm* const tm = gmtime(>); - if (NULL == tm) { - perror("read time"); - exit(1); - } - snprintf( - date, - 37, - "%d%02d%02d", - tm->tm_year + 1900, - tm->tm_mon + 1, - tm->tm_mday); - if (0 != prev[0]) { - if (0 == strncmp(prev, date, 37)) - count++; - else break; // Last commit is not deallocated! + ver = datever_from_time(git_commit_time(commit)); + if (datever_is_valid(&prev)) { + if (0 == datever_compare(&prev, &ver)) + ver.revision++; + else break; } - strcpy(prev, date); + prev = ver; git_commit_free(commit); } - printf("%s.%d\n", date, count + 1); + git_commit_free(commit); + return prev; +} + + +/// Initialize empty, and thus invalid, version. +struct datever +datever_init() +{ + return (struct datever){ + .year = -1, + .month = -1, + .day = -1, + .revision = -1, + }; +} + + +struct datever +datever_from_time(const time_t time) +{ + const struct tm* tm = gmtime(&time); + return (struct datever){ + .year = tm->tm_year + 1900, + .month = tm->tm_mon + 1, + .day = tm->tm_mday, + .revision = 1, + }; } -/// If [[err]] is considered erroneuos, print [[msg]] and the last libgit2 error to standard error and then terminate. int -must(const char* msg, const int err) +datever_is_valid(const struct datever* const ver) { - if (0 > err) { - const git_error* const e = git_error_last(); - if (NULL != msg) - dprintf(2, "%s: ", msg); - dprintf(2, "%s\n", e->message); - exit(1); - } - return err; + return 0 <= ver->year && 0 <= ver->month && 0 <= ver->day && 0 <= ver->revision; +} + + +/// Compares two versions date-wise ignoring revision count. Returns similarly to strcmp(3). +int +datever_compare(const struct datever* const lhs, const struct datever* const rhs) +{ + if (lhs->year > rhs->year) return -1; + if (lhs->year < rhs->year) return 1; + if (lhs->month > rhs->month) return -1; + if (lhs->month < rhs->month) return 1; + if (lhs->day > rhs->day) return -1; + if (lhs->day < rhs->day) return 1; + return 0; } |