Skip to content

Commit 466be3e

Browse files
committed
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
2 parents be6ab59 + 3c0cb0c commit 466be3e

File tree

3 files changed

+134
-112
lines changed

3 files changed

+134
-112
lines changed

refs.c

Lines changed: 81 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
#include "cache.h"
6+
#include "hashmap.h"
67
#include "lockfile.h"
78
#include "refs.h"
89
#include "refs/refs-internal.h"
@@ -1234,10 +1235,10 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
12341235
}
12351236

12361237
/* This function needs to return a meaningful errno on failure */
1237-
static const char *resolve_ref_recursively(struct ref_store *refs,
1238-
const char *refname,
1239-
int resolve_flags,
1240-
unsigned char *sha1, int *flags)
1238+
const char *resolve_ref_recursively(struct ref_store *refs,
1239+
const char *refname,
1240+
int resolve_flags,
1241+
unsigned char *sha1, int *flags)
12411242
{
12421243
static struct strbuf sb_refname = STRBUF_INIT;
12431244
int unused_flags;
@@ -1357,62 +1358,102 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
13571358
return 0;
13581359
}
13591360

1361+
struct submodule_hash_entry
1362+
{
1363+
struct hashmap_entry ent; /* must be the first member! */
1364+
1365+
struct ref_store *refs;
1366+
1367+
/* NUL-terminated name of submodule: */
1368+
char submodule[FLEX_ARRAY];
1369+
};
1370+
1371+
static int submodule_hash_cmp(const void *entry, const void *entry_or_key,
1372+
const void *keydata)
1373+
{
1374+
const struct submodule_hash_entry *e1 = entry, *e2 = entry_or_key;
1375+
const char *submodule = keydata ? keydata : e2->submodule;
1376+
1377+
return strcmp(e1->submodule, submodule);
1378+
}
1379+
1380+
static struct submodule_hash_entry *alloc_submodule_hash_entry(
1381+
const char *submodule, struct ref_store *refs)
1382+
{
1383+
struct submodule_hash_entry *entry;
1384+
1385+
FLEX_ALLOC_STR(entry, submodule, submodule);
1386+
hashmap_entry_init(entry, strhash(submodule));
1387+
entry->refs = refs;
1388+
return entry;
1389+
}
1390+
13601391
/* A pointer to the ref_store for the main repository: */
13611392
static struct ref_store *main_ref_store;
13621393

1363-
/* A linked list of ref_stores for submodules: */
1364-
static struct ref_store *submodule_ref_stores;
1394+
/* A hashmap of ref_stores, stored by submodule name: */
1395+
static struct hashmap submodule_ref_stores;
13651396

1366-
void base_ref_store_init(struct ref_store *refs,
1367-
const struct ref_storage_be *be,
1368-
const char *submodule)
1397+
/*
1398+
* Return the ref_store instance for the specified submodule (or the
1399+
* main repository if submodule is NULL). If that ref_store hasn't
1400+
* been initialized yet, return NULL.
1401+
*/
1402+
static struct ref_store *lookup_ref_store(const char *submodule)
1403+
{
1404+
struct submodule_hash_entry *entry;
1405+
1406+
if (!submodule)
1407+
return main_ref_store;
1408+
1409+
if (!submodule_ref_stores.tablesize)
1410+
/* It's initialized on demand in register_ref_store(). */
1411+
return NULL;
1412+
1413+
entry = hashmap_get_from_hash(&submodule_ref_stores,
1414+
strhash(submodule), submodule);
1415+
return entry ? entry->refs : NULL;
1416+
}
1417+
1418+
/*
1419+
* Register the specified ref_store to be the one that should be used
1420+
* for submodule (or the main repository if submodule is NULL). It is
1421+
* a fatal error to call this function twice for the same submodule.
1422+
*/
1423+
static void register_ref_store(struct ref_store *refs, const char *submodule)
13691424
{
1370-
refs->be = be;
13711425
if (!submodule) {
13721426
if (main_ref_store)
13731427
die("BUG: main_ref_store initialized twice");
13741428

1375-
refs->submodule = "";
1376-
refs->next = NULL;
13771429
main_ref_store = refs;
13781430
} else {
1379-
if (lookup_ref_store(submodule))
1431+
if (!submodule_ref_stores.tablesize)
1432+
hashmap_init(&submodule_ref_stores, submodule_hash_cmp, 0);
1433+
1434+
if (hashmap_put(&submodule_ref_stores,
1435+
alloc_submodule_hash_entry(submodule, refs)))
13801436
die("BUG: ref_store for submodule '%s' initialized twice",
13811437
submodule);
1382-
1383-
refs->submodule = xstrdup(submodule);
1384-
refs->next = submodule_ref_stores;
1385-
submodule_ref_stores = refs;
13861438
}
13871439
}
13881440

1389-
struct ref_store *ref_store_init(const char *submodule)
1441+
/*
1442+
* Create, record, and return a ref_store instance for the specified
1443+
* submodule (or the main repository if submodule is NULL).
1444+
*/
1445+
static struct ref_store *ref_store_init(const char *submodule)
13901446
{
13911447
const char *be_name = "files";
13921448
struct ref_storage_be *be = find_ref_storage_backend(be_name);
1449+
struct ref_store *refs;
13931450

13941451
if (!be)
13951452
die("BUG: reference backend %s is unknown", be_name);
13961453

1397-
if (!submodule || !*submodule)
1398-
return be->init(NULL);
1399-
else
1400-
return be->init(submodule);
1401-
}
1402-
1403-
struct ref_store *lookup_ref_store(const char *submodule)
1404-
{
1405-
struct ref_store *refs;
1406-
1407-
if (!submodule || !*submodule)
1408-
return main_ref_store;
1409-
1410-
for (refs = submodule_ref_stores; refs; refs = refs->next) {
1411-
if (!strcmp(submodule, refs->submodule))
1412-
return refs;
1413-
}
1414-
1415-
return NULL;
1454+
refs = be->init(submodule);
1455+
register_ref_store(refs, submodule);
1456+
return refs;
14161457
}
14171458

14181459
struct ref_store *get_ref_store(const char *submodule)
@@ -1440,10 +1481,10 @@ struct ref_store *get_ref_store(const char *submodule)
14401481
return refs;
14411482
}
14421483

1443-
void assert_main_repository(struct ref_store *refs, const char *caller)
1484+
void base_ref_store_init(struct ref_store *refs,
1485+
const struct ref_storage_be *be)
14441486
{
1445-
if (*refs->submodule)
1446-
die("BUG: %s called for a submodule", caller);
1487+
refs->be = be;
14471488
}
14481489

14491490
/* backend functions */

refs/files-backend.c

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,14 @@ struct packed_ref_cache {
912912
*/
913913
struct files_ref_store {
914914
struct ref_store base;
915+
916+
/*
917+
* The name of the submodule represented by this object, or
918+
* NULL if it represents the main repository's reference
919+
* store:
920+
*/
921+
const char *submodule;
922+
915923
struct ref_entry *loose;
916924
struct packed_ref_cache *packed;
917925
};
@@ -972,11 +980,24 @@ static struct ref_store *files_ref_store_create(const char *submodule)
972980
struct files_ref_store *refs = xcalloc(1, sizeof(*refs));
973981
struct ref_store *ref_store = (struct ref_store *)refs;
974982

975-
base_ref_store_init(ref_store, &refs_be_files, submodule);
983+
base_ref_store_init(ref_store, &refs_be_files);
984+
985+
refs->submodule = xstrdup_or_null(submodule);
976986

977987
return ref_store;
978988
}
979989

990+
/*
991+
* Die if refs is for a submodule (i.e., not for the main repository).
992+
* caller is used in any necessary error messages.
993+
*/
994+
static void files_assert_main_repository(struct files_ref_store *refs,
995+
const char *caller)
996+
{
997+
if (refs->submodule)
998+
die("BUG: %s called for a submodule", caller);
999+
}
1000+
9801001
/*
9811002
* Downcast ref_store to files_ref_store. Die if ref_store is not a
9821003
* files_ref_store. If submodule_allowed is not true, then also die if
@@ -987,14 +1008,18 @@ static struct files_ref_store *files_downcast(
9871008
struct ref_store *ref_store, int submodule_allowed,
9881009
const char *caller)
9891010
{
1011+
struct files_ref_store *refs;
1012+
9901013
if (ref_store->be != &refs_be_files)
9911014
die("BUG: ref_store is type \"%s\" not \"files\" in %s",
9921015
ref_store->be->name, caller);
9931016

1017+
refs = (struct files_ref_store *)ref_store;
1018+
9941019
if (!submodule_allowed)
995-
assert_main_repository(ref_store, caller);
1020+
files_assert_main_repository(refs, caller);
9961021

997-
return (struct files_ref_store *)ref_store;
1022+
return refs;
9981023
}
9991024

10001025
/* The length of a peeled reference line in packed-refs, including EOL: */
@@ -1133,8 +1158,8 @@ static struct packed_ref_cache *get_packed_ref_cache(struct files_ref_store *ref
11331158
{
11341159
char *packed_refs_file;
11351160

1136-
if (*refs->base.submodule)
1137-
packed_refs_file = git_pathdup_submodule(refs->base.submodule,
1161+
if (refs->submodule)
1162+
packed_refs_file = git_pathdup_submodule(refs->submodule,
11381163
"packed-refs");
11391164
else
11401165
packed_refs_file = git_pathdup("packed-refs");
@@ -1203,8 +1228,8 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
12031228
size_t path_baselen;
12041229
int err = 0;
12051230

1206-
if (*refs->base.submodule)
1207-
err = strbuf_git_path_submodule(&path, refs->base.submodule, "%s", dirname);
1231+
if (refs->submodule)
1232+
err = strbuf_git_path_submodule(&path, refs->submodule, "%s", dirname);
12081233
else
12091234
strbuf_git_path(&path, "%s", dirname);
12101235
path_baselen = path.len;
@@ -1242,20 +1267,10 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
12421267
create_dir_entry(refs, refname.buf,
12431268
refname.len, 1));
12441269
} else {
1245-
int read_ok;
1246-
1247-
if (*refs->base.submodule) {
1248-
hashclr(sha1);
1249-
flag = 0;
1250-
read_ok = !resolve_gitlink_ref(refs->base.submodule,
1251-
refname.buf, sha1);
1252-
} else {
1253-
read_ok = !read_ref_full(refname.buf,
1254-
RESOLVE_REF_READING,
1255-
sha1, &flag);
1256-
}
1257-
1258-
if (!read_ok) {
1270+
if (!resolve_ref_recursively(&refs->base,
1271+
refname.buf,
1272+
RESOLVE_REF_READING,
1273+
sha1, &flag)) {
12591274
hashclr(sha1);
12601275
flag |= REF_ISBROKEN;
12611276
} else if (is_null_sha1(sha1)) {
@@ -1358,8 +1373,8 @@ static int files_read_raw_ref(struct ref_store *ref_store,
13581373
*type = 0;
13591374
strbuf_reset(&sb_path);
13601375

1361-
if (*refs->base.submodule)
1362-
strbuf_git_path_submodule(&sb_path, refs->base.submodule, "%s", refname);
1376+
if (refs->submodule)
1377+
strbuf_git_path_submodule(&sb_path, refs->submodule, "%s", refname);
13631378
else
13641379
strbuf_git_path(&sb_path, "%s", refname);
13651380

@@ -1540,7 +1555,7 @@ static int lock_raw_ref(struct files_ref_store *refs,
15401555
int ret = TRANSACTION_GENERIC_ERROR;
15411556

15421557
assert(err);
1543-
assert_main_repository(&refs->base, "lock_raw_ref");
1558+
files_assert_main_repository(refs, "lock_raw_ref");
15441559

15451560
*type = 0;
15461561

@@ -2011,7 +2026,7 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
20112026
int resolve_flags = RESOLVE_REF_NO_RECURSE;
20122027
int resolved;
20132028

2014-
assert_main_repository(&refs->base, "lock_ref_sha1_basic");
2029+
files_assert_main_repository(refs, "lock_ref_sha1_basic");
20152030
assert(err);
20162031

20172032
lock = xcalloc(1, sizeof(struct ref_lock));
@@ -2134,7 +2149,7 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)
21342149
static int timeout_value = 1000;
21352150
struct packed_ref_cache *packed_ref_cache;
21362151

2137-
assert_main_repository(&refs->base, "lock_packed_refs");
2152+
files_assert_main_repository(refs, "lock_packed_refs");
21382153

21392154
if (!timeout_configured) {
21402155
git_config_get_int("core.packedrefstimeout", &timeout_value);
@@ -2172,7 +2187,7 @@ static int commit_packed_refs(struct files_ref_store *refs)
21722187
int save_errno = 0;
21732188
FILE *out;
21742189

2175-
assert_main_repository(&refs->base, "commit_packed_refs");
2190+
files_assert_main_repository(refs, "commit_packed_refs");
21762191

21772192
if (!packed_ref_cache->lock)
21782193
die("internal error: packed-refs not locked");
@@ -2205,7 +2220,7 @@ static void rollback_packed_refs(struct files_ref_store *refs)
22052220
struct packed_ref_cache *packed_ref_cache =
22062221
get_packed_ref_cache(refs);
22072222

2208-
assert_main_repository(&refs->base, "rollback_packed_refs");
2223+
files_assert_main_repository(refs, "rollback_packed_refs");
22092224

22102225
if (!packed_ref_cache->lock)
22112226
die("internal error: packed-refs not locked");
@@ -2392,7 +2407,7 @@ static int repack_without_refs(struct files_ref_store *refs,
23922407
struct string_list_item *refname;
23932408
int ret, needs_repacking = 0, removed = 0;
23942409

2395-
assert_main_repository(&refs->base, "repack_without_refs");
2410+
files_assert_main_repository(refs, "repack_without_refs");
23962411
assert(err);
23972412

23982413
/* Look for a packed ref */
@@ -2902,7 +2917,7 @@ static int commit_ref_update(struct files_ref_store *refs,
29022917
const unsigned char *sha1, const char *logmsg,
29032918
struct strbuf *err)
29042919
{
2905-
assert_main_repository(&refs->base, "commit_ref_update");
2920+
files_assert_main_repository(refs, "commit_ref_update");
29062921

29072922
clear_loose_ref_cache(refs);
29082923
if (files_log_ref_write(lock->ref_name, lock->old_oid.hash, sha1,
@@ -3534,7 +3549,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
35343549
int ret;
35353550
struct ref_lock *lock;
35363551

3537-
assert_main_repository(&refs->base, "lock_ref_for_update");
3552+
files_assert_main_repository(refs, "lock_ref_for_update");
35383553

35393554
if ((update->flags & REF_HAVE_NEW) && is_null_sha1(update->new_sha1))
35403555
update->flags |= REF_DELETING;

0 commit comments

Comments
 (0)