diff options
| author | Emily Shaffer <emilyshaffer@google.com> | 2026-02-19 00:23:51 +0200 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2026-02-19 13:24:39 -0800 |
| commit | b51e238ddf896439d2746b883d892f8f9bba649f (patch) | |
| tree | db0e317b5b8adaf1d2d807281784d22c0b07d1f0 /hook.c | |
| parent | d084fa2a915784d65257fbaff43f00b3ea5c8a44 (diff) | |
| download | git-b51e238ddf896439d2746b883d892f8f9bba649f.tar.xz | |
hook: allow out-of-repo 'git hook' invocations
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 <emilyshaffer@google.com>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'hook.c')
| -rw-r--r-- | hook.c | 30 |
1 files changed, 28 insertions, 2 deletions
@@ -18,6 +18,9 @@ const char *find_hook(struct repository *r, const char *name) int found_hook; + if (!r || !r->gitdir) + return NULL; + repo_git_path_replace(r, &path, "hooks/%s", name); found_hook = access(path.buf, X_OK) >= 0; #ifdef STRIP_EXTENSION @@ -268,12 +271,18 @@ static void build_hook_config_map(struct repository *r, struct strmap *cache) strmap_clear(&cb_data.event_hooks, 0); } -/* Return the hook config map for `r`, populating it first if needed. */ +/* + * Return the hook config map for `r`, populating it first if needed. + * + * Out-of-repo calls (r->gitdir == NULL) allocate and return a temporary + * cache map; the caller is responsible for freeing it with + * hook_cache_clear() + free(). + */ static struct strmap *get_hook_config_cache(struct repository *r) { struct strmap *cache = NULL; - if (r) { + if (r && r->gitdir) { /* * For in-repo calls, the map is stored in r->hook_config_cache, * so repeated invocations don't parse the configs, so allocate @@ -285,6 +294,14 @@ static struct strmap *get_hook_config_cache(struct repository *r) build_hook_config_map(r, r->hook_config_cache); } cache = r->hook_config_cache; + } else { + /* + * Out-of-repo calls (no gitdir) allocate and return a temporary + * map cache which gets free'd immediately by the caller. + */ + cache = xcalloc(1, sizeof(*cache)); + strmap_init(cache); + build_hook_config_map(r, cache); } return cache; @@ -315,6 +332,15 @@ static void list_hooks_add_configured(struct repository *r, string_list_append(list, friendly_name)->util = hook; } + + /* + * Cleanup temporary cache for out-of-repo calls since they can't be + * stored persistently. Next out-of-repo calls will have to re-parse. + */ + if (!r || !r->gitdir) { + hook_cache_clear(cache); + free(cache); + } } struct string_list *list_hooks(struct repository *r, const char *hookname, |
