Browse Source
Teaches the object name parser things like a "git describe" output is always a commit object, "A" in "git log A" must be a committish, and "A" and "B" in "git log A...B" both must be committish, etc., to prolong the lifetime of abbreviated object names. * jc/sha1-name-more: (27 commits) t1512: match the "other" object names t1512: ignore whitespaces in wc -l output rev-parse --disambiguate=<prefix> rev-parse: A and B in "rev-parse A..B" refer to committish reset: the command takes committish commit-tree: the command wants a tree and commits apply: --build-fake-ancestor expects blobs sha1_name.c: add support for disambiguating other types revision.c: the "log" family, except for "show", takes committish revision.c: allow handle_revision_arg() to take other flags sha1_name.c: introduce get_sha1_committish() sha1_name.c: teach lookup context to get_sha1_with_context() sha1_name.c: many short names can only be committish sha1_name.c: get_sha1_1() takes lookup flags sha1_name.c: get_describe_name() by definition groks only commits sha1_name.c: teach get_short_sha1() a commit-only option sha1_name.c: allow get_short_sha1() to take other flags get_sha1(): fix error status regression sha1_name.c: restructure disambiguation of short names sha1_name.c: correct misnamed "canonical" and "res" ...maint

15 changed files with 714 additions and 172 deletions
@ -0,0 +1,264 @@
@@ -0,0 +1,264 @@
|
||||
#!/bin/sh |
||||
|
||||
test_description='object name disambiguation |
||||
|
||||
Create blobs, trees, commits and a tag that all share the same |
||||
prefix, and make sure "git rev-parse" can take advantage of |
||||
type information to disambiguate short object names that are |
||||
not necessarily unique. |
||||
|
||||
The final history used in the test has five commits, with the bottom |
||||
one tagged as v1.0.0. They all have one regular file each. |
||||
|
||||
+-------------------------------------------+ |
||||
| | |
||||
| .-------b3wettvi---- ad2uee | |
||||
| / / | |
||||
| a2onsxbvj---czy8f73t--ioiley5o | |
||||
| | |
||||
+-------------------------------------------+ |
||||
|
||||
' |
||||
|
||||
. ./test-lib.sh |
||||
|
||||
test_expect_success 'blob and tree' ' |
||||
test_tick && |
||||
( |
||||
for i in 0 1 2 3 4 5 6 7 8 9 |
||||
do |
||||
echo $i |
||||
done |
||||
echo |
||||
echo b1rwzyc3 |
||||
) >a0blgqsjc && |
||||
|
||||
# create one blob 0000000000b36 |
||||
git add a0blgqsjc && |
||||
|
||||
# create one tree 0000000000cdc |
||||
git write-tree |
||||
' |
||||
|
||||
test_expect_success 'warn ambiguity when no candidate matches type hint' ' |
||||
test_must_fail git rev-parse --verify 000000000^{commit} 2>actual && |
||||
grep "short SHA1 000000000 is ambiguous" actual |
||||
' |
||||
|
||||
test_expect_success 'disambiguate tree-ish' ' |
||||
# feed tree-ish in an unambiguous way |
||||
git rev-parse --verify 0000000000cdc:a0blgqsjc && |
||||
|
||||
# ambiguous at the object name level, but there is only one |
||||
# such tree-ish (the other is a blob) |
||||
git rev-parse --verify 000000000:a0blgqsjc |
||||
' |
||||
|
||||
test_expect_success 'disambiguate blob' ' |
||||
sed -e "s/|$//" >patch <<-EOF && |
||||
diff --git a/frotz b/frotz |
||||
index 000000000..ffffff 100644 |
||||
--- a/frotz |
||||
+++ b/frotz |
||||
@@ -10,3 +10,4 @@ |
||||
9 |
||||
| |
||||
b1rwzyc3 |
||||
+irwry |
||||
EOF |
||||
( |
||||
GIT_INDEX_FILE=frotz && |
||||
export GIT_INDEX_FILE && |
||||
git apply --build-fake-ancestor frotz patch && |
||||
git cat-file blob :frotz >actual |
||||
) && |
||||
test_cmp a0blgqsjc actual |
||||
' |
||||
|
||||
test_expect_success 'disambiguate tree' ' |
||||
commit=$(echo "d7xm" | git commit-tree 000000000) && |
||||
test $(git rev-parse $commit^{tree}) = $(git rev-parse 0000000000cdc) |
||||
' |
||||
|
||||
test_expect_success 'first commit' ' |
||||
# create one commit 0000000000e4f |
||||
git commit -m a2onsxbvj |
||||
' |
||||
|
||||
test_expect_success 'disambiguate commit-ish' ' |
||||
# feed commit-ish in an unambiguous way |
||||
git rev-parse --verify 0000000000e4f^{commit} && |
||||
|
||||
# ambiguous at the object name level, but there is only one |
||||
# such commit (the others are tree and blob) |
||||
git rev-parse --verify 000000000^{commit} && |
||||
|
||||
# likewise |
||||
git rev-parse --verify 000000000^0 |
||||
' |
||||
|
||||
test_expect_success 'disambiguate commit' ' |
||||
commit=$(echo "hoaxj" | git commit-tree 0000000000cdc -p 000000000) && |
||||
test $(git rev-parse $commit^) = $(git rev-parse 0000000000e4f) |
||||
' |
||||
|
||||
test_expect_success 'log name1..name2 takes only commit-ishes on both ends' ' |
||||
git log 000000000..000000000 && |
||||
git log ..000000000 && |
||||
git log 000000000.. && |
||||
git log 000000000...000000000 && |
||||
git log ...000000000 && |
||||
git log 000000000... |
||||
' |
||||
|
||||
test_expect_success 'rev-parse name1..name2 takes only commit-ishes on both ends' ' |
||||
git rev-parse 000000000..000000000 && |
||||
git rev-parse ..000000000 && |
||||
git rev-parse 000000000.. |
||||
' |
||||
|
||||
test_expect_success 'git log takes only commit-ish' ' |
||||
git log 000000000 |
||||
' |
||||
|
||||
test_expect_success 'git reset takes only commit-ish' ' |
||||
git reset 000000000 |
||||
' |
||||
|
||||
test_expect_success 'first tag' ' |
||||
# create one tag 0000000000f8f |
||||
git tag -a -m j7cp83um v1.0.0 |
||||
' |
||||
|
||||
test_expect_failure 'two semi-ambiguous commit-ish' ' |
||||
# Once the parser becomes ultra-smart, it could notice that |
||||
# 110282 before ^{commit} name many different objects, but |
||||
# that only two (HEAD and v1.0.0 tag) can be peeled to commit, |
||||
# and that peeling them down to commit yield the same commit |
||||
# without ambiguity. |
||||
git rev-parse --verify 110282^{commit} && |
||||
|
||||
# likewise |
||||
git log 000000000..000000000 && |
||||
git log ..000000000 && |
||||
git log 000000000.. && |
||||
git log 000000000...000000000 && |
||||
git log ...000000000 && |
||||
git log 000000000... |
||||
' |
||||
|
||||
test_expect_failure 'three semi-ambiguous tree-ish' ' |
||||
# Likewise for tree-ish. HEAD, v1.0.0 and HEAD^{tree} share |
||||
# the prefix but peeling them to tree yields the same thing |
||||
git rev-parse --verify 000000000^{tree} |
||||
' |
||||
|
||||
test_expect_success 'parse describe name' ' |
||||
# feed an unambiguous describe name |
||||
git rev-parse --verify v1.0.0-0-g0000000000e4f && |
||||
|
||||
# ambiguous at the object name level, but there is only one |
||||
# such commit (others are blob, tree and tag) |
||||
git rev-parse --verify v1.0.0-0-g000000000 |
||||
' |
||||
|
||||
test_expect_success 'more history' ' |
||||
# commit 0000000000043 |
||||
git mv a0blgqsjc d12cr3h8t && |
||||
echo h62xsjeu >>d12cr3h8t && |
||||
git add d12cr3h8t && |
||||
|
||||
test_tick && |
||||
git commit -m czy8f73t && |
||||
|
||||
# commit 00000000008ec |
||||
git mv d12cr3h8t j000jmpzn && |
||||
echo j08bekfvt >>j000jmpzn && |
||||
git add j000jmpzn && |
||||
|
||||
test_tick && |
||||
git commit -m ioiley5o && |
||||
|
||||
# commit 0000000005b0 |
||||
git checkout v1.0.0^0 && |
||||
git mv a0blgqsjc f5518nwu && |
||||
|
||||
for i in h62xsjeu j08bekfvt kg7xflhm |
||||
do |
||||
echo $i |
||||
done >>f5518nwu && |
||||
git add f5518nwu && |
||||
|
||||
test_tick && |
||||
git commit -m b3wettvi && |
||||
side=$(git rev-parse HEAD) && |
||||
|
||||
# commit 000000000066 |
||||
git checkout master && |
||||
|
||||
# If you use recursive, merge will fail and you will need to |
||||
# clean up a0blgqsjc as well. If you use resolve, merge will |
||||
# succeed. |
||||
test_might_fail git merge --no-commit -s recursive $side && |
||||
git rm -f f5518nwu j000jmpzn && |
||||
|
||||
test_might_fail git rm -f a0blgqsjc && |
||||
( |
||||
git cat-file blob $side:f5518nwu |
||||
echo j3l0i9s6 |
||||
) >ab2gs879 && |
||||
git add ab2gs879 && |
||||
|
||||
test_tick && |
||||
git commit -m ad2uee |
||||
|
||||
' |
||||
|
||||
test_expect_failure 'parse describe name taking advantage of generation' ' |
||||
# ambiguous at the object name level, but there is only one |
||||
# such commit at generation 0 |
||||
git rev-parse --verify v1.0.0-0-g000000000 && |
||||
|
||||
# likewise for generation 2 and 4 |
||||
git rev-parse --verify v1.0.0-2-g000000000 && |
||||
git rev-parse --verify v1.0.0-4-g000000000 |
||||
' |
||||
|
||||
# Note: because rev-parse does not even try to disambiguate based on |
||||
# the generation number, this test currently succeeds for a wrong |
||||
# reason. When it learns to use the generation number, the previous |
||||
# test should succeed, and also this test should fail because the |
||||
# describe name used in the test with generation number can name two |
||||
# commits. Make sure that such a future enhancement does not randomly |
||||
# pick one. |
||||
test_expect_success 'parse describe name not ignoring ambiguity' ' |
||||
# ambiguous at the object name level, and there are two such |
||||
# commits at generation 1 |
||||
test_must_fail git rev-parse --verify v1.0.0-1-g000000000 |
||||
' |
||||
|
||||
test_expect_success 'ambiguous commit-ish' ' |
||||
# Now there are many commits that begin with the |
||||
# common prefix, none of these should pick one at |
||||
# random. They all should result in ambiguity errors. |
||||
test_must_fail git rev-parse --verify 110282^{commit} && |
||||
|
||||
# likewise |
||||
test_must_fail git log 000000000..000000000 && |
||||
test_must_fail git log ..000000000 && |
||||
test_must_fail git log 000000000.. && |
||||
test_must_fail git log 000000000...000000000 && |
||||
test_must_fail git log ...000000000 && |
||||
test_must_fail git log 000000000... |
||||
' |
||||
|
||||
test_expect_success 'rev-parse --disambiguate' ' |
||||
# The test creates 16 objects that share the prefix and two |
||||
# commits created by commit-tree in earlier tests share a |
||||
# different prefix. |
||||
git rev-parse --disambiguate=000000000 >actual && |
||||
test $(wc -l <actual) = 16 && |
||||
test "$(sed -e "s/^\(.........\).*/\1/" actual | sort -u)" = 000000000 |
||||
' |
||||
|
||||
test_done |
Loading…
Reference in new issue