diff mbox series

[v20,15/21] Read FETCH_HEAD as loose ref

Message ID a6449d4346cfb715ce8309010334bd60543cc1d3.1596209238.git.gitgitgadget@gmail.com (mailing list archive)
State New, archived
Headers show
Series Reftable support git-core | expand

Commit Message

Johannes Schindelin via GitGitGadget July 31, 2020, 3:27 p.m. UTC
From: Han-Wen Nienhuys <hanwen@google.com>

FETCH_HEAD is a loose ref (either symref or OID), followed by further
metadata. It can therefore not be read through a ref backend
normally. Special case this in reftable-backend.c.

This functionality is shared between all backends, but the ref backend
interface doesn't have a method to retrieve the repository directory,
hence this functionality must be pushed down to the backend
implementation.

Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
---
 refs/reftable-backend.c | 31 +++++++++++++++++++++++++++++++
 t/t0031-reftable.sh     |  9 ++++++++-
 2 files changed, 39 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 93f3d337b6..8d30f3ea61 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1304,6 +1304,33 @@  git_reftable_reflog_expire(struct ref_store *ref_store, const char *refname,
 	return err;
 }
 
+static int read_fetch_head(struct git_reftable_ref_store *refs,
+			   const char *refname, struct object_id *oid,
+			   struct strbuf *referent, unsigned int *type)
+{
+	struct strbuf sb = STRBUF_INIT;
+	struct strbuf path_sb = STRBUF_INIT;
+	int ret = -1;
+	int fd;
+	strbuf_addf(&path_sb, "%s/%s", refs->repo_dir, refname);
+	fd = open(path_sb.buf, O_RDONLY);
+	if (fd < 0) {
+		goto out;
+	}
+	strbuf_reset(&sb);
+	if (strbuf_read(&sb, fd, 256) < 0) {
+		ret = -1;
+	}
+	strbuf_rtrim(&sb);
+
+	ret = parse_loose_ref_contents(sb.buf, oid, referent, type);
+out:
+	close(fd);
+	strbuf_release(&sb);
+	strbuf_release(&path_sb);
+	return ret;
+}
+
 static int git_reftable_read_raw_ref(struct ref_store *ref_store,
 				     const char *refname, struct object_id *oid,
 				     struct strbuf *referent,
@@ -1319,6 +1346,10 @@  static int git_reftable_read_raw_ref(struct ref_store *ref_store,
 		return refs->err;
 	}
 
+	if (!strcmp(refname, "FETCH_HEAD")) {
+		return read_fetch_head(refs, refname, oid, referent, type);
+	}
+
 	/* This is usually not needed, but Git doesn't signal to ref backend if
 	   a subprocess updated the ref DB.  So we always check.
 	*/
diff --git a/t/t0031-reftable.sh b/t/t0031-reftable.sh
index a6634bc882..9f90c10030 100755
--- a/t/t0031-reftable.sh
+++ b/t/t0031-reftable.sh
@@ -169,5 +169,12 @@  test_expect_success 'worktrees 2' '
 	git worktree add --detach existing_empty master
 '
 
-test_done
+test_expect_success 'FETCH_HEAD' '
+        initialize &&
+	test_commit one &&
+	(git init sub && cd sub && test_commit two) &&
+	git fetch sub &&
+	git checkout FETCH_HEAD
+'
 
+test_done