refs: create a base class "ref_store" for files_ref_store

We want ref_stores to be polymorphic, so invent a base class of which
files_ref_store is a derived class. For now there is exactly one
ref_store for the main repository and one for any submodules whose
references have been accessed.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Michael Haggerty
2016-09-04 18:08:11 +02:00
committed by Junio C Hamano
parent 3dce444f17
commit 00eebe351c
3 changed files with 271 additions and 79 deletions

93
refs.c
View File

@ -1151,8 +1151,12 @@ int head_ref(each_ref_fn fn, void *cb_data)
static int do_for_each_ref(const char *submodule, const char *prefix,
each_ref_fn fn, int trim, int flags, void *cb_data)
{
struct ref_store *refs = get_ref_store(submodule);
struct ref_iterator *iter;
if (!refs)
return 0;
iter = files_ref_iterator_begin(submodule, prefix, flags);
iter = prefix_ref_iterator_begin(iter, prefix, trim);
@ -1284,3 +1288,92 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
errno = ELOOP;
return NULL;
}
/* A pointer to the ref_store for the main repository: */
static struct ref_store *main_ref_store;
/* A linked list of ref_stores for submodules: */
static struct ref_store *submodule_ref_stores;
void base_ref_store_init(struct ref_store *refs,
const struct ref_storage_be *be,
const char *submodule)
{
refs->be = be;
if (!submodule) {
if (main_ref_store)
die("BUG: main_ref_store initialized twice");
refs->submodule = "";
refs->next = NULL;
main_ref_store = refs;
} else {
if (lookup_ref_store(submodule))
die("BUG: ref_store for submodule '%s' initialized twice",
submodule);
refs->submodule = xstrdup(submodule);
refs->next = submodule_ref_stores;
submodule_ref_stores = refs;
}
}
struct ref_store *ref_store_init(const char *submodule)
{
const char *be_name = "files";
struct ref_storage_be *be = find_ref_storage_backend(be_name);
if (!be)
die("BUG: reference backend %s is unknown", be_name);
if (!submodule || !*submodule)
return be->init(NULL);
else
return be->init(submodule);
}
struct ref_store *lookup_ref_store(const char *submodule)
{
struct ref_store *refs;
if (!submodule || !*submodule)
return main_ref_store;
for (refs = submodule_ref_stores; refs; refs = refs->next) {
if (!strcmp(submodule, refs->submodule))
return refs;
}
return NULL;
}
struct ref_store *get_ref_store(const char *submodule)
{
struct ref_store *refs;
if (!submodule || !*submodule) {
refs = lookup_ref_store(NULL);
if (!refs)
refs = ref_store_init(NULL);
} else {
refs = lookup_ref_store(submodule);
if (!refs) {
struct strbuf submodule_sb = STRBUF_INIT;
strbuf_addstr(&submodule_sb, submodule);
if (is_nonbare_repository_dir(&submodule_sb))
refs = ref_store_init(submodule);
strbuf_release(&submodule_sb);
}
}
return refs;
}
void assert_main_repository(struct ref_store *refs, const char *caller)
{
if (*refs->submodule)
die("BUG: %s called for a submodule", caller);
}