diff options
| author | Adrian Ratiu <adrian.ratiu@collabora.com> | 2026-03-25 21:55:03 +0200 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2026-03-25 14:00:48 -0700 |
| commit | 5c58dbc887a1f3530cb29c995f63675beebb22e9 (patch) | |
| tree | 1db89b9b9a4ef3f852b228f62c11c813174c2336 /builtin | |
| parent | e17bd99281ae01a758d717bdfaa759bbeefb6149 (diff) | |
| download | git-5c58dbc887a1f3530cb29c995f63675beebb22e9.tar.xz | |
hook: reject unknown hook names in git-hook(1)
Teach "git hook run" and "git hook list" to reject hook event names
that are not recognized by Git. This helps catch typos such as
"prereceive" when "pre-receive" was intended, since in 99% of the
cases users want known (already-existing) hook names.
The list of known hooks is derived from the generated hook-list.h
(built from Documentation/githooks.adoc). This is why the Makefile
is updated, so builtin/hook.c depends on hook-list.h. In meson the
header is already a dependency for all builtins, no change required.
The "--allow-unknown-hook-name" flag can be used to bypass this check.
Suggested-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin')
| -rw-r--r-- | builtin/hook.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/builtin/hook.c b/builtin/hook.c index f671e7f91a..c0585587e5 100644 --- a/builtin/hook.c +++ b/builtin/hook.c @@ -4,12 +4,22 @@ #include "environment.h" #include "gettext.h" #include "hook.h" +#include "hook-list.h" #include "parse-options.h" #define BUILTIN_HOOK_RUN_USAGE \ - N_("git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-args>]") + N_("git hook run [--allow-unknown-hook-name] [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-args>]") #define BUILTIN_HOOK_LIST_USAGE \ - N_("git hook list [-z] [--show-scope] <hook-name>") + N_("git hook list [--allow-unknown-hook-name] [-z] [--show-scope] <hook-name>") + +static int is_known_hook(const char *name) +{ + const char **p; + for (p = hook_name_list; *p; p++) + if (!strcmp(*p, name)) + return 1; + return 0; +} static const char * const builtin_hook_usage[] = { BUILTIN_HOOK_RUN_USAGE, @@ -34,6 +44,7 @@ static int list(int argc, const char **argv, const char *prefix, const char *hookname = NULL; int line_terminator = '\n'; int show_scope = 0; + int allow_unknown = 0; int ret = 0; struct option list_options[] = { @@ -41,6 +52,8 @@ static int list(int argc, const char **argv, const char *prefix, N_("use NUL as line terminator"), '\0'), OPT_BOOL(0, "show-scope", &show_scope, N_("show the config scope that defined each hook")), + OPT_BOOL(0, "allow-unknown-hook-name", &allow_unknown, + N_("allow running a hook with a non-native hook name")), OPT_END(), }; @@ -57,6 +70,13 @@ static int list(int argc, const char **argv, const char *prefix, hookname = argv[0]; + if (!allow_unknown && !is_known_hook(hookname)) { + error(_("unknown hook event '%s';\n" + "use --allow-unknown-hook-name to allow non-native hook names"), + hookname); + return 1; + } + head = list_hooks(repo, hookname, NULL); if (!head->nr) { @@ -103,8 +123,11 @@ static int run(int argc, const char **argv, const char *prefix, int i; struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT; int ignore_missing = 0; + int allow_unknown = 0; const char *hook_name; struct option run_options[] = { + OPT_BOOL(0, "allow-unknown-hook-name", &allow_unknown, + N_("allow running a hook with a non-native hook name")), OPT_BOOL(0, "ignore-missing", &ignore_missing, N_("silently ignore missing requested <hook-name>")), OPT_STRING(0, "to-stdin", &opt.path_to_stdin, N_("path"), @@ -136,6 +159,14 @@ static int run(int argc, const char **argv, const char *prefix, repo_config(the_repository, git_default_config, NULL); hook_name = argv[0]; + + if (!allow_unknown && !is_known_hook(hook_name)) { + error(_("unknown hook event '%s';\n" + "use --allow-unknown-hook-name to allow non-native hook names"), + hook_name); + return 1; + } + if (!ignore_missing) opt.error_if_missing = 1; ret = run_hooks_opt(the_repository, hook_name, &opt); |
