summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2022-07-06 22:06:42 +0200
committerAki <please@ignore.pl>2022-07-06 22:06:42 +0200
commit6e997d497c90562bfc1a1759142439b347a9e27a (patch)
tree12f6d51ffa97f76b892b9003d426ac014c61286b
downloadpkgrel-6e997d497c90562bfc1a1759142439b347a9e27a.zip
pkgrel-6e997d497c90562bfc1a1759142439b347a9e27a.tar.gz
pkgrel-6e997d497c90562bfc1a1759142439b347a9e27a.tar.bz2
Implemented a naive printer for commits that change cwd/PKGBUILD
-rw-r--r--.gitignore2
-rw-r--r--Makefile9
-rw-r--r--pkgrel.c132
3 files changed, 143 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ad2ddb2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.o
+pkgrel
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..17249eb
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,9 @@
+CFLAGS=`pkg-config --cflags libgit2 libpcre2-8`
+LDLIBS=`pkg-config --libs libgit2 libpcre2-8`
+
+all: pkgrel
+
+clean:
+ rm -f *.o pkgrel
+
+.PHONY: all clean
diff --git a/pkgrel.c b/pkgrel.c
new file mode 100644
index 0000000..a803c39
--- /dev/null
+++ b/pkgrel.c
@@ -0,0 +1,132 @@
+#define PCRE2_CODE_UNIT_WIDTH 8
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <git2.h>
+#include <pcre2.h>
+
+
+size_t
+min(const size_t lhs, const size_t rhs)
+{
+ return lhs > rhs ? rhs : lhs;
+}
+
+
+char*
+relative_path_in_current_dir(git_repository* repo, const char* filename)
+{
+ const long maximum = pathconf(".", _PC_PATH_MAX);
+ size_t len = 0 > maximum ? 1024 : maximum;
+ char* buf = NULL;
+ char* cwd = NULL;
+ for (; NULL == cwd && 1024 * 50 > len; len *= 2) {
+ if (NULL == (cwd = realloc(buf, len))) {
+ if (NULL != buf)
+ free(buf);
+ return NULL;
+ }
+ buf = cwd;
+ cwd = getcwd(buf, len);
+ if (NULL == cwd && ERANGE != errno) {
+ free(buf);
+ return NULL;
+ }
+ }
+ const char* workdir = git_repository_workdir(repo);
+ const size_t prefix = min(strlen(cwd), strlen(workdir));
+ if (0 != strncmp(cwd, workdir, prefix)) {
+ free(cwd);
+ return NULL;
+ }
+ const size_t relative = strlen(cwd + prefix);
+ if (NULL == (buf = malloc(relative + strlen(filename) + 2))) {
+ free(cwd);
+ return NULL;
+ }
+ strcpy(buf, cwd + prefix);
+ if (0 < relative)
+ strcat(buf, "/");
+ strcat(buf, filename);
+ free(cwd);
+ return buf;
+}
+
+
+void
+gerror(void)
+{
+ const git_error* err = git_error_last();
+ dprintf(2, "%s\n", err->message);
+}
+
+
+int
+main(int argc, char* argv[])
+{
+ git_libgit2_init();
+ git_repository* repo = NULL;
+ int err = git_repository_open_ext(&repo, NULL, GIT_REPOSITORY_OPEN_FROM_ENV, NULL);
+ if (0 > err) {
+ gerror();
+ return 1;
+ }
+ git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
+ diffopts.pathspec.strings = (char*[]){relative_path_in_current_dir(repo, "PKGBUILD")};
+ diffopts.pathspec.count = 1;
+ git_pathspec* pathspec = NULL;
+ err = git_pathspec_new(&pathspec, &diffopts.pathspec);
+ if (0 > err) {
+ gerror();
+ return 1;
+ }
+ git_revwalk* walker = NULL;
+ err = git_revwalk_new(&walker, repo);
+ if (0 > err) {
+ gerror();
+ return 1;
+ }
+ err = git_revwalk_push_head(walker);
+ if (0 > err) {
+ gerror();
+ return 1;
+ }
+ git_oid oid;
+ git_tree* earlier = NULL;
+ git_tree* later = NULL;
+ while (0 == git_revwalk_next(&oid, walker)) {
+ git_commit* commit;
+ err = git_commit_lookup(&commit, repo, &oid);
+ if (0 > err) {
+ gerror();
+ return 1;
+ }
+ if (NULL != earlier)
+ git_tree_free(earlier);
+ earlier = later;
+ err = git_commit_tree(&later, commit);
+ if (0 > err) {
+ gerror();
+ return 1;
+ }
+ const int matched = 0 == git_pathspec_match_tree(NULL, later, GIT_PATHSPEC_NO_MATCH_ERROR, pathspec);
+ if (matched) {
+ char buf[GIT_OID_HEXSZ + 1];
+ git_oid_tostr(buf, sizeof(buf), git_commit_id(commit));
+ puts(buf);
+ }
+ git_commit_free(commit);
+ }
+ if (NULL != earlier)
+ git_tree_free(earlier);
+ if (NULL != later)
+ git_tree_free(later);
+ git_revwalk_free(walker);
+ git_pathspec_free(pathspec);
+ free(diffopts.pathspec.strings[0]);
+ git_repository_free(repo);
+}