refs: propagate errno when reading special refs fails

Some refs in Git are more special than others due to reasons explained in the next commit. These refs are read via `refs_read_special_head()`, but this function doesn't behave the same as when we try to read a normal ref. Most importantly, we do not propagate `failure_errno` in the case where the reference does not exist, which is behaviour that we rely on in many parts of Git. Fix this bug by propagating errno when `strbuf_read_file()` fails. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Dec 14, 2023 at 14:37 UTC 668cdc043fe6f6d1fa2bf2b3f3c2375a20819e77
2 files changed +13 -1
refs.c
+3 -1
@@ -1806,8 +1806,10 @@ static int refs_read_special_head(struct ref_store *ref_store,
1806 int result = -1;
1807 strbuf_addf(&full_path, "%s/%s", ref_store->gitdir, refname);
1808
1809 - if (strbuf_read_file(&content, full_path.buf, 0) < 0)
1809 + if (strbuf_read_file(&content, full_path.buf, 0) < 0) {
1810 + *failure_errno = errno;
1811 goto done;
1812 + }
1813
1814 result = parse_loose_ref_contents(content.buf, oid, referent, type,
1815 failure_errno);
t/t1403-show-ref.sh
+10
@@ -266,4 +266,14 @@ test_expect_success '--exists with directory fails with generic error' '
266 test_cmp expect err
267 '
268
269 +test_expect_success '--exists with non-existent special ref' '
270 + test_expect_code 2 git show-ref --exists FETCH_HEAD
271 +'
272 +
273 +test_expect_success '--exists with existing special ref' '
274 + test_when_finished "rm .git/FETCH_HEAD" &&
275 + git rev-parse HEAD >.git/FETCH_HEAD &&
276 + git show-ref --exists FETCH_HEAD
277 +'
278 +
279 test_done