summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--datever.c126
2 files changed, 93 insertions, 36 deletions
diff --git a/Makefile b/Makefile
index 5a5f407..f48a6f7 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/datever.c b/datever.c
index a8c63df..626899b 100644
--- a/datever.c
+++ b/datever.c
@@ -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(&gt);
- 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;
}