]> git.ipfire.org Git - thirdparty/git.git/commitdiff
hook: add -z option to "git hook list"
authorAdrian Ratiu <adrian.ratiu@collabora.com>
Wed, 18 Feb 2026 22:23:52 +0000 (00:23 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 19 Feb 2026 21:24:57 +0000 (13:24 -0800)
Add a NUL-terminate mode to git hook list, just in case hooks are
configured with weird characters like newlines in their names.

Suggested-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-hook.adoc
builtin/hook.c
t/t1800-hook.sh

index 7e4259e4f042aa14143eca6ca28412a12cfd8d65..12d2701b5228acd0029f9bbe5ff2975a7b569f37 100644 (file)
@@ -9,7 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git hook' run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-args>]
-'git hook' list <hook-name>
+'git hook' list [-z] <hook-name>
 
 DESCRIPTION
 -----------
@@ -113,9 +113,10 @@ Any positional arguments to the hook should be passed after a
 mandatory `--` (or `--end-of-options`, see linkgit:gitcli[7]). See
 linkgit:githooks[5] for arguments hooks might expect (if any).
 
-list::
+list [-z]::
        Print a list of hooks which will be run on `<hook-name>` event. If no
        hooks are configured for that event, print a warning and return 1.
+       Use `-z` to terminate output lines with NUL instead of newlines.
 
 OPTIONS
 -------
@@ -130,6 +131,9 @@ OPTIONS
        tools that want to do a blind one-shot run of a hook that may
        or may not be present.
 
+-z::
+       Terminate "list" output lines with NUL instead of newlines.
+
 WRAPPERS
 --------
 
index e151bb2cd1d68468a23add9e0f1954740531f5d1..83020dfb4fc57e775c6957f08ce0e44e03e4bf5b 100644 (file)
@@ -11,7 +11,7 @@
 #define BUILTIN_HOOK_RUN_USAGE \
        N_("git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-args>]")
 #define BUILTIN_HOOK_LIST_USAGE \
-       N_("git hook list <hook-name>")
+       N_("git hook list [-z] <hook-name>")
 
 static const char * const builtin_hook_usage[] = {
        BUILTIN_HOOK_RUN_USAGE,
@@ -34,9 +34,12 @@ static int list(int argc, const char **argv, const char *prefix,
        struct string_list *head;
        struct string_list_item *item;
        const char *hookname = NULL;
+       int line_terminator = '\n';
        int ret = 0;
 
        struct option list_options[] = {
+               OPT_SET_INT('z', NULL, &line_terminator,
+                           N_("use NUL as line terminator"), '\0'),
                OPT_END(),
        };
 
@@ -66,10 +69,10 @@ static int list(int argc, const char **argv, const char *prefix,
 
                switch (h->kind) {
                case HOOK_TRADITIONAL:
-                       printf("%s\n", _("hook from hookdir"));
+                       printf("%s%c", _("hook from hookdir"), line_terminator);
                        break;
                case HOOK_CONFIGURED:
-                       printf("%s\n", h->u.configured.friendly_name);
+                       printf("%s%c", h->u.configured.friendly_name, line_terminator);
                        break;
                default:
                        BUG("unknown hook kind");
index e58151e8f868ba7f9bd80b120ad98a40c7296cf2..b1583e9ef9ac5702403f1d88bc0ad45cbaf68a5d 100755 (executable)
@@ -61,6 +61,19 @@ test_expect_success 'git hook list: configured hook' '
        test_cmp expect actual
 '
 
+test_expect_success 'git hook list: -z shows NUL-terminated output' '
+       test_hook test-hook <<-EOF &&
+       echo Test hook
+       EOF
+       test_config hook.myhook.command "echo Hello" &&
+       test_config hook.myhook.event test-hook --add &&
+
+       printf "myhookQhook from hookdirQ" >expect &&
+       git hook list -z test-hook >actual.raw &&
+       nul_to_q <actual.raw >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'git hook run: nonexistent hook' '
        cat >stderr.expect <<-\EOF &&
        error: cannot find a hook named test-hook