]> git.ipfire.org Git - thirdparty/git.git/commitdiff
refs: move parsing of "core.logAllRefUpdates" back into ref stores
authorPatrick Steinhardt <ps@pks.im>
Thu, 25 Jun 2026 09:20:05 +0000 (11:20 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 25 Jun 2026 20:19:57 +0000 (13:19 -0700)
In cc42c88945 (refs: extract out reflog config to generic layer,
2026-05-04) we have refactored how we parse "core.logAllRefUpdates" so
that it happens in the generic layer. Unfortunately, this has worsened a
preexisting issue where we may recurse when creating the reference store
because of a chicken-and-egg problem between parsing the configuration
and evaluating "onbranch" conditions.

Prepare for a fix by essentially reverting that change so that we handle
this setting in the respective backends again. The backends are already
parsing other configuration anyway, so by moving the logic back in there
we can ensure that all backend configuration is parsed the same way.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/checkout.c
refs.c
refs.h
refs/files-backend.c
refs/refs-internal.h
refs/reftable-backend.c
repo-settings.c
repo-settings.h
setup.c

index b78b3a1d16def48852204be587c9131d5fb5363d..aee84ca89742b0a755fc436749c8942d43d94066 100644 (file)
@@ -952,10 +952,13 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
        const char *old_desc, *reflog_msg;
        if (opts->new_branch) {
                if (opts->new_orphan_branch) {
-                       enum log_refs_config log_all_ref_updates =
-                               repo_settings_get_log_all_ref_updates(the_repository);
+                       enum log_refs_config log_all_ref_updates = LOG_REFS_UNSET;
+                       const char *value;
                        char *refname;
 
+                       if (!repo_config_get_string_tmp(the_repository, "core.logallrefupdates", &value))
+                               log_all_ref_updates = refs_parse_log_all_ref_updates_config(value);
+
                        refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch);
                        if (opts->new_branch_log &&
                            !should_autocreate_reflog(log_all_ref_updates, refname)) {
diff --git a/refs.c b/refs.c
index d3caa9a633503f94d652e3bd653a1ffbdc184c9f..5b773b1c151e94b9dfdef271e7151f69562cd837 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1053,6 +1053,15 @@ static char *normalize_reflog_message(const char *msg)
        return strbuf_detach(&sb, NULL);
 }
 
+enum log_refs_config refs_parse_log_all_ref_updates_config(const char *value)
+{
+       if (value && !strcasecmp(value, "always"))
+               return LOG_REFS_ALWAYS;
+       else if (git_config_bool("core.logallrefupdates", value))
+               return LOG_REFS_NORMAL;
+       return LOG_REFS_NONE;
+}
+
 int should_autocreate_reflog(enum log_refs_config log_all_ref_updates,
                             const char *refname)
 {
@@ -2327,7 +2336,6 @@ static struct ref_store *ref_store_init(struct repository *repo,
        struct ref_store *refs;
        struct ref_store_init_options opts = {
                .access_flags = flags,
-               .log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo),
        };
 
        be = find_ref_storage_backend(format);
diff --git a/refs.h b/refs.h
index 71d5c186d044bbd278dbfe8685287196d780243e..a381022c77065a21d3a1142248ec5bf4604c93f2 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -146,6 +146,15 @@ enum ref_transaction_error refs_verify_refname_available(struct ref_store *refs,
 
 int refs_ref_exists(struct ref_store *refs, const char *refname);
 
+enum log_refs_config {
+       LOG_REFS_UNSET = -1,
+       LOG_REFS_NONE = 0,
+       LOG_REFS_NORMAL,
+       LOG_REFS_ALWAYS
+};
+
+enum log_refs_config refs_parse_log_all_ref_updates_config(const char *value);
+
 int should_autocreate_reflog(enum log_refs_config log_all_ref_updates,
                             const char *refname);
 
index 296981584b6f9946debfa78a0e37fdbbc2dbcb3e..79fb6735e1e3a3af6cae7deb9eb8c3061e7389c2 100644 (file)
@@ -117,6 +117,21 @@ static void files_ref_store_reparent(const char *name UNUSED,
        refs->gitcommondir = tmp;
 }
 
+static int files_ref_store_config(const char *var, const char *value,
+                                 const struct config_context *ctx UNUSED,
+                                 void *payload)
+{
+       struct files_ref_store *refs = payload;
+
+       if (!strcmp(var, "core.prefersymlinkrefs")) {
+               refs->prefer_symlink_refs = git_config_bool(var, value);
+       } else if (!strcmp(var, "core.logallrefupdates")) {
+               refs->log_all_ref_updates = refs_parse_log_all_ref_updates_config(value);
+       }
+
+       return 0;
+}
+
 /*
  * Create a new submodule ref cache and add it to the internal
  * set of caches.
@@ -141,10 +156,9 @@ static struct ref_store *files_ref_store_init(struct repository *repo,
        refs->packed_ref_store =
                packed_ref_store_init(repo, NULL, refs->gitcommondir, opts);
        refs->store_flags = opts->access_flags;
-       refs->log_all_ref_updates = opts->log_all_ref_updates;
-
-       repo_config_get_bool(repo, "core.prefersymlinkrefs", &refs->prefer_symlink_refs);
+       refs->log_all_ref_updates = LOG_REFS_UNSET;
 
+       repo_config(repo, files_ref_store_config, refs);
        chdir_notify_register(NULL, files_ref_store_reparent, refs);
 
        strbuf_release(&refdir);
index a08d58900eb644a7c003b0adaa3bd0d40991d9fe..c3ac7b556f37163d0f3b0b130b47dad38937500a 100644 (file)
@@ -406,12 +406,6 @@ struct ref_store;
 struct ref_store_init_options {
        /* The kind of operations that the ref_store is allowed to perform. */
        unsigned int access_flags;
-
-       /*
-        * Denotes under what conditions reflogs should be created when updating
-        * references.
-        */
-       enum log_refs_config log_all_ref_updates;
 };
 
 /*
index 8c93070677dcc3ea8e13b3a4a2504fd124fc9062..5115a3f4ce6f5f97685e79fe7ac49f27336520c3 100644 (file)
@@ -332,34 +332,36 @@ static void fill_reftable_log_record(struct reftable_log_record *log, const stru
 
 static int reftable_be_config(const char *var, const char *value,
                              const struct config_context *ctx,
-                             void *_opts)
+                             void *payload)
 {
-       struct reftable_write_options *opts = _opts;
+       struct reftable_ref_store *refs = payload;
 
        if (!strcmp(var, "reftable.blocksize")) {
                unsigned long block_size = git_config_ulong(var, value, ctx->kvi);
                if (block_size > 16777215)
                        die("reftable block size cannot exceed 16MB");
-               opts->block_size = block_size;
+               refs->write_options.block_size = block_size;
        } else if (!strcmp(var, "reftable.restartinterval")) {
                unsigned long restart_interval = git_config_ulong(var, value, ctx->kvi);
                if (restart_interval > UINT16_MAX)
                        die("reftable block size cannot exceed %u", (unsigned)UINT16_MAX);
-               opts->restart_interval = restart_interval;
+               refs->write_options.restart_interval = restart_interval;
        } else if (!strcmp(var, "reftable.indexobjects")) {
-               opts->skip_index_objects = !git_config_bool(var, value);
+               refs->write_options.skip_index_objects = !git_config_bool(var, value);
        } else if (!strcmp(var, "reftable.geometricfactor")) {
                unsigned long factor = git_config_ulong(var, value, ctx->kvi);
                if (factor > UINT8_MAX)
                        die("reftable geometric factor cannot exceed %u", (unsigned)UINT8_MAX);
-               opts->auto_compaction_factor = factor;
+               refs->write_options.auto_compaction_factor = factor;
        } else if (!strcmp(var, "reftable.locktimeout")) {
                int64_t lock_timeout = git_config_int64(var, value, ctx->kvi);
                if (lock_timeout > LONG_MAX)
                        die("reftable lock timeout cannot exceed %"PRIdMAX, (intmax_t)LONG_MAX);
                if (lock_timeout < 0 && lock_timeout != -1)
                        die("reftable lock timeout does not support negative values other than -1");
-               opts->lock_timeout_ms = lock_timeout;
+               refs->write_options.lock_timeout_ms = lock_timeout;
+       } else if (!strcmp(var, "core.logallrefupdates")) {
+               refs->log_all_ref_updates = refs_parse_log_all_ref_updates_config(value);
        }
 
        return 0;
@@ -398,7 +400,6 @@ static struct ref_store *reftable_be_init(struct repository *repo,
 
        base_ref_store_init(&refs->base, repo, refdir.buf, &refs_be_reftable);
        strmap_init(&refs->worktree_backends);
-       refs->log_all_ref_updates = opts->log_all_ref_updates;
        refs->store_flags = opts->access_flags;
 
        switch (repo->hash_algo->format_id) {
@@ -415,8 +416,9 @@ static struct ref_store *reftable_be_init(struct repository *repo,
        refs->write_options.disable_auto_compact =
                !git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1);
        refs->write_options.lock_timeout_ms = 100;
+       refs->log_all_ref_updates = LOG_REFS_UNSET;
 
-       repo_config(repo, reftable_be_config, &refs->write_options);
+       repo_config(repo, reftable_be_config, refs);
 
        /*
         * It is somewhat unfortunate that we have to mirror the default block
index 208e09ff17fcee5232daab12f7d9ac6e34a412c1..f3be3b8c5a3d095711e153677319f7a5f7e0474b 100644 (file)
@@ -177,22 +177,6 @@ void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long
        repo->settings.big_file_threshold = value;
 }
 
-enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)
-{
-       const char *value;
-
-       if (!repo_config_get_string_tmp(repo, "core.logallrefupdates", &value)) {
-               if (value && !strcasecmp(value, "always"))
-                       return LOG_REFS_ALWAYS;
-               else if (git_config_bool("core.logallrefupdates", value))
-                       return LOG_REFS_NORMAL;
-               else
-                       return LOG_REFS_NONE;
-       }
-
-       return LOG_REFS_UNSET;
-}
-
 int repo_settings_get_warn_ambiguous_refs(struct repository *repo)
 {
        prepare_repo_settings(repo);
index cad9c3f0cc15f32c9d6710efb3700f6734d3f63a..e5253ead025c83b85c8165567d9fece5432f905a 100644 (file)
@@ -16,13 +16,6 @@ enum fetch_negotiation_setting {
        FETCH_NEGOTIATION_NOOP,
 };
 
-enum log_refs_config {
-       LOG_REFS_UNSET = -1,
-       LOG_REFS_NONE = 0,
-       LOG_REFS_NORMAL,
-       LOG_REFS_ALWAYS
-};
-
 struct repo_settings {
        int initialized;
 
@@ -86,8 +79,6 @@ struct repo_settings {
 void prepare_repo_settings(struct repository *r);
 void repo_settings_clear(struct repository *r);
 
-/* Read the value for "core.logAllRefUpdates". */
-enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo);
 /* Read the value for "core.warnAmbiguousRefs". */
 int repo_settings_get_warn_ambiguous_refs(struct repository *repo);
 /* Read the value for "core.hooksPath". */
diff --git a/setup.c b/setup.c
index 79125db56567b758bfb0f7fc92d1a650ceabab1c..592753457c29a45bad019be5b492e1ddac2369f4 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -2584,10 +2584,14 @@ static int create_default_files(struct repository *repo,
        if (is_bare_repository())
                repo_config_set(repo, "core.bare", "true");
        else {
+               const char *value;
+
                repo_config_set(repo, "core.bare", "false");
+
                /* allow template config file to override the default */
-               if (repo_settings_get_log_all_ref_updates(repo) == LOG_REFS_UNSET)
+               if (repo_config_get_string_tmp(repo, "core.logallrefupdates", &value))
                        repo_config_set(repo, "core.logallrefupdates", "true");
+
                if (needs_work_tree_config(original_git_dir, work_tree))
                        repo_config_set(repo, "core.worktree", work_tree);
        }