Merge branch 'mh/submodule-hash'
Code and design clean-up for the refs API. * mh/submodule-hash: read_loose_refs(): read refs using resolve_ref_recursively() files_ref_store::submodule: use NULL for the main repository base_ref_store_init(): remove submodule argument refs: push the submodule attribute down refs: store submodule ref stores in a hashmap register_ref_store(): new function refs: remove some unnecessary handling of submodule == "" refs: make some ref_store lookup functions private refs: reorder some function definitions
This commit is contained in:
121
refs.c
121
refs.c
@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include "cache.h"
|
||||
#include "hashmap.h"
|
||||
#include "lockfile.h"
|
||||
#include "refs.h"
|
||||
#include "refs/refs-internal.h"
|
||||
@ -1234,10 +1235,10 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
|
||||
}
|
||||
|
||||
/* This function needs to return a meaningful errno on failure */
|
||||
static const char *resolve_ref_recursively(struct ref_store *refs,
|
||||
const char *refname,
|
||||
int resolve_flags,
|
||||
unsigned char *sha1, int *flags)
|
||||
const char *resolve_ref_recursively(struct ref_store *refs,
|
||||
const char *refname,
|
||||
int resolve_flags,
|
||||
unsigned char *sha1, int *flags)
|
||||
{
|
||||
static struct strbuf sb_refname = STRBUF_INIT;
|
||||
int unused_flags;
|
||||
@ -1357,62 +1358,102 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct submodule_hash_entry
|
||||
{
|
||||
struct hashmap_entry ent; /* must be the first member! */
|
||||
|
||||
struct ref_store *refs;
|
||||
|
||||
/* NUL-terminated name of submodule: */
|
||||
char submodule[FLEX_ARRAY];
|
||||
};
|
||||
|
||||
static int submodule_hash_cmp(const void *entry, const void *entry_or_key,
|
||||
const void *keydata)
|
||||
{
|
||||
const struct submodule_hash_entry *e1 = entry, *e2 = entry_or_key;
|
||||
const char *submodule = keydata ? keydata : e2->submodule;
|
||||
|
||||
return strcmp(e1->submodule, submodule);
|
||||
}
|
||||
|
||||
static struct submodule_hash_entry *alloc_submodule_hash_entry(
|
||||
const char *submodule, struct ref_store *refs)
|
||||
{
|
||||
struct submodule_hash_entry *entry;
|
||||
|
||||
FLEX_ALLOC_STR(entry, submodule, submodule);
|
||||
hashmap_entry_init(entry, strhash(submodule));
|
||||
entry->refs = refs;
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* A hashmap of ref_stores, stored by submodule name: */
|
||||
static struct hashmap submodule_ref_stores;
|
||||
|
||||
void base_ref_store_init(struct ref_store *refs,
|
||||
const struct ref_storage_be *be,
|
||||
const char *submodule)
|
||||
/*
|
||||
* Return the ref_store instance for the specified submodule (or the
|
||||
* main repository if submodule is NULL). If that ref_store hasn't
|
||||
* been initialized yet, return NULL.
|
||||
*/
|
||||
static struct ref_store *lookup_ref_store(const char *submodule)
|
||||
{
|
||||
struct submodule_hash_entry *entry;
|
||||
|
||||
if (!submodule)
|
||||
return main_ref_store;
|
||||
|
||||
if (!submodule_ref_stores.tablesize)
|
||||
/* It's initialized on demand in register_ref_store(). */
|
||||
return NULL;
|
||||
|
||||
entry = hashmap_get_from_hash(&submodule_ref_stores,
|
||||
strhash(submodule), submodule);
|
||||
return entry ? entry->refs : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the specified ref_store to be the one that should be used
|
||||
* for submodule (or the main repository if submodule is NULL). It is
|
||||
* a fatal error to call this function twice for the same submodule.
|
||||
*/
|
||||
static void register_ref_store(struct ref_store *refs, 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))
|
||||
if (!submodule_ref_stores.tablesize)
|
||||
hashmap_init(&submodule_ref_stores, submodule_hash_cmp, 0);
|
||||
|
||||
if (hashmap_put(&submodule_ref_stores,
|
||||
alloc_submodule_hash_entry(submodule, refs)))
|
||||
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)
|
||||
/*
|
||||
* Create, record, and return a ref_store instance for the specified
|
||||
* submodule (or the main repository if submodule is NULL).
|
||||
*/
|
||||
static 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);
|
||||
struct ref_store *refs;
|
||||
|
||||
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;
|
||||
refs = be->init(submodule);
|
||||
register_ref_store(refs, submodule);
|
||||
return refs;
|
||||
}
|
||||
|
||||
struct ref_store *get_ref_store(const char *submodule)
|
||||
@ -1440,10 +1481,10 @@ struct ref_store *get_ref_store(const char *submodule)
|
||||
return refs;
|
||||
}
|
||||
|
||||
void assert_main_repository(struct ref_store *refs, const char *caller)
|
||||
void base_ref_store_init(struct ref_store *refs,
|
||||
const struct ref_storage_be *be)
|
||||
{
|
||||
if (*refs->submodule)
|
||||
die("BUG: %s called for a submodule", caller);
|
||||
refs->be = be;
|
||||
}
|
||||
|
||||
/* backend functions */
|
||||
|
Reference in New Issue
Block a user