Skip to content

Commit 70c70de

Browse files
pks-tgitster
authored andcommitted
refs: complete list of special refs
We have some references that are more special than others. The reason for them being special is that they either do not follow the usual format of references, or that they are written to the filesystem directly by the respective owning subsystem and thus circumvent the reference backend. This works perfectly fine right now because the reffiles backend will know how to read those refs just fine. But with the prospect of gaining a new reference backend implementation we need to be a lot more careful here: - We need to make sure that we are consistent about how those refs are written. They must either always be written via the filesystem, or they must always be written via the reference backend. Any mixture will lead to inconsistent state. - We need to make sure that such special refs are always handled specially when reading them. We're already mostly good with regard to the first item, except for `BISECT_EXPECTED_REV` which will be addressed in a subsequent commit. But the current list of special refs is missing some refs that really should be treated specially. Right now, we only treat `FETCH_HEAD` and `MERGE_HEAD` specially here. Introduce a new function `is_special_ref()` that contains all current instances of special refs to fix the reading path. Note that this is only a temporary measure where we record and rectify the current state. Ideally, the list of special refs should in the end only contain `FETCH_HEAD` and `MERGE_HEAD` again because they both may reference multiple objects and can contain annotations, so they indeed are special. Based-on-patch-by: Han-Wen Nienhuys <[email protected]> Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 668cdc0 commit 70c70de

File tree

1 file changed

+52
-2
lines changed

1 file changed

+52
-2
lines changed

refs.c

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,15 +1820,65 @@ static int refs_read_special_head(struct ref_store *ref_store,
18201820
return result;
18211821
}
18221822

1823+
static int is_special_ref(const char *refname)
1824+
{
1825+
/*
1826+
* Special references get written and read directly via the filesystem
1827+
* by the subsystems that create them. Thus, they must not go through
1828+
* the reference backend but must instead be read directly. It is
1829+
* arguable whether this behaviour is sensible, or whether it's simply
1830+
* a leaky abstraction enabled by us only having a single reference
1831+
* backend implementation. But at least for a subset of references it
1832+
* indeed does make sense to treat them specially:
1833+
*
1834+
* - FETCH_HEAD may contain multiple object IDs, and each one of them
1835+
* carries additional metadata like where it came from.
1836+
*
1837+
* - MERGE_HEAD may contain multiple object IDs when merging multiple
1838+
* heads.
1839+
*
1840+
* There are some exceptions that you might expect to see on this list
1841+
* but which are handled exclusively via the reference backend:
1842+
*
1843+
* - CHERRY_PICK_HEAD
1844+
*
1845+
* - HEAD
1846+
*
1847+
* - ORIG_HEAD
1848+
*
1849+
* - "rebase-apply/" and "rebase-merge/" contain all of the state for
1850+
* rebases, including some reference-like files. These are
1851+
* exclusively read and written via the filesystem and never go
1852+
* through the refdb.
1853+
*
1854+
* Writing or deleting references must consistently go either through
1855+
* the filesystem (special refs) or through the reference backend
1856+
* (normal ones).
1857+
*/
1858+
static const char * const special_refs[] = {
1859+
"AUTO_MERGE",
1860+
"BISECT_EXPECTED_REV",
1861+
"FETCH_HEAD",
1862+
"MERGE_AUTOSTASH",
1863+
"MERGE_HEAD",
1864+
};
1865+
size_t i;
1866+
1867+
for (i = 0; i < ARRAY_SIZE(special_refs); i++)
1868+
if (!strcmp(refname, special_refs[i]))
1869+
return 1;
1870+
1871+
return 0;
1872+
}
1873+
18231874
int refs_read_raw_ref(struct ref_store *ref_store, const char *refname,
18241875
struct object_id *oid, struct strbuf *referent,
18251876
unsigned int *type, int *failure_errno)
18261877
{
18271878
assert(failure_errno);
1828-
if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) {
1879+
if (is_special_ref(refname))
18291880
return refs_read_special_head(ref_store, refname, oid, referent,
18301881
type, failure_errno);
1831-
}
18321882

18331883
return ref_store->be->read_raw_ref(ref_store, refname, oid, referent,
18341884
type, failure_errno);

0 commit comments

Comments
 (0)