From: Han-Wen Nienhuys <hanwen@xxxxxxxxxx> 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@xxxxxxxxxx> --- refs/reftable-backend.c | 31 +++++++++++++++++++++++++++++++ t/t0031-reftable.sh | 9 ++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) 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 -- gitgitgadget