diff options
author | Aki <please@ignore.pl> | 2022-07-06 22:06:42 +0200 |
---|---|---|
committer | Aki <please@ignore.pl> | 2022-07-06 22:06:42 +0200 |
commit | 6e997d497c90562bfc1a1759142439b347a9e27a (patch) | |
tree | 12f6d51ffa97f76b892b9003d426ac014c61286b | |
download | pkgrel-6e997d497c90562bfc1a1759142439b347a9e27a.zip pkgrel-6e997d497c90562bfc1a1759142439b347a9e27a.tar.gz pkgrel-6e997d497c90562bfc1a1759142439b347a9e27a.tar.bz2 |
Implemented a naive printer for commits that change cwd/PKGBUILD
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | pkgrel.c | 132 |
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); +} |