From 620a66b9e2d68433aab2ae3daf5a62896c0547d8 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 10 Feb 2017 12:16:11 +0100 Subject: refs: reorder some function definitions This avoids the need to add forward declarations in the next step. Signed-off-by: Michael Haggerty Reviewed-by: Jeff King Signed-off-by: Junio C Hamano --- refs.c | 64 ++++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 9bd0bc177b..707092f99b 100644 --- a/refs.c +++ b/refs.c @@ -1358,27 +1358,19 @@ 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) +struct ref_store *lookup_ref_store(const char *submodule) { - refs->be = be; - if (!submodule) { - if (main_ref_store) - die("BUG: main_ref_store initialized twice"); + struct ref_store *refs; - 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); + if (!submodule || !*submodule) + return main_ref_store; - refs->submodule = xstrdup(submodule); - refs->next = submodule_ref_stores; - submodule_ref_stores = refs; + for (refs = submodule_ref_stores; refs; refs = refs->next) { + if (!strcmp(submodule, refs->submodule)) + return refs; } + + return NULL; } struct ref_store *ref_store_init(const char *submodule) @@ -1395,21 +1387,6 @@ struct ref_store *ref_store_init(const char *submodule) 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; @@ -1435,6 +1412,29 @@ struct ref_store *get_ref_store(const char *submodule) return refs; } +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; + } +} + void assert_main_repository(struct ref_store *refs, const char *caller) { if (*refs->submodule) -- cgit v1.2.1 From c468da4e2796868362c2f33b499d9bb6d6cd7043 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 10 Feb 2017 12:16:12 +0100 Subject: refs: make some ref_store lookup functions private The following functions currently don't need to be exposed: * ref_store_init() * lookup_ref_store() That might change in the future, but for now make them private. Signed-off-by: Michael Haggerty Reviewed-by: Jeff King Signed-off-by: Junio C Hamano --- refs.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 707092f99b..d7265ccc8f 100644 --- a/refs.c +++ b/refs.c @@ -1358,7 +1358,15 @@ static struct ref_store *main_ref_store; /* A linked list of ref_stores for submodules: */ static struct ref_store *submodule_ref_stores; -struct ref_store *lookup_ref_store(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. + * + * For backwards compatibility, submodule=="" is treated the same as + * submodule==NULL. + */ +static struct ref_store *lookup_ref_store(const char *submodule) { struct ref_store *refs; @@ -1373,7 +1381,14 @@ struct ref_store *lookup_ref_store(const char *submodule) return NULL; } -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). + * + * For backwards compatibility, submodule=="" is treated the same as + * submodule==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); -- cgit v1.2.1 From b4f540b6cefdb33f35ffd5f8b2fb459c184a1bd7 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 10 Feb 2017 12:16:13 +0100 Subject: refs: remove some unnecessary handling of submodule == "" The only external entry point to the ref_store lookup functions is get_ref_store(), which ensures that submodule == "" is passed along as NULL. So ref_store_init() and lookup_ref_store() don't have to handle submodule being specified as the empty string. Signed-off-by: Michael Haggerty Reviewed-by: Jeff King Signed-off-by: Junio C Hamano --- refs.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index d7265ccc8f..63484140f6 100644 --- a/refs.c +++ b/refs.c @@ -1362,15 +1362,12 @@ static struct ref_store *submodule_ref_stores; * 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. - * - * For backwards compatibility, submodule=="" is treated the same as - * submodule==NULL. */ static struct ref_store *lookup_ref_store(const char *submodule) { struct ref_store *refs; - if (!submodule || !*submodule) + if (!submodule) return main_ref_store; for (refs = submodule_ref_stores; refs; refs = refs->next) { @@ -1384,9 +1381,6 @@ static struct ref_store *lookup_ref_store(const char *submodule) /* * Create, record, and return a ref_store instance for the specified * submodule (or the main repository if submodule is NULL). - * - * For backwards compatibility, submodule=="" is treated the same as - * submodule==NULL. */ static struct ref_store *ref_store_init(const char *submodule) { @@ -1396,10 +1390,7 @@ static struct ref_store *ref_store_init(const char *submodule) if (!be) die("BUG: reference backend %s is unknown", be_name); - if (!submodule || !*submodule) - return be->init(NULL); - else - return be->init(submodule); + return be->init(submodule); } struct ref_store *get_ref_store(const char *submodule) -- cgit v1.2.1 From ba88add58176a883e4137ee9bb5e66235799a9d9 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 10 Feb 2017 12:16:14 +0100 Subject: register_ref_store(): new function Move the responsibility for registering the ref_store for a submodule from base_ref_store_init() to a new function, register_ref_store(). Call the latter from ref_store_init(). Signed-off-by: Michael Haggerty Reviewed-by: Jeff King Signed-off-by: Junio C Hamano --- refs.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 63484140f6..d7158b6289 100644 --- a/refs.c +++ b/refs.c @@ -1378,6 +1378,29 @@ static struct ref_store *lookup_ref_store(const char *submodule) return 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) +{ + if (!submodule) { + if (main_ref_store) + die("BUG: main_ref_store initialized twice"); + + refs->next = NULL; + main_ref_store = refs; + } else { + if (lookup_ref_store(submodule)) + die("BUG: ref_store for submodule '%s' initialized twice", + submodule); + + refs->next = submodule_ref_stores; + submodule_ref_stores = refs; + } +} + /* * Create, record, and return a ref_store instance for the specified * submodule (or the main repository if submodule is NULL). @@ -1386,11 +1409,14 @@ 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); - return be->init(submodule); + refs = be->init(submodule); + register_ref_store(refs, submodule); + return refs; } struct ref_store *get_ref_store(const char *submodule) @@ -1423,22 +1449,11 @@ void base_ref_store_init(struct ref_store *refs, const char *submodule) { refs->be = be; - if (!submodule) { - if (main_ref_store) - die("BUG: main_ref_store initialized twice"); + if (!submodule) 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); - + else refs->submodule = xstrdup(submodule); - refs->next = submodule_ref_stores; - submodule_ref_stores = refs; - } } void assert_main_repository(struct ref_store *refs, const char *caller) -- cgit v1.2.1 From 7d4558c462f0d1a280abec59e8c64a2f2b42a9f2 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 10 Feb 2017 12:16:15 +0100 Subject: refs: store submodule ref stores in a hashmap Aside from scaling better, this means that the submodule name needn't be stored in the ref_store instance anymore (which will be changed in a moment). This, in turn, will help loosen the strict 1:1 relationship between ref_stores and submodules. Signed-off-by: Michael Haggerty Reviewed-by: Jeff King Signed-off-by: Junio C Hamano --- refs.c | 58 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 13 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index d7158b6289..5121c57b78 100644 --- a/refs.c +++ b/refs.c @@ -3,6 +3,7 @@ */ #include "cache.h" +#include "hashmap.h" #include "lockfile.h" #include "refs.h" #include "refs/refs-internal.h" @@ -1352,11 +1353,41 @@ 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; /* * Return the ref_store instance for the specified submodule (or the @@ -1365,17 +1396,18 @@ static struct ref_store *submodule_ref_stores; */ static struct ref_store *lookup_ref_store(const char *submodule) { - struct ref_store *refs; + struct submodule_hash_entry *entry; if (!submodule) return main_ref_store; - for (refs = submodule_ref_stores; refs; refs = refs->next) { - if (!strcmp(submodule, refs->submodule)) - return refs; - } + if (!submodule_ref_stores.tablesize) + /* It's initialized on demand in register_ref_store(). */ + return NULL; - return NULL; + entry = hashmap_get_from_hash(&submodule_ref_stores, + strhash(submodule), submodule); + return entry ? entry->refs : NULL; } /* @@ -1389,15 +1421,15 @@ static void register_ref_store(struct ref_store *refs, const char *submodule) if (main_ref_store) die("BUG: main_ref_store initialized twice"); - 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->next = submodule_ref_stores; - submodule_ref_stores = refs; } } -- cgit v1.2.1 From 32c597e7b2d85c1ae313e369b21398638cafe45d Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 10 Feb 2017 12:16:16 +0100 Subject: refs: push the submodule attribute down Push the submodule attribute down from ref_store to files_ref_store. This is another step towards loosening the 1:1 connection between ref_stores and submodules. Signed-off-by: Michael Haggerty Reviewed-by: Jeff King Signed-off-by: Junio C Hamano --- refs.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 5121c57b78..07959ff3e6 100644 --- a/refs.c +++ b/refs.c @@ -1481,17 +1481,6 @@ void base_ref_store_init(struct ref_store *refs, const char *submodule) { refs->be = be; - - if (!submodule) - refs->submodule = ""; - else - refs->submodule = xstrdup(submodule); -} - -void assert_main_repository(struct ref_store *refs, const char *caller) -{ - if (*refs->submodule) - die("BUG: %s called for a submodule", caller); } /* backend functions */ -- cgit v1.2.1 From fbfd0a291596a698773d3f687af3ab4c36a841bf Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Fri, 10 Feb 2017 12:16:17 +0100 Subject: base_ref_store_init(): remove submodule argument This is another step towards weakening the 1:1 relationship between ref_stores and submodules. Signed-off-by: Michael Haggerty Reviewed-by: Jeff King Signed-off-by: Junio C Hamano --- refs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 07959ff3e6..05af56b50a 100644 --- a/refs.c +++ b/refs.c @@ -1477,8 +1477,7 @@ struct ref_store *get_ref_store(const char *submodule) } void base_ref_store_init(struct ref_store *refs, - const struct ref_storage_be *be, - const char *submodule) + const struct ref_storage_be *be) { refs->be = be; } -- cgit v1.2.1 From 3c0cb0cbaef699f699b79c8be716086053760ea9 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 9 Feb 2017 21:53:52 +0100 Subject: read_loose_refs(): read refs using resolve_ref_recursively() There is no need to call read_ref_full() or resolve_gitlink_ref() from read_loose_refs(), because we already have a ref_store object in hand. So we can call resolve_ref_recursively() ourselves. Happily, this unifies the code for the submodule vs. non-submodule cases. This requires resolve_ref_recursively() to be exposed to the refs subsystem, though not to non-refs code. Signed-off-by: Michael Haggerty Reviewed-by: Jeff King Signed-off-by: Junio C Hamano --- refs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index 05af56b50a..4f845798ba 100644 --- a/refs.c +++ b/refs.c @@ -1230,10 +1230,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; -- cgit v1.2.1