]> git.ipfire.org Git - thirdparty/git.git/commitdiff
refs API: add a version of refs_resolve_ref_unsafe() with "errno"
authorÆvar Arnfjörð Bjarmason <avarab@gmail.com>
Sat, 16 Oct 2021 09:39:08 +0000 (11:39 +0200)
committerJunio C Hamano <gitster@pobox.com>
Sat, 16 Oct 2021 18:17:02 +0000 (11:17 -0700)
Add a new refs_werrres_ref_unsafe() function, which is like
refs_resolve_ref_unsafe() except that it explicitly saves away the
"errno" to a passed-in parameter, the refs_resolve_ref_unsafe() then
becomes a wrapper for it.

In subsequent commits we'll migrate code over to it, before finally
making "refs_resolve_ref_unsafe()" with an "errno" parameter the
canonical version, so this this function exists only so that we can
incrementally migrate callers, it will be going away in a subsequent
commit.

As the added comment notes has a rather tortured name to be the same
length as "refs_resolve_ref_unsafe", to avoid churn as we won't need
to re-indent the argument lists, similarly the documentation and
structure of it in refs.h is designed to minimize a diff in a
subsequent commit, where that documentation will be added to the new
refs_resolve_ref_unsafe().

At the end of this migration the "meaningful errno" TODO item left in
76d70dc0c63 (refs.c: make resolve_ref_unsafe set errno to something
meaningful on error, 2014-06-20) will be resolved.

As can be seen from the use of refs_read_raw_ref() we'll also need to
convert some functions that the new refs_werrres_ref_unsafe() itself
calls to take this "failure_errno". That will be done in subsequent
commits.

Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs.c
refs.h

diff --git a/refs.c b/refs.c
index 7f019c2377effa49a90427ffec0451c400941e0c..ad56dbb0125d753332615626f263279ed659c580 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1679,17 +1679,19 @@ int refs_read_raw_ref(struct ref_store *ref_store,
                                           type, &errno);
 }
 
-/* This function needs to return a meaningful errno on failure */
-const char *refs_resolve_ref_unsafe(struct ref_store *refs,
+const char *refs_werrres_ref_unsafe(struct ref_store *refs,
                                    const char *refname,
                                    int resolve_flags,
-                                   struct object_id *oid, int *flags)
+                                   struct object_id *oid,
+                                   int *flags, int *failure_errno)
 {
        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,7 +1702,7 @@ 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)) {
-                       errno = EINVAL;
+                       *failure_errno = EINVAL;
                        return NULL;
                }
 
@@ -1718,9 +1720,12 @@ 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;
 
+               errno = 0;
                if (refs_read_raw_ref(refs, refname,
                                      oid, &sb_refname, &read_flags)) {
                        *flags |= read_flags;
+                       if (errno)
+                               *failure_errno = errno;
 
                        /* In reading mode, refs must eventually resolve */
                        if (resolve_flags & RESOLVE_REF_READING)
@@ -1731,9 +1736,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
                         * may show errors besides ENOENT if there are
                         * similarly-named refs.
                         */
-                       if (errno != ENOENT &&
-                           errno != EISDIR &&
-                           errno != ENOTDIR)
+                       if (*failure_errno != ENOENT &&
+                           *failure_errno != EISDIR &&
+                           *failure_errno != ENOTDIR)
                                return NULL;
 
                        oidclr(oid);
@@ -1760,7 +1765,7 @@ 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)) {
-                               errno = EINVAL;
+                               *failure_errno = EINVAL;
                                return NULL;
                        }
 
@@ -1768,10 +1773,23 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
                }
        }
 
-       errno = ELOOP;
+       *failure_errno = ELOOP;
        return NULL;
 }
 
+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 = 0;
+       const char *refn;
+       refn = refs_werrres_ref_unsafe(refs, refname, resolve_flags,
+                                      oid, flags, &failure_errno);
+       if (!refn)
+               errno = failure_errno;
+       return refn;
+}
+
 /* backend functions */
 int refs_init_db(struct strbuf *err)
 {
diff --git a/refs.h b/refs.h
index d5099d4984ef9c9fe248897528344ab9019eba65..c8afde6bb507bff43d5e4fa70a97bfe12c35d43e 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -11,6 +11,18 @@ struct string_list;
 struct string_list_item;
 struct worktree;
 
+/*
+ * 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.
+ */
+const char *refs_werrres_ref_unsafe(struct ref_store *refs,
+                                   const char *refname,
+                                   int resolve_flags,
+                                   struct object_id *oid,
+                                   int *flags, int *failure_errno);
+
 /*
  * Resolve a reference, recursively following symbolic refererences.
  *