hook: add --porcelain to list command

Teach 'git hook list --porcelain <hookname>', which prints simply the
commands to be run in the order suggested by the config. This option is
intended for use by user scripts, wrappers, or out-of-process Git
commands which still want to execute hooks. For example, the following
snippet might be added to git-send-email.perl to introduce a
`pre-send-email` hook:

  sub pre_send_email {
    open(my $fh, 'git hook list --porcelain pre-send-email |');
    chomp(my @hooks = <$fh>);
    close($fh);

    foreach $hook (@hooks) {
            system $hook
    }

Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Emily Shaffer
2020-05-21 11:54:14 -07:00
committed by Junio C Hamano
parent 933f1b2e0c
commit 09b4d75c01
3 changed files with 35 additions and 6 deletions

View File

@ -8,7 +8,7 @@ git-hook - Manage configured hooks
SYNOPSIS
--------
[verse]
'git hook' list <hook-name>
'git hook' list [--porcelain] <hook-name>
DESCRIPTION
-----------
@ -43,11 +43,20 @@ Local config
COMMANDS
--------
list <hook-name>::
list [--porcelain] <hook-name>::
List the hooks which have been configured for <hook-name>. Hooks appear
in the order they should be run, and note the config scope where the relevant
`hook.<hook-name>.command` was specified, not the `hookcmd` (if applicable).
+
If `--porcelain` is specified, instead print the commands alone, separated by
newlines, for easy parsing by a script.
OPTIONS
-------
--porcelain::
With `list`, print the commands in the order they should be run,
separated by newlines, for easy parsing by a script.
GIT
---

View File

@ -16,8 +16,11 @@ static int list(int argc, const char **argv, const char *prefix)
struct list_head *head, *pos;
struct hook *item;
struct strbuf hookname = STRBUF_INIT;
int porcelain = 0;
struct option list_options[] = {
OPT_BOOL(0, "porcelain", &porcelain,
"format for execution by a script"),
OPT_END(),
};
@ -29,6 +32,8 @@ static int list(int argc, const char **argv, const char *prefix)
builtin_hook_usage, list_options);
}
strbuf_addstr(&hookname, argv[0]);
head = hook_list(&hookname);
@ -41,10 +46,14 @@ static int list(int argc, const char **argv, const char *prefix)
list_for_each(pos, head) {
item = list_entry(pos, struct hook, list);
if (item)
printf("%s:\t%s\n",
config_scope_name(item->origin),
item->command.buf);
if (item) {
if (porcelain)
printf("%s\n", item->command.buf);
else
printf("%s:\t%s\n",
config_scope_name(item->origin),
item->command.buf);
}
}
clear_hook_list();

View File

@ -55,4 +55,15 @@ test_expect_success 'git hook list reorders on duplicate commands' '
test_cmp expected actual
'
test_expect_success 'git hook list --porcelain prints just the command' '
cat >expected <<-\EOF &&
/path/ghi
/path/abc
/path/def
EOF
git hook list --porcelain pre-commit >actual &&
test_cmp expected actual
'
test_done