refs API: add a version of refs_resolve_ref_unsafe() with "errno"

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>

Ævar Arnfjörð Bjarmason committed Oct 16, 2021 at 11:39 UTC ef18119dec8a9c65ed545fdd60c7ae9a6bc31f6f
2 files changed +39 -9
refs.c
+27 -9
@@ -1679,17 +1679,19 @@ int refs_read_raw_ref(struct ref_store *ref_store,
1679 type, &errno);
1680 }
1681
1682 -/* This function needs to return a meaningful errno on failure */
1683 -const char *refs_resolve_ref_unsafe(struct ref_store *refs,
1682 +const char *refs_werrres_ref_unsafe(struct ref_store *refs,
1683 const char *refname,
1684 int resolve_flags,
1686 - struct object_id *oid, int *flags)
1685 + struct object_id *oid,
1686 + int *flags, int *failure_errno)
1687 {
1688 static struct strbuf sb_refname = STRBUF_INIT;
1689 struct object_id unused_oid;
1690 int unused_flags;
1691 int symref_count;
1692
1693 + assert(failure_errno);
1694 +
1695 if (!oid)
1696 oid = &unused_oid;
1697 if (!flags)
@@ -1700,7 +1702,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
1702 if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
1703 if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
1704 !refname_is_safe(refname)) {
1703 - errno = EINVAL;
1705 + *failure_errno = EINVAL;
1706 return NULL;
1707 }
1708
@@ -1718,9 +1720,12 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
1720 for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
1721 unsigned int read_flags = 0;
1722
1723 + errno = 0;
1724 if (refs_read_raw_ref(refs, refname,
1725 oid, &sb_refname, &read_flags)) {
1726 *flags |= read_flags;
1727 + if (errno)
1728 + *failure_errno = errno;
1729
1730 /* In reading mode, refs must eventually resolve */
1731 if (resolve_flags & RESOLVE_REF_READING)
@@ -1731,9 +1736,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
1736 * may show errors besides ENOENT if there are
1737 * similarly-named refs.
1738 */
1734 - if (errno != ENOENT &&
1735 - errno != EISDIR &&
1736 - errno != ENOTDIR)
1739 + if (*failure_errno != ENOENT &&
1740 + *failure_errno != EISDIR &&
1741 + *failure_errno != ENOTDIR)
1742 return NULL;
1743
1744 oidclr(oid);
@@ -1760,7 +1765,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
1765 if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
1766 if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
1767 !refname_is_safe(refname)) {
1763 - errno = EINVAL;
1768 + *failure_errno = EINVAL;
1769 return NULL;
1770 }
1771
@@ -1768,10 +1773,23 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
1773 }
1774 }
1775
1771 - errno = ELOOP;
1776 + *failure_errno = ELOOP;
1777 return NULL;
1778 }
1779
1780 +const char *refs_resolve_ref_unsafe(struct ref_store *refs, const char *refname,
1781 + int resolve_flags, struct object_id *oid,
1782 + int *flags)
1783 +{
1784 + int failure_errno = 0;
1785 + const char *refn;
1786 + refn = refs_werrres_ref_unsafe(refs, refname, resolve_flags,
1787 + oid, flags, &failure_errno);
1788 + if (!refn)
1789 + errno = failure_errno;
1790 + return refn;
1791 +}
1792 +
1793 /* backend functions */
1794 int refs_init_db(struct strbuf *err)
1795 {
refs.h
+12
@@ -11,6 +11,18 @@ struct string_list;
11 struct string_list_item;
12 struct worktree;
13
14 +/*
15 + * Callers should not inspect "errno" on failure, but rather pass in a
16 + * "failure_errno" parameter, on failure the "errno" will indicate the
17 + * type of failure encountered, but not necessarily one that came from
18 + * a syscall. We might have faked it up.
19 + */
20 +const char *refs_werrres_ref_unsafe(struct ref_store *refs,
21 + const char *refname,
22 + int resolve_flags,
23 + struct object_id *oid,
24 + int *flags, int *failure_errno);
25 +
26 /*
27 * Resolve a reference, recursively following symbolic refererences.
28 *