From 657d96507b7f5a5056702171d380c8a0eb96c56d Mon Sep 17 00:00:00 2001 From: Karthik Nayak Date: Wed, 5 Nov 2025 16:04:48 +0100 Subject: [PATCH 1/4] EDITME: cover title for kn-alternate-ref-dir # Describe the purpose of this series. The information you put here # will be used by the project maintainer to make a decision whether # your patches should be reviewed, and in what priority order. Please be # very detailed and link to any relevant discussions or sites that the # maintainer can review to better understand your proposed changes. If you # only have a single patch in your series, the contents of the cover # letter will be appended to the "under-the-cut" portion of the patch. # Lines starting with # will be removed from the cover letter. You can # use them to add notes or reminders to yourself. If you want to use # markdown headers in your cover letter, start the line with ">#". # You can add trailers to the cover letter. Any email addresses found in # these trailers will be added to the addresses specified/generated # during the b4 send stage. You can also run "b4 prep --auto-to-cc" to # auto-populate the To: and Cc: trailers based on the code being # modified. Signed-off-by: Karthik Nayak --- b4-submit-tracking --- # This section is used internally by b4 prep for tracking purposes. { "series": { "revision": 1, "change-id": "20251105-kn-alternate-ref-dir-3e572e8cd0ef", "prefixes": [] } } -- GitLab From 773352997ada82216b121cdfd55b714188188db0 Mon Sep 17 00:00:00 2001 From: Karthik Nayak Date: Wed, 5 Nov 2025 16:10:01 +0100 Subject: [PATCH 2/4] refs: avoid using global 'the_repository' variable The 'builtin/refs.c' file provides the 'git-refs(1)' command, while the command and its subcommands have access to a 'struct repository *repo' variable, they tend to use the global 'the_repository' variable instead. Use the locally available variable, this makes the code more maintainable by avoiding global variables and also takes us one step closer in our goal to cleanup global variables. With this remove the no-longer needed 'USE_THE_REPOSITORY_VARIABLE' defination. Signed-off-by: Karthik Nayak --- builtin/refs.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/builtin/refs.c b/builtin/refs.c index 3064f888b24..97f1d748acf 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "fsck.h" @@ -23,7 +22,7 @@ N_("git refs optimize " PACK_REFS_OPTS) static int cmd_refs_migrate(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { const char * const migrate_usage[] = { REFS_MIGRATE_USAGE, @@ -59,13 +58,13 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix, goto out; } - if (the_repository->ref_storage_format == format) { + if (repo->ref_storage_format == format) { err = error(_("repository already uses '%s' format"), ref_storage_format_to_name(format)); goto out; } - if (repo_migrate_ref_storage_format(the_repository, format, flags, &errbuf) < 0) { + if (repo_migrate_ref_storage_format(repo, format, flags, &errbuf) < 0) { err = error("%s", errbuf.buf); goto out; } @@ -78,7 +77,7 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix, } static int cmd_refs_verify(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct fsck_options fsck_refs_options = FSCK_REFS_OPTIONS_DEFAULT; struct worktree **worktrees; @@ -97,8 +96,8 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix, if (argc) usage(_("'git refs verify' takes no arguments")); - repo_config(the_repository, git_fsck_config, &fsck_refs_options); - prepare_repo_settings(the_repository); + repo_config(repo, git_fsck_config, &fsck_refs_options); + prepare_repo_settings(repo); worktrees = get_worktrees_without_reading_head(); for (size_t i = 0; worktrees[i]; i++) @@ -122,7 +121,7 @@ static int cmd_refs_list(int argc, const char **argv, const char *prefix, } static int cmd_refs_exists(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct strbuf unused_referent = STRBUF_INIT; struct object_id unused_oid; @@ -143,7 +142,7 @@ static int cmd_refs_exists(int argc, const char **argv, const char *prefix, die(_("'git refs exists' requires a reference")); ref = *argv++; - if (refs_read_raw_ref(get_main_ref_store(the_repository), ref, + if (refs_read_raw_ref(get_main_ref_store(repo), ref, &unused_oid, &unused_referent, &unused_type, &failure_errno)) { if (failure_errno == ENOENT || failure_errno == EISDIR) { -- GitLab From 8ae140b3ba680fc6783bb77a345b2377902bfc59 Mon Sep 17 00:00:00 2001 From: Karthik Nayak Date: Thu, 6 Nov 2025 08:57:56 +0100 Subject: [PATCH 3/4] refs: support obtaining ref_store for given dir The refs subsystem exposes the `get_main_ref_store()` to obtain the main ref_store for a given repository. In the upcoming patches we also want to create a ref_store for any given reference directory, which may exist in arbitrary paths. To support such behavior, extract out the core logic for creating out the ref_store from `get_main_ref_store()` into a new function `get_ref_store_for_dir()` which can provide the ref_store for a given (repository, directory, reference format) combination. Signed-off-by: Karthik Nayak --- refs.c | 12 +++++++++--- refs.h | 2 ++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/refs.c b/refs.c index 965381367e0..a775c644c4b 100644 --- a/refs.c +++ b/refs.c @@ -2177,6 +2177,14 @@ void ref_store_release(struct ref_store *ref_store) free(ref_store->gitdir); } +struct ref_store *get_ref_store_for_dir(struct repository *r, char *dir, + enum ref_storage_format format) +{ + struct ref_store *ref_store = ref_store_init(r, format, dir, + REF_STORE_ALL_CAPS); + return maybe_debug_wrap_ref_store(dir, ref_store); +} + struct ref_store *get_main_ref_store(struct repository *r) { if (r->refs_private) @@ -2185,9 +2193,7 @@ struct ref_store *get_main_ref_store(struct repository *r) if (!r->gitdir) BUG("attempting to get main_ref_store outside of repository"); - r->refs_private = ref_store_init(r, r->ref_storage_format, - r->gitdir, REF_STORE_ALL_CAPS); - r->refs_private = maybe_debug_wrap_ref_store(r->gitdir, r->refs_private); + r->refs_private = get_ref_store_for_dir(r, r->gitdir, r->ref_storage_format); return r->refs_private; } diff --git a/refs.h b/refs.h index 4e6bd63aa86..f96522fe688 100644 --- a/refs.h +++ b/refs.h @@ -1066,6 +1066,8 @@ int refs_reflog_expire(struct ref_store *refs, reflog_expiry_cleanup_fn cleanup_fn, void *policy_cb_data); +struct ref_store *get_ref_store_for_dir(struct repository *r, char *dir, + enum ref_storage_format format); struct ref_store *get_main_ref_store(struct repository *r); /** -- GitLab From 4c4c1872df7993dc7f55ad1b96508c55e154177c Mon Sep 17 00:00:00 2001 From: Karthik Nayak Date: Thu, 6 Nov 2025 11:45:42 +0100 Subject: [PATCH 4/4] refs: allow setting the reference directory Signed-off-by: Karthik Nayak --- environment.h | 2 ++ repository.c | 11 +++++++++++ repository.h | 2 ++ setup.c | 2 ++ 4 files changed, 17 insertions(+) diff --git a/environment.h b/environment.h index 51898c99cd1..ac6a3905df9 100644 --- a/environment.h +++ b/environment.h @@ -42,6 +42,8 @@ #define GIT_OPTIONAL_LOCKS_ENVIRONMENT "GIT_OPTIONAL_LOCKS" #define GIT_TEXT_DOMAIN_DIR_ENVIRONMENT "GIT_TEXTDOMAINDIR" #define GIT_ATTR_SOURCE_ENVIRONMENT "GIT_ATTR_SOURCE" +#define GIT_REF_DIRECTORY_ENVIRONMENT "GIT_REF_DIRECTORY" +#define GIT_REF_FORMAT_ENVIRONMENT "GIT_REF_FORMAT" /* * Environment variable used to propagate the --no-advice global option to the diff --git a/repository.c b/repository.c index 6faf5c73981..6a4463238a2 100644 --- a/repository.c +++ b/repository.c @@ -177,6 +177,17 @@ void repo_set_gitdir(struct repository *repo, repo->objects->sources->disable_ref_updates = o->disable_ref_updates; + if ((o->ref_dir != NULL) ^ (o->ref_format != NULL)) + BUG("both reference directory and reference format must be set"); + + if (o->ref_dir != NULL && o->ref_format != NULL) { + enum ref_storage_format format = ref_storage_format_by_name(o->ref_format); + if (format == REF_STORAGE_FORMAT_UNKNOWN) + BUG("unknown ref storage format '%s'", o->ref_format); + + repo->refs_private = get_ref_store_for_dir(repo, (char *)o->ref_dir, format); + } + free(repo->objects->alternate_db); repo->objects->alternate_db = xstrdup_or_null(o->alternate_db); expand_base_dir(&repo->graft_file, o->graft_file, diff --git a/repository.h b/repository.h index 5808a5d6108..28c7dcd4c29 100644 --- a/repository.h +++ b/repository.h @@ -187,6 +187,8 @@ struct set_gitdir_args { const char *graft_file; const char *index_file; const char *alternate_db; + const char *ref_dir; + const char *ref_format; int disable_ref_updates; }; diff --git a/setup.c b/setup.c index 7086741e6c2..198538b1dd1 100644 --- a/setup.c +++ b/setup.c @@ -1641,6 +1641,8 @@ void setup_git_env(const char *git_dir) args.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT); args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT); args.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT); + args.ref_dir = getenv_safe(&to_free, GIT_REF_DIRECTORY_ENVIRONMENT); + args.ref_format = getenv_safe(&to_free, GIT_REF_FORMAT_ENVIRONMENT); if (getenv(GIT_QUARANTINE_ENVIRONMENT)) { args.disable_ref_updates = 1; } -- GitLab