Skip to content

Commit 96a4b73

Browse files
committed
Merge branch 'kn/ref-location' into seen
* kn/ref-location: refs: add GIT_REF_URI to specify reference backend and directory refs: support obtaining ref_store for given dir
2 parents c3f4709 + ec7d86a commit 96a4b73

File tree

5 files changed

+180
-3
lines changed

5 files changed

+180
-3
lines changed

Documentation/git.adoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,14 @@ 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_REF_URI`::
588+
Specify which reference backend and path to be used, if not specified the
589+
backend is inferred from the configuration and $GIT_DIR is used as the
590+
path.
591+
+
592+
Expects the format '<ref_backend>://<path>', where the 'backend' specifies the
593+
reference backend and the 'path' specifies the directory used by the backend.
594+
587595
Git Commits
588596
~~~~~~~~~~~
589597
`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_REF_URI_ENVIRONMENT "GIT_REF_URI"
4546

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

refs.c

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,17 +2191,75 @@ void ref_store_release(struct ref_store *ref_store)
21912191
free(ref_store->gitdir);
21922192
}
21932193

2194+
static struct ref_store *get_ref_store_for_dir(struct repository *r,
2195+
char *dir,
2196+
enum ref_storage_format format)
2197+
{
2198+
struct ref_store *ref_store = ref_store_init(r, format, dir,
2199+
REF_STORE_ALL_CAPS);
2200+
return maybe_debug_wrap_ref_store(dir, ref_store);
2201+
}
2202+
2203+
static struct ref_store *get_ref_store_from_uri(struct repository *repo,
2204+
const char *uri)
2205+
{
2206+
struct string_list ref_backend_info = STRING_LIST_INIT_DUP;
2207+
enum ref_storage_format format;
2208+
struct ref_store *store = NULL;
2209+
char *format_string;
2210+
char *dir;
2211+
2212+
if (!uri || !uri[0]) {
2213+
error("reference backend uri is empty");
2214+
goto cleanup;
2215+
}
2216+
2217+
if (string_list_split(&ref_backend_info, uri, ":", 2) != 2) {
2218+
error("invalid reference backend uri format '%s'", uri);
2219+
goto cleanup;
2220+
}
2221+
2222+
format_string = ref_backend_info.items[0].string;
2223+
dir = ref_backend_info.items[1].string + 2;
2224+
2225+
if (!dir || !dir[0]) {
2226+
error("invalid path in uri '%s'", uri);
2227+
goto cleanup;
2228+
}
2229+
2230+
format = ref_storage_format_by_name(format_string);
2231+
if (format == REF_STORAGE_FORMAT_UNKNOWN) {
2232+
error("unknown reference backend '%s'", format_string);
2233+
goto cleanup;
2234+
}
2235+
2236+
store = get_ref_store_for_dir(repo, dir, format);
2237+
2238+
cleanup:
2239+
string_list_clear(&ref_backend_info, 0);
2240+
return store;
2241+
}
2242+
21942243
struct ref_store *get_main_ref_store(struct repository *r)
21952244
{
2245+
char *ref_uri;
2246+
21962247
if (r->refs_private)
21972248
return r->refs_private;
21982249

21992250
if (!r->gitdir)
22002251
BUG("attempting to get main_ref_store outside of repository");
22012252

2202-
r->refs_private = ref_store_init(r, r->ref_storage_format,
2203-
r->gitdir, REF_STORE_ALL_CAPS);
2204-
r->refs_private = maybe_debug_wrap_ref_store(r->gitdir, r->refs_private);
2253+
ref_uri = getenv(GIT_REF_URI_ENVIRONMENT);
2254+
if (ref_uri) {
2255+
r->refs_private = get_ref_store_from_uri(r, ref_uri);
2256+
if (!r->refs_private)
2257+
die("failed to initialize ref store from URI: %s", ref_uri);
2258+
2259+
} else {
2260+
r->refs_private = get_ref_store_for_dir(r, r->gitdir,
2261+
r->ref_storage_format);
2262+
}
22052263
return r->refs_private;
22062264
}
22072265

t/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ integration_tests = [
210210
't1420-lost-found.sh',
211211
't1421-reflog-write.sh',
212212
't1422-show-ref-exists.sh',
213+
't1423-ref-backend.sh',
213214
't1430-bad-ref-name.sh',
214215
't1450-fsck.sh',
215216
't1451-fsck-buffer.sh',

t/t1423-ref-backend.sh

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/bin/sh
2+
3+
test_description='Test different reference backend URIs'
4+
5+
. ./test-lib.sh
6+
7+
test_expect_success 'empty uri provided' '
8+
test_when_finished "rm -rf repo" &&
9+
git init --ref-format=files repo &&
10+
(
11+
cd repo &&
12+
GIT_REF_URI="" &&
13+
export GIT_REF_URI &&
14+
! git refs list 2>err &&
15+
test_grep "reference backend uri is empty" err
16+
)
17+
'
18+
19+
test_expect_success 'invalid uri provided' '
20+
test_when_finished "rm -rf repo" &&
21+
git init --ref-format=files repo &&
22+
(
23+
cd repo &&
24+
GIT_REF_URI="reftable@/home/reftable" &&
25+
export GIT_REF_URI &&
26+
! git refs list 2>err &&
27+
test_grep "invalid reference backend uri format" err
28+
)
29+
'
30+
31+
test_expect_success 'empty path in uri' '
32+
test_when_finished "rm -rf repo" &&
33+
git init --ref-format=files repo &&
34+
(
35+
cd repo &&
36+
GIT_REF_URI="reftable://" &&
37+
export GIT_REF_URI &&
38+
! git refs list 2>err &&
39+
test_grep "invalid path in uri" err
40+
)
41+
'
42+
43+
test_expect_success 'unknown reference backend' '
44+
test_when_finished "rm -rf repo" &&
45+
git init --ref-format=files repo &&
46+
(
47+
cd repo &&
48+
GIT_REF_URI="db://.git" &&
49+
export GIT_REF_URI &&
50+
! git refs list 2>err &&
51+
test_grep "unknown reference backend" err
52+
)
53+
'
54+
55+
ref_formats="files reftable"
56+
for from_format in $ref_formats
57+
do
58+
for to_format in $ref_formats
59+
do
60+
if test "$from_format" = "$to_format"
61+
then
62+
continue
63+
fi
64+
65+
test_expect_success 'read from other reference backend' '
66+
test_when_finished "rm -rf repo" &&
67+
git init --ref-format=files repo &&
68+
(
69+
cd repo &&
70+
test_commit 1 &&
71+
test_commit 2 &&
72+
test_commit 3 &&
73+
74+
git refs migrate --dry-run --ref-format=reftable >out &&
75+
REFTABLE_PATH=$(cat out | sed "s/.* ${SQ}\(.*\)${SQ}/\1/") &&
76+
git refs list >expect &&
77+
GIT_REF_URI="reftable://$REFTABLE_PATH" git refs list >actual &&
78+
test_cmp expect actual
79+
)
80+
'
81+
82+
test_expect_success 'write to other reference backend' '
83+
test_when_finished "rm -rf repo" &&
84+
git init --ref-format=files repo &&
85+
(
86+
cd repo &&
87+
test_commit 1 &&
88+
test_commit 2 &&
89+
test_commit 3 &&
90+
91+
git refs migrate --dry-run --ref-format=reftable >out &&
92+
git refs list >expect &&
93+
94+
REFTABLE_PATH=$(cat out | sed "s/.* ${SQ}\(.*\)${SQ}/\1/") &&
95+
GIT_REF_URI="reftable://$REFTABLE_PATH" git tag -d 1 &&
96+
97+
git refs list >actual &&
98+
test_cmp expect actual &&
99+
100+
GIT_REF_URI="reftable://$REFTABLE_PATH" git refs list >expect &&
101+
git refs list >out &&
102+
cat out | grep -v "refs/tags/1" >actual &&
103+
test_cmp expect actual
104+
)
105+
'
106+
done
107+
done
108+
109+
test_done

0 commit comments

Comments
 (0)