diff --git a/refs.c b/refs.c index 6b826b002e..8eaec5eca7 100644 --- a/refs.c +++ b/refs.c @@ -1109,6 +1109,21 @@ int read_ref_at(struct ref_store *refs, const char *refname, refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent, &cb); if (!cb.reccnt) { + if (cnt == 0) { + /* + * The caller asked for ref@{0}, and we had no entries. + * It's a bit subtle, but in practice all callers have + * prepped the "oid" field with the current value of + * the ref, which is the most reasonable fallback. + * + * We'll put dummy values into the out-parameters (so + * they're not just uninitialized garbage), and the + * caller can take our return value as a hint that + * we did not find any such reflog. + */ + set_read_ref_cutoffs(&cb, 0, 0, "empty reflog"); + return 1; + } if (flags & GET_OID_QUIETLY) exit(128); else diff --git a/refs.h b/refs.h index 303c5fac4d..37116ad2b2 100644 --- a/refs.h +++ b/refs.h @@ -440,7 +440,20 @@ int refs_create_reflog(struct ref_store *refs, const char *refname, struct strbuf *err); int safe_create_reflog(const char *refname, struct strbuf *err); -/** Reads log for the value of ref during at_time. **/ +/** + * Reads log for the value of ref during at_time (in which case "cnt" should be + * negative) or the reflog "cnt" entries from the top (in which case "at_time" + * should be 0). + * + * If we found the reflog entry in question, returns 0 (and details of the + * entry can be found in the out-parameters). + * + * If we ran out of reflog entries, the out-parameters are filled with the + * details of the oldest entry we did find, and the function returns 1. Note + * that there is one important special case here! If the reflog was empty + * and the caller asked for the 0-th cnt, we will return "1" but leave the + * "oid" field untouched. + **/ int read_ref_at(struct ref_store *refs, const char *refname, unsigned int flags, timestamp_t at_time, int cnt, diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh index 370bf7137e..e841309d0e 100755 --- a/t/t1508-at-combinations.sh +++ b/t/t1508-at-combinations.sh @@ -110,7 +110,7 @@ test_expect_success '@{1} works with only one reflog entry' ' test_cmp_rev newbranch~ newbranch@{1} ' -test_expect_failure '@{0} works with empty reflog' ' +test_expect_success '@{0} works with empty reflog' ' git checkout -B newbranch main && git reflog expire --expire=now refs/heads/newbranch && test_cmp_rev newbranch newbranch@{0} diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh index 35f35f8091..a1139f79e2 100755 --- a/t/t3202-show-branch.sh +++ b/t/t3202-show-branch.sh @@ -279,8 +279,8 @@ test_expect_success '--reflog shows reflog entries' ' test_expect_success '--reflog handles missing reflog' ' git reflog expire --expire=now branch && - test_must_fail git show-branch --reflog branch 2>err && - grep "log .* is empty" err + git show-branch --reflog branch >actual && + test_must_be_empty actual ' test_done