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>
This commit is contained in:
committed by
Junio C Hamano
parent
1ae6ed230a
commit
5b12e16bb1
@ -341,9 +341,9 @@ static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs)
|
||||
return refs->loose;
|
||||
}
|
||||
|
||||
static int files_read_raw_ref(struct ref_store *ref_store,
|
||||
const char *refname, struct object_id *oid,
|
||||
struct strbuf *referent, unsigned int *type)
|
||||
static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
|
||||
struct object_id *oid, struct strbuf *referent,
|
||||
unsigned int *type, int *failure_errno)
|
||||
{
|
||||
struct files_ref_store *refs =
|
||||
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,
|
||||
struct stat st;
|
||||
int fd;
|
||||
int ret = -1;
|
||||
int save_errno;
|
||||
int remaining_retries = 3;
|
||||
|
||||
*type = 0;
|
||||
@ -459,10 +458,9 @@ stat_ref:
|
||||
ret = parse_loose_ref_contents(buf, oid, referent, type);
|
||||
|
||||
out:
|
||||
save_errno = errno;
|
||||
*failure_errno = errno;
|
||||
strbuf_release(&sb_path);
|
||||
strbuf_release(&sb_contents);
|
||||
errno = save_errno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -540,6 +538,7 @@ static int lock_raw_ref(struct files_ref_store *refs,
|
||||
struct strbuf ref_file = STRBUF_INIT;
|
||||
int attempts_remaining = 3;
|
||||
int ret = TRANSACTION_GENERIC_ERROR;
|
||||
int failure_errno;
|
||||
|
||||
assert(err);
|
||||
files_assert_main_repository(refs, "lock_raw_ref");
|
||||
@ -610,7 +609,9 @@ retry:
|
||||
if (hold_lock_file_for_update_timeout(
|
||||
&lock->lk, ref_file.buf, LOCK_NO_DEREF,
|
||||
get_files_ref_lock_timeout_ms()) < 0) {
|
||||
if (errno == ENOENT && --attempts_remaining > 0) {
|
||||
int myerr = errno;
|
||||
errno = 0;
|
||||
if (myerr == ENOENT && --attempts_remaining > 0) {
|
||||
/*
|
||||
* Maybe somebody just deleted one of the
|
||||
* directories leading to ref_file. Try
|
||||
@ -618,7 +619,7 @@ retry:
|
||||
*/
|
||||
goto retry;
|
||||
} else {
|
||||
unable_to_lock_message(ref_file.buf, errno, err);
|
||||
unable_to_lock_message(ref_file.buf, myerr, err);
|
||||
goto error_return;
|
||||
}
|
||||
}
|
||||
@ -628,9 +629,9 @@ retry:
|
||||
* fear that its value will change.
|
||||
*/
|
||||
|
||||
if (files_read_raw_ref(&refs->base, refname,
|
||||
&lock->old_oid, referent, type)) {
|
||||
if (errno == ENOENT) {
|
||||
if (files_read_raw_ref(&refs->base, refname, &lock->old_oid, referent,
|
||||
type, &failure_errno)) {
|
||||
if (failure_errno == ENOENT) {
|
||||
if (mustexist) {
|
||||
/* Garden variety missing reference. */
|
||||
strbuf_addf(err, "unable to resolve reference '%s'",
|
||||
@ -654,7 +655,7 @@ retry:
|
||||
* reference named "refs/foo/bar/baz".
|
||||
*/
|
||||
}
|
||||
} else if (errno == EISDIR) {
|
||||
} else if (failure_errno == EISDIR) {
|
||||
/*
|
||||
* There is a directory in the way. It might have
|
||||
* contained references that have been deleted. If
|
||||
@ -692,13 +693,13 @@ retry:
|
||||
goto error_return;
|
||||
}
|
||||
}
|
||||
} else if (errno == EINVAL && (*type & REF_ISBROKEN)) {
|
||||
} else if (failure_errno == EINVAL && (*type & REF_ISBROKEN)) {
|
||||
strbuf_addf(err, "unable to resolve reference '%s': "
|
||||
"reference broken", refname);
|
||||
goto error_return;
|
||||
} else {
|
||||
strbuf_addf(err, "unable to resolve reference '%s': %s",
|
||||
refname, strerror(errno));
|
||||
refname, strerror(failure_errno));
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user