aboutsummaryrefslogtreecommitdiff
path: root/hook.c
diff options
context:
space:
mode:
authorAdrian Ratiu <adrian.ratiu@collabora.com>2026-03-25 21:55:01 +0200
committerJunio C Hamano <gitster@pobox.com>2026-03-25 14:00:47 -0700
commitb66efad2b1f53755a80699dc39f94e2b15d6af67 (patch)
tree3e42cefd6493973af8c8e6e6aa6059836cb1fc50 /hook.c
parentd8513bc5d84f21ea6d327a9cf9a369077eb19c67 (diff)
downloadgit-b66efad2b1f53755a80699dc39f94e2b15d6af67.tar.xz
hook: show config scope in git hook list
Users running "git hook list" can see which hooks are configured but have no way to tell at which config scope (local, global, system...) each hook was defined. Store the scope from ctx->kvi->scope in the single-pass config callback, then carry it through the cache to the hook structs, so we can expose it to users via the "git hook list --show-scope" flag, which mirrors the existing git config --show-scope convention. Without the flag the output is unchanged. The scope is printed as a tab-separated prefix (like "git config --show-scope"), making it unambiguously machine-parseable even when the friendly name contains spaces. Example usage: $ git hook list --show-scope pre-commit global linter local no-leaks hook from hookdir Traditional hooks from the hookdir are unaffected by --show-scope since the config scope concept does not apply to them. Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'hook.c')
-rw-r--r--hook.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/hook.c b/hook.c
index 54f99f4989..74f5a1df35 100644
--- a/hook.c
+++ b/hook.c
@@ -110,11 +110,11 @@ static void list_hooks_add_default(struct repository *r, const char *hookname,
/*
* Cache entry stored as the .util pointer of string_list items inside the
- * hook config cache. For now carries only the command for the hook. Next
- * commits will add more data.
+ * hook config cache.
*/
struct hook_config_cache_entry {
char *command;
+ enum config_scope scope;
};
/*
@@ -131,7 +131,7 @@ struct hook_all_config_cb {
/* repo_config() callback that collects all hook.* configuration in one pass. */
static int hook_config_lookup_all(const char *key, const char *value,
- const struct config_context *ctx UNUSED,
+ const struct config_context *ctx,
void *cb_data)
{
struct hook_all_config_cb *data = cb_data;
@@ -168,7 +168,19 @@ static int hook_config_lookup_all(const char *key, const char *value,
/* Re-insert if necessary to preserve last-seen order. */
unsorted_string_list_remove(hooks, hook_name, 0);
- string_list_append(hooks, hook_name);
+
+ if (!ctx->kvi)
+ BUG("hook config callback called without key-value info");
+
+ /*
+ * Stash the config scope in the util pointer for
+ * later retrieval in build_hook_config_map(). This
+ * intermediate struct is transient and never leaves
+ * that function, so we pack the enum value into the
+ * pointer rather than heap-allocating a wrapper.
+ */
+ string_list_append(hooks, hook_name)->util =
+ (void *)(uintptr_t)ctx->kvi->scope;
}
} else if (!strcmp(subkey, "command")) {
/* Store command overwriting the old value */
@@ -246,6 +258,8 @@ static void build_hook_config_map(struct repository *r, struct strmap *cache)
for (size_t i = 0; i < hook_names->nr; i++) {
const char *hname = hook_names->items[i].string;
+ enum config_scope scope =
+ (enum config_scope)(uintptr_t)hook_names->items[i].util;
struct hook_config_cache_entry *entry;
char *command;
@@ -263,6 +277,7 @@ static void build_hook_config_map(struct repository *r, struct strmap *cache)
/* util stores a cache entry; owned by the cache. */
CALLOC_ARRAY(entry, 1);
entry->command = xstrdup(command);
+ entry->scope = scope;
string_list_append(hooks, hname)->util = entry;
}
@@ -344,6 +359,7 @@ static void list_hooks_add_configured(struct repository *r,
hook->kind = HOOK_CONFIGURED;
hook->u.configured.friendly_name = xstrdup(friendly_name);
hook->u.configured.command = xstrdup(entry->command);
+ hook->u.configured.scope = entry->scope;
string_list_append(list, friendly_name)->util = hook;
}