Skip to content

Commit 77b34ea

Browse files
committed
Merge branch 'mh/separate-ref-cache'
The internals of the refs API around the cached refs has been streamlined. * mh/separate-ref-cache: do_for_each_entry_in_dir(): delete function files_pack_refs(): use reference iteration commit_packed_refs(): use reference iteration cache_ref_iterator_begin(): make function smarter get_loose_ref_cache(): new function get_loose_ref_dir(): function renamed from get_loose_refs() do_for_each_entry_in_dir(): eliminate `offset` argument refs: handle "refs/bisect/" in `loose_fill_ref_dir()` ref-cache: use a callback function to fill the cache refs: record the ref_store in ref_cache, not ref_dir ref-cache: introduce a new type, ref_cache refs: split `ref_cache` code into separate files ref-cache: rename `remove_entry()` to `remove_entry_from_dir()` ref-cache: rename `find_ref()` to `find_ref_entry()` ref-cache: rename `add_ref()` to `add_ref_entry()` refs_verify_refname_available(): use function in more places refs_verify_refname_available(): implement once for all backends refs_ref_iterator_begin(): new function refs_read_raw_ref(): new function get_ref_dir(): don't call read_loose_refs() for "refs/bisect"
2 parents e311597 + f890db8 commit 77b34ea

File tree

7 files changed

+1066
-1089
lines changed

7 files changed

+1066
-1089
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ LIB_OBJS += reflog-walk.o
817817
LIB_OBJS += refs.o
818818
LIB_OBJS += refs/files-backend.o
819819
LIB_OBJS += refs/iterator.o
820+
LIB_OBJS += refs/ref-cache.o
820821
LIB_OBJS += ref-filter.o
821822
LIB_OBJS += remote.o
822823
LIB_OBJS += replace_object.o

refs.c

Lines changed: 105 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "cache.h"
66
#include "hashmap.h"
77
#include "lockfile.h"
8+
#include "iterator.h"
89
#include "refs.h"
910
#include "refs/refs-internal.h"
1011
#include "object.h"
@@ -1238,6 +1239,18 @@ int head_ref(each_ref_fn fn, void *cb_data)
12381239
return head_ref_submodule(NULL, fn, cb_data);
12391240
}
12401241

1242+
struct ref_iterator *refs_ref_iterator_begin(
1243+
struct ref_store *refs,
1244+
const char *prefix, int trim, int flags)
1245+
{
1246+
struct ref_iterator *iter;
1247+
1248+
iter = refs->be->iterator_begin(refs, prefix, flags);
1249+
iter = prefix_ref_iterator_begin(iter, prefix, trim);
1250+
1251+
return iter;
1252+
}
1253+
12411254
/*
12421255
* Call fn for each reference in the specified submodule for which the
12431256
* refname begins with prefix. If trim is non-zero, then trim that
@@ -1255,8 +1268,7 @@ static int do_for_each_ref(struct ref_store *refs, const char *prefix,
12551268
if (!refs)
12561269
return 0;
12571270

1258-
iter = refs->be->iterator_begin(refs, prefix, flags);
1259-
iter = prefix_ref_iterator_begin(iter, prefix, trim);
1271+
iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
12601272

12611273
return do_for_each_ref_iterator(iter, fn, cb_data);
12621274
}
@@ -1334,6 +1346,13 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
13341346
return refs_for_each_rawref(get_main_ref_store(), fn, cb_data);
13351347
}
13361348

1349+
int refs_read_raw_ref(struct ref_store *ref_store,
1350+
const char *refname, unsigned char *sha1,
1351+
struct strbuf *referent, unsigned int *type)
1352+
{
1353+
return ref_store->be->read_raw_ref(ref_store, refname, sha1, referent, type);
1354+
}
1355+
13371356
/* This function needs to return a meaningful errno on failure */
13381357
const char *refs_resolve_ref_unsafe(struct ref_store *refs,
13391358
const char *refname,
@@ -1370,8 +1389,8 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
13701389
for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
13711390
unsigned int read_flags = 0;
13721391

1373-
if (refs->be->read_raw_ref(refs, refname,
1374-
sha1, &sb_refname, &read_flags)) {
1392+
if (refs_read_raw_ref(refs, refname,
1393+
sha1, &sb_refname, &read_flags)) {
13751394
*flags |= read_flags;
13761395
if (errno != ENOENT || (resolve_flags & RESOLVE_REF_READING))
13771396
return NULL;
@@ -1654,11 +1673,91 @@ int ref_transaction_commit(struct ref_transaction *transaction,
16541673

16551674
int refs_verify_refname_available(struct ref_store *refs,
16561675
const char *refname,
1657-
const struct string_list *extra,
1676+
const struct string_list *extras,
16581677
const struct string_list *skip,
16591678
struct strbuf *err)
16601679
{
1661-
return refs->be->verify_refname_available(refs, refname, extra, skip, err);
1680+
const char *slash;
1681+
const char *extra_refname;
1682+
struct strbuf dirname = STRBUF_INIT;
1683+
struct strbuf referent = STRBUF_INIT;
1684+
struct object_id oid;
1685+
unsigned int type;
1686+
struct ref_iterator *iter;
1687+
int ok;
1688+
int ret = -1;
1689+
1690+
/*
1691+
* For the sake of comments in this function, suppose that
1692+
* refname is "refs/foo/bar".
1693+
*/
1694+
1695+
assert(err);
1696+
1697+
strbuf_grow(&dirname, strlen(refname) + 1);
1698+
for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
1699+
/* Expand dirname to the new prefix, not including the trailing slash: */
1700+
strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len);
1701+
1702+
/*
1703+
* We are still at a leading dir of the refname (e.g.,
1704+
* "refs/foo"; if there is a reference with that name,
1705+
* it is a conflict, *unless* it is in skip.
1706+
*/
1707+
if (skip && string_list_has_string(skip, dirname.buf))
1708+
continue;
1709+
1710+
if (!refs_read_raw_ref(refs, dirname.buf, oid.hash, &referent, &type)) {
1711+
strbuf_addf(err, "'%s' exists; cannot create '%s'",
1712+
dirname.buf, refname);
1713+
goto cleanup;
1714+
}
1715+
1716+
if (extras && string_list_has_string(extras, dirname.buf)) {
1717+
strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
1718+
refname, dirname.buf);
1719+
goto cleanup;
1720+
}
1721+
}
1722+
1723+
/*
1724+
* We are at the leaf of our refname (e.g., "refs/foo/bar").
1725+
* There is no point in searching for a reference with that
1726+
* name, because a refname isn't considered to conflict with
1727+
* itself. But we still need to check for references whose
1728+
* names are in the "refs/foo/bar/" namespace, because they
1729+
* *do* conflict.
1730+
*/
1731+
strbuf_addstr(&dirname, refname + dirname.len);
1732+
strbuf_addch(&dirname, '/');
1733+
1734+
iter = refs_ref_iterator_begin(refs, dirname.buf, 0,
1735+
DO_FOR_EACH_INCLUDE_BROKEN);
1736+
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
1737+
if (skip &&
1738+
string_list_has_string(skip, iter->refname))
1739+
continue;
1740+
1741+
strbuf_addf(err, "'%s' exists; cannot create '%s'",
1742+
iter->refname, refname);
1743+
ref_iterator_abort(iter);
1744+
goto cleanup;
1745+
}
1746+
1747+
if (ok != ITER_DONE)
1748+
die("BUG: error while iterating over references");
1749+
1750+
extra_refname = find_descendant_ref(dirname.buf, extras, skip);
1751+
if (extra_refname)
1752+
strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
1753+
refname, extra_refname);
1754+
else
1755+
ret = 0;
1756+
1757+
cleanup:
1758+
strbuf_release(&referent);
1759+
strbuf_release(&dirname);
1760+
return ret;
16621761
}
16631762

16641763
int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)

refs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ int read_ref(const char *refname, unsigned char *sha1);
9797

9898
int refs_verify_refname_available(struct ref_store *refs,
9999
const char *refname,
100-
const struct string_list *extra,
100+
const struct string_list *extras,
101101
const struct string_list *skip,
102102
struct strbuf *err);
103103

0 commit comments

Comments
 (0)