Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2024-01-03 00:51:30 +0300
committerJunio C Hamano <gitster@pobox.com>2024-01-03 00:51:30 +0300
commitdbf668a1b7d814b4fcb57c292934cbbc2d926490 (patch)
tree147f6a9d23df350ae6c8e24094a4c973e306ad2c /refs.c
parent601b1571e8e61e7dc1473a6d5049261a9524f381 (diff)
parent0a06892ddde5bc3a82a4fe2963e3ea294252ffdd (diff)
Merge branch 'ps/pseudo-refs'
Assorted changes around pseudoref handling. * ps/pseudo-refs: bisect: consistently write BISECT_EXPECTED_REV via the refdb refs: complete list of special refs refs: propagate errno when reading special refs fails wt-status: read HEAD and ORIG_HEAD via the refdb
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c59
1 files changed, 56 insertions, 3 deletions
diff --git a/refs.c b/refs.c
index 16bfa21df7..2f58a3460a 100644
--- a/refs.c
+++ b/refs.c
@@ -1806,8 +1806,10 @@ static int refs_read_special_head(struct ref_store *ref_store,
int result = -1;
strbuf_addf(&full_path, "%s/%s", ref_store->gitdir, refname);
- if (strbuf_read_file(&content, full_path.buf, 0) < 0)
+ if (strbuf_read_file(&content, full_path.buf, 0) < 0) {
+ *failure_errno = errno;
goto done;
+ }
result = parse_loose_ref_contents(content.buf, oid, referent, type,
failure_errno);
@@ -1818,15 +1820,66 @@ done:
return result;
}
+static int is_special_ref(const char *refname)
+{
+ /*
+ * Special references get written and read directly via the filesystem
+ * by the subsystems that create them. Thus, they must not go through
+ * the reference backend but must instead be read directly. It is
+ * arguable whether this behaviour is sensible, or whether it's simply
+ * a leaky abstraction enabled by us only having a single reference
+ * backend implementation. But at least for a subset of references it
+ * indeed does make sense to treat them specially:
+ *
+ * - FETCH_HEAD may contain multiple object IDs, and each one of them
+ * carries additional metadata like where it came from.
+ *
+ * - MERGE_HEAD may contain multiple object IDs when merging multiple
+ * heads.
+ *
+ * There are some exceptions that you might expect to see on this list
+ * but which are handled exclusively via the reference backend:
+ *
+ * - BISECT_EXPECTED_REV
+ *
+ * - CHERRY_PICK_HEAD
+ *
+ * - HEAD
+ *
+ * - ORIG_HEAD
+ *
+ * - "rebase-apply/" and "rebase-merge/" contain all of the state for
+ * rebases, including some reference-like files. These are
+ * exclusively read and written via the filesystem and never go
+ * through the refdb.
+ *
+ * Writing or deleting references must consistently go either through
+ * the filesystem (special refs) or through the reference backend
+ * (normal ones).
+ */
+ static const char * const special_refs[] = {
+ "AUTO_MERGE",
+ "FETCH_HEAD",
+ "MERGE_AUTOSTASH",
+ "MERGE_HEAD",
+ };
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(special_refs); i++)
+ if (!strcmp(refname, special_refs[i]))
+ return 1;
+
+ return 0;
+}
+
int refs_read_raw_ref(struct ref_store *ref_store, const char *refname,
struct object_id *oid, struct strbuf *referent,
unsigned int *type, int *failure_errno)
{
assert(failure_errno);
- if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) {
+ if (is_special_ref(refname))
return refs_read_special_head(ref_store, refname, oid, referent,
type, failure_errno);
- }
return ref_store->be->read_raw_ref(ref_store, refname, oid, referent,
type, failure_errno);