From: Patrick Steinhardt Date: Fri, 23 Oct 2026 12:50:21 GMT Subject: [PATCH 4/7] rerere: cache result of `is_rerere_enabled()` Message-ID: <20261023-pks-rerere-wo-the-repository-v1-4-b6ac0c2e4b81@pks.im> In-Reply-To: <20261023-pks-rerere-wo-the-repository-v1-0-b6ac0c2e4b81@pks.im> The function `setup_rerere()` reads the rerere configuration and then figures out whether the rerere cache is enabled after all, either because it has been explicitly enabled or because it's implicitly enabled and ".git/rr-cache" exists. Whether the cache is enabled will not change in a single process though, so it does not make sense to reevaluate these conditions every single time `setup_rerere()` is called. Adapt the function to instead cache the status of the rerere cache via a new `struct repository::rerere_cache_enabled` member. This allows us to get rid of the `GIT_PATH_FUNC()`, which caches the path to the rerere cache directory. But now that we already cache the enabled state in the first place it becomes moot to cache the path, as well. Signed-off-by: Patrick Steinhardt --- repository.c | 1 + repository.h | 6 ++++++ rerere.c | 43 +++++++++++++++++++++++-------------------- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/repository.c b/repository.c index e584d6c405..f51699a6dd 100644 --- a/repository.c +++ b/repository.c @@ -76,6 +76,7 @@ void initialize_repository(struct repository *repo) repo->bare_cfg = -1; repo->fetch_if_missing = 1; repo_config_values_init(&repo->config_values_private_); + repo->rerere_cache_enabled = -1; /* * When a command runs inside a repository, it learns what diff --git a/repository.h b/repository.h index 91b1f57db7..86795b6946 100644 --- a/repository.h +++ b/repository.h @@ -185,6 +185,12 @@ struct repository { /* True if commit-graph has been disabled within this process. */ int commit_graph_disabled; + /* + * Indicates whether the rerere-cache has been enabled. -1 (the default + * value) causes us to perform auto-detection via ".git/rr-cache". + */ + int rerere_cache_enabled; + /* * Controls whether the repository should lazily fetch missing * objects from promisor remotes. Defaults to 1. diff --git a/rerere.c b/rerere.c index 56b6ef547b..8fa921fc8f 100644 --- a/rerere.c +++ b/rerere.c @@ -27,9 +27,6 @@ #define THREE_STAGED 2 void *RERERE_RESOLVED = &RERERE_RESOLVED; -/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */ -static int rerere_enabled = -1; - /* automatically update cleanly resolved paths to the index */ static int rerere_autoupdate; @@ -873,40 +870,46 @@ static int do_plain_rerere(struct repository *r, return write_rr(rr, fd); } -static void git_rerere_config(struct repository *r) -{ - repo_config_get_bool(r, "rerere.enabled", &rerere_enabled); - repo_config_get_bool(r, "rerere.autoupdate", &rerere_autoupdate); - repo_config_get_int(r, "rerere.locktimeout", &rerere_lock_timeout_ms); -} - -static GIT_PATH_FUNC(git_path_rr_cache, "rr-cache") - static int is_rerere_enabled(struct repository *r) { int rr_cache_exists; + char *dir; - if (!rerere_enabled) + if (r->rerere_cache_enabled != -1) + return r->rerere_cache_enabled; + + repo_config_get_bool(r, "rerere.enabled", &r->rerere_cache_enabled); + if (!r->rerere_cache_enabled) return 0; - rr_cache_exists = is_directory(git_path_rr_cache()); - if (rerere_enabled < 0) - return rr_cache_exists; + dir = repo_git_path(r, "rr-cache"); + + rr_cache_exists = is_directory(dir); + if (r->rerere_cache_enabled < 0) { + r->rerere_cache_enabled = rr_cache_exists; + goto out; + } if (!rr_cache_exists && - safe_create_dir_in_gitdir(r, git_path_rr_cache())) - die(_("could not create directory '%s'"), git_path_rr_cache()); - return 1; + safe_create_dir_in_gitdir(r, dir)) + die(_("could not create directory '%s'"), dir); + r->rerere_cache_enabled = 1; + +out: + free(dir); + return r->rerere_cache_enabled; } int setup_rerere(struct repository *r, struct string_list *merge_rr, int flags) { int fd; - git_rerere_config(r); if (!is_rerere_enabled(r)) return -1; + repo_config_get_bool(r, "rerere.autoupdate", &rerere_autoupdate); + repo_config_get_int(r, "rerere.locktimeout", &rerere_lock_timeout_ms); + if (flags & (RERERE_AUTOUPDATE|RERERE_NOAUTOUPDATE)) rerere_autoupdate = !!(flags & RERERE_AUTOUPDATE); if ((flags & RERERE_READONLY) && (flags & RERERE_NOWAIT)) -- 2.56.0.307.g5fe7bd680c.dirty