return maybe_debug_wrap_ref_store(dir, ref_store);
}
+static struct ref_store *get_ref_store_from_uri(struct repository *repo,
+ const char *uri)
+{
+ struct string_list ref_backend_info = STRING_LIST_INIT_DUP;
+ enum ref_storage_format format;
+ struct ref_store *store = NULL;
+ char *format_string;
+ char *dir;
+
+ if (!uri) {
+ error(_("reference backend uri is not provided"));
+ goto cleanup;
+ }
+
+ if (string_list_split(&ref_backend_info, uri, ":", 2) != 2) {
+ error(_("invalid reference backend uri format '%s'"), uri);
+ goto cleanup;
+ }
+
+ format_string = ref_backend_info.items[0].string;
+ if (!starts_with(ref_backend_info.items[1].string, "//")) {
+ error(_("invalid reference backend uri format '%s'"), uri);
+ goto cleanup;
+ }
+ dir = ref_backend_info.items[1].string + 2;
+
+ if (!dir[0]) {
+ error(_("invalid path in uri '%s'"), uri);
+ goto cleanup;
+ }
+
+ format = ref_storage_format_by_name(format_string);
+ if (format == REF_STORAGE_FORMAT_UNKNOWN) {
+ error(_("unknown reference backend '%s'"), format_string);
+ goto cleanup;
+ }
+
+ store = get_ref_store_for_dir(repo, dir, format);
+
+cleanup:
+ string_list_clear(&ref_backend_info, 0);
+ return store;
+}
+
struct ref_store *get_main_ref_store(struct repository *r)
{
+ char *ref_uri;
+
if (r->refs_private)
return r->refs_private;
if (!r->gitdir)
BUG("attempting to get main_ref_store outside of repository");
- r->refs_private = get_ref_store_for_dir(r, r->gitdir, r->ref_storage_format);
+ ref_uri = getenv(GIT_REF_URI_ENVIRONMENT);
+ if (ref_uri) {
+ r->refs_private = get_ref_store_from_uri(r, ref_uri);
+ if (!r->refs_private)
+ die("failed to initialize ref store from URI: %s", ref_uri);
+
+ } else {
+ r->refs_private = get_ref_store_for_dir(r, r->gitdir,
+ r->ref_storage_format);
+ }
return r->refs_private;
}
--- /dev/null
+#!/bin/sh
+
+test_description='Test different reference backend URIs'
+
+. ./test-lib.sh
+
+test_expect_success 'empty uri provided' '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=files repo &&
+ (
+ cd repo &&
+ GIT_REF_URI="" &&
+ export GIT_REF_URI &&
+ test_must_fail git refs list 2>err &&
+ test_grep "invalid reference backend uri format" err
+ )
+'
+
+test_expect_success 'invalid uri provided' '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=files repo &&
+ (
+ cd repo &&
+ GIT_REF_URI="reftable@/home/reftable" &&
+ export GIT_REF_URI &&
+ test_must_fail git refs list 2>err &&
+ test_grep "invalid reference backend uri format" err
+ )
+'
+
+test_expect_success 'empty path in uri' '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=files repo &&
+ (
+ cd repo &&
+ GIT_REF_URI="reftable://" &&
+ export GIT_REF_URI &&
+ test_must_fail git refs list 2>err &&
+ test_grep "invalid path in uri" err
+ )
+'
+
+test_expect_success 'uri ends at colon' '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=files repo &&
+ (
+ cd repo &&
+ GIT_REF_URI="reftable:" &&
+ export GIT_REF_URI &&
+ test_must_fail git refs list 2>err &&
+ test_grep "invalid reference backend uri format" err
+ )
+'
+
+test_expect_success 'unknown reference backend' '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=files repo &&
+ (
+ cd repo &&
+ GIT_REF_URI="db://.git" &&
+ export GIT_REF_URI &&
+ test_must_fail git refs list 2>err &&
+ test_grep "unknown reference backend" err
+ )
+'
+
+ref_formats="files reftable"
+for from_format in $ref_formats
+do
+ for to_format in $ref_formats
+ do
+ if test "$from_format" = "$to_format"
+ then
+ continue
+ fi
+
+ test_expect_success "read from $to_format backend" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ (
+ cd repo &&
+ test_commit 1 &&
+ test_commit 2 &&
+ test_commit 3 &&
+
+ git refs migrate --dry-run --ref-format=$to_format >out &&
+ BACKEND_PATH=$(cat out | sed "s/.* ${SQ}\(.*\)${SQ}/\1/") &&
+ git refs list >expect &&
+ GIT_REF_URI="$to_format://$BACKEND_PATH" git refs list >actual &&
+ test_cmp expect actual
+ )
+ '
+
+ test_expect_success "write to $to_format backend" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ (
+ cd repo &&
+ test_commit 1 &&
+ test_commit 2 &&
+ test_commit 3 &&
+
+ git refs migrate --dry-run --ref-format=$to_format >out &&
+ git refs list >expect &&
+
+ BACKEND_PATH=$(cat out | sed "s/.* ${SQ}\(.*\)${SQ}/\1/") &&
+ GIT_REF_URI="$to_format://$BACKEND_PATH" git tag -d 1 &&
+
+ git refs list >actual &&
+ test_cmp expect actual &&
+
+ GIT_REF_URI="$to_format://$BACKEND_PATH" git refs list >expect &&
+ git refs list >out &&
+ cat out | grep -v "refs/tags/1" >actual &&
+ test_cmp expect actual
+ )
+ '
+ done
+done
+
+test_done