mirror of
https://github.com/git/git.git
synced 2026-03-10 17:18:43 +01:00
hook: show disabled hooks in "git hook list"
Disabled hooks were filtered out of the cache entirely, making them invisible to "git hook list". Keep them in the cache with a new "disabled" flag which is propagated to the respective struct hook. "git hook list" now shows disabled hooks annotated with "(disabled)" in the config order. With --show-scope, it looks like: $ git hook list --show-scope pre-commit linter (global) no-leaks (local, disabled) hook from hookdir A disabled hook without a command issues a warning instead of the fatal "hook.X.command must be configured" error. We could also throw an error, however it seemd a bit excessive to me in this case. 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>
This commit is contained in:
committed by
Junio C Hamano
parent
dcd7ab7d2e
commit
86a30747ae
@@ -72,16 +72,20 @@ static int list(int argc, const char **argv, const char *prefix,
|
||||
case HOOK_TRADITIONAL:
|
||||
printf("%s%c", _("hook from hookdir"), line_terminator);
|
||||
break;
|
||||
case HOOK_CONFIGURED:
|
||||
if (show_scope)
|
||||
printf("%s (%s)%c",
|
||||
h->u.configured.friendly_name,
|
||||
config_scope_name(h->u.configured.scope),
|
||||
case HOOK_CONFIGURED: {
|
||||
const char *name = h->u.configured.friendly_name;
|
||||
const char *scope = show_scope ?
|
||||
config_scope_name(h->u.configured.scope) : NULL;
|
||||
if (scope)
|
||||
printf("%s (%s%s)%c", name, scope,
|
||||
h->u.configured.disabled ? ", disabled" : "",
|
||||
line_terminator);
|
||||
else if (h->u.configured.disabled)
|
||||
printf("%s (disabled)%c", name, line_terminator);
|
||||
else
|
||||
printf("%s%c", h->u.configured.friendly_name,
|
||||
line_terminator);
|
||||
printf("%s%c", name, line_terminator);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BUG("unknown hook kind");
|
||||
}
|
||||
|
||||
54
hook.c
54
hook.c
@@ -119,6 +119,7 @@ static void list_hooks_add_default(struct repository *r, const char *hookname,
|
||||
struct hook_config_cache_entry {
|
||||
char *command;
|
||||
enum config_scope scope;
|
||||
int disabled;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -217,8 +218,10 @@ static int hook_config_lookup_all(const char *key, const char *value,
|
||||
* every item's string is the hook's friendly-name and its util pointer is
|
||||
* a hook_config_cache_entry. All strings are owned by the map.
|
||||
*
|
||||
* Disabled hooks and hooks missing a command are already filtered out at
|
||||
* parse time, so callers can iterate the list directly.
|
||||
* Disabled hooks are kept in the cache with entry->disabled set, so that
|
||||
* "git hook list" can display them. Hooks missing a command are filtered
|
||||
* out at build time; if a disabled hook has no command it is silently
|
||||
* skipped rather than triggering a fatal error.
|
||||
*/
|
||||
void hook_cache_clear(struct hook_config_cache *cache)
|
||||
{
|
||||
@@ -268,21 +271,26 @@ static void build_hook_config_map(struct repository *r,
|
||||
struct hook_config_cache_entry *entry;
|
||||
char *command;
|
||||
|
||||
/* filter out disabled hooks */
|
||||
if (unsorted_string_list_lookup(&cb_data.disabled_hooks,
|
||||
hname))
|
||||
continue;
|
||||
int is_disabled =
|
||||
!!unsorted_string_list_lookup(
|
||||
&cb_data.disabled_hooks, hname);
|
||||
|
||||
command = strmap_get(&cb_data.commands, hname);
|
||||
if (!command)
|
||||
die(_("'hook.%s.command' must be configured or "
|
||||
"'hook.%s.event' must be removed;"
|
||||
" aborting."), hname, hname);
|
||||
if (!command) {
|
||||
if (is_disabled)
|
||||
warning(_("disabled hook '%s' has no "
|
||||
"command configured"), hname);
|
||||
else
|
||||
die(_("'hook.%s.command' must be configured or "
|
||||
"'hook.%s.event' must be removed;"
|
||||
" aborting."), hname, hname);
|
||||
}
|
||||
|
||||
/* util stores a cache entry; owned by the cache. */
|
||||
CALLOC_ARRAY(entry, 1);
|
||||
entry->command = xstrdup(command);
|
||||
entry->command = command ? xstrdup(command) : NULL;
|
||||
entry->scope = scope;
|
||||
entry->disabled = is_disabled;
|
||||
string_list_append(hooks, hname)->util = entry;
|
||||
}
|
||||
|
||||
@@ -362,8 +370,10 @@ static void list_hooks_add_configured(struct repository *r,
|
||||
|
||||
hook->kind = HOOK_CONFIGURED;
|
||||
hook->u.configured.friendly_name = xstrdup(friendly_name);
|
||||
hook->u.configured.command = xstrdup(entry->command);
|
||||
hook->u.configured.command =
|
||||
entry->command ? xstrdup(entry->command) : NULL;
|
||||
hook->u.configured.scope = entry->scope;
|
||||
hook->u.configured.disabled = entry->disabled;
|
||||
|
||||
string_list_append(list, friendly_name)->util = hook;
|
||||
}
|
||||
@@ -401,7 +411,16 @@ struct string_list *list_hooks(struct repository *r, const char *hookname,
|
||||
int hook_exists(struct repository *r, const char *name)
|
||||
{
|
||||
struct string_list *hooks = list_hooks(r, name, NULL);
|
||||
int exists = hooks->nr > 0;
|
||||
int exists = 0;
|
||||
|
||||
for (size_t i = 0; i < hooks->nr; i++) {
|
||||
struct hook *h = hooks->items[i].util;
|
||||
if (h->kind == HOOK_TRADITIONAL ||
|
||||
!h->u.configured.disabled) {
|
||||
exists = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
string_list_clear_func(hooks, hook_free);
|
||||
free(hooks);
|
||||
return exists;
|
||||
@@ -416,10 +435,11 @@ static int pick_next_hook(struct child_process *cp,
|
||||
struct string_list *hook_list = hook_cb->hook_command_list;
|
||||
struct hook *h;
|
||||
|
||||
if (hook_cb->hook_to_run_index >= hook_list->nr)
|
||||
return 0;
|
||||
|
||||
h = hook_list->items[hook_cb->hook_to_run_index++].util;
|
||||
do {
|
||||
if (hook_cb->hook_to_run_index >= hook_list->nr)
|
||||
return 0;
|
||||
h = hook_list->items[hook_cb->hook_to_run_index++].util;
|
||||
} while (h->kind == HOOK_CONFIGURED && h->u.configured.disabled);
|
||||
|
||||
cp->no_stdin = 1;
|
||||
strvec_pushv(&cp->env, hook_cb->options->env.v);
|
||||
|
||||
1
hook.h
1
hook.h
@@ -31,6 +31,7 @@ struct hook {
|
||||
const char *friendly_name;
|
||||
const char *command;
|
||||
enum config_scope scope;
|
||||
int disabled;
|
||||
} configured;
|
||||
} u;
|
||||
|
||||
|
||||
@@ -357,7 +357,15 @@ test_expect_success 'disabled hook is not run' '
|
||||
test_must_be_empty actual
|
||||
'
|
||||
|
||||
test_expect_success 'disabled hook does not appear in git hook list' '
|
||||
test_expect_success 'disabled hook with no command warns' '
|
||||
test_config hook.nocommand.event "pre-commit" &&
|
||||
test_config hook.nocommand.enabled false &&
|
||||
|
||||
git hook list pre-commit 2>actual &&
|
||||
test_grep "disabled hook.*nocommand.*no command configured" actual
|
||||
'
|
||||
|
||||
test_expect_success 'disabled hook appears as disabled in git hook list' '
|
||||
test_config hook.active.event "pre-commit" &&
|
||||
test_config hook.active.command "echo active" &&
|
||||
test_config hook.inactive.event "pre-commit" &&
|
||||
@@ -365,8 +373,27 @@ test_expect_success 'disabled hook does not appear in git hook list' '
|
||||
test_config hook.inactive.enabled false &&
|
||||
|
||||
git hook list pre-commit >actual &&
|
||||
test_grep "active" actual &&
|
||||
test_grep ! "inactive" actual
|
||||
test_grep "^active$" actual &&
|
||||
test_grep "^inactive (disabled)$" actual
|
||||
'
|
||||
|
||||
test_expect_success 'disabled hook shows scope with --show-scope' '
|
||||
test_config hook.myhook.event "pre-commit" &&
|
||||
test_config hook.myhook.command "echo hi" &&
|
||||
test_config hook.myhook.enabled false &&
|
||||
|
||||
git hook list --show-scope pre-commit >actual &&
|
||||
test_grep "myhook (local, disabled)" actual
|
||||
'
|
||||
|
||||
test_expect_success 'disabled configured hook is not reported as existing by hook_exists' '
|
||||
test_when_finished "rm -f git-bugreport-hook-exists-test.txt" &&
|
||||
test_config hook.linter.event "pre-commit" &&
|
||||
test_config hook.linter.command "echo lint" &&
|
||||
test_config hook.linter.enabled false &&
|
||||
|
||||
git bugreport -s hook-exists-test &&
|
||||
test_grep ! "pre-commit" git-bugreport-hook-exists-test.txt
|
||||
'
|
||||
|
||||
test_expect_success 'globally disabled hook can be re-enabled locally' '
|
||||
|
||||
Reference in New Issue
Block a user