git@vger.kernel.org list mirror (unofficial, one of many)
 help / color / mirror / code / Atom feed
* errno oversight
@ 2021-12-08 11:38 Han-Wen Nienhuys
  2021-12-08 12:47 ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 24+ messages in thread
From: Han-Wen Nienhuys @ 2021-12-08 11:38 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git

In refs.c in origin/next and origin/seen, we have the following fragment:

                   if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
                                      &read_flags, failure_errno)) {
                        *flags |= read_flags;
                        if (errno)
                                *failure_errno = errno;

overwriting failure_errno looks like an oversight?

-- 
Han-Wen Nienhuys - Google Munich
I work 80%. Don't expect answers from me on Fridays.
--
Google Germany GmbH, Erika-Mann-Strasse 33, 80636 Munich
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschäftsführer: Paul Manicle, Halimah DeLaine Prado

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: errno oversight
  2021-12-08 11:38 errno oversight Han-Wen Nienhuys
@ 2021-12-08 12:47 ` Ævar Arnfjörð Bjarmason
  2021-12-08 13:00   ` Ævar Arnfjörð Bjarmason
  2021-12-08 13:05   ` errno oversight Han-Wen Nienhuys
  0 siblings, 2 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-12-08 12:47 UTC (permalink / raw)
  To: Han-Wen Nienhuys; +Cc: git


On Wed, Dec 08 2021, Han-Wen Nienhuys wrote:

> In refs.c in origin/next and origin/seen, we have the following fragment:

It's in "master".

>                    if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
>                                       &read_flags, failure_errno)) {
>                         *flags |= read_flags;
>                         if (errno)
>                                 *failure_errno = errno;
>
> overwriting failure_errno looks like an oversight?

This is from my ef18119dec8 (refs API: add a version of
refs_resolve_ref_unsafe() with "errno", 2021-10-16).

I don't see the bug here, overwriting *failure_errno is the point of
that variable. We're keeping the right errno value right after a
failure, and passing it up to our caller.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: errno oversight
  2021-12-08 12:47 ` Ævar Arnfjörð Bjarmason
@ 2021-12-08 13:00   ` Ævar Arnfjörð Bjarmason
  2021-12-08 19:02     ` Junio C Hamano
  2021-12-08 13:05   ` errno oversight Han-Wen Nienhuys
  1 sibling, 1 reply; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-12-08 13:00 UTC (permalink / raw)
  To: Han-Wen Nienhuys; +Cc: git


On Wed, Dec 08 2021, Ævar Arnfjörð Bjarmason wrote:

> On Wed, Dec 08 2021, Han-Wen Nienhuys wrote:
>
>> In refs.c in origin/next and origin/seen, we have the following fragment:
>
> It's in "master".
>
>>                    if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
>>                                       &read_flags, failure_errno)) {
>>                         *flags |= read_flags;
>>                         if (errno)
>>                                 *failure_errno = errno;
>>
>> overwriting failure_errno looks like an oversight?
>
> This is from my ef18119dec8 (refs API: add a version of
> refs_resolve_ref_unsafe() with "errno", 2021-10-16).
>
> I don't see the bug here, overwriting *failure_errno is the point of
> that variable. We're keeping the right errno value right after a
> failure, and passing it up to our caller.

Urg, sorry. Yes obviously that should use the failure_errno from
refs_read_raw_ref().

I'll submit a fix for this soon. There's some good post-cleanup to be
done here, it seems only one upstream caller of
refs_resolve_ref_unsafe() cares about the failure_errno currently (but I
didn't look into your reftable code).

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: errno oversight
  2021-12-08 12:47 ` Ævar Arnfjörð Bjarmason
  2021-12-08 13:00   ` Ævar Arnfjörð Bjarmason
@ 2021-12-08 13:05   ` Han-Wen Nienhuys
  1 sibling, 0 replies; 24+ messages in thread
From: Han-Wen Nienhuys @ 2021-12-08 13:05 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: git

On Wed, Dec 8, 2021 at 1:51 PM Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:
> > In refs.c in origin/next and origin/seen, we have the following fragment:
>
> It's in "master".

Correct, but it's also in seen.

> >                    if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
> >                                       &read_flags, failure_errno)) {
> >                         *flags |= read_flags;
> >                         if (errno)
> >                                 *failure_errno = errno;
> >
> > overwriting failure_errno looks like an oversight?
>
> This is from my ef18119dec8 (refs API: add a version of
> refs_resolve_ref_unsafe() with "errno", 2021-10-16).
>
> I don't see the bug here, overwriting *failure_errno is the point of
> that variable. We're keeping the right errno value right after a
> failure, and passing it up to our caller.

The reftable code for refs_read_raw_ref places a sensible value into
its failure_errno argument. Then the "if (errno)" replaces it with
whatever the outcome of the last syscall was. I started the errno work
to get rid of this kind of global state manipulation; am I missing
something?

-- 
Han-Wen Nienhuys - Google Munich
I work 80%. Don't expect answers from me on Fridays.
--

Google Germany GmbH, Erika-Mann-Strasse 33, 80636 Munich

Registergericht und -nummer: Hamburg, HRB 86891

Sitz der Gesellschaft: Hamburg

Geschäftsführer: Paul Manicle, Halimah DeLaine Prado

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: errno oversight
  2021-12-08 13:00   ` Ævar Arnfjörð Bjarmason
@ 2021-12-08 19:02     ` Junio C Hamano
  2021-12-09  5:02       ` [PATCH 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 24+ messages in thread
From: Junio C Hamano @ 2021-12-08 19:02 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: Han-Wen Nienhuys, git

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

>>>                    if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
>>>                                       &read_flags, failure_errno)) {
>>>                         *flags |= read_flags;
>>>                         if (errno)
>>>                                 *failure_errno = errno;
> ...
> Urg, sorry. Yes obviously that should use the failure_errno from
> refs_read_raw_ref().

Yeah, I was wondering about the same thing, "refs_read_raw_ref()
takes the failure_errno pointer for stuffing errno there, doesn't
it?  does the caller need to do anything?".

> I'll submit a fix for this soon. There's some good post-cleanup to be
> done here, it seems only one upstream caller of
> refs_resolve_ref_unsafe() cares about the failure_errno currently (but I
> didn't look into your reftable code).

Thanks.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno"
  2021-12-08 19:02     ` Junio C Hamano
@ 2021-12-09  5:02       ` Ævar Arnfjörð Bjarmason
  2021-12-09  5:02         ` [PATCH 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
                           ` (3 more replies)
  0 siblings, 4 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-12-09  5:02 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Ævar Arnfjörð Bjarmason

The 1/3 here fixes the bug Han-Wen pointed out in[1]. As discussed
there it's obviously bad in the pre-image, but some oddities in
refs_resolve_ref_unsafe() interacts with code it calls ended mostly
plastering over the differences by accident, so it wasn't caught by
testing.

Then 2/3 makes the one external user of that "failure_errno" stop
using it, and 3/3 removes it entirely from the API interface.

1. https://lore.kernel.org/git/CAFQ2z_NHXKss4LVBAFVpE7LFXt2OeOz9P9wi-z8riwHXWDb28w@mail.gmail.com/

Ævar Arnfjörð Bjarmason (3):
  refs API: use "failure_errno", not "errno"
  sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure
  refs API: remove "failure_errno" from refs_resolve_ref_unsafe()

 refs.c                    | 53 +++++++++++++--------------------------
 refs.h                    |  7 +-----
 refs/files-backend.c      | 34 ++++++++-----------------
 sequencer.c               | 10 +++-----
 t/helper/test-ref-store.c |  3 +--
 worktree.c                | 11 +++-----
 6 files changed, 35 insertions(+), 83 deletions(-)

-- 
2.34.1.930.g218b4aae189


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 1/3] refs API: use "failure_errno", not "errno"
  2021-12-09  5:02       ` [PATCH 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
@ 2021-12-09  5:02         ` Ævar Arnfjörð Bjarmason
  2021-12-09  5:02         ` [PATCH 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
                           ` (2 subsequent siblings)
  3 siblings, 0 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-12-09  5:02 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Ævar Arnfjörð Bjarmason

Fix a logic error in refs_resolve_ref_unsafe() introduced in a recent
series of mine to abstract the refs API away from errno. See
96f6623ada0 (Merge branch 'ab/refs-errno-cleanup', 2021-11-29)for that
series.

In that series introduction of "failure_errno" to
refs_resolve_ref_unsafe came in ef18119dec8 (refs API: add a version
of refs_resolve_ref_unsafe() with "errno", 2021-10-16). There we'd set
"errno = 0" immediately before refs_read_raw_ref(), and then set
"failure_errno" to "errno" if errno was non-zero afterwards.

Then in the next commit 8b72fea7e91 (refs API: make
refs_read_raw_ref() not set errno, 2021-10-16) we started expecting
"refs_read_raw_ref()" to set "failure_errno". It would do that if
refs_read_raw_ref() failed, but it wouldn't be the same errno.

So we might set the "errno" here to any arbitrary bad value, and end
up e.g. returning NULL when we meant to return the refname from
refs_resolve_ref_unsafe(), or the other way around. Instrumenting this
code will reveal cases where refs_read_raw_ref() will fail, and
"errno" and "failure_errno" will be set to different values.

In practice I haven't found a case where this scary bug changed
anything in practice. The reason for that is that we'll not care about
the actual value of "errno" here per-se, but only whether:

 1. We have an errno
 2. If it's one of ENOENT, EISDIR or ENOTDIR. See the adjacent code
    added in a1c1d8170db (refs_resolve_ref_unsafe: handle d/f
    conflicts for writes, 2017-10-06)

I.e. if we clobber "failure_errno" with "errno", but it happened to be
one of those three, and we'll clobber it with another one of the three
we were OK.

Perhaps there are cases where the difference ended up mattering, but I
haven't found them. Instrumenting the test suite to fail if "errno"
and "failure_errno" are different shows a lot of failures, checking if
they're different *and* one is but not the other is outside that list
of three "errno" values yields no failures.

But let's fix the obvious bug. We should just stop paying attention to
"errno" in refs_resolve_ref_unsafe(). In addition let's change the
partial resetting of "errno" in files_read_raw_ref() to happen just
before the "return", to ensure that any such bug will be more easily
spotted in the future.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 refs.c               | 2 --
 refs/files-backend.c | 3 +--
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/refs.c b/refs.c
index 996ac271641..533cf5a2b2e 100644
--- a/refs.c
+++ b/refs.c
@@ -1714,8 +1714,6 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 		if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
 				      &read_flags, failure_errno)) {
 			*flags |= read_flags;
-			if (errno)
-				*failure_errno = errno;
 
 			/* In reading mode, refs must eventually resolve */
 			if (resolve_flags & RESOLVE_REF_READING)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 4b14f30d48f..85e195a2573 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -387,7 +387,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 	if (lstat(path, &st) < 0) {
 		int ignore_errno;
 		myerr = errno;
-		errno = 0;
 		if (myerr != ENOENT)
 			goto out;
 		if (refs_read_raw_ref(refs->packed_ref_store, refname, oid,
@@ -404,7 +403,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 		strbuf_reset(&sb_contents);
 		if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) {
 			myerr = errno;
-			errno = 0;
 			if (myerr == ENOENT || myerr == EINVAL)
 				/* inconsistent with lstat; retry */
 				goto stat_ref;
@@ -474,6 +472,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 
 	strbuf_release(&sb_path);
 	strbuf_release(&sb_contents);
+	errno = 0;
 	return ret;
 }
 
-- 
2.34.1.930.g218b4aae189


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure
  2021-12-09  5:02       ` [PATCH 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
  2021-12-09  5:02         ` [PATCH 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
@ 2021-12-09  5:02         ` Ævar Arnfjörð Bjarmason
  2021-12-09  5:02         ` [PATCH 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
  2021-12-12 19:53         ` [PATCH v2 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
  3 siblings, 0 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-12-09  5:02 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Ævar Arnfjörð Bjarmason

Change code that was faithfully migrated to the new "resolve_errno"
API in ed90f04155d (refs API: make resolve_ref_unsafe() not set errno,
2021-10-16) to stop caring about the errno at all.

When we fail to resolve "HEAD" after the sequencer runs it doesn't
really help to say what the "errno" value is, since the fake backend
errno may or may not reflect anything real about the state of the
".git/HEAD". With the upcoming reftable backend this fakery will
become even more pronounced.

So let's just die() instead of die_errno() here. This will also help
simplify the refs_resolve_ref_unsafe() API. This was the only user of
it that wasn't ignoring the "failure_errno" output parameter.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 sequencer.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index b4135a78c91..a649bd737ba 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1285,7 +1285,7 @@ void print_commit_summary(struct repository *r,
 	struct strbuf author_ident = STRBUF_INIT;
 	struct strbuf committer_ident = STRBUF_INIT;
 	struct ref_store *refs;
-	int resolve_errno;
+	int ignore_errno;
 
 	commit = lookup_commit(r, oid);
 	if (!commit)
@@ -1337,11 +1337,9 @@ void print_commit_summary(struct repository *r,
 
 	refs = get_main_ref_store(the_repository);
 	head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL,
-				       &resolve_errno);
-	if (!head) {
-		errno = resolve_errno;
-		die_errno(_("unable to resolve HEAD after creating commit"));
-	}
+				       &ignore_errno);
+	if (!head)
+		die(_("unable to resolve HEAD after creating commit"));
 	if (!strcmp(head, "HEAD"))
 		head = _("detached HEAD");
 	else
-- 
2.34.1.930.g218b4aae189


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe()
  2021-12-09  5:02       ` [PATCH 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
  2021-12-09  5:02         ` [PATCH 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
  2021-12-09  5:02         ` [PATCH 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
@ 2021-12-09  5:02         ` Ævar Arnfjörð Bjarmason
  2021-12-12 19:53         ` [PATCH v2 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
  3 siblings, 0 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-12-09  5:02 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Ævar Arnfjörð Bjarmason

Remove the now-unused "failure_errno" parameter from the
refs_resolve_ref_unsafe() signature. In my recent 96f6623ada0 (Merge
branch 'ab/refs-errno-cleanup', 2021-11-29) series we made all of its
callers explicitly request the errno via an output parameter.

As that series shows all but one caller ended up passing in a
boilerplate "ignore_errno", since they only cared about whether the
return value was NULL or not, i.e. if the ref could be resolved.

There was one caller left in sequencer.c that used the
"failure_errnO', but as of the preceding commit it doesn't use that
"failure_errno" either.

So let's remove this output parameter. Not only isn't it used now, but
we'd like to slowly move the refs API to a more file-backend
independent way of communicating error codes, having it use a
"failure_errno" was only the first step in that direction. If this or
any other function needs to communicate what specifically is wrong
with the requested "refname" it'll be better to have the function set
some output enum of well-defined error states than piggy-backend on
"errno".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 refs.c                    | 51 +++++++++++++--------------------------
 refs.h                    |  7 +-----
 refs/files-backend.c      | 31 +++++++-----------------
 sequencer.c               |  4 +--
 t/helper/test-ref-store.c |  3 +--
 worktree.c                | 11 +++------
 6 files changed, 32 insertions(+), 75 deletions(-)

diff --git a/refs.c b/refs.c
index 533cf5a2b2e..4b1f990213d 100644
--- a/refs.c
+++ b/refs.c
@@ -269,10 +269,9 @@ char *refs_resolve_refdup(struct ref_store *refs,
 			  struct object_id *oid, int *flags)
 {
 	const char *result;
-	int ignore_errno;
 
 	result = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
-					 oid, flags, &ignore_errno);
+					 oid, flags);
 	return xstrdup_or_null(result);
 }
 
@@ -294,11 +293,10 @@ struct ref_filter {
 
 int read_ref_full(const char *refname, int resolve_flags, struct object_id *oid, int *flags)
 {
-	int ignore_errno;
 	struct ref_store *refs = get_main_ref_store(the_repository);
 
 	if (refs_resolve_ref_unsafe(refs, refname, resolve_flags,
-				    oid, flags, &ignore_errno))
+				    oid, flags))
 		return 0;
 	return -1;
 }
@@ -310,9 +308,8 @@ int read_ref(const char *refname, struct object_id *oid)
 
 int refs_ref_exists(struct ref_store *refs, const char *refname)
 {
-	int ignore_errno;
 	return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING,
-					 NULL, NULL, &ignore_errno);
+					 NULL, NULL);
 }
 
 int ref_exists(const char *refname)
@@ -656,15 +653,13 @@ int expand_ref(struct repository *repo, const char *str, int len,
 		struct object_id *this_result;
 		int flag;
 		struct ref_store *refs = get_main_ref_store(repo);
-		int ignore_errno;
 
 		this_result = refs_found ? &oid_from_ref : oid;
 		strbuf_reset(&fullref);
 		strbuf_addf(&fullref, *p, len, str);
 		r = refs_resolve_ref_unsafe(refs, fullref.buf,
 					    RESOLVE_REF_READING,
-					    this_result, &flag,
-					    &ignore_errno);
+					    this_result, &flag);
 		if (r) {
 			if (!refs_found++)
 				*ref = xstrdup(r);
@@ -693,14 +688,12 @@ int repo_dwim_log(struct repository *r, const char *str, int len,
 	for (p = ref_rev_parse_rules; *p; p++) {
 		struct object_id hash;
 		const char *ref, *it;
-		int ignore_errno;
 
 		strbuf_reset(&path);
 		strbuf_addf(&path, *p, len, str);
 		ref = refs_resolve_ref_unsafe(refs, path.buf,
 					      RESOLVE_REF_READING,
-					      oid ? &hash : NULL, NULL,
-					      &ignore_errno);
+					      oid ? &hash : NULL, NULL);
 		if (!ref)
 			continue;
 		if (refs_reflog_exists(refs, path.buf))
@@ -1382,10 +1375,9 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 {
 	struct object_id oid;
 	int flag;
-	int ignore_errno;
 
 	if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
-				    &oid, &flag, &ignore_errno))
+				    &oid, &flag))
 		return fn("HEAD", &oid, flag, cb_data);
 
 	return 0;
@@ -1674,15 +1666,13 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 				    const char *refname,
 				    int resolve_flags,
 				    struct object_id *oid,
-				    int *flags, int *failure_errno)
+				    int *flags)
 {
 	static struct strbuf sb_refname = STRBUF_INIT;
 	struct object_id unused_oid;
 	int unused_flags;
 	int symref_count;
 
-	assert(failure_errno);
-
 	if (!oid)
 		oid = &unused_oid;
 	if (!flags)
@@ -1692,10 +1682,8 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 
 	if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
 		if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
-		    !refname_is_safe(refname)) {
-			*failure_errno = EINVAL;
+		    !refname_is_safe(refname))
 			return NULL;
-		}
 
 		/*
 		 * dwim_ref() uses REF_ISBROKEN to distinguish between
@@ -1710,9 +1698,10 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 
 	for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
 		unsigned int read_flags = 0;
+		int failure_errno;
 
 		if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
-				      &read_flags, failure_errno)) {
+				      &read_flags, &failure_errno)) {
 			*flags |= read_flags;
 
 			/* In reading mode, refs must eventually resolve */
@@ -1724,9 +1713,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 			 * may show errors besides ENOENT if there are
 			 * similarly-named refs.
 			 */
-			if (*failure_errno != ENOENT &&
-			    *failure_errno != EISDIR &&
-			    *failure_errno != ENOTDIR)
+			if (failure_errno != ENOENT &&
+			    failure_errno != EISDIR &&
+			    failure_errno != ENOTDIR)
 				return NULL;
 
 			oidclr(oid);
@@ -1752,16 +1741,13 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 		}
 		if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
 			if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
-			    !refname_is_safe(refname)) {
-				*failure_errno = EINVAL;
+			    !refname_is_safe(refname))
 				return NULL;
-			}
 
 			*flags |= REF_ISBROKEN | REF_BAD_NAME;
 		}
 	}
 
-	*failure_errno = ELOOP;
 	return NULL;
 }
 
@@ -1776,10 +1762,8 @@ int refs_init_db(struct strbuf *err)
 const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
 			       struct object_id *oid, int *flags)
 {
-	int ignore_errno;
-
 	return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname,
-				       resolve_flags, oid, flags, &ignore_errno);
+				       resolve_flags, oid, flags);
 }
 
 int resolve_gitlink_ref(const char *submodule, const char *refname,
@@ -1787,15 +1771,14 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
 {
 	struct ref_store *refs;
 	int flags;
-	int ignore_errno;
 
 	refs = get_submodule_ref_store(submodule);
 
 	if (!refs)
 		return -1;
 
-	if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags,
-				     &ignore_errno) || is_null_oid(oid))
+	if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags) ||
+	    is_null_oid(oid))
 		return -1;
 	return 0;
 }
diff --git a/refs.h b/refs.h
index 45c34e99e3a..859dfe946af 100644
--- a/refs.h
+++ b/refs.h
@@ -58,11 +58,6 @@ struct worktree;
  * resolved. The function returns NULL for such ref names.
  * Caps and underscores refers to the special refs, such as HEAD,
  * FETCH_HEAD and friends, that all live outside of the refs/ directory.
- *
- * Callers should not inspect "errno" on failure, but rather pass in a
- * "failure_errno" parameter, on failure the "errno" will indicate the
- * type of failure encountered, but not necessarily one that came from
- * a syscall. We might have faked it up.
  */
 #define RESOLVE_REF_READING 0x01
 #define RESOLVE_REF_NO_RECURSE 0x02
@@ -72,7 +67,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 				    const char *refname,
 				    int resolve_flags,
 				    struct object_id *oid,
-				    int *flags, int *failure_errno);
+				    int *flags);
 
 const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
 			       struct object_id *oid, int *flags);
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 85e195a2573..0356debdaff 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -282,11 +282,10 @@ static void loose_fill_ref_dir(struct ref_store *ref_store,
 					 create_dir_entry(dir->cache, refname.buf,
 							  refname.len));
 		} else {
-			int ignore_errno;
 			if (!refs_resolve_ref_unsafe(&refs->base,
 						     refname.buf,
 						     RESOLVE_REF_READING,
-						     &oid, &flag, &ignore_errno)) {
+						     &oid, &flag)) {
 				oidclr(&oid);
 				flag |= REF_ISBROKEN;
 			} else if (is_null_oid(&oid)) {
@@ -1011,7 +1010,6 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
 {
 	struct strbuf ref_file = STRBUF_INIT;
 	struct ref_lock *lock;
-	int ignore_errno;
 
 	files_assert_main_repository(refs, "lock_ref_oid_basic");
 	assert(err);
@@ -1039,7 +1037,7 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
 	}
 
 	if (!refs_resolve_ref_unsafe(&refs->base, lock->ref_name, 0,
-				     &lock->old_oid, NULL, &ignore_errno))
+				     &lock->old_oid, NULL))
 		oidclr(&lock->old_oid);
 	goto out;
 
@@ -1403,7 +1401,6 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
 	struct strbuf tmp_renamed_log = STRBUF_INIT;
 	int log, ret;
 	struct strbuf err = STRBUF_INIT;
-	int ignore_errno;
 
 	files_reflog_path(refs, &sb_oldref, oldrefname);
 	files_reflog_path(refs, &sb_newref, newrefname);
@@ -1417,7 +1414,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
 
 	if (!refs_resolve_ref_unsafe(&refs->base, oldrefname,
 				     RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
-				     &orig_oid, &flag, &ignore_errno)) {
+				     &orig_oid, &flag)) {
 		ret = error("refname %s not found", oldrefname);
 		goto out;
 	}
@@ -1463,7 +1460,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
 	 */
 	if (!copy && refs_resolve_ref_unsafe(&refs->base, newrefname,
 					     RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
-					     NULL, NULL, &ignore_errno) &&
+					     NULL, NULL) &&
 	    refs_delete_ref(&refs->base, NULL, newrefname,
 			    NULL, REF_NO_DEREF)) {
 		if (errno == EISDIR) {
@@ -1828,12 +1825,10 @@ static int commit_ref_update(struct files_ref_store *refs,
 		 */
 		int head_flag;
 		const char *head_ref;
-		int ignore_errno;
 
 		head_ref = refs_resolve_ref_unsafe(&refs->base, "HEAD",
 						   RESOLVE_REF_READING,
-						   NULL, &head_flag,
-						   &ignore_errno);
+						   NULL, &head_flag);
 		if (head_ref && (head_flag & REF_ISSYMREF) &&
 		    !strcmp(head_ref, lock->ref_name)) {
 			struct strbuf log_err = STRBUF_INIT;
@@ -1877,12 +1872,10 @@ static void update_symref_reflog(struct files_ref_store *refs,
 {
 	struct strbuf err = STRBUF_INIT;
 	struct object_id new_oid;
-	int ignore_errno;
 
 	if (logmsg &&
 	    refs_resolve_ref_unsafe(&refs->base, target,
-				    RESOLVE_REF_READING, &new_oid, NULL,
-				    &ignore_errno) &&
+				    RESOLVE_REF_READING, &new_oid, NULL) &&
 	    files_log_ref_write(refs, refname, &lock->old_oid,
 				&new_oid, logmsg, 0, &err)) {
 		error("%s", err.buf);
@@ -2156,7 +2149,6 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
 		(struct files_reflog_iterator *)ref_iterator;
 	struct dir_iterator *diter = iter->dir_iterator;
 	int ok;
-	int ignore_errno;
 
 	while ((ok = dir_iterator_advance(diter)) == ITER_OK) {
 		int flags;
@@ -2170,8 +2162,7 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
 
 		if (!refs_resolve_ref_unsafe(iter->ref_store,
 					     diter->relative_path, 0,
-					     &iter->oid, &flags,
-					     &ignore_errno)) {
+					     &iter->oid, &flags)) {
 			error("bad ref for %s", diter->path.buf);
 			continue;
 		}
@@ -2515,11 +2506,9 @@ static int lock_ref_for_update(struct files_ref_store *refs,
 			 * the transaction, so we have to read it here
 			 * to record and possibly check old_oid:
 			 */
-			int ignore_errno;
 			if (!refs_resolve_ref_unsafe(&refs->base,
 						     referent.buf, 0,
-						     &lock->old_oid, NULL,
-						     &ignore_errno)) {
+						     &lock->old_oid, NULL)) {
 				if (update->flags & REF_HAVE_OLD) {
 					strbuf_addf(err, "cannot lock ref '%s': "
 						    "error reading reference",
@@ -3210,14 +3199,12 @@ static int files_reflog_expire(struct ref_store *ref_store,
 
 		if ((flags & EXPIRE_REFLOGS_UPDATE_REF) &&
 		    !is_null_oid(&cb.last_kept_oid)) {
-			int ignore_errno;
 			int type;
 			const char *ref;
 
 			ref = refs_resolve_ref_unsafe(&refs->base, refname,
 						      RESOLVE_REF_NO_RECURSE,
-						      NULL, &type,
-						      &ignore_errno);
+						      NULL, &type);
 			update = !!(ref && !(type & REF_ISSYMREF));
 		}
 
diff --git a/sequencer.c b/sequencer.c
index a649bd737ba..d2002513cbe 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1285,7 +1285,6 @@ void print_commit_summary(struct repository *r,
 	struct strbuf author_ident = STRBUF_INIT;
 	struct strbuf committer_ident = STRBUF_INIT;
 	struct ref_store *refs;
-	int ignore_errno;
 
 	commit = lookup_commit(r, oid);
 	if (!commit)
@@ -1336,8 +1335,7 @@ void print_commit_summary(struct repository *r,
 	diff_setup_done(&rev.diffopt);
 
 	refs = get_main_ref_store(the_repository);
-	head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL,
-				       &ignore_errno);
+	head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL);
 	if (!head)
 		die(_("unable to resolve HEAD after creating commit"));
 	if (!strcmp(head, "HEAD"))
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 3986665037a..b314b81a45b 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -123,10 +123,9 @@ static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
 	int resolve_flags = arg_flags(*argv++, "resolve-flags");
 	int flags;
 	const char *ref;
-	int ignore_errno;
 
 	ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
-				      &oid, &flags, &ignore_errno);
+				      &oid, &flags);
 	printf("%s %s 0x%x\n", oid_to_hex(&oid), ref ? ref : "(null)", flags);
 	return ref ? 0 : 1;
 }
diff --git a/worktree.c b/worktree.c
index 2c155b10150..b127eda266b 100644
--- a/worktree.c
+++ b/worktree.c
@@ -28,13 +28,11 @@ static void add_head_info(struct worktree *wt)
 {
 	int flags;
 	const char *target;
-	int ignore_errno;
 
 	target = refs_resolve_ref_unsafe(get_worktree_ref_store(wt),
 					 "HEAD",
 					 0,
-					 &wt->head_oid, &flags,
-					 &ignore_errno);
+					 &wt->head_oid, &flags);
 	if (!target)
 		return;
 
@@ -420,7 +418,6 @@ const struct worktree *find_shared_symref(const char *symref,
 		const char *symref_target;
 		struct ref_store *refs;
 		int flags;
-		int ignore_errno;
 
 		if (wt->is_bare)
 			continue;
@@ -438,8 +435,7 @@ const struct worktree *find_shared_symref(const char *symref,
 
 		refs = get_worktree_ref_store(wt);
 		symref_target = refs_resolve_ref_unsafe(refs, symref, 0,
-							NULL, &flags,
-							&ignore_errno);
+							NULL, &flags);
 		if ((flags & REF_ISSYMREF) &&
 		    symref_target && !strcmp(symref_target, target)) {
 			existing = wt;
@@ -567,7 +563,6 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
 		struct worktree *wt = *p;
 		struct object_id oid;
 		int flag;
-		int ignore_errno;
 
 		if (wt->is_current)
 			continue;
@@ -577,7 +572,7 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
 		if (refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
 					    refname.buf,
 					    RESOLVE_REF_READING,
-					    &oid, &flag, &ignore_errno))
+					    &oid, &flag))
 			ret = fn(refname.buf, &oid, flag, cb_data);
 		if (ret)
 			break;
-- 
2.34.1.930.g218b4aae189


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v2 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno"
  2021-12-09  5:02       ` [PATCH 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
                           ` (2 preceding siblings ...)
  2021-12-09  5:02         ` [PATCH 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
@ 2021-12-12 19:53         ` Ævar Arnfjörð Bjarmason
  2021-12-12 19:53           ` [PATCH v2 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
                             ` (3 more replies)
  3 siblings, 4 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-12-12 19:53 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Bagas Sanjaya,
	Ævar Arnfjörð Bjarmason

A re-roll of a fix to my recently landed topic to remove "errno" use
from the refs API.

The only update is a rebasing on "master", this previouly semantically
conflicted with an in-flight topic that's been merged to "master".

1. https://lore.kernel.org/git/cover-0.3-00000000000-20211209T045735Z-avarab@gmail.com/

Ævar Arnfjörð Bjarmason (3):
  refs API: use "failure_errno", not "errno"
  sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure
  refs API: remove "failure_errno" from refs_resolve_ref_unsafe()

 refs.c                    | 53 +++++++++++++--------------------------
 refs.h                    |  7 +-----
 refs/files-backend.c      | 34 ++++++++-----------------
 remote.c                  |  3 +--
 sequencer.c               | 10 +++-----
 t/helper/test-ref-store.c |  3 +--
 worktree.c                | 11 +++-----
 7 files changed, 36 insertions(+), 85 deletions(-)

Range-diff against v1:
1:  b983d3b6033 = 1:  161fcad1578 refs API: use "failure_errno", not "errno"
2:  a4d1dadb9c9 = 2:  12d453d3884 sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure
3:  a42539d103c ! 3:  614590b2d10 refs API: remove "failure_errno" from refs_resolve_ref_unsafe()
    @@ refs/files-backend.c: static int files_reflog_expire(struct ref_store *ref_store
      		}
      
     
    + ## remote.c ##
    +@@ remote.c: static void read_config(struct repository *repo)
    + 
    + 	repo->remote_state->current_branch = NULL;
    + 	if (startup_info->have_repository) {
    +-		int ignore_errno;
    + 		const char *head_ref = refs_resolve_ref_unsafe(
    +-			get_main_ref_store(repo), "HEAD", 0, NULL, &flag, &ignore_errno);
    ++			get_main_ref_store(repo), "HEAD", 0, NULL, &flag);
    + 		if (head_ref && (flag & REF_ISSYMREF) &&
    + 		    skip_prefix(head_ref, "refs/heads/", &head_ref)) {
    + 			repo->remote_state->current_branch = make_branch(
    +
      ## sequencer.c ##
     @@ sequencer.c: void print_commit_summary(struct repository *r,
      	struct strbuf author_ident = STRBUF_INIT;
-- 
2.34.1.929.ge922d848c7a


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v2 1/3] refs API: use "failure_errno", not "errno"
  2021-12-12 19:53         ` [PATCH v2 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
@ 2021-12-12 19:53           ` Ævar Arnfjörð Bjarmason
  2021-12-12 19:53           ` [PATCH v2 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
                             ` (2 subsequent siblings)
  3 siblings, 0 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-12-12 19:53 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Bagas Sanjaya,
	Ævar Arnfjörð Bjarmason

Fix a logic error in refs_resolve_ref_unsafe() introduced in a recent
series of mine to abstract the refs API away from errno. See
96f6623ada0 (Merge branch 'ab/refs-errno-cleanup', 2021-11-29)for that
series.

In that series introduction of "failure_errno" to
refs_resolve_ref_unsafe came in ef18119dec8 (refs API: add a version
of refs_resolve_ref_unsafe() with "errno", 2021-10-16). There we'd set
"errno = 0" immediately before refs_read_raw_ref(), and then set
"failure_errno" to "errno" if errno was non-zero afterwards.

Then in the next commit 8b72fea7e91 (refs API: make
refs_read_raw_ref() not set errno, 2021-10-16) we started expecting
"refs_read_raw_ref()" to set "failure_errno". It would do that if
refs_read_raw_ref() failed, but it wouldn't be the same errno.

So we might set the "errno" here to any arbitrary bad value, and end
up e.g. returning NULL when we meant to return the refname from
refs_resolve_ref_unsafe(), or the other way around. Instrumenting this
code will reveal cases where refs_read_raw_ref() will fail, and
"errno" and "failure_errno" will be set to different values.

In practice I haven't found a case where this scary bug changed
anything in practice. The reason for that is that we'll not care about
the actual value of "errno" here per-se, but only whether:

 1. We have an errno
 2. If it's one of ENOENT, EISDIR or ENOTDIR. See the adjacent code
    added in a1c1d8170db (refs_resolve_ref_unsafe: handle d/f
    conflicts for writes, 2017-10-06)

I.e. if we clobber "failure_errno" with "errno", but it happened to be
one of those three, and we'll clobber it with another one of the three
we were OK.

Perhaps there are cases where the difference ended up mattering, but I
haven't found them. Instrumenting the test suite to fail if "errno"
and "failure_errno" are different shows a lot of failures, checking if
they're different *and* one is but not the other is outside that list
of three "errno" values yields no failures.

But let's fix the obvious bug. We should just stop paying attention to
"errno" in refs_resolve_ref_unsafe(). In addition let's change the
partial resetting of "errno" in files_read_raw_ref() to happen just
before the "return", to ensure that any such bug will be more easily
spotted in the future.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 refs.c               | 2 --
 refs/files-backend.c | 3 +--
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/refs.c b/refs.c
index 4338875d86b..6cc845c7ac2 100644
--- a/refs.c
+++ b/refs.c
@@ -1721,8 +1721,6 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 		if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
 				      &read_flags, failure_errno)) {
 			*flags |= read_flags;
-			if (errno)
-				*failure_errno = errno;
 
 			/* In reading mode, refs must eventually resolve */
 			if (resolve_flags & RESOLVE_REF_READING)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 237a2afb5d7..fd34d344c30 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -387,7 +387,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 	if (lstat(path, &st) < 0) {
 		int ignore_errno;
 		myerr = errno;
-		errno = 0;
 		if (myerr != ENOENT)
 			goto out;
 		if (refs_read_raw_ref(refs->packed_ref_store, refname, oid,
@@ -404,7 +403,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 		strbuf_reset(&sb_contents);
 		if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) {
 			myerr = errno;
-			errno = 0;
 			if (myerr == ENOENT || myerr == EINVAL)
 				/* inconsistent with lstat; retry */
 				goto stat_ref;
@@ -474,6 +472,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 
 	strbuf_release(&sb_path);
 	strbuf_release(&sb_contents);
+	errno = 0;
 	return ret;
 }
 
-- 
2.34.1.929.ge922d848c7a


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v2 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure
  2021-12-12 19:53         ` [PATCH v2 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
  2021-12-12 19:53           ` [PATCH v2 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
@ 2021-12-12 19:53           ` Ævar Arnfjörð Bjarmason
  2021-12-12 19:53           ` [PATCH v2 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
  2022-01-12 12:36           ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
  3 siblings, 0 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-12-12 19:53 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Bagas Sanjaya,
	Ævar Arnfjörð Bjarmason

Change code that was faithfully migrated to the new "resolve_errno"
API in ed90f04155d (refs API: make resolve_ref_unsafe() not set errno,
2021-10-16) to stop caring about the errno at all.

When we fail to resolve "HEAD" after the sequencer runs it doesn't
really help to say what the "errno" value is, since the fake backend
errno may or may not reflect anything real about the state of the
".git/HEAD". With the upcoming reftable backend this fakery will
become even more pronounced.

So let's just die() instead of die_errno() here. This will also help
simplify the refs_resolve_ref_unsafe() API. This was the only user of
it that wasn't ignoring the "failure_errno" output parameter.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 sequencer.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 795b370dd34..62bf6cac66b 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1285,7 +1285,7 @@ void print_commit_summary(struct repository *r,
 	struct strbuf author_ident = STRBUF_INIT;
 	struct strbuf committer_ident = STRBUF_INIT;
 	struct ref_store *refs;
-	int resolve_errno;
+	int ignore_errno;
 
 	commit = lookup_commit(r, oid);
 	if (!commit)
@@ -1337,11 +1337,9 @@ void print_commit_summary(struct repository *r,
 
 	refs = get_main_ref_store(the_repository);
 	head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL,
-				       &resolve_errno);
-	if (!head) {
-		errno = resolve_errno;
-		die_errno(_("unable to resolve HEAD after creating commit"));
-	}
+				       &ignore_errno);
+	if (!head)
+		die(_("unable to resolve HEAD after creating commit"));
 	if (!strcmp(head, "HEAD"))
 		head = _("detached HEAD");
 	else
-- 
2.34.1.929.ge922d848c7a


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v2 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe()
  2021-12-12 19:53         ` [PATCH v2 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
  2021-12-12 19:53           ` [PATCH v2 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
  2021-12-12 19:53           ` [PATCH v2 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
@ 2021-12-12 19:53           ` Ævar Arnfjörð Bjarmason
  2022-01-12 12:36           ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
  3 siblings, 0 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-12-12 19:53 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Bagas Sanjaya,
	Ævar Arnfjörð Bjarmason

Remove the now-unused "failure_errno" parameter from the
refs_resolve_ref_unsafe() signature. In my recent 96f6623ada0 (Merge
branch 'ab/refs-errno-cleanup', 2021-11-29) series we made all of its
callers explicitly request the errno via an output parameter.

As that series shows all but one caller ended up passing in a
boilerplate "ignore_errno", since they only cared about whether the
return value was NULL or not, i.e. if the ref could be resolved.

There was one caller left in sequencer.c that used the
"failure_errnO', but as of the preceding commit it doesn't use that
"failure_errno" either.

So let's remove this output parameter. Not only isn't it used now, but
we'd like to slowly move the refs API to a more file-backend
independent way of communicating error codes, having it use a
"failure_errno" was only the first step in that direction. If this or
any other function needs to communicate what specifically is wrong
with the requested "refname" it'll be better to have the function set
some output enum of well-defined error states than piggy-backend on
"errno".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 refs.c                    | 51 +++++++++++++--------------------------
 refs.h                    |  7 +-----
 refs/files-backend.c      | 31 +++++++-----------------
 remote.c                  |  3 +--
 sequencer.c               |  4 +--
 t/helper/test-ref-store.c |  3 +--
 worktree.c                | 11 +++------
 7 files changed, 33 insertions(+), 77 deletions(-)

diff --git a/refs.c b/refs.c
index 6cc845c7ac2..1ab97f99e23 100644
--- a/refs.c
+++ b/refs.c
@@ -269,10 +269,9 @@ char *refs_resolve_refdup(struct ref_store *refs,
 			  struct object_id *oid, int *flags)
 {
 	const char *result;
-	int ignore_errno;
 
 	result = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
-					 oid, flags, &ignore_errno);
+					 oid, flags);
 	return xstrdup_or_null(result);
 }
 
@@ -294,11 +293,10 @@ struct ref_filter {
 
 int read_ref_full(const char *refname, int resolve_flags, struct object_id *oid, int *flags)
 {
-	int ignore_errno;
 	struct ref_store *refs = get_main_ref_store(the_repository);
 
 	if (refs_resolve_ref_unsafe(refs, refname, resolve_flags,
-				    oid, flags, &ignore_errno))
+				    oid, flags))
 		return 0;
 	return -1;
 }
@@ -310,9 +308,8 @@ int read_ref(const char *refname, struct object_id *oid)
 
 int refs_ref_exists(struct ref_store *refs, const char *refname)
 {
-	int ignore_errno;
 	return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING,
-					 NULL, NULL, &ignore_errno);
+					 NULL, NULL);
 }
 
 int ref_exists(const char *refname)
@@ -656,15 +653,13 @@ int expand_ref(struct repository *repo, const char *str, int len,
 		struct object_id *this_result;
 		int flag;
 		struct ref_store *refs = get_main_ref_store(repo);
-		int ignore_errno;
 
 		this_result = refs_found ? &oid_from_ref : oid;
 		strbuf_reset(&fullref);
 		strbuf_addf(&fullref, *p, len, str);
 		r = refs_resolve_ref_unsafe(refs, fullref.buf,
 					    RESOLVE_REF_READING,
-					    this_result, &flag,
-					    &ignore_errno);
+					    this_result, &flag);
 		if (r) {
 			if (!refs_found++)
 				*ref = xstrdup(r);
@@ -693,14 +688,12 @@ int repo_dwim_log(struct repository *r, const char *str, int len,
 	for (p = ref_rev_parse_rules; *p; p++) {
 		struct object_id hash;
 		const char *ref, *it;
-		int ignore_errno;
 
 		strbuf_reset(&path);
 		strbuf_addf(&path, *p, len, str);
 		ref = refs_resolve_ref_unsafe(refs, path.buf,
 					      RESOLVE_REF_READING,
-					      oid ? &hash : NULL, NULL,
-					      &ignore_errno);
+					      oid ? &hash : NULL, NULL);
 		if (!ref)
 			continue;
 		if (refs_reflog_exists(refs, path.buf))
@@ -1389,10 +1382,9 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 {
 	struct object_id oid;
 	int flag;
-	int ignore_errno;
 
 	if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
-				    &oid, &flag, &ignore_errno))
+				    &oid, &flag))
 		return fn("HEAD", &oid, flag, cb_data);
 
 	return 0;
@@ -1681,15 +1673,13 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 				    const char *refname,
 				    int resolve_flags,
 				    struct object_id *oid,
-				    int *flags, int *failure_errno)
+				    int *flags)
 {
 	static struct strbuf sb_refname = STRBUF_INIT;
 	struct object_id unused_oid;
 	int unused_flags;
 	int symref_count;
 
-	assert(failure_errno);
-
 	if (!oid)
 		oid = &unused_oid;
 	if (!flags)
@@ -1699,10 +1689,8 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 
 	if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
 		if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
-		    !refname_is_safe(refname)) {
-			*failure_errno = EINVAL;
+		    !refname_is_safe(refname))
 			return NULL;
-		}
 
 		/*
 		 * dwim_ref() uses REF_ISBROKEN to distinguish between
@@ -1717,9 +1705,10 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 
 	for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
 		unsigned int read_flags = 0;
+		int failure_errno;
 
 		if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
-				      &read_flags, failure_errno)) {
+				      &read_flags, &failure_errno)) {
 			*flags |= read_flags;
 
 			/* In reading mode, refs must eventually resolve */
@@ -1731,9 +1720,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 			 * may show errors besides ENOENT if there are
 			 * similarly-named refs.
 			 */
-			if (*failure_errno != ENOENT &&
-			    *failure_errno != EISDIR &&
-			    *failure_errno != ENOTDIR)
+			if (failure_errno != ENOENT &&
+			    failure_errno != EISDIR &&
+			    failure_errno != ENOTDIR)
 				return NULL;
 
 			oidclr(oid);
@@ -1759,16 +1748,13 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 		}
 		if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
 			if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
-			    !refname_is_safe(refname)) {
-				*failure_errno = EINVAL;
+			    !refname_is_safe(refname))
 				return NULL;
-			}
 
 			*flags |= REF_ISBROKEN | REF_BAD_NAME;
 		}
 	}
 
-	*failure_errno = ELOOP;
 	return NULL;
 }
 
@@ -1783,10 +1769,8 @@ int refs_init_db(struct strbuf *err)
 const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
 			       struct object_id *oid, int *flags)
 {
-	int ignore_errno;
-
 	return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname,
-				       resolve_flags, oid, flags, &ignore_errno);
+				       resolve_flags, oid, flags);
 }
 
 int resolve_gitlink_ref(const char *submodule, const char *refname,
@@ -1794,15 +1778,14 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
 {
 	struct ref_store *refs;
 	int flags;
-	int ignore_errno;
 
 	refs = get_submodule_ref_store(submodule);
 
 	if (!refs)
 		return -1;
 
-	if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags,
-				     &ignore_errno) || is_null_oid(oid))
+	if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags) ||
+	    is_null_oid(oid))
 		return -1;
 	return 0;
 }
diff --git a/refs.h b/refs.h
index bb50d1eb195..6f27d4abfc1 100644
--- a/refs.h
+++ b/refs.h
@@ -58,11 +58,6 @@ struct worktree;
  * resolved. The function returns NULL for such ref names.
  * Caps and underscores refers to the special refs, such as HEAD,
  * FETCH_HEAD and friends, that all live outside of the refs/ directory.
- *
- * Callers should not inspect "errno" on failure, but rather pass in a
- * "failure_errno" parameter, on failure the "errno" will indicate the
- * type of failure encountered, but not necessarily one that came from
- * a syscall. We might have faked it up.
  */
 #define RESOLVE_REF_READING 0x01
 #define RESOLVE_REF_NO_RECURSE 0x02
@@ -72,7 +67,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 				    const char *refname,
 				    int resolve_flags,
 				    struct object_id *oid,
-				    int *flags, int *failure_errno);
+				    int *flags);
 
 const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
 			       struct object_id *oid, int *flags);
diff --git a/refs/files-backend.c b/refs/files-backend.c
index fd34d344c30..4d5f14dc594 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -282,11 +282,10 @@ static void loose_fill_ref_dir(struct ref_store *ref_store,
 					 create_dir_entry(dir->cache, refname.buf,
 							  refname.len));
 		} else {
-			int ignore_errno;
 			if (!refs_resolve_ref_unsafe(&refs->base,
 						     refname.buf,
 						     RESOLVE_REF_READING,
-						     &oid, &flag, &ignore_errno)) {
+						     &oid, &flag)) {
 				oidclr(&oid);
 				flag |= REF_ISBROKEN;
 			} else if (is_null_oid(&oid)) {
@@ -1011,7 +1010,6 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
 {
 	struct strbuf ref_file = STRBUF_INIT;
 	struct ref_lock *lock;
-	int ignore_errno;
 
 	files_assert_main_repository(refs, "lock_ref_oid_basic");
 	assert(err);
@@ -1039,7 +1037,7 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
 	}
 
 	if (!refs_resolve_ref_unsafe(&refs->base, lock->ref_name, 0,
-				     &lock->old_oid, NULL, &ignore_errno))
+				     &lock->old_oid, NULL))
 		oidclr(&lock->old_oid);
 	goto out;
 
@@ -1403,7 +1401,6 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
 	struct strbuf tmp_renamed_log = STRBUF_INIT;
 	int log, ret;
 	struct strbuf err = STRBUF_INIT;
-	int ignore_errno;
 
 	files_reflog_path(refs, &sb_oldref, oldrefname);
 	files_reflog_path(refs, &sb_newref, newrefname);
@@ -1417,7 +1414,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
 
 	if (!refs_resolve_ref_unsafe(&refs->base, oldrefname,
 				     RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
-				     &orig_oid, &flag, &ignore_errno)) {
+				     &orig_oid, &flag)) {
 		ret = error("refname %s not found", oldrefname);
 		goto out;
 	}
@@ -1463,7 +1460,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
 	 */
 	if (!copy && refs_resolve_ref_unsafe(&refs->base, newrefname,
 					     RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
-					     NULL, NULL, &ignore_errno) &&
+					     NULL, NULL) &&
 	    refs_delete_ref(&refs->base, NULL, newrefname,
 			    NULL, REF_NO_DEREF)) {
 		if (errno == EISDIR) {
@@ -1827,12 +1824,10 @@ static int commit_ref_update(struct files_ref_store *refs,
 		 */
 		int head_flag;
 		const char *head_ref;
-		int ignore_errno;
 
 		head_ref = refs_resolve_ref_unsafe(&refs->base, "HEAD",
 						   RESOLVE_REF_READING,
-						   NULL, &head_flag,
-						   &ignore_errno);
+						   NULL, &head_flag);
 		if (head_ref && (head_flag & REF_ISSYMREF) &&
 		    !strcmp(head_ref, lock->ref_name)) {
 			struct strbuf log_err = STRBUF_INIT;
@@ -1876,12 +1871,10 @@ static void update_symref_reflog(struct files_ref_store *refs,
 {
 	struct strbuf err = STRBUF_INIT;
 	struct object_id new_oid;
-	int ignore_errno;
 
 	if (logmsg &&
 	    refs_resolve_ref_unsafe(&refs->base, target,
-				    RESOLVE_REF_READING, &new_oid, NULL,
-				    &ignore_errno) &&
+				    RESOLVE_REF_READING, &new_oid, NULL) &&
 	    files_log_ref_write(refs, refname, &lock->old_oid,
 				&new_oid, logmsg, 0, &err)) {
 		error("%s", err.buf);
@@ -2155,7 +2148,6 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
 		(struct files_reflog_iterator *)ref_iterator;
 	struct dir_iterator *diter = iter->dir_iterator;
 	int ok;
-	int ignore_errno;
 
 	while ((ok = dir_iterator_advance(diter)) == ITER_OK) {
 		int flags;
@@ -2169,8 +2161,7 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
 
 		if (!refs_resolve_ref_unsafe(iter->ref_store,
 					     diter->relative_path, 0,
-					     &iter->oid, &flags,
-					     &ignore_errno)) {
+					     &iter->oid, &flags)) {
 			error("bad ref for %s", diter->path.buf);
 			continue;
 		}
@@ -2514,11 +2505,9 @@ static int lock_ref_for_update(struct files_ref_store *refs,
 			 * the transaction, so we have to read it here
 			 * to record and possibly check old_oid:
 			 */
-			int ignore_errno;
 			if (!refs_resolve_ref_unsafe(&refs->base,
 						     referent.buf, 0,
-						     &lock->old_oid, NULL,
-						     &ignore_errno)) {
+						     &lock->old_oid, NULL)) {
 				if (update->flags & REF_HAVE_OLD) {
 					strbuf_addf(err, "cannot lock ref '%s': "
 						    "error reading reference",
@@ -3209,14 +3198,12 @@ static int files_reflog_expire(struct ref_store *ref_store,
 
 		if ((flags & EXPIRE_REFLOGS_UPDATE_REF) &&
 		    !is_null_oid(&cb.last_kept_oid)) {
-			int ignore_errno;
 			int type;
 			const char *ref;
 
 			ref = refs_resolve_ref_unsafe(&refs->base, refname,
 						      RESOLVE_REF_NO_RECURSE,
-						      NULL, &type,
-						      &ignore_errno);
+						      NULL, &type);
 			update = !!(ref && !(type & REF_ISSYMREF));
 		}
 
diff --git a/remote.c b/remote.c
index a6d8ec6c1ac..c97c626eaa8 100644
--- a/remote.c
+++ b/remote.c
@@ -508,9 +508,8 @@ static void read_config(struct repository *repo)
 
 	repo->remote_state->current_branch = NULL;
 	if (startup_info->have_repository) {
-		int ignore_errno;
 		const char *head_ref = refs_resolve_ref_unsafe(
-			get_main_ref_store(repo), "HEAD", 0, NULL, &flag, &ignore_errno);
+			get_main_ref_store(repo), "HEAD", 0, NULL, &flag);
 		if (head_ref && (flag & REF_ISSYMREF) &&
 		    skip_prefix(head_ref, "refs/heads/", &head_ref)) {
 			repo->remote_state->current_branch = make_branch(
diff --git a/sequencer.c b/sequencer.c
index 62bf6cac66b..015e0bdd832 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1285,7 +1285,6 @@ void print_commit_summary(struct repository *r,
 	struct strbuf author_ident = STRBUF_INIT;
 	struct strbuf committer_ident = STRBUF_INIT;
 	struct ref_store *refs;
-	int ignore_errno;
 
 	commit = lookup_commit(r, oid);
 	if (!commit)
@@ -1336,8 +1335,7 @@ void print_commit_summary(struct repository *r,
 	diff_setup_done(&rev.diffopt);
 
 	refs = get_main_ref_store(the_repository);
-	head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL,
-				       &ignore_errno);
+	head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL);
 	if (!head)
 		die(_("unable to resolve HEAD after creating commit"));
 	if (!strcmp(head, "HEAD"))
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 73461c29d3c..98f827edfb7 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -123,10 +123,9 @@ static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
 	int resolve_flags = arg_flags(*argv++, "resolve-flags");
 	int flags;
 	const char *ref;
-	int ignore_errno;
 
 	ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
-				      &oid, &flags, &ignore_errno);
+				      &oid, &flags);
 	printf("%s %s 0x%x\n", oid_to_hex(&oid), ref ? ref : "(null)", flags);
 	return ref ? 0 : 1;
 }
diff --git a/worktree.c b/worktree.c
index 2c155b10150..b127eda266b 100644
--- a/worktree.c
+++ b/worktree.c
@@ -28,13 +28,11 @@ static void add_head_info(struct worktree *wt)
 {
 	int flags;
 	const char *target;
-	int ignore_errno;
 
 	target = refs_resolve_ref_unsafe(get_worktree_ref_store(wt),
 					 "HEAD",
 					 0,
-					 &wt->head_oid, &flags,
-					 &ignore_errno);
+					 &wt->head_oid, &flags);
 	if (!target)
 		return;
 
@@ -420,7 +418,6 @@ const struct worktree *find_shared_symref(const char *symref,
 		const char *symref_target;
 		struct ref_store *refs;
 		int flags;
-		int ignore_errno;
 
 		if (wt->is_bare)
 			continue;
@@ -438,8 +435,7 @@ const struct worktree *find_shared_symref(const char *symref,
 
 		refs = get_worktree_ref_store(wt);
 		symref_target = refs_resolve_ref_unsafe(refs, symref, 0,
-							NULL, &flags,
-							&ignore_errno);
+							NULL, &flags);
 		if ((flags & REF_ISSYMREF) &&
 		    symref_target && !strcmp(symref_target, target)) {
 			existing = wt;
@@ -567,7 +563,6 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
 		struct worktree *wt = *p;
 		struct object_id oid;
 		int flag;
-		int ignore_errno;
 
 		if (wt->is_current)
 			continue;
@@ -577,7 +572,7 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
 		if (refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
 					    refname.buf,
 					    RESOLVE_REF_READING,
-					    &oid, &flag, &ignore_errno))
+					    &oid, &flag))
 			ret = fn(refname.buf, &oid, flag, cb_data);
 		if (ret)
 			break;
-- 
2.34.1.929.ge922d848c7a


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno"
  2021-12-12 19:53         ` [PATCH v2 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
                             ` (2 preceding siblings ...)
  2021-12-12 19:53           ` [PATCH v2 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
@ 2022-01-12 12:36           ` Ævar Arnfjörð Bjarmason
  2022-01-12 12:36             ` [PATCH v3 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
                               ` (3 more replies)
  3 siblings, 4 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-01-12 12:36 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Bagas Sanjaya,
	Ævar Arnfjörð Bjarmason

This is a follow-up to the recently landed ab/refs-errno-cleanup
topic, I missed a spot and left some meaningless use of "errno" in the
refs (file) backend.

Per the $subject I hope we can get this into v2.35.0. I submitted a
v1[1] and v2[2] of this around the holidays so I think it may have
fallen through the cracks.

1. https://lore.kernel.org/git/cover-0.3-00000000000-20211209T045735Z-avarab@gmail.com/
2. https://lore.kernel.org/git/cover-v2-0.3-00000000000-20211212T195108Z-avarab@gmail.com/

Ævar Arnfjörð Bjarmason (3):
  refs API: use "failure_errno", not "errno"
  sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure
  refs API: remove "failure_errno" from refs_resolve_ref_unsafe()

 refs.c                    | 53 +++++++++++++--------------------------
 refs.h                    |  7 +-----
 refs/files-backend.c      | 34 ++++++++-----------------
 remote.c                  |  3 +--
 sequencer.c               | 10 +++-----
 t/helper/test-ref-store.c |  3 +--
 worktree.c                | 11 +++-----
 7 files changed, 36 insertions(+), 85 deletions(-)

Range-diff against v2:
1:  161fcad1578 = 1:  a45268ac24b refs API: use "failure_errno", not "errno"
2:  12d453d3884 = 2:  8d8691a5e93 sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure
3:  614590b2d10 ! 3:  8f937d8f64a refs API: remove "failure_errno" from refs_resolve_ref_unsafe()
    @@ Commit message
         return value was NULL or not, i.e. if the ref could be resolved.
     
         There was one caller left in sequencer.c that used the
    -    "failure_errnO', but as of the preceding commit it doesn't use that
    -    "failure_errno" either.
    +    "failure_errno', but as of the preceding commit it uses a boilerplate
    +    "ignore_errno" instead.
     
         So let's remove this output parameter. Not only isn't it used now, but
    -    we'd like to slowly move the refs API to a more file-backend
    -    independent way of communicating error codes, having it use a
    -    "failure_errno" was only the first step in that direction. If this or
    -    any other function needs to communicate what specifically is wrong
    -    with the requested "refname" it'll be better to have the function set
    -    some output enum of well-defined error states than piggy-backend on
    -    "errno".
    +    it's unlikely that we'll want it again in the future. We'd like to
    +    slowly move the refs API to a more file-backend independent way of
    +    communicating error codes, having it use a "failure_errno" was only
    +    the first step in that direction. If this or any other function needs
    +    to communicate what specifically is wrong with the requested "refname"
    +    it'll be better to have the function set some output enum of
    +    well-defined error states than piggy-backend on "errno".
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    @@ refs/files-backend.c: static int lock_ref_for_update(struct files_ref_store *ref
      						    "error reading reference",
     @@ refs/files-backend.c: static int files_reflog_expire(struct ref_store *ref_store,
      
    - 		if ((flags & EXPIRE_REFLOGS_UPDATE_REF) &&
    + 		if ((expire_flags & EXPIRE_REFLOGS_UPDATE_REF) &&
      		    !is_null_oid(&cb.last_kept_oid)) {
     -			int ignore_errno;
      			int type;
    @@ sequencer.c: void print_commit_summary(struct repository *r,
     
      ## t/helper/test-ref-store.c ##
     @@ t/helper/test-ref-store.c: static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
    - 	int resolve_flags = arg_flags(*argv++, "resolve-flags");
    + 	int resolve_flags = arg_flags(*argv++, "resolve-flags", empty_flags);
      	int flags;
      	const char *ref;
     -	int ignore_errno;
    @@ worktree.c: static void add_head_info(struct worktree *wt)
      	if (!target)
      		return;
      
    -@@ worktree.c: const struct worktree *find_shared_symref(const char *symref,
    +@@ worktree.c: const struct worktree *find_shared_symref(struct worktree **worktrees,
      		const char *symref_target;
      		struct ref_store *refs;
      		int flags;
    @@ worktree.c: const struct worktree *find_shared_symref(const char *symref,
      
      		if (wt->is_bare)
      			continue;
    -@@ worktree.c: const struct worktree *find_shared_symref(const char *symref,
    +@@ worktree.c: const struct worktree *find_shared_symref(struct worktree **worktrees,
      
      		refs = get_worktree_ref_store(wt);
      		symref_target = refs_resolve_ref_unsafe(refs, symref, 0,
-- 
2.35.0.rc0.848.gb9d3879eb1d


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 1/3] refs API: use "failure_errno", not "errno"
  2022-01-12 12:36           ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
@ 2022-01-12 12:36             ` Ævar Arnfjörð Bjarmason
  2022-01-12 19:59               ` Junio C Hamano
  2022-01-12 12:36             ` [PATCH v3 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
                               ` (2 subsequent siblings)
  3 siblings, 1 reply; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-01-12 12:36 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Bagas Sanjaya,
	Ævar Arnfjörð Bjarmason

Fix a logic error in refs_resolve_ref_unsafe() introduced in a recent
series of mine to abstract the refs API away from errno. See
96f6623ada0 (Merge branch 'ab/refs-errno-cleanup', 2021-11-29)for that
series.

In that series introduction of "failure_errno" to
refs_resolve_ref_unsafe came in ef18119dec8 (refs API: add a version
of refs_resolve_ref_unsafe() with "errno", 2021-10-16). There we'd set
"errno = 0" immediately before refs_read_raw_ref(), and then set
"failure_errno" to "errno" if errno was non-zero afterwards.

Then in the next commit 8b72fea7e91 (refs API: make
refs_read_raw_ref() not set errno, 2021-10-16) we started expecting
"refs_read_raw_ref()" to set "failure_errno". It would do that if
refs_read_raw_ref() failed, but it wouldn't be the same errno.

So we might set the "errno" here to any arbitrary bad value, and end
up e.g. returning NULL when we meant to return the refname from
refs_resolve_ref_unsafe(), or the other way around. Instrumenting this
code will reveal cases where refs_read_raw_ref() will fail, and
"errno" and "failure_errno" will be set to different values.

In practice I haven't found a case where this scary bug changed
anything in practice. The reason for that is that we'll not care about
the actual value of "errno" here per-se, but only whether:

 1. We have an errno
 2. If it's one of ENOENT, EISDIR or ENOTDIR. See the adjacent code
    added in a1c1d8170db (refs_resolve_ref_unsafe: handle d/f
    conflicts for writes, 2017-10-06)

I.e. if we clobber "failure_errno" with "errno", but it happened to be
one of those three, and we'll clobber it with another one of the three
we were OK.

Perhaps there are cases where the difference ended up mattering, but I
haven't found them. Instrumenting the test suite to fail if "errno"
and "failure_errno" are different shows a lot of failures, checking if
they're different *and* one is but not the other is outside that list
of three "errno" values yields no failures.

But let's fix the obvious bug. We should just stop paying attention to
"errno" in refs_resolve_ref_unsafe(). In addition let's change the
partial resetting of "errno" in files_read_raw_ref() to happen just
before the "return", to ensure that any such bug will be more easily
spotted in the future.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 refs.c               | 2 --
 refs/files-backend.c | 3 +--
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/refs.c b/refs.c
index bd2546ae230..addb26293b4 100644
--- a/refs.c
+++ b/refs.c
@@ -1722,8 +1722,6 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 		if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
 				      &read_flags, failure_errno)) {
 			*flags |= read_flags;
-			if (errno)
-				*failure_errno = errno;
 
 			/* In reading mode, refs must eventually resolve */
 			if (resolve_flags & RESOLVE_REF_READING)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index b529fdf237e..43a3b882d7c 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -382,7 +382,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 	if (lstat(path, &st) < 0) {
 		int ignore_errno;
 		myerr = errno;
-		errno = 0;
 		if (myerr != ENOENT)
 			goto out;
 		if (refs_read_raw_ref(refs->packed_ref_store, refname, oid,
@@ -399,7 +398,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 		strbuf_reset(&sb_contents);
 		if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) {
 			myerr = errno;
-			errno = 0;
 			if (myerr == ENOENT || myerr == EINVAL)
 				/* inconsistent with lstat; retry */
 				goto stat_ref;
@@ -469,6 +467,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 
 	strbuf_release(&sb_path);
 	strbuf_release(&sb_contents);
+	errno = 0;
 	return ret;
 }
 
-- 
2.35.0.rc0.848.gb9d3879eb1d


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure
  2022-01-12 12:36           ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
  2022-01-12 12:36             ` [PATCH v3 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
@ 2022-01-12 12:36             ` Ævar Arnfjörð Bjarmason
  2022-01-12 20:02               ` Junio C Hamano
  2022-01-12 12:36             ` [PATCH v3 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
  2022-01-12 19:34             ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Junio C Hamano
  3 siblings, 1 reply; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-01-12 12:36 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Bagas Sanjaya,
	Ævar Arnfjörð Bjarmason

Change code that was faithfully migrated to the new "resolve_errno"
API in ed90f04155d (refs API: make resolve_ref_unsafe() not set errno,
2021-10-16) to stop caring about the errno at all.

When we fail to resolve "HEAD" after the sequencer runs it doesn't
really help to say what the "errno" value is, since the fake backend
errno may or may not reflect anything real about the state of the
".git/HEAD". With the upcoming reftable backend this fakery will
become even more pronounced.

So let's just die() instead of die_errno() here. This will also help
simplify the refs_resolve_ref_unsafe() API. This was the only user of
it that wasn't ignoring the "failure_errno" output parameter.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 sequencer.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 6abd72160cc..03cdf548d72 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1281,7 +1281,7 @@ void print_commit_summary(struct repository *r,
 	struct strbuf author_ident = STRBUF_INIT;
 	struct strbuf committer_ident = STRBUF_INIT;
 	struct ref_store *refs;
-	int resolve_errno;
+	int ignore_errno;
 
 	commit = lookup_commit(r, oid);
 	if (!commit)
@@ -1333,11 +1333,9 @@ void print_commit_summary(struct repository *r,
 
 	refs = get_main_ref_store(the_repository);
 	head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL,
-				       &resolve_errno);
-	if (!head) {
-		errno = resolve_errno;
-		die_errno(_("unable to resolve HEAD after creating commit"));
-	}
+				       &ignore_errno);
+	if (!head)
+		die(_("unable to resolve HEAD after creating commit"));
 	if (!strcmp(head, "HEAD"))
 		head = _("detached HEAD");
 	else
-- 
2.35.0.rc0.848.gb9d3879eb1d


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe()
  2022-01-12 12:36           ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
  2022-01-12 12:36             ` [PATCH v3 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
  2022-01-12 12:36             ` [PATCH v3 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
@ 2022-01-12 12:36             ` Ævar Arnfjörð Bjarmason
  2022-01-12 19:34             ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Junio C Hamano
  3 siblings, 0 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-01-12 12:36 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Han-Wen Nienhuys, Bagas Sanjaya,
	Ævar Arnfjörð Bjarmason

Remove the now-unused "failure_errno" parameter from the
refs_resolve_ref_unsafe() signature. In my recent 96f6623ada0 (Merge
branch 'ab/refs-errno-cleanup', 2021-11-29) series we made all of its
callers explicitly request the errno via an output parameter.

As that series shows all but one caller ended up passing in a
boilerplate "ignore_errno", since they only cared about whether the
return value was NULL or not, i.e. if the ref could be resolved.

There was one caller left in sequencer.c that used the
"failure_errno', but as of the preceding commit it uses a boilerplate
"ignore_errno" instead.

So let's remove this output parameter. Not only isn't it used now, but
it's unlikely that we'll want it again in the future. We'd like to
slowly move the refs API to a more file-backend independent way of
communicating error codes, having it use a "failure_errno" was only
the first step in that direction. If this or any other function needs
to communicate what specifically is wrong with the requested "refname"
it'll be better to have the function set some output enum of
well-defined error states than piggy-backend on "errno".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 refs.c                    | 51 +++++++++++++--------------------------
 refs.h                    |  7 +-----
 refs/files-backend.c      | 31 +++++++-----------------
 remote.c                  |  3 +--
 sequencer.c               |  4 +--
 t/helper/test-ref-store.c |  3 +--
 worktree.c                | 11 +++------
 7 files changed, 33 insertions(+), 77 deletions(-)

diff --git a/refs.c b/refs.c
index addb26293b4..7017ae59804 100644
--- a/refs.c
+++ b/refs.c
@@ -269,10 +269,9 @@ char *refs_resolve_refdup(struct ref_store *refs,
 			  struct object_id *oid, int *flags)
 {
 	const char *result;
-	int ignore_errno;
 
 	result = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
-					 oid, flags, &ignore_errno);
+					 oid, flags);
 	return xstrdup_or_null(result);
 }
 
@@ -294,11 +293,10 @@ struct ref_filter {
 
 int read_ref_full(const char *refname, int resolve_flags, struct object_id *oid, int *flags)
 {
-	int ignore_errno;
 	struct ref_store *refs = get_main_ref_store(the_repository);
 
 	if (refs_resolve_ref_unsafe(refs, refname, resolve_flags,
-				    oid, flags, &ignore_errno))
+				    oid, flags))
 		return 0;
 	return -1;
 }
@@ -310,9 +308,8 @@ int read_ref(const char *refname, struct object_id *oid)
 
 int refs_ref_exists(struct ref_store *refs, const char *refname)
 {
-	int ignore_errno;
 	return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING,
-					 NULL, NULL, &ignore_errno);
+					 NULL, NULL);
 }
 
 int ref_exists(const char *refname)
@@ -656,15 +653,13 @@ int expand_ref(struct repository *repo, const char *str, int len,
 		struct object_id *this_result;
 		int flag;
 		struct ref_store *refs = get_main_ref_store(repo);
-		int ignore_errno;
 
 		this_result = refs_found ? &oid_from_ref : oid;
 		strbuf_reset(&fullref);
 		strbuf_addf(&fullref, *p, len, str);
 		r = refs_resolve_ref_unsafe(refs, fullref.buf,
 					    RESOLVE_REF_READING,
-					    this_result, &flag,
-					    &ignore_errno);
+					    this_result, &flag);
 		if (r) {
 			if (!refs_found++)
 				*ref = xstrdup(r);
@@ -693,14 +688,12 @@ int repo_dwim_log(struct repository *r, const char *str, int len,
 	for (p = ref_rev_parse_rules; *p; p++) {
 		struct object_id hash;
 		const char *ref, *it;
-		int ignore_errno;
 
 		strbuf_reset(&path);
 		strbuf_addf(&path, *p, len, str);
 		ref = refs_resolve_ref_unsafe(refs, path.buf,
 					      RESOLVE_REF_READING,
-					      oid ? &hash : NULL, NULL,
-					      &ignore_errno);
+					      oid ? &hash : NULL, NULL);
 		if (!ref)
 			continue;
 		if (refs_reflog_exists(refs, path.buf))
@@ -1390,10 +1383,9 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 {
 	struct object_id oid;
 	int flag;
-	int ignore_errno;
 
 	if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
-				    &oid, &flag, &ignore_errno))
+				    &oid, &flag))
 		return fn("HEAD", &oid, flag, cb_data);
 
 	return 0;
@@ -1682,15 +1674,13 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 				    const char *refname,
 				    int resolve_flags,
 				    struct object_id *oid,
-				    int *flags, int *failure_errno)
+				    int *flags)
 {
 	static struct strbuf sb_refname = STRBUF_INIT;
 	struct object_id unused_oid;
 	int unused_flags;
 	int symref_count;
 
-	assert(failure_errno);
-
 	if (!oid)
 		oid = &unused_oid;
 	if (!flags)
@@ -1700,10 +1690,8 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 
 	if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
 		if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
-		    !refname_is_safe(refname)) {
-			*failure_errno = EINVAL;
+		    !refname_is_safe(refname))
 			return NULL;
-		}
 
 		/*
 		 * dwim_ref() uses REF_ISBROKEN to distinguish between
@@ -1718,9 +1706,10 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 
 	for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
 		unsigned int read_flags = 0;
+		int failure_errno;
 
 		if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
-				      &read_flags, failure_errno)) {
+				      &read_flags, &failure_errno)) {
 			*flags |= read_flags;
 
 			/* In reading mode, refs must eventually resolve */
@@ -1732,9 +1721,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 			 * may show errors besides ENOENT if there are
 			 * similarly-named refs.
 			 */
-			if (*failure_errno != ENOENT &&
-			    *failure_errno != EISDIR &&
-			    *failure_errno != ENOTDIR)
+			if (failure_errno != ENOENT &&
+			    failure_errno != EISDIR &&
+			    failure_errno != ENOTDIR)
 				return NULL;
 
 			oidclr(oid);
@@ -1760,16 +1749,13 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 		}
 		if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
 			if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
-			    !refname_is_safe(refname)) {
-				*failure_errno = EINVAL;
+			    !refname_is_safe(refname))
 				return NULL;
-			}
 
 			*flags |= REF_ISBROKEN | REF_BAD_NAME;
 		}
 	}
 
-	*failure_errno = ELOOP;
 	return NULL;
 }
 
@@ -1784,10 +1770,8 @@ int refs_init_db(struct strbuf *err)
 const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
 			       struct object_id *oid, int *flags)
 {
-	int ignore_errno;
-
 	return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname,
-				       resolve_flags, oid, flags, &ignore_errno);
+				       resolve_flags, oid, flags);
 }
 
 int resolve_gitlink_ref(const char *submodule, const char *refname,
@@ -1795,15 +1779,14 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
 {
 	struct ref_store *refs;
 	int flags;
-	int ignore_errno;
 
 	refs = get_submodule_ref_store(submodule);
 
 	if (!refs)
 		return -1;
 
-	if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags,
-				     &ignore_errno) || is_null_oid(oid))
+	if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags) ||
+	    is_null_oid(oid))
 		return -1;
 	return 0;
 }
diff --git a/refs.h b/refs.h
index 8f91a7f9ff2..cd2d0c1ac09 100644
--- a/refs.h
+++ b/refs.h
@@ -58,11 +58,6 @@ struct worktree;
  * resolved. The function returns NULL for such ref names.
  * Caps and underscores refers to the special refs, such as HEAD,
  * FETCH_HEAD and friends, that all live outside of the refs/ directory.
- *
- * Callers should not inspect "errno" on failure, but rather pass in a
- * "failure_errno" parameter, on failure the "errno" will indicate the
- * type of failure encountered, but not necessarily one that came from
- * a syscall. We might have faked it up.
  */
 #define RESOLVE_REF_READING 0x01
 #define RESOLVE_REF_NO_RECURSE 0x02
@@ -72,7 +67,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 				    const char *refname,
 				    int resolve_flags,
 				    struct object_id *oid,
-				    int *flags, int *failure_errno);
+				    int *flags);
 
 const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
 			       struct object_id *oid, int *flags);
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 43a3b882d7c..a40267b3ae9 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -277,11 +277,10 @@ static void loose_fill_ref_dir(struct ref_store *ref_store,
 					 create_dir_entry(dir->cache, refname.buf,
 							  refname.len));
 		} else {
-			int ignore_errno;
 			if (!refs_resolve_ref_unsafe(&refs->base,
 						     refname.buf,
 						     RESOLVE_REF_READING,
-						     &oid, &flag, &ignore_errno)) {
+						     &oid, &flag)) {
 				oidclr(&oid);
 				flag |= REF_ISBROKEN;
 			} else if (is_null_oid(&oid)) {
@@ -1006,7 +1005,6 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
 {
 	struct strbuf ref_file = STRBUF_INIT;
 	struct ref_lock *lock;
-	int ignore_errno;
 
 	files_assert_main_repository(refs, "lock_ref_oid_basic");
 	assert(err);
@@ -1034,7 +1032,7 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
 	}
 
 	if (!refs_resolve_ref_unsafe(&refs->base, lock->ref_name, 0,
-				     &lock->old_oid, NULL, &ignore_errno))
+				     &lock->old_oid, NULL))
 		oidclr(&lock->old_oid);
 	goto out;
 
@@ -1399,7 +1397,6 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
 	struct strbuf tmp_renamed_log = STRBUF_INIT;
 	int log, ret;
 	struct strbuf err = STRBUF_INIT;
-	int ignore_errno;
 
 	files_reflog_path(refs, &sb_oldref, oldrefname);
 	files_reflog_path(refs, &sb_newref, newrefname);
@@ -1413,7 +1410,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
 
 	if (!refs_resolve_ref_unsafe(&refs->base, oldrefname,
 				     RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
-				     &orig_oid, &flag, &ignore_errno)) {
+				     &orig_oid, &flag)) {
 		ret = error("refname %s not found", oldrefname);
 		goto out;
 	}
@@ -1459,7 +1456,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
 	 */
 	if (!copy && refs_resolve_ref_unsafe(&refs->base, newrefname,
 					     RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
-					     NULL, NULL, &ignore_errno) &&
+					     NULL, NULL) &&
 	    refs_delete_ref(&refs->base, NULL, newrefname,
 			    NULL, REF_NO_DEREF)) {
 		if (errno == EISDIR) {
@@ -1828,12 +1825,10 @@ static int commit_ref_update(struct files_ref_store *refs,
 		 */
 		int head_flag;
 		const char *head_ref;
-		int ignore_errno;
 
 		head_ref = refs_resolve_ref_unsafe(&refs->base, "HEAD",
 						   RESOLVE_REF_READING,
-						   NULL, &head_flag,
-						   &ignore_errno);
+						   NULL, &head_flag);
 		if (head_ref && (head_flag & REF_ISSYMREF) &&
 		    !strcmp(head_ref, lock->ref_name)) {
 			struct strbuf log_err = STRBUF_INIT;
@@ -1877,12 +1872,10 @@ static void update_symref_reflog(struct files_ref_store *refs,
 {
 	struct strbuf err = STRBUF_INIT;
 	struct object_id new_oid;
-	int ignore_errno;
 
 	if (logmsg &&
 	    refs_resolve_ref_unsafe(&refs->base, target,
-				    RESOLVE_REF_READING, &new_oid, NULL,
-				    &ignore_errno) &&
+				    RESOLVE_REF_READING, &new_oid, NULL) &&
 	    files_log_ref_write(refs, refname, &lock->old_oid,
 				&new_oid, logmsg, 0, &err)) {
 		error("%s", err.buf);
@@ -2156,7 +2149,6 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
 		(struct files_reflog_iterator *)ref_iterator;
 	struct dir_iterator *diter = iter->dir_iterator;
 	int ok;
-	int ignore_errno;
 
 	while ((ok = dir_iterator_advance(diter)) == ITER_OK) {
 		int flags;
@@ -2170,8 +2162,7 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
 
 		if (!refs_resolve_ref_unsafe(iter->ref_store,
 					     diter->relative_path, 0,
-					     &iter->oid, &flags,
-					     &ignore_errno)) {
+					     &iter->oid, &flags)) {
 			error("bad ref for %s", diter->path.buf);
 			continue;
 		}
@@ -2515,11 +2506,9 @@ static int lock_ref_for_update(struct files_ref_store *refs,
 			 * the transaction, so we have to read it here
 			 * to record and possibly check old_oid:
 			 */
-			int ignore_errno;
 			if (!refs_resolve_ref_unsafe(&refs->base,
 						     referent.buf, 0,
-						     &lock->old_oid, NULL,
-						     &ignore_errno)) {
+						     &lock->old_oid, NULL)) {
 				if (update->flags & REF_HAVE_OLD) {
 					strbuf_addf(err, "cannot lock ref '%s': "
 						    "error reading reference",
@@ -3208,14 +3197,12 @@ static int files_reflog_expire(struct ref_store *ref_store,
 
 		if ((expire_flags & EXPIRE_REFLOGS_UPDATE_REF) &&
 		    !is_null_oid(&cb.last_kept_oid)) {
-			int ignore_errno;
 			int type;
 			const char *ref;
 
 			ref = refs_resolve_ref_unsafe(&refs->base, refname,
 						      RESOLVE_REF_NO_RECURSE,
-						      NULL, &type,
-						      &ignore_errno);
+						      NULL, &type);
 			update = !!(ref && !(type & REF_ISSYMREF));
 		}
 
diff --git a/remote.c b/remote.c
index a6d8ec6c1ac..c97c626eaa8 100644
--- a/remote.c
+++ b/remote.c
@@ -508,9 +508,8 @@ static void read_config(struct repository *repo)
 
 	repo->remote_state->current_branch = NULL;
 	if (startup_info->have_repository) {
-		int ignore_errno;
 		const char *head_ref = refs_resolve_ref_unsafe(
-			get_main_ref_store(repo), "HEAD", 0, NULL, &flag, &ignore_errno);
+			get_main_ref_store(repo), "HEAD", 0, NULL, &flag);
 		if (head_ref && (flag & REF_ISSYMREF) &&
 		    skip_prefix(head_ref, "refs/heads/", &head_ref)) {
 			repo->remote_state->current_branch = make_branch(
diff --git a/sequencer.c b/sequencer.c
index 03cdf548d72..d57b51ed555 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1281,7 +1281,6 @@ void print_commit_summary(struct repository *r,
 	struct strbuf author_ident = STRBUF_INIT;
 	struct strbuf committer_ident = STRBUF_INIT;
 	struct ref_store *refs;
-	int ignore_errno;
 
 	commit = lookup_commit(r, oid);
 	if (!commit)
@@ -1332,8 +1331,7 @@ void print_commit_summary(struct repository *r,
 	diff_setup_done(&rev.diffopt);
 
 	refs = get_main_ref_store(the_repository);
-	head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL,
-				       &ignore_errno);
+	head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL);
 	if (!head)
 		die(_("unable to resolve HEAD after creating commit"));
 	if (!strcmp(head, "HEAD"))
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 3e4ddaee705..9646d85fc84 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -180,10 +180,9 @@ static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
 	int resolve_flags = arg_flags(*argv++, "resolve-flags", empty_flags);
 	int flags;
 	const char *ref;
-	int ignore_errno;
 
 	ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
-				      &oid, &flags, &ignore_errno);
+				      &oid, &flags);
 	printf("%s %s 0x%x\n", oid_to_hex(&oid), ref ? ref : "(null)", flags);
 	return ref ? 0 : 1;
 }
diff --git a/worktree.c b/worktree.c
index 6f598dcfcdf..e8f6f6ae6f4 100644
--- a/worktree.c
+++ b/worktree.c
@@ -28,13 +28,11 @@ static void add_head_info(struct worktree *wt)
 {
 	int flags;
 	const char *target;
-	int ignore_errno;
 
 	target = refs_resolve_ref_unsafe(get_worktree_ref_store(wt),
 					 "HEAD",
 					 0,
-					 &wt->head_oid, &flags,
-					 &ignore_errno);
+					 &wt->head_oid, &flags);
 	if (!target)
 		return;
 
@@ -416,7 +414,6 @@ const struct worktree *find_shared_symref(struct worktree **worktrees,
 		const char *symref_target;
 		struct ref_store *refs;
 		int flags;
-		int ignore_errno;
 
 		if (wt->is_bare)
 			continue;
@@ -434,8 +431,7 @@ const struct worktree *find_shared_symref(struct worktree **worktrees,
 
 		refs = get_worktree_ref_store(wt);
 		symref_target = refs_resolve_ref_unsafe(refs, symref, 0,
-							NULL, &flags,
-							&ignore_errno);
+							NULL, &flags);
 		if ((flags & REF_ISSYMREF) &&
 		    symref_target && !strcmp(symref_target, target)) {
 			existing = wt;
@@ -563,7 +559,6 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
 		struct worktree *wt = *p;
 		struct object_id oid;
 		int flag;
-		int ignore_errno;
 
 		if (wt->is_current)
 			continue;
@@ -573,7 +568,7 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
 		if (refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
 					    refname.buf,
 					    RESOLVE_REF_READING,
-					    &oid, &flag, &ignore_errno))
+					    &oid, &flag))
 			ret = fn(refname.buf, &oid, flag, cb_data);
 		if (ret)
 			break;
-- 
2.35.0.rc0.848.gb9d3879eb1d


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno"
  2022-01-12 12:36           ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
                               ` (2 preceding siblings ...)
  2022-01-12 12:36             ` [PATCH v3 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
@ 2022-01-12 19:34             ` Junio C Hamano
  2022-01-13 12:22               ` Ævar Arnfjörð Bjarmason
  3 siblings, 1 reply; 24+ messages in thread
From: Junio C Hamano @ 2022-01-12 19:34 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Han-Wen Nienhuys, Bagas Sanjaya

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> This is a follow-up to the recently landed ab/refs-errno-cleanup
> topic, I missed a spot and left some meaningless use of "errno" in the
> refs (file) backend.

Is it a fix "oops the ones we merged to 'master' were buggy and
needs these on top to be correct"?

If it is merely a follow-up "I am doing more of the same thing as we
aimed to do in that topic", I'd rather leave it to the next cycle.

I'll come back to the topic to find it out from the patches
themselves, but after I dealt with other patches that are more
clearly fix-ups first.

Thanks.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 1/3] refs API: use "failure_errno", not "errno"
  2022-01-12 12:36             ` [PATCH v3 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
@ 2022-01-12 19:59               ` Junio C Hamano
  2022-01-13 12:14                 ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 24+ messages in thread
From: Junio C Hamano @ 2022-01-12 19:59 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Han-Wen Nienhuys, Bagas Sanjaya

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> @@ -1722,8 +1722,6 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
>  		if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
>  				      &read_flags, failure_errno)) {
>  			*flags |= read_flags;
> -			if (errno)
> -				*failure_errno = errno;

Looks good.  

The whole point of passing failure_errno down to refs_read_raw_ref()
is that we capture the reason of the failure there without having to
rely on errno at this point in the flow.  Removal of this assignment
makes perfect sense.

But ...

> diff --git a/refs/files-backend.c b/refs/files-backend.c
> index b529fdf237e..43a3b882d7c 100644
> --- a/refs/files-backend.c
> +++ b/refs/files-backend.c
> @@ -382,7 +382,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
>  	if (lstat(path, &st) < 0) {
>  		int ignore_errno;
>  		myerr = errno;
> -		errno = 0;
>  		if (myerr != ENOENT)
>  			goto out;
>  		if (refs_read_raw_ref(refs->packed_ref_store, refname, oid,
> @@ -399,7 +398,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
>  		strbuf_reset(&sb_contents);
>  		if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) {
>  			myerr = errno;
> -			errno = 0;
>  			if (myerr == ENOENT || myerr == EINVAL)
>  				/* inconsistent with lstat; retry */
>  				goto stat_ref;
> @@ -469,6 +467,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
>  
>  	strbuf_release(&sb_path);
>  	strbuf_release(&sb_contents);
> +	errno = 0;
>  	return ret;
>  }

... it is not clear to me if this part makes sense.  If everybody
above the callstack uses failure_errno as the source of truth,
clearing errno here in this function should not be necessary and is
misleading to readers of the code, no?

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure
  2022-01-12 12:36             ` [PATCH v3 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
@ 2022-01-12 20:02               ` Junio C Hamano
  0 siblings, 0 replies; 24+ messages in thread
From: Junio C Hamano @ 2022-01-12 20:02 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Han-Wen Nienhuys, Bagas Sanjaya

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Change code that was faithfully migrated to the new "resolve_errno"
> API in ed90f04155d (refs API: make resolve_ref_unsafe() not set errno,
> 2021-10-16) to stop caring about the errno at all.
>
> When we fail to resolve "HEAD" after the sequencer runs it doesn't
> really help to say what the "errno" value is, since the fake backend
> errno may or may not reflect anything real about the state of the
> ".git/HEAD". With the upcoming reftable backend this fakery will
> become even more pronounced.

OK.  In principle I agree with the reasoning.  Perhaps it can be
better done as a preparation for the reftable backend in future
cycles, not now.

> So let's just die() instead of die_errno() here. This will also help
> simplify the refs_resolve_ref_unsafe() API. This was the only user of
> it that wasn't ignoring the "failure_errno" output parameter.

> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  sequencer.c | 10 ++++------
>  1 file changed, 4 insertions(+), 6 deletions(-)
>
> diff --git a/sequencer.c b/sequencer.c
> index 6abd72160cc..03cdf548d72 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -1281,7 +1281,7 @@ void print_commit_summary(struct repository *r,
>  	struct strbuf author_ident = STRBUF_INIT;
>  	struct strbuf committer_ident = STRBUF_INIT;
>  	struct ref_store *refs;
> -	int resolve_errno;
> +	int ignore_errno;
>  
>  	commit = lookup_commit(r, oid);
>  	if (!commit)
> @@ -1333,11 +1333,9 @@ void print_commit_summary(struct repository *r,
>  
>  	refs = get_main_ref_store(the_repository);
>  	head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL,
> -				       &resolve_errno);
> -	if (!head) {
> -		errno = resolve_errno;
> -		die_errno(_("unable to resolve HEAD after creating commit"));
> -	}
> +				       &ignore_errno);
> +	if (!head)
> +		die(_("unable to resolve HEAD after creating commit"));
>  	if (!strcmp(head, "HEAD"))
>  		head = _("detached HEAD");
>  	else

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 1/3] refs API: use "failure_errno", not "errno"
  2022-01-12 19:59               ` Junio C Hamano
@ 2022-01-13 12:14                 ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-01-13 12:14 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Han-Wen Nienhuys, Bagas Sanjaya


On Wed, Jan 12 2022, Junio C Hamano wrote:

> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
>
>> @@ -1722,8 +1722,6 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
>>  		if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
>>  				      &read_flags, failure_errno)) {
>>  			*flags |= read_flags;
>> -			if (errno)
>> -				*failure_errno = errno;
>
> Looks good.  
>
> The whole point of passing failure_errno down to refs_read_raw_ref()
> is that we capture the reason of the failure there without having to
> rely on errno at this point in the flow.  Removal of this assignment
> makes perfect sense.
>
> But ...
>
>> diff --git a/refs/files-backend.c b/refs/files-backend.c
>> index b529fdf237e..43a3b882d7c 100644
>> --- a/refs/files-backend.c
>> +++ b/refs/files-backend.c
>> @@ -382,7 +382,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
>>  	if (lstat(path, &st) < 0) {
>>  		int ignore_errno;
>>  		myerr = errno;
>> -		errno = 0;
>>  		if (myerr != ENOENT)
>>  			goto out;
>>  		if (refs_read_raw_ref(refs->packed_ref_store, refname, oid,
>> @@ -399,7 +398,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
>>  		strbuf_reset(&sb_contents);
>>  		if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) {
>>  			myerr = errno;
>> -			errno = 0;
>>  			if (myerr == ENOENT || myerr == EINVAL)
>>  				/* inconsistent with lstat; retry */
>>  				goto stat_ref;
>> @@ -469,6 +467,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
>>  
>>  	strbuf_release(&sb_path);
>>  	strbuf_release(&sb_contents);
>> +	errno = 0;
>>  	return ret;
>>  }
>
> ... it is not clear to me if this part makes sense.  If everybody
> above the callstack uses failure_errno as the source of truth,
> clearing errno here in this function should not be necessary and is
> misleading to readers of the code, no?

It's consistent with various other existing refs* code as we made this
transition, see:

    git grep -W 'errno = 0' -- 'refs*'

I.e. we'd like to not only transition existing users away from errno,
but to ensure that the file backend errno semantics don't inadvertently
leak outside the API.

Doing so is a bit pedantic for sure, but ensures that we won't need to
deal with any subtle bugs in that are with the reftable backend.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno"
  2022-01-12 19:34             ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Junio C Hamano
@ 2022-01-13 12:22               ` Ævar Arnfjörð Bjarmason
  2022-01-13 18:54                 ` Junio C Hamano
  0 siblings, 1 reply; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-01-13 12:22 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Han-Wen Nienhuys, Bagas Sanjaya


On Wed, Jan 12 2022, Junio C Hamano wrote:

> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
>
>> This is a follow-up to the recently landed ab/refs-errno-cleanup
>> topic, I missed a spot and left some meaningless use of "errno" in the
>> refs (file) backend.
>
> Is it a fix "oops the ones we merged to 'master' were buggy and
> needs these on top to be correct"?
>
> If it is merely a follow-up "I am doing more of the same thing as we
> aimed to do in that topic", I'd rather leave it to the next cycle.
>
> I'll come back to the topic to find it out from the patches
> themselves, but after I dealt with other patches that are more
> clearly fix-ups first.

3/3 isn't needed for v2.35.0, but I figured if you were queuing this
that obvious cleanup after the also-not-strictly-needed 2/3 made sense.

But I can leave both of those until after the release if you'd like.

I think we should have 1/3 for 2.35.0 as rationalized in its commit
message. I.e. I haven't found a way for that omission in my ef18119dec8
to break things in practice, but I'm also not confident that I thought
through all the potential cases. Changing that code to be obviously
correct in terms of the current API is an easy enough fix.

So just let me know how you'd like to proceed. I.e. I can re-roll a v2
with just 1/3, but I think this v1 is also good-to-go as-is. Thanks!

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno"
  2022-01-13 12:22               ` Ævar Arnfjörð Bjarmason
@ 2022-01-13 18:54                 ` Junio C Hamano
  2022-01-14 12:21                   ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 24+ messages in thread
From: Junio C Hamano @ 2022-01-13 18:54 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Han-Wen Nienhuys, Bagas Sanjaya

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> So just let me know how you'd like to proceed. I.e. I can re-roll a v2
> with just 1/3, but I think this v1 is also good-to-go as-is. Thanks!

I can just pick up [v1 1/3] and ignore the rest, which would mean
you do not have to send v2, right?

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno"
  2022-01-13 18:54                 ` Junio C Hamano
@ 2022-01-14 12:21                   ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 24+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-01-14 12:21 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Han-Wen Nienhuys, Bagas Sanjaya


On Thu, Jan 13 2022, Junio C Hamano wrote:

> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> So just let me know how you'd like to proceed. I.e. I can re-roll a v2
>> with just 1/3, but I think this v1 is also good-to-go as-is. Thanks!
>
> I can just pick up [v1 1/3] and ignore the rest, which would mean
> you do not have to send v2, right?

Late reply, but yes (and I see you did that already). Thanks!

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2022-01-14 12:21 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-08 11:38 errno oversight Han-Wen Nienhuys
2021-12-08 12:47 ` Ævar Arnfjörð Bjarmason
2021-12-08 13:00   ` Ævar Arnfjörð Bjarmason
2021-12-08 19:02     ` Junio C Hamano
2021-12-09  5:02       ` [PATCH 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
2021-12-09  5:02         ` [PATCH 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
2021-12-09  5:02         ` [PATCH 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
2021-12-09  5:02         ` [PATCH 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
2021-12-12 19:53         ` [PATCH v2 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
2021-12-12 19:53           ` [PATCH v2 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
2021-12-12 19:53           ` [PATCH v2 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
2021-12-12 19:53           ` [PATCH v2 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
2022-01-12 12:36           ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
2022-01-12 12:36             ` [PATCH v3 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
2022-01-12 19:59               ` Junio C Hamano
2022-01-13 12:14                 ` Ævar Arnfjörð Bjarmason
2022-01-12 12:36             ` [PATCH v3 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
2022-01-12 20:02               ` Junio C Hamano
2022-01-12 12:36             ` [PATCH v3 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
2022-01-12 19:34             ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Junio C Hamano
2022-01-13 12:22               ` Ævar Arnfjörð Bjarmason
2022-01-13 18:54                 ` Junio C Hamano
2022-01-14 12:21                   ` Ævar Arnfjörð Bjarmason
2021-12-08 13:05   ` errno oversight Han-Wen Nienhuys

Code repositories for project(s) associated with this inbox:

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).