Thread (581 messages) flat view 581 messages, 16 authors, 2021-10-12
STALE1799d

[PATCH 7/9] hook: allow out-of-repo 'git hook' invocations

From: Emily Shaffer <hidden>
Date: 2021-07-15 23:26:39
Subsystem: the rest · Maintainer: Linus Torvalds

Since hooks can now be supplied via the config, and a config can be
present without a gitdir via the global and system configs, we can start
to allow 'git hook run' to occur without a gitdir. This enables us to do
things like run sendemail-validate hooks when running 'git send-email'
from a nongit directory.

It still doesn't make sense to look for hooks in the hookdir in nongit
repos, though, as there is no hookdir.

Signed-off-by: Emily Shaffer <redacted>
---

Notes:
    For hookdir hooks, do we want to run them in nongit dir when core.hooksPath
    is set? For example, if someone set core.hooksPath in their global config and
    then ran 'git hook run sendemail-validate' in a nongit dir?

 git.c                         |  2 +-
 hook.c                        | 18 ++++++++++--------
 t/t1360-config-based-hooks.sh | 13 +++++++++++++
 3 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/git.c b/git.c
index 540909c391..39988ee3b0 100644
--- a/git.c
+++ b/git.c
@@ -538,7 +538,7 @@ static struct cmd_struct commands[] = {
 	{ "grep", cmd_grep, RUN_SETUP_GENTLY },
 	{ "hash-object", cmd_hash_object },
 	{ "help", cmd_help },
-	{ "hook", cmd_hook, RUN_SETUP },
+	{ "hook", cmd_hook, RUN_SETUP_GENTLY },
 	{ "index-pack", cmd_index_pack, RUN_SETUP_GENTLY | NO_PARSEOPT },
 	{ "init", cmd_init_db },
 	{ "init-db", cmd_init_db },
diff --git a/hook.c b/hook.c
index ed90edcad7..b08b876d5d 100644
--- a/hook.c
+++ b/hook.c
@@ -202,7 +202,6 @@ static int hook_config_lookup(const char *key, const char *value, void *cb_data)
 struct list_head* hook_list(const char* hookname, int allow_unknown)
 {
 	struct list_head *hook_head = xmalloc(sizeof(struct list_head));
-	const char *hook_path;
 	struct strbuf hook_key = STRBUF_INIT;
 	struct hook_config_cb cb_data = { &hook_key, hook_head };
 
@@ -216,14 +215,17 @@ struct list_head* hook_list(const char* hookname, int allow_unknown)
 	git_config(hook_config_lookup, &cb_data);
 
 
-	if (allow_unknown)
-		hook_path = find_hook_gently(hookname);
-	else
-		hook_path = find_hook(hookname);
+	if (have_git_dir()) {
+		const char *hook_path;
+		if (allow_unknown)
+			hook_path = find_hook_gently(hookname);
+		else
+			hook_path = find_hook(hookname);
 
-	/* Add the hook from the hookdir */
-	if (hook_path)
-		append_or_move_hook(hook_head, hook_path)->from_hookdir = 1;
+		/* Add the hook from the hookdir */
+		if (hook_path)
+			append_or_move_hook(hook_head, hook_path)->from_hookdir = 1;
+	}
 
 	return hook_head;
 }
diff --git a/t/t1360-config-based-hooks.sh b/t/t1360-config-based-hooks.sh
index 12fca516ec..e4a7b06ad1 100755
--- a/t/t1360-config-based-hooks.sh
+++ b/t/t1360-config-based-hooks.sh
@@ -34,6 +34,19 @@ test_expect_success 'git hook rejects commands without a hookname' '
 	test_must_fail git hook list
 '
 
+test_expect_success 'git hook runs outside of a repo' '
+	setup_hooks &&
+
+	cat >expected <<-EOF &&
+	$ROOT/path/def
+	EOF
+
+	nongit git config --list --global &&
+
+	nongit git hook list pre-commit >actual &&
+	test_cmp expected actual
+'
+
 test_expect_success 'git hook list orders by config order' '
 	setup_hooks &&
 
-- 
2.32.0.402.g57bb445576-goog
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help