Skip to content

Commit d084fa2

Browse files
10ne1gitster
authored andcommitted
hook: allow event = "" to overwrite previous values
Add the ability for empty events to clear previously set multivalue variables, so the newly added "hook.*.event" behave like the other multivalued keys. 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>
1 parent 1ecce72 commit d084fa2

File tree

3 files changed

+34
-11
lines changed

3 files changed

+34
-11
lines changed

Documentation/config/hook.adoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ hook.<name>.event::
1212
linkgit:githooks[5] for a complete list of hook events.) On the
1313
specified event, the associated `hook.<name>.command` is executed.
1414
This is a multi-valued key. To run `hook.<name>` on multiple
15-
events, specify the key more than once. See linkgit:git-hook[1].
15+
events, specify the key more than once. An empty value resets
16+
the list of events, clearing any previously defined events for
17+
`hook.<name>`. See linkgit:git-hook[1].
1618

1719
hook.<name>.enabled::
1820
Whether the hook `hook.<name>` is enabled. Defaults to `true`.

hook.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -147,18 +147,27 @@ static int hook_config_lookup_all(const char *key, const char *value,
147147
hook_name = xmemdupz(name, name_len);
148148

149149
if (!strcmp(subkey, "event")) {
150-
struct string_list *hooks =
151-
strmap_get(&data->event_hooks, value);
150+
if (!*value) {
151+
/* Empty values reset previous events for this hook. */
152+
struct hashmap_iter iter;
153+
struct strmap_entry *e;
154+
155+
strmap_for_each_entry(&data->event_hooks, &iter, e)
156+
unsorted_string_list_remove(e->value, hook_name);
157+
} else {
158+
struct string_list *hooks =
159+
strmap_get(&data->event_hooks, value);
160+
161+
if (!hooks) {
162+
hooks = xcalloc(1, sizeof(*hooks));
163+
string_list_init_dup(hooks);
164+
strmap_put(&data->event_hooks, value, hooks);
165+
}
152166

153-
if (!hooks) {
154-
hooks = xcalloc(1, sizeof(*hooks));
155-
string_list_init_dup(hooks);
156-
strmap_put(&data->event_hooks, value, hooks);
167+
/* Re-insert if necessary to preserve last-seen order. */
168+
unsorted_string_list_remove(hooks, hook_name);
169+
string_list_append(hooks, hook_name);
157170
}
158-
159-
/* Re-insert if necessary to preserve last-seen order. */
160-
unsorted_string_list_remove(hooks, hook_name);
161-
string_list_append(hooks, hook_name);
162171
} else if (!strcmp(subkey, "command")) {
163172
/* Store command overwriting the old value */
164173
char *old = strmap_put(&data->commands, hook_name,

t/t1800-hook.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,18 @@ test_expect_success 'git hook list reorders on duplicate event declarations' '
226226
test_cmp expected actual
227227
'
228228

229+
test_expect_success 'git hook list: empty event value resets events' '
230+
setup_hooks &&
231+
232+
# ghi is configured for pre-commit; reset it with an empty value
233+
test_config hook.ghi.event "" --add &&
234+
235+
# only def should remain for pre-commit
236+
echo "def" >expected &&
237+
git hook list pre-commit >actual &&
238+
test_cmp expected actual
239+
'
240+
229241
test_expect_success 'hook can be configured for multiple events' '
230242
setup_hooks &&
231243

0 commit comments

Comments
 (0)