refs: make errno output explicit for read_raw_ref_fn

This makes it explicit how alternative ref backends should report errors in read_raw_ref_fn. read_raw_ref_fn needs to supply a credible errno for a number of cases. These are primarily: 1) The files backend calls read_raw_ref from lock_raw_ref, and uses the resulting error codes to create/remove directories as needed. 2) ENOENT should be translated in a zero OID, optionally with REF_ISBROKEN set, returning the last successfully resolved symref. This is necessary so read_raw_ref("HEAD") on an empty repo returns refs/heads/main (or the default branch du-jour), and we know on which branch to create the first commit. Make this information flow explicit by adding a failure_errno to the signature of read_raw_ref. All errnos from the files backend are still propagated unchanged, even though inspection suggests only ENOTDIR, EISDIR and ENOENT are relevant. Signed-off-by: Han-Wen Nienhuys <hanwen@google.com> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Han-Wen Nienhuys committed Aug 23, 2021 at 13:52 UTC 5b12e16bb134969747eaa983ab8d83d57f41e960
5 files changed +35 -31
refs.c
+1 -1
@@ -1682,7 +1682,7 @@ int refs_read_raw_ref(struct ref_store *ref_store,
1682 }
1683
1684 return ref_store->be->read_raw_ref(ref_store, refname, oid, referent,
1685 - type);
1685 + type, &errno);
1686 }
1687
1688 /* This function needs to return a meaningful errno on failure */
refs/debug.c
+3 -4
@@ -238,15 +238,14 @@ debug_ref_iterator_begin(struct ref_store *ref_store, const char *prefix,
238
239 static int debug_read_raw_ref(struct ref_store *ref_store, const char *refname,
240 struct object_id *oid, struct strbuf *referent,
241 - unsigned int *type)
241 + unsigned int *type, int *failure_errno)
242 {
243 struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
244 int res = 0;
245
246 oidcpy(oid, null_oid());
247 - errno = 0;
247 res = drefs->refs->be->read_raw_ref(drefs->refs, refname, oid, referent,
249 - type);
248 + type, failure_errno);
249
250 if (res == 0) {
251 trace_printf_key(&trace_refs, "read_raw_ref: %s: %s (=> %s) type %x: %d\n",
@@ -254,7 +253,7 @@ static int debug_read_raw_ref(struct ref_store *ref_store, const char *refname,
253 } else {
254 trace_printf_key(&trace_refs,
255 "read_raw_ref: %s: %d (errno %d)\n", refname,
257 - res, errno);
256 + res, *failure_errno);
257 }
258 return res;
259 }
refs/files-backend.c
+15 -14
@@ -341,9 +341,9 @@ static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs)
341 return refs->loose;
342 }
343
344 -static int files_read_raw_ref(struct ref_store *ref_store,
345 - const char *refname, struct object_id *oid,
346 - struct strbuf *referent, unsigned int *type)
344 +static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
345 + struct object_id *oid, struct strbuf *referent,
346 + unsigned int *type, int *failure_errno)
347 {
348 struct files_ref_store *refs =
349 files_downcast(ref_store, REF_STORE_READ, "read_raw_ref");
@@ -354,7 +354,6 @@ static int files_read_raw_ref(struct ref_store *ref_store,
354 struct stat st;
355 int fd;
356 int ret = -1;
357 - int save_errno;
357 int remaining_retries = 3;
358
359 *type = 0;
@@ -459,10 +458,9 @@ stat_ref:
458 ret = parse_loose_ref_contents(buf, oid, referent, type);
459
460 out:
462 - save_errno = errno;
461 + *failure_errno = errno;
462 strbuf_release(&sb_path);
463 strbuf_release(&sb_contents);
465 - errno = save_errno;
464 return ret;
465 }
466
@@ -540,6 +538,7 @@ static int lock_raw_ref(struct files_ref_store *refs,
538 struct strbuf ref_file = STRBUF_INIT;
539 int attempts_remaining = 3;
540 int ret = TRANSACTION_GENERIC_ERROR;
541 + int failure_errno;
542
543 assert(err);
544 files_assert_main_repository(refs, "lock_raw_ref");
@@ -610,7 +609,9 @@ retry:
609 if (hold_lock_file_for_update_timeout(
610 &lock->lk, ref_file.buf, LOCK_NO_DEREF,
611 get_files_ref_lock_timeout_ms()) < 0) {
613 - if (errno == ENOENT && --attempts_remaining > 0) {
612 + int myerr = errno;
613 + errno = 0;
614 + if (myerr == ENOENT && --attempts_remaining > 0) {
615 /*
616 * Maybe somebody just deleted one of the
617 * directories leading to ref_file. Try
@@ -618,7 +619,7 @@ retry:
619 */
620 goto retry;
621 } else {
621 - unable_to_lock_message(ref_file.buf, errno, err);
622 + unable_to_lock_message(ref_file.buf, myerr, err);
623 goto error_return;
624 }
625 }
@@ -628,9 +629,9 @@ retry:
629 * fear that its value will change.
630 */
631
631 - if (files_read_raw_ref(&refs->base, refname,
632 - &lock->old_oid, referent, type)) {
633 - if (errno == ENOENT) {
632 + if (files_read_raw_ref(&refs->base, refname, &lock->old_oid, referent,
633 + type, &failure_errno)) {
634 + if (failure_errno == ENOENT) {
635 if (mustexist) {
636 /* Garden variety missing reference. */
637 strbuf_addf(err, "unable to resolve reference '%s'",
@@ -654,7 +655,7 @@ retry:
655 * reference named "refs/foo/bar/baz".
656 */
657 }
657 - } else if (errno == EISDIR) {
658 + } else if (failure_errno == EISDIR) {
659 /*
660 * There is a directory in the way. It might have
661 * contained references that have been deleted. If
@@ -692,13 +693,13 @@ retry:
693 goto error_return;
694 }
695 }
695 - } else if (errno == EINVAL && (*type & REF_ISBROKEN)) {
696 + } else if (failure_errno == EINVAL && (*type & REF_ISBROKEN)) {
697 strbuf_addf(err, "unable to resolve reference '%s': "
698 "reference broken", refname);
699 goto error_return;
700 } else {
701 strbuf_addf(err, "unable to resolve reference '%s': %s",
701 - refname, strerror(errno));
702 + refname, strerror(failure_errno));
703 goto error_return;
704 }
705
refs/packed-backend.c
+4 -4
@@ -724,9 +724,9 @@ static struct snapshot *get_snapshot(struct packed_ref_store *refs)
724 return refs->snapshot;
725 }
726
727 -static int packed_read_raw_ref(struct ref_store *ref_store,
728 - const char *refname, struct object_id *oid,
729 - struct strbuf *referent, unsigned int *type)
727 +static int packed_read_raw_ref(struct ref_store *ref_store, const char *refname,
728 + struct object_id *oid, struct strbuf *referent,
729 + unsigned int *type, int *failure_errno)
730 {
731 struct packed_ref_store *refs =
732 packed_downcast(ref_store, REF_STORE_READ, "read_raw_ref");
@@ -739,7 +739,7 @@ static int packed_read_raw_ref(struct ref_store *ref_store,
739
740 if (!rec) {
741 /* refname is not a packed reference. */
742 - errno = ENOENT;
742 + *failure_errno = ENOENT;
743 return -1;
744 }
745
refs/refs-internal.h
+12 -8
@@ -620,11 +620,15 @@ typedef int reflog_expire_fn(struct ref_store *ref_store,
620 * properly-formatted or even safe reference name. NEITHER INPUT NOR
621 * OUTPUT REFERENCE NAMES ARE VALIDATED WITHIN THIS FUNCTION.
622 *
623 - * Return 0 on success. If the ref doesn't exist, set errno to ENOENT
624 - * and return -1. If the ref exists but is neither a symbolic ref nor
625 - * an object ID, it is broken; set REF_ISBROKEN in type, and return -1
626 - * (errno should not be ENOENT) If there is another error reading the
627 - * ref, set errno appropriately and return -1.
623 + * Return 0 on success, or -1 on failure. If the ref exists but is neither a
624 + * symbolic ref nor an object ID, it is broken. In this case set REF_ISBROKEN in
625 + * type, and return -1 (failure_errno should not be ENOENT)
626 + *
627 + * failure_errno provides errno codes that are interpreted beyond error
628 + * reporting. The following error codes have special meaning:
629 + * * ENOENT: the ref doesn't exist
630 + * * EISDIR: ref name is a directory
631 + * * ENOTDIR: ref prefix is not a directory
632 *
633 * Backend-specific flags might be set in type as well, regardless of
634 * outcome.
@@ -638,9 +642,9 @@ typedef int reflog_expire_fn(struct ref_store *ref_store,
642 * - in all other cases, referent will be untouched, and therefore
643 * refname will still be valid and unchanged.
644 */
641 -typedef int read_raw_ref_fn(struct ref_store *ref_store,
642 - const char *refname, struct object_id *oid,
643 - struct strbuf *referent, unsigned int *type);
645 +typedef int read_raw_ref_fn(struct ref_store *ref_store, const char *refname,
646 + struct object_id *oid, struct strbuf *referent,
647 + unsigned int *type, int *failure_errno);
648
649 struct ref_storage_be {
650 struct ref_storage_be *next;