mirror of
https://github.com/git/git.git
synced 2024-10-28 12:59:41 +01:00
5edd126720
The previous commit special-cased get_oid_basic()'s handling of ref@{n} for a reflog with n entries. But its special case doesn't work for ref@{0} in an empty reflog, because read_ref_at() dies when it notices the empty reflog! We can make this work by special-casing this in read_ref_at(). It's somewhat gross, for two reasons: 1. We have no reflog entry to describe in the "msg" out-parameter. So we have to leave it uninitialized or make something up. 2. Likewise, we have no oid to put in the "oid" out-parameter. Leaving it untouched is actually the best thing here, as all of the callers will have initialized it with the current ref value via repo_dwim_log(). This is rather subtle, but it is how things worked in6436a20284
(refs: allow @{n} to work with n-sized reflog, 2021-01-07) before we reverted it. The key difference from6436a20284
here is that we'll return "1" to indicate that we _didn't_ find the requested reflog entry. Coupled with the special-casing in get_oid_basic() in the previous commit, that's enough to make looking up ref@{0} work, and we can flip 6436a20284's test back to expect_success. It also means that the call in show-branch which segfaulted with6436a20284
(and which is now tested in t3202) remains OK. The caller notices that we could not find any reflog entry, and so it breaks out of its loop, showing nothing. This is different from the current behavior of producing an error, but it's just as reasonable (and is exactly what we'd do if you asked it to walk starting at ref@{1} but there was only 1 entry). Thus nobody should actually look at the reflog entry info we return. But we'll still put in some fake values just to be on the safe side, since this is such a subtle and confusing interface. Likewise, we'll document what's going on in a comment above the function declaration. If this were a function with a lot of callers, the footgun would probably not be worth it. But it has only ever had two callers in its 18-year existence, and it seems unlikely to grow more. So let's hold our noses and let users enjoy the convenience of a simulated ref@{0}. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
119 lines
2.8 KiB
Bash
Executable file
119 lines
2.8 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
test_description='test various @{X} syntax combinations together'
|
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|
|
|
TEST_PASSES_SANITIZE_LEAK=true
|
|
. ./test-lib.sh
|
|
|
|
check() {
|
|
test_expect_${4:-success} "$1 = $3" "
|
|
echo '$3' >expect &&
|
|
if test '$2' = 'commit'
|
|
then
|
|
git log -1 --format=%s '$1' >actual
|
|
elif test '$2' = 'ref'
|
|
then
|
|
git rev-parse --symbolic-full-name '$1' >actual
|
|
else
|
|
git cat-file -p '$1' >actual
|
|
fi &&
|
|
test_cmp expect actual
|
|
"
|
|
}
|
|
|
|
nonsense() {
|
|
test_expect_${2:-success} "$1 is nonsensical" "
|
|
test_must_fail git rev-parse --verify '$1'
|
|
"
|
|
}
|
|
|
|
fail() {
|
|
"$@" failure
|
|
}
|
|
|
|
test_expect_success 'setup' '
|
|
test_commit main-one &&
|
|
test_commit main-two &&
|
|
git checkout -b upstream-branch &&
|
|
test_commit upstream-one &&
|
|
test_commit upstream-two &&
|
|
if test_have_prereq !MINGW
|
|
then
|
|
git checkout -b @/at-test
|
|
fi &&
|
|
git checkout -b @@/at-test &&
|
|
git checkout -b @at-test &&
|
|
git checkout -b old-branch &&
|
|
test_commit old-one &&
|
|
test_commit old-two &&
|
|
git checkout -b new-branch &&
|
|
test_commit new-one &&
|
|
test_commit new-two &&
|
|
git branch -u main old-branch &&
|
|
git branch -u upstream-branch new-branch
|
|
'
|
|
|
|
check HEAD ref refs/heads/new-branch
|
|
check "@{1}" commit new-one
|
|
check "HEAD@{1}" commit new-one
|
|
check "@{now}" commit new-two
|
|
check "HEAD@{now}" commit new-two
|
|
check "@{-1}" ref refs/heads/old-branch
|
|
check "@{-1}@{0}" commit old-two
|
|
check "@{-1}@{1}" commit old-one
|
|
check "@{u}" ref refs/heads/upstream-branch
|
|
check "HEAD@{u}" ref refs/heads/upstream-branch
|
|
check "@{u}@{1}" commit upstream-one
|
|
check "@{-1}@{u}" ref refs/heads/main
|
|
check "@{-1}@{u}@{1}" commit main-one
|
|
check "@" commit new-two
|
|
check "@@{u}" ref refs/heads/upstream-branch
|
|
check "@@/at-test" ref refs/heads/@@/at-test
|
|
test_have_prereq MINGW ||
|
|
check "@/at-test" ref refs/heads/@/at-test
|
|
check "@at-test" ref refs/heads/@at-test
|
|
nonsense "@{u}@{-1}"
|
|
nonsense "@{0}@{0}"
|
|
nonsense "@{1}@{u}"
|
|
nonsense "HEAD@{-1}"
|
|
nonsense "@{-1}@{-1}"
|
|
|
|
# @{N} versus HEAD@{N}
|
|
|
|
check "HEAD@{3}" commit old-two
|
|
nonsense "@{3}"
|
|
|
|
test_expect_success 'switch to old-branch' '
|
|
git checkout old-branch
|
|
'
|
|
|
|
check HEAD ref refs/heads/old-branch
|
|
check "HEAD@{1}" commit new-two
|
|
check "@{1}" commit old-one
|
|
|
|
test_expect_success 'create path with @' '
|
|
echo content >normal &&
|
|
echo content >fun@ny &&
|
|
git add normal fun@ny &&
|
|
git commit -m "funny path"
|
|
'
|
|
|
|
check "@:normal" blob content
|
|
check "@:fun@ny" blob content
|
|
|
|
test_expect_success '@{1} works with only one reflog entry' '
|
|
git checkout -B newbranch main &&
|
|
git reflog expire --expire=now refs/heads/newbranch &&
|
|
git commit --allow-empty -m "first after expiration" &&
|
|
test_cmp_rev newbranch~ newbranch@{1}
|
|
'
|
|
|
|
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}
|
|
'
|
|
|
|
test_done
|