From 6269b6b676310d9fa2560da49be618372b39acf4 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 18 Jun 2012 13:45:56 -0700 Subject: sha1_name.c: get_describe_name() by definition groks only commits Teach get_describe_name() to pass the disambiguation hint down the callchain to get_short_sha1(). Also add tests to show various syntactic elements that we could take advantage of the object type information to help disambiguration of abbreviated object names. Many of them are marked as broken, and some of them will be fixed in later patches in this series. Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 255 ++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100755 t/t1512-rev-parse-disambiguation.sh (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh new file mode 100755 index 0000000000..0d3f05b992 --- /dev/null +++ b/t/t1512-rev-parse-disambiguation.sh @@ -0,0 +1,255 @@ +#!/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_failure '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_failure '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_failure '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_failure '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_failure 'disambiguate commit' ' + commit=$(echo "j9xqh" | git commit-tree 0000000000cdc -p 000000000) && + test $(git rev-parse $commit^) = $(git rev-parse 0000000000e4f) +' + +test_expect_failure '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_failure '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_failure 'git log takes only commit-ish' ' + git log 000000000 +' + +test_expect_failure '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_done -- cgit v1.2.3 From e2643617d75e53e5a69278f8d7382553d1c14cf0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 2 Jul 2012 10:00:40 -0700 Subject: sha1_name.c: many short names can only be committish We know that the token "$name" that appear in "$name^{commit}", "$name^4", "$name~4" etc. can only name a committish (either a commit or a tag that peels to a commit). Teach get_short_sha1() to take advantage of that knowledge when disambiguating an abbreviated SHA-1 given as an object name. Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 0d3f05b992..7652f1c2e9 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -85,7 +85,7 @@ test_expect_success 'first commit' ' git commit -m a2onsxbvj ' -test_expect_failure 'disambiguate commit-ish' ' +test_expect_success 'disambiguate commit-ish' ' # feed commit-ish in an unambiguous way git rev-parse --verify 0000000000e4f^{commit} && -- cgit v1.2.3 From cd74e4733db3e2353077bdc7021caa70bed2a483 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 2 Jul 2012 12:04:52 -0700 Subject: sha1_name.c: introduce get_sha1_committish() Many callers know that the user meant to name a committish by syntactical positions where the object name appears. Calling this function allows the machinery to disambiguate shorter-than-unique abbreviated object names between committish and others. Note that this does NOT error out when the named object is not a committish. It is merely to give a hint to the disambiguation machinery. Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 7652f1c2e9..6f87d8ea9d 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -102,7 +102,7 @@ test_expect_failure 'disambiguate commit' ' test $(git rev-parse $commit^) = $(git rev-parse 0000000000e4f) ' -test_expect_failure 'log name1..name2 takes only commit-ishes on both ends' ' +test_expect_success 'log name1..name2 takes only commit-ishes on both ends' ' git log 000000000..000000000 && git log ..000000000 && git log 000000000.. && -- cgit v1.2.3 From d5f6b1d756a29255efedee3cb6e8526aedcfeb00 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 2 Jul 2012 12:43:05 -0700 Subject: revision.c: the "log" family, except for "show", takes committish Add a field to setup_revision_opt structure and allow these callers to tell the setup_revisions command parsing machinery that short SHA1 it encounters are meant to name committish. This step does not go all the way to connect the setup_revisions() to sha1_name.c yet. Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 6f87d8ea9d..da25fad924 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -117,7 +117,7 @@ test_expect_failure 'rev-parse name1..name2 takes only commit-ishes on both ends git rev-parse 000000000.. ' -test_expect_failure 'git log takes only commit-ish' ' +test_expect_success 'git log takes only commit-ish' ' git log 000000000 ' -- cgit v1.2.3 From daba53aeaf6565b4bbdd6783c659480453ec3c5e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 2 Jul 2012 23:35:05 -0700 Subject: sha1_name.c: add support for disambiguating other types This teaches the revision parser that in "$name:$path" (used for a blob object name), "$name" must be a tree-ish. There are many more places where we know what types of objects are called for. This patch adds support for "commit", "treeish", "tree", and "blob", which could be used in the following contexts: - "git apply --build-fake-ancestor" reads the "index" lines from the patch; they must name blob objects (not even "blob-ish"); - "git commit-tree" reads a tree object name (not "tree-ish"), and zero or more commit object names (not "committish"); - "git reset $rev" wants a committish; "git reset $rev -- $path" wants a treeish. They will come in later patches in the series. Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index da25fad924..fbd3658ca8 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -45,7 +45,7 @@ test_expect_success 'warn ambiguity when no candidate matches type hint' ' grep "short SHA1 000000000 is ambiguous" actual ' -test_expect_failure 'disambiguate tree-ish' ' +test_expect_success 'disambiguate tree-ish' ' # feed tree-ish in an unambiguous way git rev-parse --verify 0000000000cdc:a0blgqsjc && -- cgit v1.2.3 From da3ac0c14993c5e8e41875cc3ead32be71647a7a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 3 Jul 2012 10:01:22 -0700 Subject: apply: --build-fake-ancestor expects blobs The "index" line read from the patch to reconstruct a partial preimage tree records the object names of blob objects. Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index fbd3658ca8..84b8dddbe3 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -54,7 +54,7 @@ test_expect_success 'disambiguate tree-ish' ' git rev-parse --verify 000000000:a0blgqsjc ' -test_expect_failure 'disambiguate blob' ' +test_expect_success 'disambiguate blob' ' sed -e "s/|$//" >patch <<-EOF && diff --git a/frotz b/frotz index 000000000..ffffff 100644 -- cgit v1.2.3 From 75f5ac04a2984fcf1e4d167047bfb63c5f385d44 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 3 Jul 2012 10:03:38 -0700 Subject: commit-tree: the command wants a tree and commits Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 84b8dddbe3..dc56f81cb7 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -75,7 +75,7 @@ test_expect_success 'disambiguate blob' ' test_cmp a0blgqsjc actual ' -test_expect_failure 'disambiguate tree' ' +test_expect_success 'disambiguate tree' ' commit=$(echo "d7xm" | git commit-tree 000000000) && test $(git rev-parse $commit^{tree}) = $(git rev-parse 0000000000cdc) ' @@ -97,7 +97,7 @@ test_expect_success 'disambiguate commit-ish' ' git rev-parse --verify 000000000^0 ' -test_expect_failure 'disambiguate commit' ' +test_expect_success 'disambiguate commit' ' commit=$(echo "j9xqh" | git commit-tree 0000000000cdc -p 000000000) && test $(git rev-parse $commit^) = $(git rev-parse 0000000000e4f) ' -- cgit v1.2.3 From 13243c2c7a758bb6510ba26d0372f384b5f422ce Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 3 Jul 2012 10:04:22 -0700 Subject: reset: the command takes committish This is not strictly correct, in that resetting selected index entries from corresponding paths out of a given tree without moving HEAD is a valid operation, and in such case a tree-ish would suffice. But the existing code already requires a committish in the codepath, so let's be consistent with it for now. Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index dc56f81cb7..0210998800 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -121,7 +121,7 @@ test_expect_success 'git log takes only commit-ish' ' git log 000000000 ' -test_expect_failure 'git reset takes only commit-ish' ' +test_expect_success 'git reset takes only commit-ish' ' git reset 000000000 ' -- cgit v1.2.3 From c036c4c5e426cc7ee8070038607edf06ef1d661e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 3 Jul 2012 13:45:12 -0700 Subject: rev-parse: A and B in "rev-parse A..B" refer to committish Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 0210998800..6de3cb0c92 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -111,7 +111,7 @@ test_expect_success 'log name1..name2 takes only commit-ishes on both ends' ' git log 000000000... ' -test_expect_failure 'rev-parse name1..name2 takes only commit-ishes on both ends' ' +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.. -- cgit v1.2.3 From 957d74062c1f0e92368aeda335e27d2d61f584f6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 3 Jul 2012 14:21:59 -0700 Subject: rev-parse --disambiguate= The new option allows you to feed an ambiguous prefix and enumerate all the objects that share it as a prefix of their object names. Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 6de3cb0c92..3ed7558c1e 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -252,4 +252,13 @@ test_expect_success 'ambiguous commit-ish' ' 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 do not share + # the prefix. + git rev-parse --disambiguate=000000000 >actual && + test "$(wc -l Date: Wed, 11 Jul 2012 16:30:28 -0700 Subject: t1512: ignore whitespaces in wc -l output Some implementations of sed (e.g. MacOS X) have whitespaces in the output of "wc -l" that reads from the standard input. Ignore these whitespaces by not quoting the command substitution to be compared with the constant "16". Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 3ed7558c1e..1eb35143f8 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -257,7 +257,7 @@ test_expect_success 'rev-parse --disambiguate' ' # commits created by commit-tree in earlier tests do not share # the prefix. git rev-parse --disambiguate=000000000 >actual && - test "$(wc -l Date: Fri, 13 Jul 2012 12:43:43 -0700 Subject: t1512: match the "other" object names The test creates 16 objects that share the same prefix, and two other objects that do not. Tweak the test so that the other two share the same prefix that is different from the one that is shared by the 16. Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 't') diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 1eb35143f8..6b3d797cea 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -98,7 +98,7 @@ test_expect_success 'disambiguate commit-ish' ' ' test_expect_success 'disambiguate commit' ' - commit=$(echo "j9xqh" | git commit-tree 0000000000cdc -p 000000000) && + commit=$(echo "hoaxj" | git commit-tree 0000000000cdc -p 000000000) && test $(git rev-parse $commit^) = $(git rev-parse 0000000000e4f) ' @@ -254,8 +254,8 @@ test_expect_success 'ambiguous commit-ish' ' 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 do not share - # the prefix. + # commits created by commit-tree in earlier tests share a + # different prefix. git rev-parse --disambiguate=000000000 >actual && test $(wc -l