hook: add list command

Teach 'git hook list <hookname>', which checks the known configs in
order to create an ordered list of hooks to run on a given hook event.

Multiple commands can be specified for a given hook by providing
multiple "hook.<hookname>.command = <path-to-hook>" lines. Hooks will be
run in config order. If more properties need to be set on a given hook
in the future, commands can also be specified by providing
"hook.<hookname>.command = <hookcmd-name>", as well as a "[hookcmd
<hookcmd-name>]" subsection; at minimum, this subsection must contain a
"hookcmd.<hookcmd-name>.command = <path-to-hook>" line.

For example:

  $ git config --list | grep ^hook
  hook.pre-commit.command=baz
  hook.pre-commit.command=~/bar.sh
  hookcmd.baz.command=~/baz/from/hookcmd.sh

  $ git hook list pre-commit
  ~/baz/from/hookcmd.sh
  ~/bar.sh

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:13 -07:00
committed by Junio C Hamano
parent aa8bbb612b
commit 933f1b2e0c
6 changed files with 242 additions and 7 deletions

View File

@ -1,21 +1,68 @@
#include "cache.h"
#include "builtin.h"
#include "config.h"
#include "hook.h"
#include "parse-options.h"
#include "strbuf.h"
static const char * const builtin_hook_usage[] = {
N_("git hook"),
N_("git hook list <hookname>"),
NULL
};
static int list(int argc, const char **argv, const char *prefix)
{
struct list_head *head, *pos;
struct hook *item;
struct strbuf hookname = STRBUF_INIT;
struct option list_options[] = {
OPT_END(),
};
argc = parse_options(argc, argv, prefix, list_options,
builtin_hook_usage, 0);
if (argc < 1) {
usage_msg_opt("a hookname must be provided to operate on.",
builtin_hook_usage, list_options);
}
strbuf_addstr(&hookname, argv[0]);
head = hook_list(&hookname);
if (!head) {
printf(_("no commands configured for hook '%s'\n"),
hookname.buf);
return 0;
}
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);
}
clear_hook_list();
strbuf_release(&hookname);
return 0;
}
int cmd_hook(int argc, const char **argv, const char *prefix)
{
struct option builtin_hook_options[] = {
OPT_END(),
};
if (argc < 2)
usage_with_options(builtin_hook_usage, builtin_hook_options);
argc = parse_options(argc, argv, prefix, builtin_hook_options,
builtin_hook_usage, 0);
if (!strcmp(argv[1], "list"))
return list(argc - 1, argv + 1, prefix);
return 0;
usage_with_options(builtin_hook_usage, builtin_hook_options);
}