133
* Callback struct to collect all hook.* keys in a single config pass.
134
* commands: friendly-name to command map.
135
* event_hooks: event-name to list of friendly-names map.
136
- * disabled_hooks: set of friendly-names with hook.<friendly-name>.enabled = false.
136
+ * disabled_hooks: set of all names with hook.<name>.enabled = false; after
137
+ * parsing, names that are not friendly-names become event-level
138
+ * disables stored in r->disabled_events. This collects all.
139
* parallel_hooks: friendly-name to parallel flag.
140
* event_jobs: event-name to per-event jobs count (stored as uintptr_t, NULL == unset).
141
* jobs: value of the global hook.jobs key. Defaults to 0 if unset (stored in r->hook_jobs).
191
strmap_for_each_entry(&data->event_hooks, &iter, e)
192
unsorted_string_list_remove(e->value, hook_name, 0);
193
} else {
192
- struct string_list *hooks =
193
- strmap_get(&data->event_hooks, value);
194
+ struct string_list *hooks;
195
+
196
+ if (is_known_hook(hook_name))
197
+ die(_("hook friendly-name '%s' collides with "
198
+ "a known event name; please choose a "
199
+ "different friendly-name"),
200
+ hook_name);
201
+
202
+ if (!strcmp(hook_name, value))
203
+ warning(_("hook friendly-name '%s' is the "
204
+ "same as its event; this may cause "
205
+ "ambiguity with hook.%s.enabled"),
206
+ hook_name, hook_name);
207
+
208
+ hooks = strmap_get(&data->event_hooks, value);
209
210
if (!hooks) {
211
CALLOC_ARRAY(hooks, 1);
360
361
warn_jobs_on_friendly_names(&cb_data);
362
363
+ /*
364
+ * Populate disabled_events: names in disabled_hooks that are not
365
+ * friendly-names are event-level switches (hook.<event>.enabled = false).
366
+ * Names that are friendly-names are already handled per-hook via the
367
+ * hook_config_cache_entry.disabled flag below.
368
+ */
369
+ if (r) {
370
+ string_list_clear(&r->disabled_events, 0);
371
+ string_list_init_dup(&r->disabled_events);
372
+ for (size_t i = 0; i < cb_data.disabled_hooks.nr; i++) {
373
+ const char *n = cb_data.disabled_hooks.items[i].string;
374
+ if (!is_friendly_name(&cb_data, n))
375
+ string_list_append(&r->disabled_events, n);
376
+ }
377
+ }
378
+
379
/* Construct the cache from parsed configs. */
380
strmap_for_each_entry(&cb_data.event_hooks, &iter, e) {
381
struct string_list *hook_names = e->value;
477
{
478
struct strmap *cache = get_hook_config_cache(r);
479
struct string_list *configured_hooks = strmap_get(cache, hookname);
480
+ bool event_is_disabled = r ? !!unsorted_string_list_lookup(&r->disabled_events,
481
+ hookname) : 0;
482
483
/* Iterate through configured hooks and initialize internal states */
484
for (size_t i = 0; configured_hooks && i < configured_hooks->nr; i++) {
505
entry->command ? xstrdup(entry->command) : NULL;
506
hook->u.configured.scope = entry->scope;
507
hook->u.configured.disabled = entry->disabled;
508
+ hook->u.configured.event_disabled = event_is_disabled;
509
hook->parallel = entry->parallel;
510
511
string_list_append(list, friendly_name)->util = hook;
518
if (!r || !r->gitdir) {
519
hook_cache_clear(cache);
520
free(cache);
521
+ if (r)
522
+ string_list_clear(&r->disabled_events, 0);
523
}
524
}
525
551
for (size_t i = 0; i < hooks->nr; i++) {
552
struct hook *h = hooks->items[i].util;
553
if (h->kind == HOOK_TRADITIONAL ||
518
- !h->u.configured.disabled) {
554
+ (!h->u.configured.disabled && !h->u.configured.event_disabled)) {
555
exists = 1;
556
break;
557
}
574
if (hook_cb->hook_to_run_index >= hook_list->nr)
575
return 0;
576
h = hook_list->items[hook_cb->hook_to_run_index++].util;
541
- } while (h->kind == HOOK_CONFIGURED && h->u.configured.disabled);
577
+ } while (h->kind == HOOK_CONFIGURED &&
578
+ (h->u.configured.disabled || h->u.configured.event_disabled));
579
580
cp->no_stdin = 1;
581
strvec_pushv(&cp->env, hook_cb->options->env.v);