Skip to content

Commit 53592d6

Browse files
KarthikNayakgitster
authored andcommitted
refs: add GIT_REFERENCE_BACKEND to specify reference backend
Git allows setting a different object directory via 'GIT_OBJECT_DIRECTORY', but provides no equivalent for references. In the previous commit we extended the 'extensions.refStorage' config to also support an URI input for reference backend with location. Let's also add a new environment variable 'GIT_REFERENCE_BACKEND' that takes in the same input as the config variable. Having an environment variable allows us to modify the reference backend and location on the fly for individual Git commands. The environment variable also allows usage of alternate reference directories during 'git-clone(1)' and 'git-init(1)'. Add the config to the repository when created with the environment variable set. When initializing the repository with an alternate reference folder, create the required stubs in the repositories $GIT_DIR. The inverse, i.e. removal of the ref store doesn't clean up the stubs in the $GIT_DIR since that would render it unusable. Removal of ref store is only used when migrating between ref formats and cleanup of the $GIT_DIR doesn't make sense in such a situation. Helped-by: Jean-Noël Avila <jn.avila@free.fr> Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 01dc845 commit 53592d6

5 files changed

Lines changed: 233 additions & 45 deletions

File tree

Documentation/git.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,11 @@ double-quotes and respecting backslash escapes. E.g., the value
584584
repositories will be set to this value. The default is "files".
585585
See `--ref-format` in linkgit:git-init[1].
586586

587+
`GIT_REFERENCE_BACKEND`::
588+
Specify which reference backend to be used along with its URI.
589+
See `extensions.refStorage` option in linkgit:git-config[1] for more
590+
details. Overrides the config variable when used.
591+
587592
Git Commits
588593
~~~~~~~~~~~
589594
`GIT_AUTHOR_NAME`::

environment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#define GIT_OPTIONAL_LOCKS_ENVIRONMENT "GIT_OPTIONAL_LOCKS"
4343
#define GIT_TEXT_DOMAIN_DIR_ENVIRONMENT "GIT_TEXTDOMAINDIR"
4444
#define GIT_ATTR_SOURCE_ENVIRONMENT "GIT_ATTR_SOURCE"
45+
#define GIT_REFERENCE_BACKEND_ENVIRONMENT "GIT_REFERENCE_BACKEND"
4546

4647
/*
4748
* Environment variable used to propagate the --no-advice global option to the

refs.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,13 +2192,17 @@ int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *e
21922192
{
21932193
int ret = refs->be->create_on_disk(refs, flags, err);
21942194

2195-
if (!ret &&
2196-
ref_storage_format_by_name(refs->be->name) != REF_STORAGE_FORMAT_FILES) {
2197-
struct strbuf msg = STRBUF_INIT;
2198-
2199-
strbuf_addf(&msg, "this repository uses the %s format", refs->be->name);
2200-
refs_create_refdir_stubs(refs->repo, refs->gitdir, msg.buf);
2201-
strbuf_release(&msg);
2195+
if (!ret) {
2196+
/* Creation of stubs for linked worktrees are handled in the worktree code. */
2197+
if (!(flags & REF_STORE_CREATE_ON_DISK_IS_WORKTREE) && refs->repo->ref_storage_payload) {
2198+
refs_create_refdir_stubs(refs->repo, refs->repo->gitdir,
2199+
"repository uses alternate refs storage");
2200+
} else if (ref_storage_format_by_name(refs->be->name) != REF_STORAGE_FORMAT_FILES) {
2201+
struct strbuf msg = STRBUF_INIT;
2202+
strbuf_addf(&msg, "this repository uses the %s format", refs->be->name);
2203+
refs_create_refdir_stubs(refs->repo, refs->gitdir, msg.buf);
2204+
strbuf_release(&msg);
2205+
}
22022206
}
22032207

22042208
return ret;
@@ -2208,10 +2212,18 @@ int ref_store_remove_on_disk(struct ref_store *refs, struct strbuf *err)
22082212
{
22092213
int ret = refs->be->remove_on_disk(refs, err);
22102214

2211-
if (!ret &&
2212-
ref_storage_format_by_name(refs->be->name) != REF_STORAGE_FORMAT_FILES) {
2215+
if (!ret) {
2216+
enum ref_storage_format format = ref_storage_format_by_name(refs->be->name);
22132217
struct strbuf sb = STRBUF_INIT;
22142218

2219+
/* Backends apart from the files backend create stubs. */
2220+
if (format == REF_STORAGE_FORMAT_FILES)
2221+
return ret;
2222+
2223+
/* Alternate refs backend require stubs in the gitdir. */
2224+
if (refs->repo->ref_storage_payload)
2225+
return ret;
2226+
22152227
strbuf_addf(&sb, "%s/HEAD", refs->gitdir);
22162228
if (unlink(sb.buf) < 0) {
22172229
strbuf_addf(err, "could not delete stub HEAD: %s",

setup.c

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,6 +1838,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
18381838
static struct strbuf cwd = STRBUF_INIT;
18391839
struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT, report = STRBUF_INIT;
18401840
const char *prefix = NULL;
1841+
const char *ref_backend_uri;
18411842
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
18421843

18431844
/*
@@ -1995,6 +1996,25 @@ const char *setup_git_directory_gently(int *nongit_ok)
19951996
setenv(GIT_PREFIX_ENVIRONMENT, "", 1);
19961997
}
19971998

1999+
/*
2000+
* The env variable should override the repository config
2001+
* for 'extensions.refStorage'.
2002+
*/
2003+
ref_backend_uri = getenv(GIT_REFERENCE_BACKEND_ENVIRONMENT);
2004+
if (ref_backend_uri) {
2005+
char *backend, *payload;
2006+
enum ref_storage_format format;
2007+
2008+
parse_reference_uri(ref_backend_uri, &backend, &payload);
2009+
format = ref_storage_format_by_name(backend);
2010+
if (format == REF_STORAGE_FORMAT_UNKNOWN)
2011+
die(_("unknown ref storage format: '%s'"), backend);
2012+
repo_set_ref_storage_format(the_repository, format, payload);
2013+
2014+
free(backend);
2015+
free(payload);
2016+
}
2017+
19982018
setup_original_cwd();
19992019

20002020
strbuf_release(&dir);
@@ -2337,7 +2357,8 @@ void initialize_repository_version(int hash_algo,
23372357
* the remote repository's format.
23382358
*/
23392359
if (hash_algo != GIT_HASH_SHA1_LEGACY ||
2340-
ref_storage_format != REF_STORAGE_FORMAT_FILES)
2360+
ref_storage_format != REF_STORAGE_FORMAT_FILES ||
2361+
the_repository->ref_storage_payload)
23412362
target_version = GIT_REPO_VERSION_READ;
23422363

23432364
if (hash_algo != GIT_HASH_SHA1_LEGACY && hash_algo != GIT_HASH_UNKNOWN)
@@ -2346,11 +2367,20 @@ void initialize_repository_version(int hash_algo,
23462367
else if (reinit)
23472368
repo_config_set_gently(the_repository, "extensions.objectformat", NULL);
23482369

2349-
if (ref_storage_format != REF_STORAGE_FORMAT_FILES)
2370+
if (the_repository->ref_storage_payload) {
2371+
struct strbuf ref_uri = STRBUF_INIT;
2372+
2373+
strbuf_addf(&ref_uri, "%s://%s",
2374+
ref_storage_format_to_name(ref_storage_format),
2375+
the_repository->ref_storage_payload);
2376+
repo_config_set(the_repository, "extensions.refstorage", ref_uri.buf);
2377+
strbuf_release(&ref_uri);
2378+
} else if (ref_storage_format != REF_STORAGE_FORMAT_FILES) {
23502379
repo_config_set(the_repository, "extensions.refstorage",
23512380
ref_storage_format_to_name(ref_storage_format));
2352-
else if (reinit)
2381+
} else if (reinit) {
23532382
repo_config_set_gently(the_repository, "extensions.refstorage", NULL);
2383+
}
23542384

23552385
if (reinit) {
23562386
struct strbuf config = STRBUF_INIT;
@@ -2623,6 +2653,7 @@ static void repository_format_configure(struct repository_format *repo_fmt,
26232653
.ignore_repo = 1,
26242654
.ignore_worktree = 1,
26252655
};
2656+
const char *ref_backend_uri;
26262657
const char *env;
26272658

26282659
config_with_options(read_default_format_config, &cfg, NULL, NULL, &opts);
@@ -2668,6 +2699,24 @@ static void repository_format_configure(struct repository_format *repo_fmt,
26682699
} else {
26692700
repo_fmt->ref_storage_format = REF_STORAGE_FORMAT_DEFAULT;
26702701
}
2702+
2703+
2704+
ref_backend_uri = getenv(GIT_REFERENCE_BACKEND_ENVIRONMENT);
2705+
if (ref_backend_uri) {
2706+
char *backend, *payload;
2707+
enum ref_storage_format format;
2708+
2709+
parse_reference_uri(ref_backend_uri, &backend, &payload);
2710+
format = ref_storage_format_by_name(backend);
2711+
if (format == REF_STORAGE_FORMAT_UNKNOWN)
2712+
die(_("unknown ref storage format: '%s'"), backend);
2713+
2714+
repo_fmt->ref_storage_format = format;
2715+
repo_fmt->ref_storage_payload = payload;
2716+
2717+
free(backend);
2718+
}
2719+
26712720
repo_set_ref_storage_format(the_repository, repo_fmt->ref_storage_format,
26722721
repo_fmt->ref_storage_payload);
26732722
}

0 commit comments

Comments
 (0)