From: Adrian Ratiu <adrian.ratiu@collabora.com>
To: git@vger.kernel.org
Cc: Jeff King <peff@peff.net>,
Emily Shaffer <emilyshaffer@google.com>,
Junio C Hamano <gitster@pobox.com>,
Patrick Steinhardt <ps@pks.im>,
Josh Steadmon <steadmon@google.com>,
Kristoffer Haugsbakk <kristofferhaugsbakk@fastmail.com>,
"brian m . carlson" <sandals@crustytoothpaste.net>,
Adrian Ratiu <adrian.ratiu@collabora.com>
Subject: [PATCH v2 03/10] hook: refactor hook_config_cache from strmap to named struct
Date: Sun, 22 Feb 2026 02:28:57 +0200 [thread overview]
Message-ID: <20260222002904.1879356-4-adrian.ratiu@collabora.com> (raw)
In-Reply-To: <20260222002904.1879356-1-adrian.ratiu@collabora.com>
Replace the raw `struct strmap *hook_config_cache` in `struct repository`
with a `struct hook_config_cache` which wraps the strmap in a named field.
Replace the bare `char *command` util pointer stored in each string_list
item with a heap-allocated `struct hook_config_cache_entry` that carries
that command string.
This is just a refactoring with no behavior changes, to give the cache
struct room to grow so it can carry the additional hook metadata we'll
be adding in the following commits.
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
---
hook.c | 65 +++++++++++++++++++++++++++++++++-------------------
hook.h | 10 +++++++-
repository.h | 3 ++-
3 files changed, 52 insertions(+), 26 deletions(-)
diff --git a/hook.c b/hook.c
index 2c8252b2c4..89b9948512 100644
--- a/hook.c
+++ b/hook.c
@@ -118,6 +118,15 @@ static void unsorted_string_list_remove(struct string_list *list,
unsorted_string_list_delete_item(list, item - list->items, 0);
}
+/*
+ * Cache entry stored as the .util pointer of string_list items inside the
+ * hook config cache. For now carries only the command for the hook. Next
+ * commits will add more data.
+ */
+struct hook_config_cache_entry {
+ char *command;
+};
+
/*
* Callback struct to collect all hook.* keys in a single config pass.
* commands: friendly-name to command map.
@@ -205,21 +214,27 @@ static int hook_config_lookup_all(const char *key, const char *value,
* Disabled hooks and hooks missing a command are already filtered out at
* parse time, so callers can iterate the list directly.
*/
-void hook_cache_clear(struct strmap *cache)
+void hook_cache_clear(struct hook_config_cache *cache)
{
struct hashmap_iter iter;
struct strmap_entry *e;
- strmap_for_each_entry(cache, &iter, e) {
+ strmap_for_each_entry(&cache->hooks, &iter, e) {
struct string_list *hooks = e->value;
- string_list_clear(hooks, 1); /* free util (command) pointers */
+ for (size_t i = 0; i < hooks->nr; i++) {
+ struct hook_config_cache_entry *entry = hooks->items[i].util;
+ free(entry->command);
+ free(entry);
+ }
+ string_list_clear(hooks, 0);
free(hooks);
}
- strmap_clear(cache, 0);
+ strmap_clear(&cache->hooks, 0);
}
/* Populate `cache` with the complete hook configuration */
-static void build_hook_config_map(struct repository *r, struct strmap *cache)
+static void build_hook_config_map(struct repository *r,
+ struct hook_config_cache *cache)
{
struct hook_all_config_cb cb_data;
struct hashmap_iter iter;
@@ -241,6 +256,7 @@ static void build_hook_config_map(struct repository *r, struct strmap *cache)
for (size_t i = 0; i < hook_names->nr; i++) {
const char *hname = hook_names->items[i].string;
+ struct hook_config_cache_entry *entry;
char *command;
/* filter out disabled hooks */
@@ -254,12 +270,13 @@ static void build_hook_config_map(struct repository *r, struct strmap *cache)
"'hook.%s.event' must be removed;"
" aborting."), hname, hname);
- /* util stores the command; owned by the cache. */
- string_list_append(hooks, hname)->util =
- xstrdup(command);
+ /* util stores a cache entry; owned by the cache. */
+ CALLOC_ARRAY(entry, 1);
+ entry->command = xstrdup(command);
+ string_list_append(hooks, hname)->util = entry;
}
- strmap_put(cache, e->key, hooks);
+ strmap_put(&cache->hooks, e->key, hooks);
}
strmap_clear(&cb_data.commands, 1);
@@ -272,35 +289,35 @@ static void build_hook_config_map(struct repository *r, struct strmap *cache)
}
/*
- * Return the hook config map for `r`, populating it first if needed.
+ * Return the hook config cache 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
+ * cache; the caller is responsible for freeing it with
* hook_cache_clear() + free().
*/
-static struct strmap *get_hook_config_cache(struct repository *r)
+static struct hook_config_cache *get_hook_config_cache(struct repository *r)
{
- struct strmap *cache = NULL;
+ struct hook_config_cache *cache = NULL;
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
+ * For in-repo calls, the cache is stored in r->hook_config_cache,
+ * so repeated invocations don't parse the configs; allocate
* it just once on the first call.
*/
if (!r->hook_config_cache) {
- r->hook_config_cache = xcalloc(1, sizeof(*cache));
- strmap_init(r->hook_config_cache);
+ CALLOC_ARRAY(r->hook_config_cache, 1);
+ strmap_init(&r->hook_config_cache->hooks);
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 which gets freed immediately by the caller.
*/
- cache = xcalloc(1, sizeof(*cache));
- strmap_init(cache);
+ CALLOC_ARRAY(cache, 1);
+ strmap_init(&cache->hooks);
build_hook_config_map(r, cache);
}
@@ -312,13 +329,13 @@ static void list_hooks_add_configured(struct repository *r,
struct string_list *list,
struct run_hooks_opt *options)
{
- struct strmap *cache = get_hook_config_cache(r);
- struct string_list *configured_hooks = strmap_get(cache, hookname);
+ struct hook_config_cache *cache = get_hook_config_cache(r);
+ struct string_list *configured_hooks = strmap_get(&cache->hooks, hookname);
/* Iterate through configured hooks and initialize internal states */
for (size_t i = 0; configured_hooks && i < configured_hooks->nr; i++) {
const char *friendly_name = configured_hooks->items[i].string;
- const char *command = configured_hooks->items[i].util;
+ struct hook_config_cache_entry *entry = configured_hooks->items[i].util;
struct hook *hook = xcalloc(1, sizeof(struct hook));
if (options && options->feed_pipe_cb_data_alloc)
@@ -328,7 +345,7 @@ 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(command);
+ hook->u.configured.command = xstrdup(entry->command);
string_list_append(list, friendly_name)->util = hook;
}
diff --git a/hook.h b/hook.h
index e949f5d488..994f15522d 100644
--- a/hook.h
+++ b/hook.h
@@ -191,11 +191,19 @@ struct string_list *list_hooks(struct repository *r, const char *hookname,
*/
void hook_list_clear(struct string_list *hooks, cb_data_free_fn cb_data_free);
+/**
+ * Persistent cache for hook configuration, stored on `struct repository`.
+ * Populated lazily on first hook use and freed by repo_clear().
+ */
+struct hook_config_cache {
+ struct strmap hooks; /* maps event name -> string_list of hooks */
+};
+
/**
* Frees the hook configuration cache stored in `struct repository`.
* Called by repo_clear().
*/
-void hook_cache_clear(struct strmap *cache);
+void hook_cache_clear(struct hook_config_cache *cache);
/**
* Returns the path to the hook file, or NULL if the hook is missing
diff --git a/repository.h b/repository.h
index 25b2801228..2105768b8c 100644
--- a/repository.h
+++ b/repository.h
@@ -11,6 +11,7 @@ struct lock_file;
struct pathspec;
struct object_database;
struct submodule_cache;
+struct hook_config_cache;
struct promisor_remote_config;
struct remote_state;
@@ -161,7 +162,7 @@ struct repository {
* Lazily-populated cache mapping hook event names to configured hooks.
* NULL until first hook use.
*/
- struct strmap *hook_config_cache;
+ struct hook_config_cache *hook_config_cache;
/* Configurations related to promisor remotes. */
char *repository_format_partial_clone;
--
2.52.0.732.gb351b5166d.dirty
next prev parent reply other threads:[~2026-02-22 0:29 UTC|newest]
Thread overview: 113+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-04 17:33 [PATCH 0/4] Run hooks in parallel Adrian Ratiu
2026-02-04 17:33 ` [PATCH 1/4] config: add a repo_config_get_uint() helper Adrian Ratiu
2026-02-04 17:33 ` [PATCH 2/4] hook: allow parallel hook execution Adrian Ratiu
2026-02-11 12:41 ` Patrick Steinhardt
2026-02-12 12:25 ` Adrian Ratiu
2026-02-04 17:33 ` [PATCH 3/4] hook: introduce extensions.hookStdoutToStderr Adrian Ratiu
2026-02-04 17:33 ` [PATCH 4/4] hook: allow runtime enabling extensions.hookStdoutToStderr Adrian Ratiu
2026-02-12 10:43 ` [PATCH 0/4] Run hooks in parallel Phillip Wood
2026-02-12 14:24 ` Adrian Ratiu
2026-02-13 14:39 ` Phillip Wood
2026-02-13 17:21 ` Adrian Ratiu
2026-02-22 0:28 ` [PATCH v2 00/10] " Adrian Ratiu
2026-02-22 0:28 ` [PATCH v2 01/10] repository: fix repo_init() memleak due to missing _clear() Adrian Ratiu
2026-02-22 0:28 ` [PATCH v2 02/10] config: add a repo_config_get_uint() helper Adrian Ratiu
2026-02-22 0:28 ` Adrian Ratiu [this message]
2026-02-22 0:28 ` [PATCH v2 04/10] hook: parse the hook.jobs config Adrian Ratiu
2026-02-22 0:28 ` [PATCH v2 05/10] hook: allow parallel hook execution Adrian Ratiu
2026-02-22 0:29 ` [PATCH v2 06/10] hook: mark non-parallelizable hooks Adrian Ratiu
2026-02-22 0:29 ` [PATCH v2 07/10] hook: add -j/--jobs option to git hook run Adrian Ratiu
2026-02-22 0:29 ` [PATCH v2 08/10] hook: add per-event jobs config Adrian Ratiu
2026-02-22 0:29 ` [PATCH v2 09/10] hook: introduce extensions.hookStdoutToStderr Adrian Ratiu
2026-02-22 0:29 ` [PATCH v2 10/10] hook: allow runtime enabling extensions.hookStdoutToStderr Adrian Ratiu
2026-03-09 13:37 ` [PATCH v3 0/9] Run hooks in parallel Adrian Ratiu
2026-03-09 13:37 ` [PATCH v3 1/9] repository: fix repo_init() memleak due to missing _clear() Adrian Ratiu
2026-03-15 4:55 ` Junio C Hamano
2026-03-15 5:05 ` Junio C Hamano
2026-03-09 13:37 ` [PATCH v3 2/9] config: add a repo_config_get_uint() helper Adrian Ratiu
2026-03-09 13:37 ` [PATCH v3 3/9] hook: parse the hook.jobs config Adrian Ratiu
2026-03-15 16:13 ` Junio C Hamano
2026-03-09 13:37 ` [PATCH v3 4/9] hook: allow parallel hook execution Adrian Ratiu
2026-03-15 20:46 ` Junio C Hamano
2026-03-18 18:02 ` Adrian Ratiu
2026-03-09 13:37 ` [PATCH v3 5/9] hook: mark non-parallelizable hooks Adrian Ratiu
2026-03-15 20:56 ` Junio C Hamano
2026-03-18 18:40 ` Adrian Ratiu
2026-03-09 13:37 ` [PATCH v3 6/9] hook: add -j/--jobs option to git hook run Adrian Ratiu
2026-03-15 21:00 ` Junio C Hamano
2026-03-18 19:00 ` Adrian Ratiu
2026-03-09 13:37 ` [PATCH v3 7/9] hook: add per-event jobs config Adrian Ratiu
2026-03-16 18:40 ` Junio C Hamano
2026-03-18 19:21 ` Adrian Ratiu
2026-03-09 13:37 ` [PATCH v3 8/9] hook: introduce extensions.hookStdoutToStderr Adrian Ratiu
2026-03-16 18:44 ` Junio C Hamano
2026-03-18 19:50 ` Adrian Ratiu
2026-03-09 13:37 ` [PATCH v3 9/9] hook: allow runtime enabling extensions.hookStdoutToStderr Adrian Ratiu
2026-03-20 13:53 ` [PATCH v4 0/9] Run hooks in parallel Adrian Ratiu
2026-03-20 13:53 ` [PATCH v4 1/9] config: add a repo_config_get_uint() helper Adrian Ratiu
2026-03-20 13:53 ` [PATCH v4 2/9] hook: parse the hook.jobs config Adrian Ratiu
2026-03-24 9:07 ` Patrick Steinhardt
2026-03-24 18:59 ` Adrian Ratiu
2026-03-20 13:53 ` [PATCH v4 3/9] hook: allow parallel hook execution Adrian Ratiu
2026-03-24 9:07 ` Patrick Steinhardt
2026-03-20 13:53 ` [PATCH v4 4/9] hook: allow pre-push parallel execution Adrian Ratiu
2026-03-20 13:53 ` [PATCH v4 5/9] hook: mark non-parallelizable hooks Adrian Ratiu
2026-03-20 13:53 ` [PATCH v4 6/9] hook: add -j/--jobs option to git hook run Adrian Ratiu
2026-03-24 9:07 ` Patrick Steinhardt
2026-03-20 13:53 ` [PATCH v4 7/9] hook: add per-event jobs config Adrian Ratiu
2026-03-24 9:08 ` Patrick Steinhardt
2026-03-20 13:53 ` [PATCH v4 8/9] hook: warn when hook.<friendly-name>.jobs is set Adrian Ratiu
2026-03-24 9:08 ` Patrick Steinhardt
2026-03-20 13:53 ` [PATCH v4 9/9] hook: add hook.<event>.enabled switch Adrian Ratiu
2026-03-24 9:08 ` Patrick Steinhardt
2026-03-25 18:43 ` Adrian Ratiu
2026-03-20 17:24 ` [PATCH v4 0/9] Run hooks in parallel Junio C Hamano
2026-03-23 15:07 ` Adrian Ratiu
2026-03-24 9:07 ` Patrick Steinhardt
2026-03-26 10:18 ` [PATCH v5 00/12] " Adrian Ratiu
2026-03-26 10:18 ` [PATCH v5 01/12] repository: fix repo_init() memleak due to missing _clear() Adrian Ratiu
2026-03-26 10:18 ` [PATCH v5 02/12] config: add a repo_config_get_uint() helper Adrian Ratiu
2026-03-26 10:18 ` [PATCH v5 03/12] hook: parse the hook.jobs config Adrian Ratiu
2026-03-26 10:18 ` [PATCH v5 04/12] hook: allow parallel hook execution Adrian Ratiu
2026-03-26 10:18 ` [PATCH v5 05/12] hook: allow pre-push parallel execution Adrian Ratiu
2026-03-26 10:18 ` [PATCH v5 06/12] hook: mark non-parallelizable hooks Adrian Ratiu
2026-03-26 10:18 ` [PATCH v5 07/12] hook: add -j/--jobs option to git hook run Adrian Ratiu
2026-03-27 14:46 ` Patrick Steinhardt
2026-03-26 10:18 ` [PATCH v5 08/12] hook: add per-event jobs config Adrian Ratiu
2026-03-26 10:18 ` [PATCH v5 09/12] hook: warn when hook.<friendly-name>.jobs is set Adrian Ratiu
2026-03-27 14:46 ` Patrick Steinhardt
2026-03-26 10:18 ` [PATCH v5 10/12] hook: move is_known_hook() to hook.c for wider use Adrian Ratiu
2026-03-27 14:46 ` Patrick Steinhardt
2026-03-27 15:59 ` Adrian Ratiu
2026-03-26 10:18 ` [PATCH v5 11/12] hook: add hook.<event>.enabled switch Adrian Ratiu
2026-03-26 10:18 ` [PATCH v5 12/12] hook: allow hook.jobs=-1 to use all available CPU cores Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 00/12] Run hooks in parallel Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 01/12] repository: fix repo_init() memleak due to missing _clear() Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 02/12] config: add a repo_config_get_uint() helper Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 03/12] hook: parse the hook.jobs config Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 04/12] hook: allow parallel hook execution Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 05/12] hook: allow pre-push parallel execution Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 06/12] hook: mark non-parallelizable hooks Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 07/12] hook: add -j/--jobs option to git hook run Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 08/12] hook: add per-event jobs config Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 09/12] hook: warn when hook.<friendly-name>.jobs is set Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 10/12] hook: move is_known_hook() to hook.c for wider use Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 11/12] hook: add hook.<event>.enabled switch Adrian Ratiu
2026-04-04 8:29 ` [PATCH v6 12/12] hook: allow hook.jobs=-1 to use all available CPU cores Adrian Ratiu
2026-04-06 16:24 ` [PATCH v6 00/12] Run hooks in parallel Junio C Hamano
2026-04-08 10:17 ` Patrick Steinhardt
2026-04-08 16:57 ` Junio C Hamano
2026-04-10 9:05 ` [PATCH v7 00/13] " Adrian Ratiu
2026-04-10 9:05 ` [PATCH v7 01/13] repository: fix repo_init() memleak due to missing _clear() Adrian Ratiu
2026-04-10 9:05 ` [PATCH v7 02/13] config: add a repo_config_get_uint() helper Adrian Ratiu
2026-04-10 9:05 ` [PATCH v7 03/13] hook: parse the hook.jobs config Adrian Ratiu
2026-04-10 9:05 ` [PATCH v7 04/13] hook: allow parallel hook execution Adrian Ratiu
2026-04-10 9:06 ` [PATCH v7 05/13] hook: allow pre-push parallel execution Adrian Ratiu
2026-04-10 9:06 ` [PATCH v7 06/13] hook: mark non-parallelizable hooks Adrian Ratiu
2026-04-10 9:06 ` [PATCH v7 07/13] hook: add -j/--jobs option to git hook run Adrian Ratiu
2026-04-10 9:06 ` [PATCH v7 08/13] hook: add per-event jobs config Adrian Ratiu
2026-04-10 9:06 ` [PATCH v7 09/13] hook: warn when hook.<friendly-name>.jobs is set Adrian Ratiu
2026-04-10 9:06 ` [PATCH v7 10/13] hook: move is_known_hook() to hook.c for wider use Adrian Ratiu
2026-04-10 9:06 ` [PATCH v7 11/13] hook: add hook.<event>.enabled switch Adrian Ratiu
2026-04-10 9:06 ` [PATCH v7 12/13] hook: allow hook.jobs=-1 to use all available CPU cores Adrian Ratiu
2026-04-10 9:06 ` [PATCH v7 13/13] t1800: test SIGPIPE with parallel hooks Adrian Ratiu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260222002904.1879356-4-adrian.ratiu@collabora.com \
--to=adrian.ratiu@collabora.com \
--cc=emilyshaffer@google.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=kristofferhaugsbakk@fastmail.com \
--cc=peff@peff.net \
--cc=ps@pks.im \
--cc=sandals@crustytoothpaste.net \
--cc=steadmon@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.