From a0d09c56ba6c2e9fc07a19531e29c43f83c445f7 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 12 Sep 2024 13:30:04 +0200 Subject: repo-settings: split out declarations into a standalone header While we have "repo-settings.c", we do not have a corresponding "repo-settings.h" file. Instead, this functionality is part of the "repository.h" header, making it hard to discover. Split the declarations out of "repository.h" and create a standalone header file with them. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- repo-settings.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 repo-settings.h (limited to 'repo-settings.h') diff --git a/repo-settings.h b/repo-settings.h new file mode 100644 index 0000000000..ff20a96537 --- /dev/null +++ b/repo-settings.h @@ -0,0 +1,56 @@ +#ifndef REPO_SETTINGS_H +#define REPO_SETTINGS_H + +struct fsmonitor_settings; +struct repository; + +enum untracked_cache_setting { + UNTRACKED_CACHE_KEEP, + UNTRACKED_CACHE_REMOVE, + UNTRACKED_CACHE_WRITE, +}; + +enum fetch_negotiation_setting { + FETCH_NEGOTIATION_CONSECUTIVE, + FETCH_NEGOTIATION_SKIPPING, + FETCH_NEGOTIATION_NOOP, +}; + +struct repo_settings { + int initialized; + + int core_commit_graph; + int commit_graph_generation_version; + int commit_graph_changed_paths_version; + int gc_write_commit_graph; + int fetch_write_commit_graph; + int command_requires_full_index; + int sparse_index; + int pack_read_reverse_index; + int pack_use_bitmap_boundary_traversal; + int pack_use_multi_pack_reuse; + + /* + * Does this repository have core.useReplaceRefs=true (on by + * default)? This provides a repository-scoped version of this + * config, though it could be disabled process-wide via some Git + * builtins or the --no-replace-objects option. See + * replace_refs_enabled() for more details. + */ + int read_replace_refs; + + struct fsmonitor_settings *fsmonitor; /* lazily loaded */ + + int index_version; + int index_skip_hash; + enum untracked_cache_setting core_untracked_cache; + + int pack_use_sparse; + enum fetch_negotiation_setting fetch_negotiation_algorithm; + + int core_multi_pack_index; +}; + +void prepare_repo_settings(struct repository *r); + +#endif /* REPO_SETTINGS_H */ -- cgit v1.2.3 From f1d3d07900e42d19f10be55bc2f793034e7d4198 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 12 Sep 2024 13:30:07 +0200 Subject: repo-settings: track defaults close to `struct repo_settings` The default values for `struct repo_settings` are set up in `prepare_repo_settings()`. This is somewhat different from how we typically do this, namely by providing an `INIT` macro that sets up the default values for us. Refactor the code to do the same. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- repo-settings.c | 9 ++++----- repo-settings.h | 5 +++++ 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'repo-settings.h') diff --git a/repo-settings.c b/repo-settings.c index 6165546e80..3a76ba276c 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -20,6 +20,7 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest, void prepare_repo_settings(struct repository *r) { + const struct repo_settings defaults = REPO_SETTINGS_INIT; int experimental; int value; const char *strval; @@ -29,13 +30,11 @@ void prepare_repo_settings(struct repository *r) if (!r->gitdir) BUG("Cannot add settings for uninitialized repository"); - if (r->settings.initialized++) + if (r->settings.initialized) return; - /* Defaults */ - r->settings.index_version = -1; - r->settings.core_untracked_cache = UNTRACKED_CACHE_KEEP; - r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE; + memcpy(&r->settings, &defaults, sizeof(defaults)); + r->settings.initialized++; /* Booleans config or default, cascades to other settings */ repo_cfg_bool(r, "feature.manyfiles", &manyfiles, 0); diff --git a/repo-settings.h b/repo-settings.h index ff20a96537..28f95695b3 100644 --- a/repo-settings.h +++ b/repo-settings.h @@ -50,6 +50,11 @@ struct repo_settings { int core_multi_pack_index; }; +#define REPO_SETTINGS_INIT { \ + .index_version = -1, \ + .core_untracked_cache = UNTRACKED_CACHE_KEEP, \ + .fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \ +} void prepare_repo_settings(struct repository *r); -- cgit v1.2.3 From 9a20b889e8703482162d9d1487b876be42564a78 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 12 Sep 2024 13:30:13 +0200 Subject: refs: stop modifying global `log_all_ref_updates` variable In refs-related code we modify the global `log_all_ref_updates` variable, which is done because `should_autocreate_reflog()` does not accept passing an `enum log_refs_config` but instead accesses the global variable. Adapt its interface such that the value is provided by the caller, which allows us to compute the proper value locally without having to modify global state. This change requires us to move the enum to "repo-settings.h", or otherwise we get compilation errors due to include cycles. We're about to fully move this setting into the repo-settings subsystem anyway, so this is fine. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/checkout.c | 3 ++- environment.h | 8 ++------ refs.c | 5 +++-- refs.h | 4 +++- refs/files-backend.c | 23 ++++++++++++----------- refs/reftable-backend.c | 12 +++++++----- repo-settings.h | 7 +++++++ 7 files changed, 36 insertions(+), 26 deletions(-) (limited to 'repo-settings.h') diff --git a/builtin/checkout.c b/builtin/checkout.c index 4cfe6fab50..6db7f39492 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -23,6 +23,7 @@ #include "read-cache.h" #include "refs.h" #include "remote.h" +#include "repo-settings.h" #include "resolve-undo.h" #include "revision.h" #include "setup.h" @@ -954,7 +955,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts, refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch); if (opts->new_branch_log && - !should_autocreate_reflog(refname)) { + !should_autocreate_reflog(log_all_ref_updates, refname)) { int ret; struct strbuf err = STRBUF_INIT; diff --git a/environment.h b/environment.h index 934859e1c5..0b4e5afc36 100644 --- a/environment.h +++ b/environment.h @@ -1,6 +1,8 @@ #ifndef ENVIRONMENT_H #define ENVIRONMENT_H +#include "repo-settings.h" + /* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR" #define GIT_COMMON_DIR_ENVIRONMENT "GIT_COMMON_DIR" @@ -179,12 +181,6 @@ extern int core_apply_sparse_checkout; extern int core_sparse_checkout_cone; extern int sparse_expect_files_outside_of_patterns; -enum log_refs_config { - LOG_REFS_UNSET = -1, - LOG_REFS_NONE = 0, - LOG_REFS_NORMAL, - LOG_REFS_ALWAYS -}; extern enum log_refs_config log_all_ref_updates; enum rebase_setup_type { diff --git a/refs.c b/refs.c index ceb72d4bd7..d7402bcd19 100644 --- a/refs.c +++ b/refs.c @@ -24,7 +24,7 @@ #include "submodule.h" #include "worktree.h" #include "strvec.h" -#include "repository.h" +#include "repo-settings.h" #include "setup.h" #include "sigchain.h" #include "date.h" @@ -958,7 +958,8 @@ static char *normalize_reflog_message(const char *msg) return strbuf_detach(&sb, NULL); } -int should_autocreate_reflog(const char *refname) +int should_autocreate_reflog(enum log_refs_config log_all_ref_updates, + const char *refname) { switch (log_all_ref_updates) { case LOG_REFS_ALWAYS: diff --git a/refs.h b/refs.h index f8b919a138..f2c4ccde61 100644 --- a/refs.h +++ b/refs.h @@ -3,6 +3,7 @@ #include "commit.h" #include "repository.h" +#include "repo-settings.h" struct fsck_options; struct object_id; @@ -111,7 +112,8 @@ int refs_verify_refname_available(struct ref_store *refs, int refs_ref_exists(struct ref_store *refs, const char *refname); -int should_autocreate_reflog(const char *refname); +int should_autocreate_reflog(enum log_refs_config log_all_ref_updates, + const char *refname); int is_branch(const char *refname); diff --git a/refs/files-backend.c b/refs/files-backend.c index 1bbb550f3a..f5871abcf7 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -8,6 +8,7 @@ #include "../hex.h" #include "../fsck.h" #include "../refs.h" +#include "../repo-settings.h" #include "refs-internal.h" #include "ref-cache.h" #include "packed-backend.h" @@ -1443,6 +1444,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs, static int commit_ref_update(struct files_ref_store *refs, struct ref_lock *lock, const struct object_id *oid, const char *logmsg, + int flags, struct strbuf *err); /* @@ -1586,7 +1588,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, oidcpy(&lock->old_oid, &orig_oid); if (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) || - commit_ref_update(refs, lock, &orig_oid, logmsg, &err)) { + commit_ref_update(refs, lock, &orig_oid, logmsg, 0, &err)) { error("unable to write current sha1 into %s: %s", newrefname, err.buf); strbuf_release(&err); goto rollback; @@ -1603,14 +1605,11 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, goto rollbacklog; } - flag = log_all_ref_updates; - log_all_ref_updates = LOG_REFS_NONE; if (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) || - commit_ref_update(refs, lock, &orig_oid, NULL, &err)) { + commit_ref_update(refs, lock, &orig_oid, NULL, REF_SKIP_CREATE_REFLOG, &err)) { error("unable to write current sha1 into %s: %s", oldrefname, err.buf); strbuf_release(&err); } - log_all_ref_updates = flag; rollbacklog: if (logmoved && rename(sb_newref.buf, sb_oldref.buf)) @@ -1705,13 +1704,17 @@ static int log_ref_setup(struct files_ref_store *refs, const char *refname, int force_create, int *logfd, struct strbuf *err) { + enum log_refs_config log_refs_cfg = log_all_ref_updates; struct strbuf logfile_sb = STRBUF_INIT; char *logfile; + if (log_refs_cfg == LOG_REFS_UNSET) + log_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL; + files_reflog_path(refs, &logfile_sb, refname); logfile = strbuf_detach(&logfile_sb, NULL); - if (force_create || should_autocreate_reflog(refname)) { + if (force_create || should_autocreate_reflog(log_refs_cfg, refname)) { if (raceproof_create_file(logfile, open_or_create_logfile, logfd)) { if (errno == ENOENT) strbuf_addf(err, "unable to create directory for '%s': " @@ -1800,9 +1803,6 @@ static int files_log_ref_write(struct files_ref_store *refs, if (flags & REF_SKIP_CREATE_REFLOG) return 0; - if (log_all_ref_updates == LOG_REFS_UNSET) - log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL; - result = log_ref_setup(refs, refname, flags & REF_FORCE_CREATE_REFLOG, &logfd, err); @@ -1891,6 +1891,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs, static int commit_ref_update(struct files_ref_store *refs, struct ref_lock *lock, const struct object_id *oid, const char *logmsg, + int flags, struct strbuf *err) { files_assert_main_repository(refs, "commit_ref_update"); @@ -1898,7 +1899,7 @@ static int commit_ref_update(struct files_ref_store *refs, clear_loose_ref_cache(refs); if (files_log_ref_write(refs, lock->ref_name, &lock->old_oid, oid, - logmsg, 0, err)) { + logmsg, flags, err)) { char *old_msg = strbuf_detach(err, NULL); strbuf_addf(err, "cannot update the ref '%s': %s", lock->ref_name, old_msg); @@ -1931,7 +1932,7 @@ static int commit_ref_update(struct files_ref_store *refs, struct strbuf log_err = STRBUF_INIT; if (files_log_ref_write(refs, "HEAD", &lock->old_oid, oid, - logmsg, 0, &log_err)) { + logmsg, flags, &log_err)) { error("%s", log_err.buf); strbuf_release(&log_err); } diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index 1c4b19e737..c78186423a 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -19,6 +19,7 @@ #include "../reftable/reftable-record.h" #include "../reftable/reftable-error.h" #include "../reftable/reftable-iterator.h" +#include "../repo-settings.h" #include "../setup.h" #include "../strmap.h" #include "parse.h" @@ -158,20 +159,21 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store, static int should_write_log(struct ref_store *refs, const char *refname) { - if (log_all_ref_updates == LOG_REFS_UNSET) - log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL; + enum log_refs_config log_refs_cfg = log_all_ref_updates; + if (log_refs_cfg == LOG_REFS_UNSET) + log_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL; - switch (log_all_ref_updates) { + switch (log_refs_cfg) { case LOG_REFS_NONE: return refs_reflog_exists(refs, refname); case LOG_REFS_ALWAYS: return 1; case LOG_REFS_NORMAL: - if (should_autocreate_reflog(refname)) + if (should_autocreate_reflog(log_refs_cfg, refname)) return 1; return refs_reflog_exists(refs, refname); default: - BUG("unhandled core.logAllRefUpdates value %d", log_all_ref_updates); + BUG("unhandled core.logAllRefUpdates value %d", log_refs_cfg); } } diff --git a/repo-settings.h b/repo-settings.h index 28f95695b3..d03b6e57f0 100644 --- a/repo-settings.h +++ b/repo-settings.h @@ -16,6 +16,13 @@ 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; -- cgit v1.2.3 From eafb126456b235c5281e3ae50bfd526552ce12d3 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 12 Sep 2024 13:30:18 +0200 Subject: environment: stop storing "core.logAllRefUpdates" globally The value of "core.logAllRefUpdates" is being stored in the global variable `log_all_ref_updates`. This design is somewhat aged nowadays, where it is entirely possible to access multiple repositories in the same process which all have different values for this setting. So using a single global variable to track it is plain wrong. Remove the global variable. Instead, we now provide a new function part of the repo-settings subsystem that parses the value for a specific repository. While that may require us to read the value multiple times, we work around this by reading it once when the ref backends are set up and caching the value there. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/checkout.c | 2 ++ config.c | 10 ---------- environment.c | 1 - environment.h | 2 -- refs/files-backend.c | 4 +++- refs/reftable-backend.c | 12 +++++++----- repo-settings.c | 16 ++++++++++++++++ repo-settings.h | 3 +++ setup.c | 2 +- 9 files changed, 32 insertions(+), 20 deletions(-) (limited to 'repo-settings.h') diff --git a/builtin/checkout.c b/builtin/checkout.c index 6db7f39492..7e18b87c7a 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -951,6 +951,8 @@ 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); char *refname; refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch); diff --git a/config.c b/config.c index f3066c3747..47101c3e97 100644 --- a/config.c +++ b/config.c @@ -1452,16 +1452,6 @@ static int git_default_core_config(const char *var, const char *value, return 0; } - if (!strcmp(var, "core.logallrefupdates")) { - if (value && !strcasecmp(value, "always")) - log_all_ref_updates = LOG_REFS_ALWAYS; - else if (git_config_bool(var, value)) - log_all_ref_updates = LOG_REFS_NORMAL; - else - log_all_ref_updates = LOG_REFS_NONE; - return 0; - } - if (!strcmp(var, "core.warnambiguousrefs")) { warn_ambiguous_refs = git_config_bool(var, value); return 0; diff --git a/environment.c b/environment.c index 64ae13ef24..992d87e0d6 100644 --- a/environment.c +++ b/environment.c @@ -77,7 +77,6 @@ int sparse_expect_files_outside_of_patterns; int merge_log_config = -1; int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */ unsigned long pack_size_limit_cfg; -enum log_refs_config log_all_ref_updates = LOG_REFS_UNSET; int max_allowed_tree_depth = #ifdef _MSC_VER /* diff --git a/environment.h b/environment.h index 0b4e5afc36..315fd31995 100644 --- a/environment.h +++ b/environment.h @@ -181,8 +181,6 @@ extern int core_apply_sparse_checkout; extern int core_sparse_checkout_cone; extern int sparse_expect_files_outside_of_patterns; -extern enum log_refs_config log_all_ref_updates; - enum rebase_setup_type { AUTOREBASE_NEVER = 0, AUTOREBASE_LOCAL, diff --git a/refs/files-backend.c b/refs/files-backend.c index f5871abcf7..a536d7d1b5 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -75,6 +75,7 @@ struct files_ref_store { unsigned int store_flags; char *gitcommondir; + enum log_refs_config log_all_ref_updates; struct ref_cache *loose; @@ -107,6 +108,7 @@ static struct ref_store *files_ref_store_init(struct repository *repo, refs->gitcommondir = strbuf_detach(&sb, NULL); refs->packed_ref_store = packed_ref_store_init(repo, refs->gitcommondir, flags); + refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo); chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir); chdir_notify_reparent("files-backend $GIT_COMMONDIR", @@ -1704,7 +1706,7 @@ static int log_ref_setup(struct files_ref_store *refs, const char *refname, int force_create, int *logfd, struct strbuf *err) { - enum log_refs_config log_refs_cfg = log_all_ref_updates; + enum log_refs_config log_refs_cfg = refs->log_all_ref_updates; struct strbuf logfile_sb = STRBUF_INIT; char *logfile; diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index c78186423a..043e19439f 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -52,6 +52,7 @@ struct reftable_ref_store { struct reftable_write_options write_options; unsigned int store_flags; + enum log_refs_config log_all_ref_updates; int err; }; @@ -157,21 +158,21 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store, } } -static int should_write_log(struct ref_store *refs, const char *refname) +static int should_write_log(struct reftable_ref_store *refs, const char *refname) { - enum log_refs_config log_refs_cfg = log_all_ref_updates; + enum log_refs_config log_refs_cfg = refs->log_all_ref_updates; if (log_refs_cfg == LOG_REFS_UNSET) log_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL; switch (log_refs_cfg) { case LOG_REFS_NONE: - return refs_reflog_exists(refs, refname); + return refs_reflog_exists(&refs->base, refname); case LOG_REFS_ALWAYS: return 1; case LOG_REFS_NORMAL: if (should_autocreate_reflog(log_refs_cfg, refname)) return 1; - return refs_reflog_exists(refs, refname); + return refs_reflog_exists(&refs->base, refname); default: BUG("unhandled core.logAllRefUpdates value %d", log_refs_cfg); } @@ -278,6 +279,7 @@ static struct ref_store *reftable_be_init(struct repository *repo, base_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable); strmap_init(&refs->worktree_stacks); refs->store_flags = store_flags; + refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo); refs->write_options.hash_id = repo->hash_algo->format_id; refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask); @@ -1220,7 +1222,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data } else if (!(u->flags & REF_SKIP_CREATE_REFLOG) && (u->flags & REF_HAVE_NEW) && (u->flags & REF_FORCE_CREATE_REFLOG || - should_write_log(&arg->refs->base, u->refname))) { + should_write_log(arg->refs, u->refname))) { struct reftable_log_record *log; int create_reflog = 1; diff --git a/repo-settings.c b/repo-settings.c index 3a76ba276c..1322fd2f97 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -124,3 +124,19 @@ void prepare_repo_settings(struct repository *r) */ r->settings.command_requires_full_index = 1; } + +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; +} diff --git a/repo-settings.h b/repo-settings.h index d03b6e57f0..76adb96a66 100644 --- a/repo-settings.h +++ b/repo-settings.h @@ -65,4 +65,7 @@ struct repo_settings { void prepare_repo_settings(struct repository *r); +/* Read the value for "core.logAllRefUpdates". */ +enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo); + #endif /* REPO_SETTINGS_H */ diff --git a/setup.c b/setup.c index 19cce5afa7..7499191472 100644 --- a/setup.c +++ b/setup.c @@ -2354,7 +2354,7 @@ static int create_default_files(const char *template_path, else { git_config_set("core.bare", "false"); /* allow template config file to override the default */ - if (log_all_ref_updates == LOG_REFS_UNSET) + if (repo_settings_get_log_all_ref_updates(the_repository) == LOG_REFS_UNSET) git_config_set("core.logallrefupdates", "true"); if (needs_work_tree_config(original_git_dir, work_tree)) git_config_set("core.worktree", work_tree); -- cgit v1.2.3 From 11dbb4ace3ac428574fadf6f7895f56aba9dca81 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 12 Sep 2024 13:30:24 +0200 Subject: environment: stop storing "core.warnAmbiguousRefs" globally Same as the preceding commits, storing the "core.warnAmbiguousRefs" value globally is misdesigned as this setting may be set per repository. Move the logic into the repo-settings subsystem. The usual pattern here is that users are expected to call `prepare_repo_settings()` before they access the settings themselves. This seems somewhat fragile though, as it is easy to miss and leads to somewhat ugly code patterns at the call sites. Instead, introduce a new function that encapsulates this logic for us. This also allows us to change how exactly the lazy initialization works in the future, e.g. by only partially initializing values as requested by the caller. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/rev-parse.c | 4 +++- config.c | 5 ----- environment.c | 1 - environment.h | 1 - object-name.c | 5 +++-- ref-filter.c | 3 ++- refs.c | 4 ++-- repo-settings.c | 9 +++++++++ repo-settings.h | 4 ++++ 9 files changed, 23 insertions(+), 13 deletions(-) (limited to 'repo-settings.h') diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index a5108266da..34b4675442 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -19,6 +19,7 @@ #include "path.h" #include "diff.h" #include "read-cache-ll.h" +#include "repo-settings.h" #include "repository.h" #include "revision.h" #include "setup.h" @@ -899,7 +900,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) } if (opt_with_value(arg, "--abbrev-ref", &arg)) { abbrev_ref = 1; - abbrev_ref_strict = warn_ambiguous_refs; + abbrev_ref_strict = + repo_settings_get_warn_ambiguous_refs(the_repository); if (arg) { if (!strcmp(arg, "strict")) abbrev_ref_strict = 1; diff --git a/config.c b/config.c index a59890180a..53c68f3da6 100644 --- a/config.c +++ b/config.c @@ -1447,11 +1447,6 @@ static int git_default_core_config(const char *var, const char *value, return 0; } - if (!strcmp(var, "core.warnambiguousrefs")) { - warn_ambiguous_refs = git_config_bool(var, value); - return 0; - } - if (!strcmp(var, "core.abbrev")) { if (!value) return config_error_nonbool(var); diff --git a/environment.c b/environment.c index 6805c7b01d..9dd000cda3 100644 --- a/environment.c +++ b/environment.c @@ -35,7 +35,6 @@ int minimum_abbrev = 4, default_abbrev = -1; int ignore_case; int assume_unchanged; int is_bare_repository_cfg = -1; /* unspecified */ -int warn_ambiguous_refs = 1; int warn_on_object_refname_ambiguity = 1; int repository_format_precious_objects; char *git_commit_encoding; diff --git a/environment.h b/environment.h index 0cab644e2d..aa38133da9 100644 --- a/environment.h +++ b/environment.h @@ -156,7 +156,6 @@ extern int has_symlinks; extern int minimum_abbrev, default_abbrev; extern int ignore_case; extern int assume_unchanged; -extern int warn_ambiguous_refs; extern int warn_on_object_refname_ambiguity; extern char *apply_default_whitespace; extern char *apply_default_ignorewhitespace; diff --git a/object-name.c b/object-name.c index 09c1bd93a3..c892fbe80a 100644 --- a/object-name.c +++ b/object-name.c @@ -20,6 +20,7 @@ #include "pretty.h" #include "object-store-ll.h" #include "read-cache-ll.h" +#include "repo-settings.h" #include "repository.h" #include "setup.h" #include "midx.h" @@ -959,7 +960,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len, int fatal = !(flags & GET_OID_QUIETLY); if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) { - if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) { + if (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) { refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0); if (refs_found > 0) { warning(warn_msg, len, str); @@ -1020,7 +1021,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len, if (!refs_found) return -1; - if (warn_ambiguous_refs && !(flags & GET_OID_QUIETLY) && + if (repo_settings_get_warn_ambiguous_refs(r) && !(flags & GET_OID_QUIETLY) && (refs_found > 1 || !get_short_oid(r, str, len, &tmp_oid, GET_OID_QUIETLY))) warning(warn_msg, len, str); diff --git a/ref-filter.c b/ref-filter.c index b6c6c10127..7f5cf5a126 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -13,6 +13,7 @@ #include "object-name.h" #include "object-store-ll.h" #include "oid-array.h" +#include "repo-settings.h" #include "repository.h" #include "commit.h" #include "mailmap.h" @@ -2160,7 +2161,7 @@ static const char *show_ref(struct refname_atom *atom, const char *refname) if (atom->option == R_SHORT) return refs_shorten_unambiguous_ref(get_main_ref_store(the_repository), refname, - warn_ambiguous_refs); + repo_settings_get_warn_ambiguous_refs(the_repository)); else if (atom->option == R_LSTRIP) return lstrip_ref_components(refname, atom->lstrip); else if (atom->option == R_RSTRIP) diff --git a/refs.c b/refs.c index d7402bcd19..3bee3e7829 100644 --- a/refs.c +++ b/refs.c @@ -730,7 +730,7 @@ int expand_ref(struct repository *repo, const char *str, int len, if (r) { if (!refs_found++) *ref = xstrdup(r); - if (!warn_ambiguous_refs) + if (!repo_settings_get_warn_ambiguous_refs(repo)) break; } else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) { warning(_("ignoring dangling symref %s"), fullref.buf); @@ -775,7 +775,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len, if (oid) oidcpy(oid, &hash); } - if (!warn_ambiguous_refs) + if (!repo_settings_get_warn_ambiguous_refs(r)) break; } strbuf_release(&path); diff --git a/repo-settings.c b/repo-settings.c index 1322fd2f97..4699b4b365 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -140,3 +140,12 @@ enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *re return LOG_REFS_UNSET; } + +int repo_settings_get_warn_ambiguous_refs(struct repository *repo) +{ + prepare_repo_settings(repo); + if (repo->settings.warn_ambiguous_refs < 0) + repo_cfg_bool(repo, "core.warnambiguousrefs", + &repo->settings.warn_ambiguous_refs, 1); + return repo->settings.warn_ambiguous_refs; +} diff --git a/repo-settings.h b/repo-settings.h index 76adb96a66..51d6156a11 100644 --- a/repo-settings.h +++ b/repo-settings.h @@ -56,16 +56,20 @@ struct repo_settings { enum fetch_negotiation_setting fetch_negotiation_algorithm; int core_multi_pack_index; + int warn_ambiguous_refs; /* lazily loaded via accessor */ }; #define REPO_SETTINGS_INIT { \ .index_version = -1, \ .core_untracked_cache = UNTRACKED_CACHE_KEEP, \ .fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \ + .warn_ambiguous_refs = -1, \ } void prepare_repo_settings(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); #endif /* REPO_SETTINGS_H */ -- cgit v1.2.3