commit 3a77b693550a7c0694176c9d3531d778de9d19c1
parent ee379d1d019648168e81ff33e182cb26a75565cc
Author: Wim Dupont <wim@wimdupont.com>
Date: Fri, 21 Nov 2025 22:19:04 +0100
git branch info when lib available
Diffstat:
4 files changed, 127 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
@@ -9,7 +9,7 @@ ${OBJ}: config.h
all: ${BIN}
-LDFLAGS=-lncurses
+LDFLAGS=-lncurses $(LIBGIT2_LDFLAGS)
.c.o:
$(CC) -g -c $(CFLAGS) $<
diff --git a/cex.c b/cex.c
@@ -15,6 +15,10 @@
#include "config.h"
+#if GIT_INFO
+#include <git2.h>
+#endif
+
#define ctrl(x) ((x) & 0x1f)
#define arrlen(arr) (sizeof(arr)/sizeof(0[arr]))
@@ -121,6 +125,14 @@ static int maxy, maxx;
static size_t selc, searchc;
static bool print_bot, hide = DEFAULT_HIDE, searchcs = DEFAULT_SEARCH_CASE_SENS;
+#if GIT_INFO
+static void init_status_options(git_status_options *out_opts);
+static int is_dirty(git_repository *repo, const git_status_options *opts);
+static char *retrieve_git_branch(char *buf, size_t bufsize, const char *repo_path);
+
+static char gitbranch[128];
+#endif
+
int
main(int argc, char **argv)
{
@@ -141,6 +153,10 @@ main(int argc, char **argv)
}
}
+#if GIT_INFO
+ git_libgit2_init();
+#endif
+
editor = getenv("EDITOR");
userinf = *getpwuid(getuid());
@@ -216,6 +232,9 @@ init_screen(void)
resize();
+#if GIT_INFO
+ retrieve_git_branch(gitbranch, sizeof(gitbranch), curwin.path);
+#endif
print_top_title();
print_bot_title();
@@ -666,6 +685,11 @@ print_top_title(void)
clrtoeol();
attron(COLOR_PAIR(TOP_TITLE_COLOR));
printw("%s:%s/%s", username, curwin.path, curwin.winfiles[curwin.highlight].d_name);
+#if GIT_INFO
+ attron(COLOR_PAIR(GIT_BRANCH_COLOR));
+ printw(gitbranch);
+ attroff(COLOR_PAIR(GIT_BRANCH_COLOR));
+#endif
attroff(COLOR_PAIR(TOP_TITLE_COLOR));
}
@@ -966,6 +990,9 @@ change_dir(const char *chdname, Direction direction, bool abspath)
set_win_files(&parwin);
update_child_win();
+#if GIT_INFO
+ retrieve_git_branch(gitbranch, sizeof(gitbranch), curwin.path);
+#endif
}
void
@@ -1215,6 +1242,10 @@ clean(void)
clear_selected();
endwin();
+
+#if GIT_INFO
+ git_libgit2_shutdown();
+#endif
}
void
@@ -1725,3 +1756,71 @@ get_dirname(char *buf, const char *path)
dirname(buf);
return buf;
}
+
+#if GIT_INFO
+void
+init_status_options(git_status_options *out_opts)
+{
+ memset(out_opts, 0, sizeof(*out_opts));
+
+ out_opts->version = GIT_STATUS_OPTIONS_VERSION;
+ out_opts->show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
+ out_opts->flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
+}
+
+int
+is_dirty(git_repository *repo, const git_status_options *opts)
+{
+ size_t change_count;
+ int dirty = 0;
+
+ git_status_list *list = NULL;
+ if (git_status_list_new(&list, repo, opts) < 0)
+ return -1;
+
+ change_count = git_status_list_entrycount(list);
+
+ for (size_t i = 0; i < change_count; ++i) {
+ const git_status_entry *entry = git_status_byindex(list, i);
+ if (entry->status != GIT_STATUS_CURRENT) {
+ dirty = 1;
+ break;
+ }
+ }
+
+ git_status_list_free(list);
+
+ return dirty;
+}
+
+char *
+retrieve_git_branch(char *buf, size_t bufsize, const char *repo_path)
+{
+ git_repository *repo = NULL;
+ git_reference *head_ref = NULL;
+ const char *branch_name = NULL;
+ git_status_options opts;
+
+ if (!buf || bufsize == 0)
+ return NULL;
+ buf[0] = '\0';
+
+ if (repo_path == NULL)
+ return NULL;
+
+ if (git_repository_open_ext(&repo, repo_path, 0, NULL) == 0)
+ if (git_repository_head(&head_ref, repo) == 0)
+ if (git_reference_is_branch(head_ref))
+ branch_name = git_reference_shorthand(head_ref);
+
+ if (branch_name != NULL) {
+ init_status_options(&opts);
+ snprintf(buf, bufsize, " (%s%s)", branch_name, is_dirty(repo, &opts) ? " *" : "");
+ }
+
+ git_reference_free(head_ref);
+ git_repository_free(repo);
+
+ return buf;
+}
+#endif
diff --git a/config.def.h b/config.def.h
@@ -10,6 +10,7 @@
#define SEARCHLEN 20
#define LN_ACCESS_DIR "$HOME/access"
#define USE_SUDO_COMMANDS 1
+#define GIT_INFO HAVE_LIBGIT2
#define KEY_QUIT 'q'
#define KEY_VUP 'k'
@@ -64,6 +65,7 @@
#define BOT_TITLE_INFO_COLOR COLOR_RED
#define PROMPT_COLOR COLOR_MAGENTA
#define CHILDWIN_MESSAGE_COLOR COLOR_MAGENTA
+#define GIT_BRANCH_COLOR COLOR_MAGENTA
#define MARK_SELECTED_COLOR COLOR_GREEN
#endif
diff --git a/config.mk b/config.mk
@@ -9,3 +9,28 @@ PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man
CC = gcc
+
+PKG_CONFIG ?= pkg-config
+
+## Check libgit2
+LIBGIT2_LDFLAGS := $(shell $(PKG_CONFIG) --libs libgit2 2>/dev/null || true)
+
+ifneq ($(strip $(LIBGIT2_LDFLAGS)),)
+ HAVE_LIBGIT2 := 1
+else
+ LIBGIT2_SEARCH_PATHS := /usr/lib /usr/local/lib /opt/homebrew/lib
+ LIBGIT2_FOUND := $(wildcard $(addsuffix /libgit2.so,$(LIBGIT2_SEARCH_PATHS))) \
+ $(wildcard $(addsuffix /libgit2.a,$(LIBGIT2_SEARCH_PATHS)))
+
+ ifneq ($(strip $(LIBGIT2_FOUND)),)
+ HAVE_LIBGIT2 := 1
+ LIBGIT2_LDFLAGS := -lgit2
+ else
+ HAVE_LIBGIT2 := 0
+ LIBGIT2_LDFLAGS :=
+ endif
+endif
+
+CFLAGS += -DHAVE_LIBGIT2=$(HAVE_LIBGIT2)
+CPPFLAGS += -DHAVE_LIBGIT2=$(HAVE_LIBGIT2)
+##