[PATCH v8 04/37] hook: include hookdir hook in list
From: Emily Shaffer <hidden>
Date: 2021-03-11 02:11:34
Subsystem:
the rest · Maintainer:
Linus Torvalds
Historically, hooks are declared by placing an executable into
$GIT_DIR/hooks/$HOOKNAME (or $HOOKDIR/$HOOKNAME). Although hooks taken
from the config are more featureful than hooks placed in the $HOOKDIR,
those hooks should not stop working for users who already have them.
Let's list them to the user, but instead of displaying a config scope
(e.g. "global: blah") we can prefix them with "hookdir:".
Signed-off-by: Emily Shaffer <redacted>
---
Notes:
Since v7, fix some nits from Jonathan Tan. The largest is to move reference to
"hookdir annotation" from this commit to the next one which introduces the
hook.runHookDir option.
builtin/hook.c | 11 +++++++++--
hook.c | 17 +++++++++++++++++
hook.h | 1 +
t/t1360-config-based-hooks.sh | 19 +++++++++++++++++++
4 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/builtin/hook.c b/builtin/hook.c
index bb64cd77ca..c8fbfbb39d 100644
--- a/builtin/hook.c
+++ b/builtin/hook.c@@ -40,10 +40,15 @@ static int list(int argc, const char **argv, const char *prefix) list_for_each(pos, head) { struct hook *item = list_entry(pos, struct hook, list); - if (item) + item = list_entry(pos, struct hook, list); + if (item) { + /* Don't translate 'hookdir' - it matches the config */ printf("%s: %s\n", - config_scope_name(item->origin), + (item->from_hookdir + ? "hookdir" + : config_scope_name(item->origin)), item->command.buf); + } } clear_hook_list(head);
@@ -60,6 +65,8 @@ int cmd_hook(int argc, const char **argv, const char *prefix) if (argc < 2) usage_with_options(builtin_hook_usage, builtin_hook_options); + git_config(git_default_config, NULL); + if (!strcmp(argv[1], "list")) return list(argc - 1, argv + 1, prefix);
diff --git a/hook.c b/hook.c
index fede40e925..080e25696b 100644
--- a/hook.c
+++ b/hook.c@@ -2,6 +2,7 @@ #include "hook.h" #include "config.h" +#include "run-command.h" void free_hook(struct hook *ptr) {
@@ -35,6 +36,7 @@ static void append_or_move_hook(struct list_head *head, const char *command) to_add = xmalloc(sizeof(*to_add)); strbuf_init(&to_add->command, 0); strbuf_addstr(&to_add->command, command); + to_add->from_hookdir = 0; } /* re-set the scope so we show where an override was specified */
@@ -115,6 +117,21 @@ struct list_head* hook_list(const struct strbuf* hookname) git_config(hook_config_lookup, &cb_data); + if (have_git_dir()) { + const char *legacy_hook_path = find_hook(hookname->buf); + + /* Unconditionally add legacy hook, but annotate it. */ + if (legacy_hook_path) { + struct hook *legacy_hook; + + append_or_move_hook(hook_head, + absolute_path(legacy_hook_path)); + legacy_hook = list_entry(hook_head->prev, struct hook, + list); + legacy_hook->from_hookdir = 1; + } + } + strbuf_release(&hook_key); return hook_head; }
diff --git a/hook.h b/hook.h
index e48dfc6d27..a97d43670d 100644
--- a/hook.h
+++ b/hook.h@@ -11,6 +11,7 @@ struct hook { enum config_scope origin; /* The literal command to run. */ struct strbuf command; + unsigned from_hookdir : 1; }; /*
diff --git a/t/t1360-config-based-hooks.sh b/t/t1360-config-based-hooks.sh
index 6e4a3e763f..0f12af4659 100755
--- a/t/t1360-config-based-hooks.sh
+++ b/t/t1360-config-based-hooks.sh@@ -23,6 +23,14 @@ setup_hookcmd () { test_config_global hookcmd.abc.command "/path/abc" --add } +setup_hookdir () { + mkdir .git/hooks + write_script .git/hooks/pre-commit <<-EOF + echo \"Legacy Hook\" + EOF + test_when_finished rm -rf .git/hooks +} + test_expect_success 'git hook rejects commands without a mode' ' test_must_fail git hook pre-commit '
@@ -85,4 +93,15 @@ test_expect_success 'git hook list reorders on duplicate commands' ' test_cmp expected actual ' +test_expect_success 'git hook list shows hooks from the hookdir' ' + setup_hookdir && + + cat >expected <<-EOF && + hookdir: $(pwd)/.git/hooks/pre-commit + EOF + + git hook list pre-commit >actual && + test_cmp expected actual +' + test_done
--
2.31.0.rc2.261.g7f71774620-goog