unsigned int store_flags;
char *gitcommondir;
- enum log_refs_config log_all_ref_updates;
- int prefer_symlink_refs;
-
struct ref_cache *loose;
-
struct ref_store *packed_ref_store;
+
+ /*
+ * Options used when writing references. These are parsed from the
+ * config lazily on first use via `files_ref_store_write_options()` so
+ * that we don't have to access the configuration when initializing the
+ * ref store. Do not access these fields directly, but use the accessor
+ * instead.
+ */
+ struct files_ref_store_write_options {
+ enum log_refs_config log_all_ref_updates;
+ int prefer_symlink_refs;
+ bool initialized;
+ } write_opts_lazy_loaded;
};
static void clear_loose_ref_cache(struct files_ref_store *refs)
const struct config_context *ctx UNUSED,
void *payload)
{
- struct files_ref_store *refs = payload;
+ struct files_ref_store_write_options *opts = payload;
if (!strcmp(var, "core.prefersymlinkrefs")) {
- refs->prefer_symlink_refs = git_config_bool(var, value);
+ opts->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);
+ opts->log_all_ref_updates = refs_parse_log_all_ref_updates_config(value);
}
return 0;
}
+static const struct files_ref_store_write_options *files_ref_store_write_options(struct files_ref_store *refs)
+{
+ struct files_ref_store_write_options *opts = &refs->write_opts_lazy_loaded;
+
+ if (opts->initialized)
+ return opts;
+
+ opts->log_all_ref_updates = LOG_REFS_UNSET;
+ repo_config(refs->base.repo, files_ref_store_config, opts);
+
+ opts->initialized = true;
+ return opts;
+}
+
/*
* Create a new submodule ref cache and add it to the internal
* set of caches.
refs->packed_ref_store =
packed_ref_store_init(repo, NULL, refs->gitcommondir, opts);
refs->store_flags = opts->access_flags;
- 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);
const char *refname, int force_create,
int *logfd, struct strbuf *err)
{
- enum log_refs_config log_refs_cfg = refs->log_all_ref_updates;
+ enum log_refs_config log_refs_cfg = files_ref_store_write_options(refs)->log_all_ref_updates;
struct strbuf logfile_sb = STRBUF_INIT;
char *logfile;
{
struct files_ref_store *refs =
files_downcast(ref_store, 0, "ref_transaction_finish");
+ const struct files_ref_store_write_options *write_opts = files_ref_store_write_options(refs);
size_t i;
int ret = 0;
struct strbuf sb = STRBUF_INIT;
* We try creating a symlink, if that succeeds we continue to the
* next update. If not, we try and create a regular symref.
*/
- if (update->new_target && refs->prefer_symlink_refs)
+ if (update->new_target && write_opts->prefer_symlink_refs)
/*
* By using the `NOT_CONSTANT()` trick, we can avoid
* errors by `clang`'s `-Wunreachable` logic that would
test_cmp expect actual
'
+test_expect_success SYMLINKS,!MINGW,!WITH_BREAKING_CHANGES 'core.preferSymlinkRefs can be set up via onbranch condition' '
+ test_when_finished "git symbolic-ref -d TEST_SYMREF_HEAD" &&
+ test_when_finished "rm -f .git/include" &&
+ git update-ref refs/heads/new @ &&
+ cat >.git/include <<-\EOF &&
+ [core]
+ preferSymlinkRefs = true
+ EOF
+ test_config includeIf.onbranch:"$(git branch --show-current)".path \
+ "$(pwd)/.git/include" &&
+ cat >stdin <<-EOF &&
+ start
+ symref-create TEST_SYMREF_HEAD refs/heads/new
+ prepare
+ commit
+ EOF
+ git update-ref --no-deref --stdin <stdin &&
+ test_path_is_symlink .git/TEST_SYMREF_HEAD &&
+ test "$(test_readlink .git/TEST_SYMREF_HEAD)" = refs/heads/new
+'
+
test_done