Skip to content

Commit 4322f38

Browse files
committed
Merge branch 'mh/ref-store'
The ref-store abstraction was introduced to the refs API so that we can plug in different backends to store references. * mh/ref-store: (38 commits) refs: implement iteration over only per-worktree refs refs: make lock generic refs: add method to rename refs refs: add methods to init refs db refs: make delete_refs() virtual refs: add method for initial ref transaction commit refs: add methods for reflog refs: add method iterator_begin files_ref_iterator_begin(): take a ref_store argument split_symref_update(): add a files_ref_store argument lock_ref_sha1_basic(): add a files_ref_store argument lock_ref_for_update(): add a files_ref_store argument commit_ref_update(): add a files_ref_store argument lock_raw_ref(): add a files_ref_store argument repack_without_refs(): add a files_ref_store argument refs: make peel_ref() virtual refs: make create_symref() virtual refs: make pack_refs() virtual refs: make verify_refname_available() virtual refs: make read_raw_ref() virtual ...
2 parents 81358dc + 0c09ec0 commit 4322f38

5 files changed

Lines changed: 812 additions & 317 deletions

File tree

builtin/init-db.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,7 @@ static int create_default_files(const char *template_path)
180180
char junk[2];
181181
int reinit;
182182
int filemode;
183-
184-
/*
185-
* Create .git/refs/{heads,tags}
186-
*/
187-
safe_create_dir(git_path_buf(&buf, "refs"), 1);
188-
safe_create_dir(git_path_buf(&buf, "refs/heads"), 1);
189-
safe_create_dir(git_path_buf(&buf, "refs/tags"), 1);
183+
struct strbuf err = STRBUF_INIT;
190184

191185
/* Just look for `init.templatedir` */
192186
git_config(git_init_db_config, NULL);
@@ -210,11 +204,18 @@ static int create_default_files(const char *template_path)
210204
*/
211205
if (get_shared_repository()) {
212206
adjust_shared_perm(get_git_dir());
213-
adjust_shared_perm(git_path_buf(&buf, "refs"));
214-
adjust_shared_perm(git_path_buf(&buf, "refs/heads"));
215-
adjust_shared_perm(git_path_buf(&buf, "refs/tags"));
216207
}
217208

209+
/*
210+
* We need to create a "refs" dir in any case so that older
211+
* versions of git can tell that this is a repository.
212+
*/
213+
safe_create_dir(git_path("refs"), 1);
214+
adjust_shared_perm(git_path("refs"));
215+
216+
if (refs_init_db(&err))
217+
die("failed to set up refs db: %s", err.buf);
218+
218219
/*
219220
* Create the default symlink from ".git/HEAD" to the "master"
220221
* branch, if it does not exist yet.

refs.c

Lines changed: 299 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,25 @@
99
#include "object.h"
1010
#include "tag.h"
1111

12+
/*
13+
* List of all available backends
14+
*/
15+
static struct ref_storage_be *refs_backends = &refs_be_files;
16+
17+
static struct ref_storage_be *find_ref_storage_backend(const char *name)
18+
{
19+
struct ref_storage_be *be;
20+
for (be = refs_backends; be; be = be->next)
21+
if (!strcmp(be->name, name))
22+
return be;
23+
return NULL;
24+
}
25+
26+
int ref_storage_backend_exists(const char *name)
27+
{
28+
return find_ref_storage_backend(name) != NULL;
29+
}
30+
1231
/*
1332
* How to handle various characters in refnames:
1433
* 0: An acceptable character for refs
@@ -1081,20 +1100,20 @@ const char *find_descendant_ref(const char *dirname,
10811100
return NULL;
10821101
}
10831102

1084-
int rename_ref_available(const char *oldname, const char *newname)
1103+
int rename_ref_available(const char *old_refname, const char *new_refname)
10851104
{
10861105
struct string_list skip = STRING_LIST_INIT_NODUP;
10871106
struct strbuf err = STRBUF_INIT;
1088-
int ret;
1107+
int ok;
10891108

1090-
string_list_insert(&skip, oldname);
1091-
ret = !verify_refname_available(newname, NULL, &skip, &err);
1092-
if (!ret)
1109+
string_list_insert(&skip, old_refname);
1110+
ok = !verify_refname_available(new_refname, NULL, &skip, &err);
1111+
if (!ok)
10931112
error("%s", err.buf);
10941113

10951114
string_list_clear(&skip, 0);
10961115
strbuf_release(&err);
1097-
return ret;
1116+
return ok;
10981117
}
10991118

11001119
int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
@@ -1132,9 +1151,13 @@ int head_ref(each_ref_fn fn, void *cb_data)
11321151
static int do_for_each_ref(const char *submodule, const char *prefix,
11331152
each_ref_fn fn, int trim, int flags, void *cb_data)
11341153
{
1154+
struct ref_store *refs = get_ref_store(submodule);
11351155
struct ref_iterator *iter;
11361156

1137-
iter = files_ref_iterator_begin(submodule, prefix, flags);
1157+
if (!refs)
1158+
return 0;
1159+
1160+
iter = refs->be->iterator_begin(refs, prefix, flags);
11381161
iter = prefix_ref_iterator_begin(iter, prefix, trim);
11391162

11401163
return do_for_each_ref_iterator(iter, fn, cb_data);
@@ -1193,8 +1216,10 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
11931216
}
11941217

11951218
/* This function needs to return a meaningful errno on failure */
1196-
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
1197-
unsigned char *sha1, int *flags)
1219+
static const char *resolve_ref_recursively(struct ref_store *refs,
1220+
const char *refname,
1221+
int resolve_flags,
1222+
unsigned char *sha1, int *flags)
11981223
{
11991224
static struct strbuf sb_refname = STRBUF_INIT;
12001225
int unused_flags;
@@ -1226,7 +1251,8 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
12261251
for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
12271252
unsigned int read_flags = 0;
12281253

1229-
if (read_raw_ref(refname, sha1, &sb_refname, &read_flags)) {
1254+
if (refs->be->read_raw_ref(refs, refname,
1255+
sha1, &sb_refname, &read_flags)) {
12301256
*flags |= read_flags;
12311257
if (errno != ENOENT || (resolve_flags & RESOLVE_REF_READING))
12321258
return NULL;
@@ -1265,3 +1291,266 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
12651291
errno = ELOOP;
12661292
return NULL;
12671293
}
1294+
1295+
/* backend functions */
1296+
int refs_init_db(struct strbuf *err)
1297+
{
1298+
struct ref_store *refs = get_ref_store(NULL);
1299+
1300+
return refs->be->init_db(refs, err);
1301+
}
1302+
1303+
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
1304+
unsigned char *sha1, int *flags)
1305+
{
1306+
return resolve_ref_recursively(get_ref_store(NULL), refname,
1307+
resolve_flags, sha1, flags);
1308+
}
1309+
1310+
int resolve_gitlink_ref(const char *submodule, const char *refname,
1311+
unsigned char *sha1)
1312+
{
1313+
size_t len = strlen(submodule);
1314+
struct ref_store *refs;
1315+
int flags;
1316+
1317+
while (len && submodule[len - 1] == '/')
1318+
len--;
1319+
1320+
if (!len)
1321+
return -1;
1322+
1323+
if (submodule[len]) {
1324+
/* We need to strip off one or more trailing slashes */
1325+
char *stripped = xmemdupz(submodule, len);
1326+
1327+
refs = get_ref_store(stripped);
1328+
free(stripped);
1329+
} else {
1330+
refs = get_ref_store(submodule);
1331+
}
1332+
1333+
if (!refs)
1334+
return -1;
1335+
1336+
if (!resolve_ref_recursively(refs, refname, 0, sha1, &flags) ||
1337+
is_null_sha1(sha1))
1338+
return -1;
1339+
return 0;
1340+
}
1341+
1342+
/* A pointer to the ref_store for the main repository: */
1343+
static struct ref_store *main_ref_store;
1344+
1345+
/* A linked list of ref_stores for submodules: */
1346+
static struct ref_store *submodule_ref_stores;
1347+
1348+
void base_ref_store_init(struct ref_store *refs,
1349+
const struct ref_storage_be *be,
1350+
const char *submodule)
1351+
{
1352+
refs->be = be;
1353+
if (!submodule) {
1354+
if (main_ref_store)
1355+
die("BUG: main_ref_store initialized twice");
1356+
1357+
refs->submodule = "";
1358+
refs->next = NULL;
1359+
main_ref_store = refs;
1360+
} else {
1361+
if (lookup_ref_store(submodule))
1362+
die("BUG: ref_store for submodule '%s' initialized twice",
1363+
submodule);
1364+
1365+
refs->submodule = xstrdup(submodule);
1366+
refs->next = submodule_ref_stores;
1367+
submodule_ref_stores = refs;
1368+
}
1369+
}
1370+
1371+
struct ref_store *ref_store_init(const char *submodule)
1372+
{
1373+
const char *be_name = "files";
1374+
struct ref_storage_be *be = find_ref_storage_backend(be_name);
1375+
1376+
if (!be)
1377+
die("BUG: reference backend %s is unknown", be_name);
1378+
1379+
if (!submodule || !*submodule)
1380+
return be->init(NULL);
1381+
else
1382+
return be->init(submodule);
1383+
}
1384+
1385+
struct ref_store *lookup_ref_store(const char *submodule)
1386+
{
1387+
struct ref_store *refs;
1388+
1389+
if (!submodule || !*submodule)
1390+
return main_ref_store;
1391+
1392+
for (refs = submodule_ref_stores; refs; refs = refs->next) {
1393+
if (!strcmp(submodule, refs->submodule))
1394+
return refs;
1395+
}
1396+
1397+
return NULL;
1398+
}
1399+
1400+
struct ref_store *get_ref_store(const char *submodule)
1401+
{
1402+
struct ref_store *refs;
1403+
1404+
if (!submodule || !*submodule) {
1405+
refs = lookup_ref_store(NULL);
1406+
1407+
if (!refs)
1408+
refs = ref_store_init(NULL);
1409+
} else {
1410+
refs = lookup_ref_store(submodule);
1411+
1412+
if (!refs) {
1413+
struct strbuf submodule_sb = STRBUF_INIT;
1414+
1415+
strbuf_addstr(&submodule_sb, submodule);
1416+
if (is_nonbare_repository_dir(&submodule_sb))
1417+
refs = ref_store_init(submodule);
1418+
strbuf_release(&submodule_sb);
1419+
}
1420+
}
1421+
1422+
return refs;
1423+
}
1424+
1425+
void assert_main_repository(struct ref_store *refs, const char *caller)
1426+
{
1427+
if (*refs->submodule)
1428+
die("BUG: %s called for a submodule", caller);
1429+
}
1430+
1431+
/* backend functions */
1432+
int pack_refs(unsigned int flags)
1433+
{
1434+
struct ref_store *refs = get_ref_store(NULL);
1435+
1436+
return refs->be->pack_refs(refs, flags);
1437+
}
1438+
1439+
int peel_ref(const char *refname, unsigned char *sha1)
1440+
{
1441+
struct ref_store *refs = get_ref_store(NULL);
1442+
1443+
return refs->be->peel_ref(refs, refname, sha1);
1444+
}
1445+
1446+
int create_symref(const char *ref_target, const char *refs_heads_master,
1447+
const char *logmsg)
1448+
{
1449+
struct ref_store *refs = get_ref_store(NULL);
1450+
1451+
return refs->be->create_symref(refs, ref_target, refs_heads_master,
1452+
logmsg);
1453+
}
1454+
1455+
int ref_transaction_commit(struct ref_transaction *transaction,
1456+
struct strbuf *err)
1457+
{
1458+
struct ref_store *refs = get_ref_store(NULL);
1459+
1460+
return refs->be->transaction_commit(refs, transaction, err);
1461+
}
1462+
1463+
int verify_refname_available(const char *refname,
1464+
const struct string_list *extra,
1465+
const struct string_list *skip,
1466+
struct strbuf *err)
1467+
{
1468+
struct ref_store *refs = get_ref_store(NULL);
1469+
1470+
return refs->be->verify_refname_available(refs, refname, extra, skip, err);
1471+
}
1472+
1473+
int for_each_reflog(each_ref_fn fn, void *cb_data)
1474+
{
1475+
struct ref_store *refs = get_ref_store(NULL);
1476+
struct ref_iterator *iter;
1477+
1478+
iter = refs->be->reflog_iterator_begin(refs);
1479+
1480+
return do_for_each_ref_iterator(iter, fn, cb_data);
1481+
}
1482+
1483+
int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
1484+
void *cb_data)
1485+
{
1486+
struct ref_store *refs = get_ref_store(NULL);
1487+
1488+
return refs->be->for_each_reflog_ent_reverse(refs, refname,
1489+
fn, cb_data);
1490+
}
1491+
1492+
int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
1493+
void *cb_data)
1494+
{
1495+
struct ref_store *refs = get_ref_store(NULL);
1496+
1497+
return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
1498+
}
1499+
1500+
int reflog_exists(const char *refname)
1501+
{
1502+
struct ref_store *refs = get_ref_store(NULL);
1503+
1504+
return refs->be->reflog_exists(refs, refname);
1505+
}
1506+
1507+
int safe_create_reflog(const char *refname, int force_create,
1508+
struct strbuf *err)
1509+
{
1510+
struct ref_store *refs = get_ref_store(NULL);
1511+
1512+
return refs->be->create_reflog(refs, refname, force_create, err);
1513+
}
1514+
1515+
int delete_reflog(const char *refname)
1516+
{
1517+
struct ref_store *refs = get_ref_store(NULL);
1518+
1519+
return refs->be->delete_reflog(refs, refname);
1520+
}
1521+
1522+
int reflog_expire(const char *refname, const unsigned char *sha1,
1523+
unsigned int flags,
1524+
reflog_expiry_prepare_fn prepare_fn,
1525+
reflog_expiry_should_prune_fn should_prune_fn,
1526+
reflog_expiry_cleanup_fn cleanup_fn,
1527+
void *policy_cb_data)
1528+
{
1529+
struct ref_store *refs = get_ref_store(NULL);
1530+
1531+
return refs->be->reflog_expire(refs, refname, sha1, flags,
1532+
prepare_fn, should_prune_fn,
1533+
cleanup_fn, policy_cb_data);
1534+
}
1535+
1536+
int initial_ref_transaction_commit(struct ref_transaction *transaction,
1537+
struct strbuf *err)
1538+
{
1539+
struct ref_store *refs = get_ref_store(NULL);
1540+
1541+
return refs->be->initial_transaction_commit(refs, transaction, err);
1542+
}
1543+
1544+
int delete_refs(struct string_list *refnames, unsigned int flags)
1545+
{
1546+
struct ref_store *refs = get_ref_store(NULL);
1547+
1548+
return refs->be->delete_refs(refs, refnames, flags);
1549+
}
1550+
1551+
int rename_ref(const char *oldref, const char *newref, const char *logmsg)
1552+
{
1553+
struct ref_store *refs = get_ref_store(NULL);
1554+
1555+
return refs->be->rename_ref(refs, oldref, newref, logmsg);
1556+
}

0 commit comments

Comments
 (0)