From aa30fe1481b9af54efea9a14a367811849a339e5 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sat, 16 Oct 2021 11:39:07 +0200 Subject: [PATCH 01/21] branch tests: test for errno propagating on failing read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a test for "git branch" to cover the case where .git/refs is symlinked. To check availability, refs_verify_refname_available() will run refs_read_raw_ref() on each prefix, leading to a read() from .git/refs (which is a directory). It would probably be more robust to re-issue the lstat() as a normal stat(), in which case, we would fall back to the directory case, but for now let's just test for the existing behavior as-is. This test covers a regression in a commit that only ever made it to "next", see [1]. 1. http://lore.kernel.org/git/pull.1068.git.git.1629203489546.gitgitgadget@gmail.com Signed-off-by: Han-Wen Nienhuys Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- t/t3200-branch.sh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index e575ffb4ff..53e0d094bb 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -731,6 +731,28 @@ test_expect_success SYMLINKS 'git branch -m u v should fail when the reflog for test_must_fail git branch -m u v ' +test_expect_success SYMLINKS 'git branch -m with symlinked .git/refs' ' + test_when_finished "rm -rf subdir" && + git init --bare subdir && + + rm -rfv subdir/refs subdir/objects subdir/packed-refs && + ln -s ../.git/refs subdir/refs && + ln -s ../.git/objects subdir/objects && + ln -s ../.git/packed-refs subdir/packed-refs && + + git -C subdir rev-parse --absolute-git-dir >subdir.dir && + git rev-parse --absolute-git-dir >our.dir && + ! test_cmp subdir.dir our.dir && + + git -C subdir log && + git -C subdir branch rename-src && + git rev-parse rename-src >expect && + git -C subdir branch -m rename-src rename-dest && + git rev-parse rename-dest >actual && + test_cmp expect actual && + git branch -D rename-dest +' + test_expect_success 'test tracking setup via --track' ' git config remote.local.url . && git config remote.local.fetch refs/heads/*:refs/remotes/local/* && From ef18119dec8a9c65ed545fdd60c7ae9a6bc31f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:08 +0200 Subject: [PATCH 02/21] refs API: add a version of refs_resolve_ref_unsafe() with "errno" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs.c | 36 +++++++++++++++++++++++++++--------- refs.h | 12 ++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/refs.c b/refs.c index 7f019c2377..ad56dbb012 100644 --- 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 d5099d4984..c8afde6bb5 100644 --- 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. * From 8b72fea7e91b5900c3a35891df1d8ea16d4b2bee Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sat, 16 Oct 2021 11:39:09 +0200 Subject: [PATCH 03/21] refs API: make refs_read_raw_ref() not set errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a "failure_errno" to refs_read_raw_ref(), his allows refs_werrres_ref_unsafe() to pass along its "failure_errno", as a first step before its own callers are migrated to pass it further up the chain. We are leaving out out the refs_read_special_head() in refs_read_raw_ref() for now, as noted in a subsequent commit moving it to "failure_errno" will require some special consideration. Signed-off-by: Han-Wen Nienhuys Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs.c | 24 ++++++++++++++++-------- refs/files-backend.c | 10 ++++++---- refs/packed-backend.c | 7 ++++--- refs/refs-internal.h | 6 +++--- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/refs.c b/refs.c index ad56dbb012..200c44e696 100644 --- a/refs.c +++ b/refs.c @@ -1666,17 +1666,18 @@ done: return result; } -int refs_read_raw_ref(struct ref_store *ref_store, - const char *refname, struct object_id *oid, - struct strbuf *referent, unsigned int *type) +int refs_read_raw_ref(struct ref_store *ref_store, const char *refname, + struct object_id *oid, struct strbuf *referent, + unsigned int *type, int *failure_errno) { + assert(failure_errno); if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) { return refs_read_special_head(ref_store, refname, oid, referent, type); } return ref_store->be->read_raw_ref(ref_store, refname, oid, referent, - type, &errno); + type, failure_errno); } const char *refs_werrres_ref_unsafe(struct ref_store *refs, @@ -1720,9 +1721,8 @@ const char *refs_werrres_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)) { + if (refs_read_raw_ref(refs, refname, oid, &sb_refname, + &read_flags, failure_errno)) { *flags |= read_flags; if (errno) *failure_errno = errno; @@ -2240,6 +2240,13 @@ int refs_verify_refname_available(struct ref_store *refs, strbuf_grow(&dirname, strlen(refname) + 1); for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) { + /* + * Just saying "Is a directory" when we e.g. can't + * lock some multi-level ref isn't very informative, + * the user won't be told *what* is a directory, so + * let's not use strerror() below. + */ + int ignore_errno; /* Expand dirname to the new prefix, not including the trailing slash: */ strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len); @@ -2251,7 +2258,8 @@ int refs_verify_refname_available(struct ref_store *refs, if (skip && string_list_has_string(skip, dirname.buf)) continue; - if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent, &type)) { + if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent, + &type, &ignore_errno)) { strbuf_addf(err, _("'%s' exists; cannot create '%s'"), dirname.buf, refname); goto cleanup; diff --git a/refs/files-backend.c b/refs/files-backend.c index 6a6ead0b99..94c194665e 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -381,10 +381,11 @@ stat_ref: goto out; if (lstat(path, &st) < 0) { + int ignore_errno; if (errno != ENOENT) goto out; - if (refs_read_raw_ref(refs->packed_ref_store, refname, - oid, referent, type)) { + if (refs_read_raw_ref(refs->packed_ref_store, refname, oid, + referent, type, &ignore_errno)) { errno = ENOENT; goto out; } @@ -418,13 +419,14 @@ stat_ref: /* Is it a directory? */ if (S_ISDIR(st.st_mode)) { + int ignore_errno; /* * Even though there is a directory where the loose * ref is supposed to be, there could still be a * packed ref: */ - if (refs_read_raw_ref(refs->packed_ref_store, refname, - oid, referent, type)) { + if (refs_read_raw_ref(refs->packed_ref_store, refname, oid, + referent, type, &ignore_errno)) { errno = EISDIR; goto out; } diff --git a/refs/packed-backend.c b/refs/packed-backend.c index 47247a1491..52cdc94a26 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -1347,6 +1347,7 @@ int is_packed_transaction_needed(struct ref_store *ref_store, ret = 0; for (i = 0; i < transaction->nr; i++) { struct ref_update *update = transaction->updates[i]; + int failure_errno; unsigned int type; struct object_id oid; @@ -1357,9 +1358,9 @@ int is_packed_transaction_needed(struct ref_store *ref_store, */ continue; - if (!refs_read_raw_ref(ref_store, update->refname, - &oid, &referent, &type) || - errno != ENOENT) { + if (!refs_read_raw_ref(ref_store, update->refname, &oid, + &referent, &type, &failure_errno) || + failure_errno != ENOENT) { /* * We have to actually delete that reference * -> this transaction is needed. diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 72746407fc..c87f1135e5 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -149,9 +149,9 @@ struct ref_update { const char refname[FLEX_ARRAY]; }; -int refs_read_raw_ref(struct ref_store *ref_store, - const char *refname, struct object_id *oid, - struct strbuf *referent, unsigned int *type); +int refs_read_raw_ref(struct ref_store *ref_store, const char *refname, + struct object_id *oid, struct strbuf *referent, + unsigned int *type, int *failure_errno); /* * Write an error to `err` and return a nonzero value iff the same From df3458e95710b14bff1e5acb830ad77b2a4b0c73 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sat, 16 Oct 2021 11:39:10 +0200 Subject: [PATCH 04/21] refs API: make parse_loose_ref_contents() not set errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the parse_loose_ref_contents() function to stop setting "errno" and failure, and to instead pass up a "failure_errno" via a parameter. This requires changing its callers to do the same. The EINVAL error from parse_loose_ref_contents is used in files-backend to create a custom error message. In untangling this we discovered a tricky edge case. The refs_read_special_head() function was relying on parse_loose_ref_contents() setting EINVAL. By converting it to use "saved_errno" we can migrate away from "errno" in this part of the code entirely, and do away with an existing "save_errno" pattern, its only purpose was to not clobber the "errno" we previously needed at the end of files_read_raw_ref(). Let's assert that we can do that by not having files_read_raw_ref() itself operate on *failure_errno in addition to passing it on. Instead we'll assert that if we return non-zero we actually do set errno, thus assuring ourselves and callers that they can trust the resulting "failure_errno". Signed-off-by: Han-Wen Nienhuys Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs.c | 8 +++++--- refs/files-backend.c | 31 ++++++++++++++++++++----------- refs/refs-internal.h | 6 ++++-- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/refs.c b/refs.c index 200c44e696..bb09993c2f 100644 --- a/refs.c +++ b/refs.c @@ -1648,7 +1648,8 @@ int for_each_fullref_in_prefixes(const char *namespace, static int refs_read_special_head(struct ref_store *ref_store, const char *refname, struct object_id *oid, - struct strbuf *referent, unsigned int *type) + struct strbuf *referent, unsigned int *type, + int *failure_errno) { struct strbuf full_path = STRBUF_INIT; struct strbuf content = STRBUF_INIT; @@ -1658,7 +1659,8 @@ static int refs_read_special_head(struct ref_store *ref_store, if (strbuf_read_file(&content, full_path.buf, 0) < 0) goto done; - result = parse_loose_ref_contents(content.buf, oid, referent, type); + result = parse_loose_ref_contents(content.buf, oid, referent, type, + failure_errno); done: strbuf_release(&full_path); @@ -1673,7 +1675,7 @@ int refs_read_raw_ref(struct ref_store *ref_store, const char *refname, assert(failure_errno); if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) { return refs_read_special_head(ref_store, refname, oid, referent, - type); + type, failure_errno); } return ref_store->be->read_raw_ref(ref_store, refname, oid, referent, diff --git a/refs/files-backend.c b/refs/files-backend.c index 94c194665e..c73ffd1ca3 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -355,6 +355,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname, int fd; int ret = -1; int remaining_retries = 3; + int myerr = 0; *type = 0; strbuf_reset(&sb_path); @@ -382,11 +383,13 @@ stat_ref: if (lstat(path, &st) < 0) { int ignore_errno; - if (errno != ENOENT) + myerr = errno; + errno = 0; + if (myerr != ENOENT) goto out; if (refs_read_raw_ref(refs->packed_ref_store, refname, oid, referent, type, &ignore_errno)) { - errno = ENOENT; + myerr = ENOENT; goto out; } ret = 0; @@ -397,7 +400,9 @@ stat_ref: if (S_ISLNK(st.st_mode)) { strbuf_reset(&sb_contents); if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) { - if (errno == ENOENT || errno == EINVAL) + myerr = errno; + errno = 0; + if (myerr == ENOENT || myerr == EINVAL) /* inconsistent with lstat; retry */ goto stat_ref; else @@ -427,7 +432,7 @@ stat_ref: */ if (refs_read_raw_ref(refs->packed_ref_store, refname, oid, referent, type, &ignore_errno)) { - errno = EISDIR; + myerr = EISDIR; goto out; } ret = 0; @@ -440,7 +445,8 @@ stat_ref: */ fd = open(path, O_RDONLY); if (fd < 0) { - if (errno == ENOENT && !S_ISLNK(st.st_mode)) + myerr = errno; + if (myerr == ENOENT && !S_ISLNK(st.st_mode)) /* inconsistent with lstat; retry */ goto stat_ref; else @@ -448,26 +454,29 @@ stat_ref: } strbuf_reset(&sb_contents); if (strbuf_read(&sb_contents, fd, 256) < 0) { - int save_errno = errno; + myerr = errno; close(fd); - errno = save_errno; goto out; } close(fd); strbuf_rtrim(&sb_contents); buf = sb_contents.buf; - ret = parse_loose_ref_contents(buf, oid, referent, type); + ret = parse_loose_ref_contents(buf, oid, referent, type, &myerr); out: - *failure_errno = errno; + if (ret && !myerr) + BUG("returning non-zero %d, should have set myerr!", ret); + *failure_errno = myerr; + strbuf_release(&sb_path); strbuf_release(&sb_contents); return ret; } int parse_loose_ref_contents(const char *buf, struct object_id *oid, - struct strbuf *referent, unsigned int *type) + struct strbuf *referent, unsigned int *type, + int *failure_errno) { const char *p; if (skip_prefix(buf, "ref:", &buf)) { @@ -486,7 +495,7 @@ int parse_loose_ref_contents(const char *buf, struct object_id *oid, if (parse_oid_hex(buf, oid, &p) || (*p != '\0' && !isspace(*p))) { *type |= REF_ISBROKEN; - errno = EINVAL; + *failure_errno = EINVAL; return -1; } return 0; diff --git a/refs/refs-internal.h b/refs/refs-internal.h index c87f1135e5..121b8fdad0 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -706,10 +706,12 @@ struct ref_store { }; /* - * Parse contents of a loose ref file. + * Parse contents of a loose ref file. *failure_errno maybe be set to EINVAL for + * invalid contents. */ int parse_loose_ref_contents(const char *buf, struct object_id *oid, - struct strbuf *referent, unsigned int *type); + struct strbuf *referent, unsigned int *type, + int *failure_errno); /* * Fill in the generic part of refs and add it to our collection of From c339ff690f5b5a9f27e27f4cb4d22023a0b7ebaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:11 +0200 Subject: [PATCH 05/21] refs API: make refs_rename_ref_available() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the refs_rename_ref_available() function into "refs/files-backend.c". It is file-backend specific. This function was added in 5fe7d825da8 (refs.c: pass a list of names to skip to is_refname_available, 2014-05-01) as rename_ref_available() and was only ever used in this one file-backend specific codepath. So let's move it there. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs.c | 19 ------------------- refs/files-backend.c | 29 +++++++++++++++++++++++++++++ refs/refs-internal.h | 14 -------------- 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/refs.c b/refs.c index bb09993c2f..44ddbb14f1 100644 --- a/refs.c +++ b/refs.c @@ -1372,25 +1372,6 @@ const char *find_descendant_ref(const char *dirname, return NULL; } -int refs_rename_ref_available(struct ref_store *refs, - const char *old_refname, - const char *new_refname) -{ - struct string_list skip = STRING_LIST_INIT_NODUP; - struct strbuf err = STRBUF_INIT; - int ok; - - string_list_insert(&skip, old_refname); - ok = !refs_verify_refname_available(refs, new_refname, - NULL, &skip, &err); - if (!ok) - error("%s", err.buf); - - string_list_clear(&skip, 0); - strbuf_release(&err); - return ok; -} - int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) { struct object_id oid; diff --git a/refs/files-backend.c b/refs/files-backend.c index c73ffd1ca3..0af6ee4455 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1363,6 +1363,35 @@ static int commit_ref_update(struct files_ref_store *refs, const struct object_id *oid, const char *logmsg, struct strbuf *err); +/* + * Check whether an attempt to rename old_refname to new_refname would + * cause a D/F conflict with any existing reference (other than + * possibly old_refname). If there would be a conflict, emit an error + * message and return false; otherwise, return true. + * + * Note that this function is not safe against all races with other + * processes (though rename_ref() catches some races that might get by + * this check). + */ +static int refs_rename_ref_available(struct ref_store *refs, + const char *old_refname, + const char *new_refname) +{ + struct string_list skip = STRING_LIST_INIT_NODUP; + struct strbuf err = STRBUF_INIT; + int ok; + + string_list_insert(&skip, old_refname); + ok = !refs_verify_refname_available(refs, new_refname, + NULL, &skip, &err); + if (!ok) + error("%s", err.buf); + + string_list_clear(&skip, 0); + strbuf_release(&err); + return ok; +} + static int files_copy_or_rename_ref(struct ref_store *ref_store, const char *oldrefname, const char *newrefname, const char *logmsg, int copy) diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 121b8fdad0..2ecd3dea9f 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -228,20 +228,6 @@ const char *find_descendant_ref(const char *dirname, const struct string_list *extras, const struct string_list *skip); -/* - * Check whether an attempt to rename old_refname to new_refname would - * cause a D/F conflict with any existing reference (other than - * possibly old_refname). If there would be a conflict, emit an error - * message and return false; otherwise, return true. - * - * Note that this function is not safe against all races with other - * processes (though rename_ref() catches some races that might get by - * this check). - */ -int refs_rename_ref_available(struct ref_store *refs, - const char *old_refname, - const char *new_refname); - /* We allow "recursive" symbolic refs. Only within reason, though */ #define SYMREF_MAXDEPTH 5 From 5ac15ad2509f31555cbb40fece720066c5d8a01b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:12 +0200 Subject: [PATCH 06/21] reflog tests: add --updateref tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add tests that cover blindspots in "git reflog delete --updateref" behavior. Before this change removing the "type & REF_ISSYMREF" check added in 5e6f003ca8a (reflog_expire(): ignore --updateref for symbolic references, 2015-03-03) would not fail any tests. The "--updateref" option was added in 55f10565371 (git-reflog: add option --updateref to write the last reflog sha1 into the ref, 2008-02-22) for use in git-stash.sh, see e25d5f9c82e (git-stash: add new 'drop' subcommand, 2008-02-22). Even though the regression test I need is just the "C" case here, let's test all these combinations for good measure. I started out doing these as a for-loop, but I think this is more readable. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- t/t1417-reflog-updateref.sh | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100755 t/t1417-reflog-updateref.sh diff --git a/t/t1417-reflog-updateref.sh b/t/t1417-reflog-updateref.sh new file mode 100755 index 0000000000..14f13b57c6 --- /dev/null +++ b/t/t1417-reflog-updateref.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +test_description='git reflog --updateref' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +test_expect_success 'setup' ' + git init -b main repo && + ( + cd repo && + + test_commit A && + test_commit B && + test_commit C && + + cp .git/logs/HEAD HEAD.old && + git reset --hard HEAD~ && + cp HEAD.old .git/logs/HEAD + ) +' + +test_reflog_updateref () { + exp=$1 + shift + args="$@" + + test_expect_success REFFILES "get '$exp' with '$args'" ' + test_when_finished "rm -rf copy" && + cp -R repo copy && + + ( + cd copy && + + $args && + git rev-parse $exp >expect && + git rev-parse HEAD >actual && + + test_cmp expect actual + ) + ' +} + +test_reflog_updateref B git reflog delete --updateref HEAD@{0} +test_reflog_updateref B git reflog delete --updateref HEAD@{1} +test_reflog_updateref C git reflog delete --updateref main@{0} +test_reflog_updateref B git reflog delete --updateref main@{1} +test_reflog_updateref B git reflog delete --updateref --rewrite HEAD@{0} +test_reflog_updateref B git reflog delete --updateref --rewrite HEAD@{1} +test_reflog_updateref C git reflog delete --updateref --rewrite main@{0} +test_reflog_updateref B git reflog delete --updateref --rewrite main@{1} +test_reflog_updateref B test_must_fail git reflog expire HEAD@{0} +test_reflog_updateref B test_must_fail git reflog expire HEAD@{1} +test_reflog_updateref B test_must_fail git reflog expire main@{0} +test_reflog_updateref B test_must_fail git reflog expire main@{1} +test_reflog_updateref B test_must_fail git reflog expire --updateref HEAD@{0} +test_reflog_updateref B test_must_fail git reflog expire --updateref HEAD@{1} +test_reflog_updateref B test_must_fail git reflog expire --updateref main@{0} +test_reflog_updateref B test_must_fail git reflog expire --updateref main@{1} +test_reflog_updateref B test_must_fail git reflog expire --updateref --rewrite HEAD@{0} +test_reflog_updateref B test_must_fail git reflog expire --updateref --rewrite HEAD@{1} +test_reflog_updateref B test_must_fail git reflog expire --updateref --rewrite main@{0} +test_reflog_updateref B test_must_fail git reflog expire --updateref --rewrite main@{1} + +test_done From 52106430dc80ea20ec2e00a6079a7bc114d36b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:13 +0200 Subject: [PATCH 07/21] refs/files: remove "name exist?" check in lock_ref_oid_basic() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In lock_ref_oid_basic() we'll happily lock a reference that doesn't exist yet. That's normal, and is how references are initially born, but we don't need to retain checks here in lock_ref_oid_basic() about the state of the ref, when what we're checking is either checked already, or something we're about to discover by trying to lock the ref with raceproof_create_file(). The one exception is the caller in files_reflog_expire(), who passes us a "type" to find out if the reference is a symref or not. We can move the that logic over to that caller, which can now defer its discovery of whether or not the ref is a symref until it's needed. In the preceding commit an exhaustive regression test was added for that case in a new test in "t1417-reflog-updateref.sh". The improved diagnostics here were added in 5b2d8d6f218 (lock_ref_sha1_basic(): improve diagnostics for ref D/F conflicts, 2015-05-11), and then much of the surrounding code went away recently in my 245fbba46d6 (refs/files: remove unused "errno == EISDIR" code, 2021-08-23). The refs_resolve_ref_unsafe() code being removed here looks like it should be tasked with doing that, but it's actually redundant to other code. The reason for that is as noted in 245fbba46d6 this once widely used function now only has a handful of callers left, which all handle this case themselves. To the extent that we're racy between their check and ours removing this check actually improves the situation, as we'll be doing fewer things between the not-under-lock initial check and acquiring the lock. Why this is OK for all the remaining callers of lock_ref_oid_basic() is noted below. There are only two of those callers: * "git branch -[cm] ": In files_copy_or_rename_ref() we'll call this when we copy or rename refs via rename_ref() and copy_ref(). but only after we've checked if the refname exists already via its own call to refs_resolve_ref_unsafe() and refs_rename_ref_available(). As the updated comment to the latter here notes neither of those are actually needed. If we delete not only this code but also refs_rename_ref_available() we'll do just fine, we'll just emit a less friendly error message if e.g. "git branch -m A B/C" would have a D/F conflict with a "B" file. Actually we'd probably die before that in case reflogs for the branch existed, i.e. when the try to rename() or copy_file() the relevant reflog, since if we've got a D/F conflict with a branch name we'll probably also have the same with its reflogs (but not necessarily, we might have reflogs, but it might not). As some #leftoverbits that code seems buggy to me, i.e. the reflog "protocol" should be to get a lock on the main ref, and then perform ref and/or reflog operations. That code dates back to c976d415e53 (git-branch: add options and tests for branch renaming, 2006-11-28) and probably pre-dated the solidifying of that convention. But in any case, that edge case is not our bug or problem right now. * "git reflog expire ": In files_reflog_expire() we'll call this without previous ref existence checking in files-backend.c, but that code is in turn called by code that's just finished checking if the refname whose reflog we're expiring exists. See ae35e16cd43 (reflog expire: don't lock reflogs using previously seen OID, 2021-08-23) for the current state of that code, and 5e6f003ca8a (reflog_expire(): ignore --updateref for symbolic references, 2015-03-03) for the code we'd break if we only did a "update = !!ref" here, which is covered by the aforementioned regression test in "t1417-reflog-updateref.sh". Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs/files-backend.c | 48 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/refs/files-backend.c b/refs/files-backend.c index 0af6ee4455..16e7832638 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1001,7 +1001,7 @@ static int create_reflock(const char *path, void *cb) * Locks a ref returning the lock on success and NULL on failure. */ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, - const char *refname, int *type, + const char *refname, struct strbuf *err) { struct strbuf ref_file = STRBUF_INIT; @@ -1013,16 +1013,6 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, CALLOC_ARRAY(lock, 1); files_ref_path(refs, &ref_file, refname); - if (!refs_resolve_ref_unsafe(&refs->base, refname, - RESOLVE_REF_NO_RECURSE, - &lock->old_oid, type)) { - if (!refs_verify_refname_available(&refs->base, refname, - NULL, NULL, err)) - strbuf_addf(err, "unable to resolve reference '%s': %s", - refname, strerror(errno)); - - goto error_return; - } /* * If the ref did not exist and we are creating it, make sure @@ -1364,14 +1354,14 @@ static int commit_ref_update(struct files_ref_store *refs, struct strbuf *err); /* - * Check whether an attempt to rename old_refname to new_refname would - * cause a D/F conflict with any existing reference (other than - * possibly old_refname). If there would be a conflict, emit an error + * Emit a better error message than lockfile.c's + * unable_to_lock_message() would in case there is a D/F conflict with + * another existing reference. If there would be a conflict, emit an error * message and return false; otherwise, return true. * * Note that this function is not safe against all races with other - * processes (though rename_ref() catches some races that might get by - * this check). + * processes, and that's not its job. We'll emit a more verbose error on D/f + * conflicts if we get past it into lock_ref_oid_basic(). */ static int refs_rename_ref_available(struct ref_store *refs, const char *old_refname, @@ -1492,7 +1482,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, logmoved = log; - lock = lock_ref_oid_basic(refs, newrefname, NULL, &err); + lock = lock_ref_oid_basic(refs, newrefname, &err); if (!lock) { if (copy) error("unable to copy '%s' to '%s': %s", oldrefname, newrefname, err.buf); @@ -1514,7 +1504,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, goto out; rollback: - lock = lock_ref_oid_basic(refs, oldrefname, NULL, &err); + lock = lock_ref_oid_basic(refs, oldrefname, &err); if (!lock) { error("unable to lock %s for rollback: %s", oldrefname, err.buf); strbuf_release(&err); @@ -1921,7 +1911,7 @@ static int files_create_symref(struct ref_store *ref_store, struct ref_lock *lock; int ret; - lock = lock_ref_oid_basic(refs, refname, NULL, &err); + lock = lock_ref_oid_basic(refs, refname, &err); if (!lock) { error("%s", err.buf); strbuf_release(&err); @@ -3125,7 +3115,6 @@ static int files_reflog_expire(struct ref_store *ref_store, struct strbuf log_file_sb = STRBUF_INIT; char *log_file; int status = 0; - int type; struct strbuf err = STRBUF_INIT; const struct object_id *oid; @@ -3139,7 +3128,7 @@ static int files_reflog_expire(struct ref_store *ref_store, * reference itself, plus we might need to update the * reference if --updateref was specified: */ - lock = lock_ref_oid_basic(refs, refname, &type, &err); + lock = lock_ref_oid_basic(refs, refname, &err); if (!lock) { error("cannot lock ref '%s': %s", refname, err.buf); strbuf_release(&err); @@ -3201,9 +3190,20 @@ static int files_reflog_expire(struct ref_store *ref_store, * a reference if there are no remaining reflog * entries. */ - int update = (flags & EXPIRE_REFLOGS_UPDATE_REF) && - !(type & REF_ISSYMREF) && - !is_null_oid(&cb.last_kept_oid); + int update = 0; + + if ((flags & EXPIRE_REFLOGS_UPDATE_REF) && + !is_null_oid(&cb.last_kept_oid)) { + int ignore_errno; + int type; + const char *ref; + + ref = refs_werrres_ref_unsafe(&refs->base, refname, + RESOLVE_REF_NO_RECURSE, + NULL, &type, + &ignore_errno); + update = !!(ref && !(type & REF_ISSYMREF)); + } if (close_lock_file_gently(&reflog_lock)) { status |= error("couldn't write %s: %s", log_file, From 76887df01440018e1e757761fea81a4d3a676f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:14 +0200 Subject: [PATCH 08/21] refs API: remove refs_read_ref_full() wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the refs_read_ref_full() wrapper in favor of migrating various refs.c API users to the underlying refs_werrres_ref_unsafe() function. A careful reading of these callers shows that the callers of this function did not care about "errno", by moving away from the refs_resolve_ref_unsafe() wrapper we can be sure that nothing relies on it anymore. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs.c | 22 ++++++++++------------ refs.h | 2 -- refs/files-backend.c | 36 ++++++++++++++++++++++-------------- worktree.c | 9 +++++---- 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/refs.c b/refs.c index 44ddbb14f1..80b85d244d 100644 --- a/refs.c +++ b/refs.c @@ -290,18 +290,15 @@ struct ref_filter { void *cb_data; }; -int refs_read_ref_full(struct ref_store *refs, const char *refname, - int resolve_flags, struct object_id *oid, int *flags) -{ - if (refs_resolve_ref_unsafe(refs, refname, resolve_flags, oid, flags)) - return 0; - return -1; -} - int read_ref_full(const char *refname, int resolve_flags, struct object_id *oid, int *flags) { - return refs_read_ref_full(get_main_ref_store(the_repository), refname, - resolve_flags, oid, flags); + int ignore_errno; + struct ref_store *refs = get_main_ref_store(the_repository); + + if (refs_werrres_ref_unsafe(refs, refname, resolve_flags, + oid, flags, &ignore_errno)) + return 0; + return -1; } int read_ref(const char *refname, struct object_id *oid) @@ -1376,9 +1373,10 @@ 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_read_ref_full(refs, "HEAD", RESOLVE_REF_READING, - &oid, &flag)) + if (refs_werrres_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING, + &oid, &flag, &ignore_errno)) return fn("HEAD", &oid, flag, cb_data); return 0; diff --git a/refs.h b/refs.h index c8afde6bb5..3938f99c90 100644 --- a/refs.h +++ b/refs.h @@ -89,8 +89,6 @@ char *refs_resolve_refdup(struct ref_store *refs, char *resolve_refdup(const char *refname, int resolve_flags, struct object_id *oid, int *flags); -int refs_read_ref_full(struct ref_store *refs, const char *refname, - int resolve_flags, struct object_id *oid, int *flags); int read_ref_full(const char *refname, int resolve_flags, struct object_id *oid, int *flags); int read_ref(const char *refname, struct object_id *oid); diff --git a/refs/files-backend.c b/refs/files-backend.c index 16e7832638..482d04de03 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1006,6 +1006,7 @@ 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); @@ -1032,9 +1033,8 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, goto error_return; } - if (refs_read_ref_full(&refs->base, lock->ref_name, - 0, - &lock->old_oid, NULL)) + if (!refs_werrres_ref_unsafe(&refs->base, lock->ref_name, 0, + &lock->old_oid, NULL, &ignore_errno)) oidclr(&lock->old_oid); goto out; @@ -1397,6 +1397,7 @@ 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); @@ -1454,9 +1455,9 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, * the safety anyway; we want to delete the reference whatever * its current value. */ - if (!copy && !refs_read_ref_full(&refs->base, newrefname, - RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, - NULL, NULL) && + if (!copy && refs_werrres_ref_unsafe(&refs->base, newrefname, + RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, + NULL, NULL, &ignore_errno) && refs_delete_ref(&refs->base, NULL, newrefname, NULL, REF_NO_DEREF)) { if (errno == EISDIR) { @@ -1868,9 +1869,12 @@ 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_read_ref_full(&refs->base, target, - RESOLVE_REF_READING, &new_oid, NULL) && + refs_werrres_ref_unsafe(&refs->base, target, + RESOLVE_REF_READING, &new_oid, NULL, + &ignore_errno) && files_log_ref_write(refs, refname, &lock->old_oid, &new_oid, logmsg, 0, &err)) { error("%s", err.buf); @@ -2144,6 +2148,7 @@ 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; @@ -2155,9 +2160,10 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator) if (ends_with(diter->basename, ".lock")) continue; - if (refs_read_ref_full(iter->ref_store, - diter->relative_path, 0, - &iter->oid, &flags)) { + if (!refs_werrres_ref_unsafe(iter->ref_store, + diter->relative_path, 0, + &iter->oid, &flags, + &ignore_errno)) { error("bad ref for %s", diter->path.buf); continue; } @@ -2501,9 +2507,11 @@ 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: */ - if (refs_read_ref_full(&refs->base, - referent.buf, 0, - &lock->old_oid, NULL)) { + int ignore_errno; + if (!refs_werrres_ref_unsafe(&refs->base, + referent.buf, 0, + &lock->old_oid, NULL, + &ignore_errno)) { if (update->flags & REF_HAVE_OLD) { strbuf_addf(err, "cannot lock ref '%s': " "error reading reference", diff --git a/worktree.c b/worktree.c index 092a4f92ad..cfffcdb62b 100644 --- a/worktree.c +++ b/worktree.c @@ -563,16 +563,17 @@ 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; strbuf_reset(&refname); strbuf_worktree_ref(wt, &refname, "HEAD"); - if (!refs_read_ref_full(get_main_ref_store(the_repository), - refname.buf, - RESOLVE_REF_READING, - &oid, &flag)) + if (refs_werrres_ref_unsafe(get_main_ref_store(the_repository), + refname.buf, + RESOLVE_REF_READING, + &oid, &flag, &ignore_errno)) ret = fn(refname.buf, &oid, flag, cb_data); if (ret) break; From db7a3d25d639ba816fb85af3ca08d689702ab294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:15 +0200 Subject: [PATCH 09/21] refs API: make resolve_gitlink_ref() not set errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I have carefully read the upstream callers of resolve_gitlink_ref() and determined that they don't care about errno. So let's move away from the errno-setting refs_resolve_ref_unsafe() wrapper to refs_werrres_ref_unsafe(), and explicitly ignore the errno it sets for us. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/refs.c b/refs.c index 80b85d244d..dc6ed56149 100644 --- a/refs.c +++ b/refs.c @@ -1791,14 +1791,15 @@ 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) || - is_null_oid(oid)) + if (!refs_werrres_ref_unsafe(refs, refname, 0, oid, &flags, + &ignore_errno) || is_null_oid(oid)) return -1; return 0; } From 096a7fbb97dc4015c97b1811aab4e08e2f0ac724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:16 +0200 Subject: [PATCH 10/21] refs API: make loose_fill_ref_dir() not set errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the refs_resolve_ref_unsafe() invoked in loose_fill_ref_dir() to a form that ignores errno. The only eventual caller of this function is create_ref_cache(), whose callers in turn don't have their failure depend on any errno set here. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs/files-backend.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/refs/files-backend.c b/refs/files-backend.c index 482d04de03..759c21e88a 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -280,10 +280,11 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, create_dir_entry(dir->cache, refname.buf, refname.len)); } else { - if (!refs_resolve_ref_unsafe(&refs->base, + int ignore_errno; + if (!refs_werrres_ref_unsafe(&refs->base, refname.buf, RESOLVE_REF_READING, - &oid, &flag)) { + &oid, &flag, &ignore_errno)) { oidclr(&oid); flag |= REF_ISBROKEN; } else if (is_null_oid(&oid)) { From ac0986e302b9a94fd927e8d0a811fe6dc4d4c074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:17 +0200 Subject: [PATCH 11/21] refs API: make files_copy_or_rename_ref() et al not set errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit None of the callers of rename_ref() and copy_ref() care about errno, and as seen in the context here we already emit our own non-errno using error() in the case where we'd use it. So let's have it explicitly ignore errno, and do the same in commit_ref_update(), which is only used within other code in files_copy_or_rename_ref() itself which doesn't care about errno either. It might actually be sensible to have the callers use errno if the failure was filesystem-specific, and with the upcoming reftable backend we don't want to rely on that sort of thing, so let's keep ignoring that for now. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs/files-backend.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/refs/files-backend.c b/refs/files-backend.c index 759c21e88a..6c854dda53 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1410,9 +1410,9 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, goto out; } - if (!refs_resolve_ref_unsafe(&refs->base, oldrefname, + if (!refs_werrres_ref_unsafe(&refs->base, oldrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, - &orig_oid, &flag)) { + &orig_oid, &flag, &ignore_errno)) { ret = error("refname %s not found", oldrefname); goto out; } @@ -1823,10 +1823,12 @@ 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", + head_ref = refs_werrres_ref_unsafe(&refs->base, "HEAD", RESOLVE_REF_READING, - NULL, &head_flag); + NULL, &head_flag, + &ignore_errno); if (head_ref && (head_flag & REF_ISSYMREF) && !strcmp(head_ref, lock->ref_name)) { struct strbuf log_err = STRBUF_INIT; From ccf3cc1b189f732cb1e99b08bda37e92a896047f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:18 +0200 Subject: [PATCH 12/21] refs API: ignore errno in worktree.c's add_head_info() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The static add_head_info() function is only used indirectly by callers of get_worktrees(), none of whom care about errno, and even if they did having the faked-up one from refs_resolve_ref_unsafe() would only confuse them if they used die_errno() et al. So let's explicitly ignore it here. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- worktree.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/worktree.c b/worktree.c index cfffcdb62b..fa988ee978 100644 --- a/worktree.c +++ b/worktree.c @@ -28,11 +28,13 @@ 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), + target = refs_werrres_ref_unsafe(get_worktree_ref_store(wt), "HEAD", 0, - &wt->head_oid, &flags); + &wt->head_oid, &flags, + &ignore_errno); if (!target) return; From 0506eb71f7b64dac71ae35fafa7ca23c7a41e276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:19 +0200 Subject: [PATCH 13/21] refs API: ignore errno in worktree.c's find_shared_symref() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are only handful of callers of find_shared_symref(), none of whom care about errno, so let's migrate to the non-errno-propagating version of refs_resolve_ref_unsafe() and explicitly ignore errno here. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- worktree.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/worktree.c b/worktree.c index fa988ee978..7d7cf05815 100644 --- a/worktree.c +++ b/worktree.c @@ -420,6 +420,7 @@ 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; @@ -436,8 +437,9 @@ 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); + symref_target = refs_werrres_ref_unsafe(refs, symref, 0, + NULL, &flags, + &ignore_errno); if ((flags & REF_ISSYMREF) && symref_target && !strcmp(symref_target, target)) { existing = wt; From 6846f7248d2915e534eebf1457600b83573f981d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:20 +0200 Subject: [PATCH 14/21] refs tests: ignore ignore errno in test-ref-store helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cmd_resolve_ref() function has always ignored errno on failure, but let's do so explicitly when using the refs_resolve_ref_unsafe() function. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- t/helper/test-ref-store.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index b314b81a45..2f91fb9b22 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -123,9 +123,10 @@ 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); + ref = refs_werrres_ref_unsafe(refs, refname, resolve_flags, + &oid, &flags, &ignore_errno); printf("%s %s 0x%x\n", oid_to_hex(&oid), ref ? ref : "(null)", flags); return ref ? 0 : 1; } From f65bb9fb06f969e8fb89de2d6dc9218f13cb361c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:21 +0200 Subject: [PATCH 15/21] refs API: make refs_resolve_refdup() not set errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move refs_resolve_refdup() from the legacy refs_resolve_ref_unsafe() to the new refs_werrres_ref_unsafe(). I have read its callers and determined that they don't care about errno being set. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/refs.c b/refs.c index dc6ed56149..09452b5e41 100644 --- a/refs.c +++ b/refs.c @@ -268,9 +268,10 @@ 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); + result = refs_werrres_ref_unsafe(refs, refname, resolve_flags, + oid, flags, &ignore_errno); return xstrdup_or_null(result); } From 1e3ccb552f3d9166009ca2bc40b27bbc0c0e2b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:22 +0200 Subject: [PATCH 16/21] refs API: make refs_ref_exists() not set errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move refs_ref_exists from the legacy refs_resolve_ref_unsafe() to the new refs_werrres_ref_unsafe(). I have read its callers and determined that they don't care about errno being set, in particular: git grep -W -w -e refs_ref_exists -e ref_exists Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/refs.c b/refs.c index 09452b5e41..8d5a76fbf2 100644 --- a/refs.c +++ b/refs.c @@ -309,7 +309,9 @@ int read_ref(const char *refname, struct object_id *oid) int refs_ref_exists(struct ref_store *refs, const char *refname) { - return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING, NULL, NULL); + int ignore_errno; + return !!refs_werrres_ref_unsafe(refs, refname, RESOLVE_REF_READING, + NULL, NULL, &ignore_errno); } int ref_exists(const char *refname) From ed90f04155df1ec757b241ae3f45889c05efae26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:23 +0200 Subject: [PATCH 17/21] refs API: make resolve_ref_unsafe() not set errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the resolve_ref_unsafe() wrapper function to use the underlying refs_werrres_ref_unsafe() directly. From a reading of the callers I determined that the only one who cared about errno was a sequencer.c caller added in e47c6cafcb5 (commit: move print_commit_summary() to libgit, 2017-11-24), I'm migrating it to using refs_werrres_ref_unsafe() directly. This adds another "set errno" instance, but in this case it's OK and idiomatic. We are setting it just before calling die_errno(). We could have some hypothetical die_errno_var(&saved_errno, ...) here, but I don't think it's worth it. The problem with errno is subtle action at distance, not this sort of thing. We already use this pattern in a couple of places in wrapper.c Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs.c | 6 ++++-- sequencer.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/refs.c b/refs.c index 8d5a76fbf2..b563729782 100644 --- a/refs.c +++ b/refs.c @@ -1785,8 +1785,10 @@ int refs_init_db(struct strbuf *err) const char *resolve_ref_unsafe(const char *refname, int resolve_flags, struct object_id *oid, int *flags) { - return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname, - resolve_flags, oid, flags); + int ignore_errno; + + return refs_werrres_ref_unsafe(get_main_ref_store(the_repository), refname, + resolve_flags, oid, flags, &ignore_errno); } int resolve_gitlink_ref(const char *submodule, const char *refname, diff --git a/sequencer.c b/sequencer.c index fac0b5162f..1223dc2d2b 100644 --- a/sequencer.c +++ b/sequencer.c @@ -1282,6 +1282,8 @@ void print_commit_summary(struct repository *r, struct pretty_print_context pctx = {0}; struct strbuf author_ident = STRBUF_INIT; struct strbuf committer_ident = STRBUF_INIT; + struct ref_store *refs; + int resolve_errno; commit = lookup_commit(r, oid); if (!commit) @@ -1331,9 +1333,13 @@ void print_commit_summary(struct repository *r, rev.diffopt.break_opt = 0; diff_setup_done(&rev.diffopt); - head = resolve_ref_unsafe("HEAD", 0, NULL, NULL); - if (!head) + refs = get_main_ref_store(the_repository); + head = refs_werrres_ref_unsafe(refs, "HEAD", 0, NULL, NULL, + &resolve_errno); + if (!head) { + errno = resolve_errno; die_errno(_("unable to resolve HEAD after creating commit")); + } if (!strcmp(head, "HEAD")) head = _("detached HEAD"); else From 6582bd31e3f3fa6cfb16fae0cd31036081c14a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:24 +0200 Subject: [PATCH 18/21] refs API: make expand_ref() & repo_dwim_log() not set errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The use of these two is rather trivial, and it's easy to see none of their callers care about errno. So let's move them from refs_resolve_ref_unsafe() to refs_resolve_ref_unsafe_with_errno(), these were the last two callers, so we can get rid of that wrapper function. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/refs.c b/refs.c index b563729782..43fe9e6d89 100644 --- a/refs.c +++ b/refs.c @@ -654,13 +654,16 @@ int expand_ref(struct repository *repo, const char *str, int len, struct object_id oid_from_ref; 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(get_main_ref_store(repo), - fullref.buf, RESOLVE_REF_READING, - this_result, &flag); + r = refs_werrres_ref_unsafe(refs, fullref.buf, + RESOLVE_REF_READING, + this_result, &flag, + &ignore_errno); if (r) { if (!refs_found++) *ref = xstrdup(r); @@ -689,12 +692,14 @@ 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, + ref = refs_werrres_ref_unsafe(refs, path.buf, RESOLVE_REF_READING, - oid ? &hash : NULL, NULL); + oid ? &hash : NULL, NULL, + &ignore_errno); if (!ref) continue; if (refs_reflog_exists(refs, path.buf)) From 4755d7dff7a27f431493926541fd6aab2e860aa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:25 +0200 Subject: [PATCH 19/21] refs API: don't expose "errno" in run_transaction_hook() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In run_transaction_hook() we've checked errno since 67541597670 (refs: implement reference transaction hook, 2020-06-19), let's reset errno afterwards to make sure nobody using refs.c directly or indirectly relies on it. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- refs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/refs.c b/refs.c index 43fe9e6d89..e90c59539b 100644 --- a/refs.c +++ b/refs.c @@ -2096,8 +2096,11 @@ static int run_transaction_hook(struct ref_transaction *transaction, update->refname); if (write_in_full(proc.in, buf.buf, buf.len) < 0) { - if (errno != EPIPE) + if (errno != EPIPE) { + /* Don't leak errno outside this API */ + errno = 0; ret = -1; + } break; } } From 25a33b33424cd6c8e2c7db0f0c4b1ba01415ce38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:26 +0200 Subject: [PATCH 20/21] refs API: post-migration API renaming [1/2] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preceding commits all callers of refs_resolve_ref_unsafe() were migrated to the transitory refs_werrres_ref_unsafe() function. As a first step in getting rid of it let's remove the old function from the public API (it went unused in a preceding commit). We then provide both a coccinelle rule to do the rename, and a macro to avoid breaking the existing callers. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- contrib/coccinelle/refs.pending.cocci | 5 +++++ refs.c | 15 +-------------- refs.h | 22 +++++++++------------- 3 files changed, 15 insertions(+), 27 deletions(-) create mode 100644 contrib/coccinelle/refs.pending.cocci diff --git a/contrib/coccinelle/refs.pending.cocci b/contrib/coccinelle/refs.pending.cocci new file mode 100644 index 0000000000..b33cb8a12a --- /dev/null +++ b/contrib/coccinelle/refs.pending.cocci @@ -0,0 +1,5 @@ +@@ +expression refs, refname, resolve_flags, oid, flags, failure_errno; +@@ +- refs_werrres_ref_unsafe(refs, refname, resolve_flags, oid, flags, failure_errno) ++ refs_resolve_ref_unsafe(refs, refname, resolve_flags, oid, flags, failure_errno) diff --git a/refs.c b/refs.c index e90c59539b..4e06745c97 100644 --- a/refs.c +++ b/refs.c @@ -1669,7 +1669,7 @@ int refs_read_raw_ref(struct ref_store *ref_store, const char *refname, type, failure_errno); } -const char *refs_werrres_ref_unsafe(struct ref_store *refs, +const char *refs_resolve_ref_unsafe(struct ref_store *refs, const char *refname, int resolve_flags, struct object_id *oid, @@ -1766,19 +1766,6 @@ const char *refs_werrres_ref_unsafe(struct ref_store *refs, 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 3938f99c90..d908a161c0 100644 --- a/refs.h +++ b/refs.h @@ -11,18 +11,6 @@ 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. * @@ -70,16 +58,24 @@ const char *refs_werrres_ref_unsafe(struct ref_store *refs, * 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 #define RESOLVE_REF_ALLOW_BAD_NAME 0x04 +#define refs_werrres_ref_unsafe(refs, refname, resolve_flags, oid, flags, failure_errno) \ + refs_resolve_ref_unsafe(refs, refname, resolve_flags, oid, flags, failure_errno) const char *refs_resolve_ref_unsafe(struct ref_store *refs, const char *refname, int resolve_flags, struct object_id *oid, - int *flags); + int *flags, int *failure_errno); + const char *resolve_ref_unsafe(const char *refname, int resolve_flags, struct object_id *oid, int *flags); From f1da24ca5eeecf8931ffc08b4c8251c689c94a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 16 Oct 2021 11:39:27 +0200 Subject: [PATCH 21/21] refs API: post-migration API renaming [2/2] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the transitory refs_werrres_ref_unsafe() function to refs_resolve_ref_unsafe(), now that all callers of the old function have learned to pass in a "failure_errno" parameter. The coccinelle semantic patch added in the preceding commit works, but I couldn't figure out how to get spatch(1) to re-flow these argument lists (and sometimes make lines way too long), so this rename was done with: perl -pi -e 's/refs_werrres_ref_unsafe/refs_resolve_ref_unsafe/g' \ $(git grep -l refs_werrres_ref_unsafe -- '*.c') But after that "make contrib/coccinelle/refs.cocci.patch" comes up empty, so the result would have been the same. Let's remove that transitory semantic patch file, we won't need to retain it for any other in-flight changes, refs_werrres_ref_unsafe() only existed within this patch series. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- contrib/coccinelle/refs.pending.cocci | 5 ----- refs.c | 16 ++++++++-------- refs.h | 2 -- refs/files-backend.c | 18 +++++++++--------- sequencer.c | 2 +- t/helper/test-ref-store.c | 2 +- worktree.c | 6 +++--- 7 files changed, 22 insertions(+), 29 deletions(-) delete mode 100644 contrib/coccinelle/refs.pending.cocci diff --git a/contrib/coccinelle/refs.pending.cocci b/contrib/coccinelle/refs.pending.cocci deleted file mode 100644 index b33cb8a12a..0000000000 --- a/contrib/coccinelle/refs.pending.cocci +++ /dev/null @@ -1,5 +0,0 @@ -@@ -expression refs, refname, resolve_flags, oid, flags, failure_errno; -@@ -- refs_werrres_ref_unsafe(refs, refname, resolve_flags, oid, flags, failure_errno) -+ refs_resolve_ref_unsafe(refs, refname, resolve_flags, oid, flags, failure_errno) diff --git a/refs.c b/refs.c index 4e06745c97..cd9b8bb114 100644 --- a/refs.c +++ b/refs.c @@ -270,7 +270,7 @@ char *refs_resolve_refdup(struct ref_store *refs, const char *result; int ignore_errno; - result = refs_werrres_ref_unsafe(refs, refname, resolve_flags, + result = refs_resolve_ref_unsafe(refs, refname, resolve_flags, oid, flags, &ignore_errno); return xstrdup_or_null(result); } @@ -296,7 +296,7 @@ int read_ref_full(const char *refname, int resolve_flags, struct object_id *oid, int ignore_errno; struct ref_store *refs = get_main_ref_store(the_repository); - if (refs_werrres_ref_unsafe(refs, refname, resolve_flags, + if (refs_resolve_ref_unsafe(refs, refname, resolve_flags, oid, flags, &ignore_errno)) return 0; return -1; @@ -310,7 +310,7 @@ 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_werrres_ref_unsafe(refs, refname, RESOLVE_REF_READING, + return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING, NULL, NULL, &ignore_errno); } @@ -660,7 +660,7 @@ int expand_ref(struct repository *repo, const char *str, int len, this_result = refs_found ? &oid_from_ref : oid; strbuf_reset(&fullref); strbuf_addf(&fullref, *p, len, str); - r = refs_werrres_ref_unsafe(refs, fullref.buf, + r = refs_resolve_ref_unsafe(refs, fullref.buf, RESOLVE_REF_READING, this_result, &flag, &ignore_errno); @@ -696,7 +696,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len, strbuf_reset(&path); strbuf_addf(&path, *p, len, str); - ref = refs_werrres_ref_unsafe(refs, path.buf, + ref = refs_resolve_ref_unsafe(refs, path.buf, RESOLVE_REF_READING, oid ? &hash : NULL, NULL, &ignore_errno); @@ -1383,7 +1383,7 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) int flag; int ignore_errno; - if (refs_werrres_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING, + if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING, &oid, &flag, &ignore_errno)) return fn("HEAD", &oid, flag, cb_data); @@ -1779,7 +1779,7 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, { int ignore_errno; - return refs_werrres_ref_unsafe(get_main_ref_store(the_repository), refname, + return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname, resolve_flags, oid, flags, &ignore_errno); } @@ -1795,7 +1795,7 @@ int resolve_gitlink_ref(const char *submodule, const char *refname, if (!refs) return -1; - if (!refs_werrres_ref_unsafe(refs, refname, 0, oid, &flags, + if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags, &ignore_errno) || is_null_oid(oid)) return -1; return 0; diff --git a/refs.h b/refs.h index d908a161c0..45c34e99e3 100644 --- a/refs.h +++ b/refs.h @@ -68,8 +68,6 @@ struct worktree; #define RESOLVE_REF_NO_RECURSE 0x02 #define RESOLVE_REF_ALLOW_BAD_NAME 0x04 -#define refs_werrres_ref_unsafe(refs, refname, resolve_flags, oid, flags, failure_errno) \ - refs_resolve_ref_unsafe(refs, refname, resolve_flags, oid, flags, failure_errno) const char *refs_resolve_ref_unsafe(struct ref_store *refs, const char *refname, int resolve_flags, diff --git a/refs/files-backend.c b/refs/files-backend.c index 6c854dda53..abb6091fcf 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -281,7 +281,7 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, refname.len)); } else { int ignore_errno; - if (!refs_werrres_ref_unsafe(&refs->base, + if (!refs_resolve_ref_unsafe(&refs->base, refname.buf, RESOLVE_REF_READING, &oid, &flag, &ignore_errno)) { @@ -1034,7 +1034,7 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, goto error_return; } - if (!refs_werrres_ref_unsafe(&refs->base, lock->ref_name, 0, + if (!refs_resolve_ref_unsafe(&refs->base, lock->ref_name, 0, &lock->old_oid, NULL, &ignore_errno)) oidclr(&lock->old_oid); goto out; @@ -1410,7 +1410,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, goto out; } - if (!refs_werrres_ref_unsafe(&refs->base, oldrefname, + if (!refs_resolve_ref_unsafe(&refs->base, oldrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, &orig_oid, &flag, &ignore_errno)) { ret = error("refname %s not found", oldrefname); @@ -1456,7 +1456,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, * the safety anyway; we want to delete the reference whatever * its current value. */ - if (!copy && refs_werrres_ref_unsafe(&refs->base, newrefname, + if (!copy && refs_resolve_ref_unsafe(&refs->base, newrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, NULL, NULL, &ignore_errno) && refs_delete_ref(&refs->base, NULL, newrefname, @@ -1825,7 +1825,7 @@ static int commit_ref_update(struct files_ref_store *refs, const char *head_ref; int ignore_errno; - head_ref = refs_werrres_ref_unsafe(&refs->base, "HEAD", + head_ref = refs_resolve_ref_unsafe(&refs->base, "HEAD", RESOLVE_REF_READING, NULL, &head_flag, &ignore_errno); @@ -1875,7 +1875,7 @@ static void update_symref_reflog(struct files_ref_store *refs, int ignore_errno; if (logmsg && - refs_werrres_ref_unsafe(&refs->base, target, + refs_resolve_ref_unsafe(&refs->base, target, RESOLVE_REF_READING, &new_oid, NULL, &ignore_errno) && files_log_ref_write(refs, refname, &lock->old_oid, @@ -2163,7 +2163,7 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator) if (ends_with(diter->basename, ".lock")) continue; - if (!refs_werrres_ref_unsafe(iter->ref_store, + if (!refs_resolve_ref_unsafe(iter->ref_store, diter->relative_path, 0, &iter->oid, &flags, &ignore_errno)) { @@ -2511,7 +2511,7 @@ static int lock_ref_for_update(struct files_ref_store *refs, * to record and possibly check old_oid: */ int ignore_errno; - if (!refs_werrres_ref_unsafe(&refs->base, + if (!refs_resolve_ref_unsafe(&refs->base, referent.buf, 0, &lock->old_oid, NULL, &ignore_errno)) { @@ -3209,7 +3209,7 @@ static int files_reflog_expire(struct ref_store *ref_store, int type; const char *ref; - ref = refs_werrres_ref_unsafe(&refs->base, refname, + ref = refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_NO_RECURSE, NULL, &type, &ignore_errno); diff --git a/sequencer.c b/sequencer.c index 1223dc2d2b..cf10f9a332 100644 --- a/sequencer.c +++ b/sequencer.c @@ -1334,7 +1334,7 @@ void print_commit_summary(struct repository *r, diff_setup_done(&rev.diffopt); refs = get_main_ref_store(the_repository); - head = refs_werrres_ref_unsafe(refs, "HEAD", 0, NULL, NULL, + head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL, &resolve_errno); if (!head) { errno = resolve_errno; diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 2f91fb9b22..3986665037 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -125,7 +125,7 @@ static int cmd_resolve_ref(struct ref_store *refs, const char **argv) const char *ref; int ignore_errno; - ref = refs_werrres_ref_unsafe(refs, refname, resolve_flags, + ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags, &oid, &flags, &ignore_errno); 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 7d7cf05815..2c155b1015 100644 --- a/worktree.c +++ b/worktree.c @@ -30,7 +30,7 @@ static void add_head_info(struct worktree *wt) const char *target; int ignore_errno; - target = refs_werrres_ref_unsafe(get_worktree_ref_store(wt), + target = refs_resolve_ref_unsafe(get_worktree_ref_store(wt), "HEAD", 0, &wt->head_oid, &flags, @@ -437,7 +437,7 @@ const struct worktree *find_shared_symref(const char *symref, } refs = get_worktree_ref_store(wt); - symref_target = refs_werrres_ref_unsafe(refs, symref, 0, + symref_target = refs_resolve_ref_unsafe(refs, symref, 0, NULL, &flags, &ignore_errno); if ((flags & REF_ISSYMREF) && @@ -574,7 +574,7 @@ int other_head_refs(each_ref_fn fn, void *cb_data) strbuf_reset(&refname); strbuf_worktree_ref(wt, &refname, "HEAD"); - if (refs_werrres_ref_unsafe(get_main_ref_store(the_repository), + if (refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname.buf, RESOLVE_REF_READING, &oid, &flag, &ignore_errno))