1#!/bin/sh 2 3test_description='object name disambiguation 4 5Create blobs, trees, commits and a tag that all share the same 6prefix, and make sure "git rev-parse" can take advantage of 7type information to disambiguate short object names that are 8not necessarily unique. 9 10The final history used in the test has five commits, with the bottom 11one tagged as v1.0.0. They all have one regular file each. 12 13 +-------------------------------------------+ 14 | | 15 | .-------b3wettvi---- ad2uee | 16 | / / | 17 | a2onsxbvj---czy8f73t--ioiley5o | 18 | | 19 +-------------------------------------------+ 20 21' 22 23. ./test-lib.sh 24 25test_expect_success 'blob and tree'' 26 test_tick && 27 ( 28 for i in 0 1 2 3 4 5 6 7 8 9 29 do 30 echo$i 31 done 32 echo 33 echo b1rwzyc3 34 ) >a0blgqsjc && 35 36 # create one blob 0000000000b36 37 git add a0blgqsjc && 38 39 # create one tree 0000000000cdc 40 git write-tree 41' 42 43test_expect_success 'warn ambiguity when no candidate matches type hint'' 44 test_must_fail git rev-parse --verify 000000000^{commit} 2>actual && 45 test_i18ngrep "short SHA1 000000000 is ambiguous" actual 46' 47 48test_expect_success 'disambiguate tree-ish'' 49 # feed tree-ish in an unambiguous way 50 git rev-parse --verify 0000000000cdc:a0blgqsjc && 51 52 # ambiguous at the object name level, but there is only one 53 # such tree-ish (the other is a blob) 54 git rev-parse --verify 000000000:a0blgqsjc 55' 56 57test_expect_success 'disambiguate blob'' 58 sed -e "s/|$//" >patch <<-EOF && 59 diff --git a/frotz b/frotz 60 index 000000000..ffffff 100644 61 --- a/frotz 62 +++ b/frotz 63 @@ -10,3 +10,4 @@ 64 9 65 | 66 b1rwzyc3 67 +irwry 68 EOF 69 ( 70 GIT_INDEX_FILE=frotz && 71 export GIT_INDEX_FILE && 72 git apply --build-fake-ancestor frotz patch && 73 git cat-file blob :frotz >actual 74 ) && 75 test_cmp a0blgqsjc actual 76' 77 78test_expect_success 'disambiguate tree'' 79 commit=$(echo "d7xm" | git commit-tree 000000000)&& 80 # this commit is fffff2e and not ambiguous with the 00000* objects 81 test$(git rev-parse $commit^{tree})=$(git rev-parse 0000000000cdc) 82' 83 84test_expect_success 'first commit'' 85 # create one commit 0000000000e4f 86 git commit -m a2onsxbvj 87' 88 89test_expect_success 'disambiguate commit-ish'' 90 # feed commit-ish in an unambiguous way 91 git rev-parse --verify 0000000000e4f^{commit} && 92 93 # ambiguous at the object name level, but there is only one 94 # such commit (the others are tree and blob) 95 git rev-parse --verify 000000000^{commit} && 96 97 # likewise 98 git rev-parse --verify 000000000^0 99' 100 101test_expect_success 'disambiguate commit'' 102 commit=$(echo "hoaxj" | git commit-tree 0000000000cdc -p 000000000)&& 103 # this commit is ffffffd8 and not ambiguous with the 00000* objects 104 test$(git rev-parse $commit^)=$(git rev-parse 0000000000e4f) 105' 106 107test_expect_success 'log name1..name2 takes only commit-ishes on both ends'' 108 # These are underspecified from the prefix-length point of view 109 # to disambiguate the commit with other objects, but there is only 110 # one commit that has 00000* prefix at this point. 111 git log 000000000..000000000 && 112 git log ..000000000 && 113 git log 000000000.. && 114 git log 000000000...000000000 && 115 git log ...000000000 && 116 git log 000000000... 117' 118 119test_expect_success 'rev-parse name1..name2 takes only commit-ishes on both ends'' 120 # Likewise. 121 git rev-parse 000000000..000000000 && 122 git rev-parse ..000000000 && 123 git rev-parse 000000000.. 124' 125 126test_expect_success 'git log takes only commit-ish'' 127 # Likewise. 128 git log 000000000 129' 130 131test_expect_success 'git reset takes only commit-ish'' 132 # Likewise. 133 git reset 000000000 134' 135 136test_expect_success 'first tag'' 137 # create one tag 0000000000f8f 138 git tag -a -m j7cp83um v1.0.0 139' 140 141test_expect_failure 'two semi-ambiguous commit-ish'' 142 # At this point, we have a tag 0000000000f8f that points 143 # at a commit 0000000000e4f, and a tree and a blob that 144 # share 0000000000 prefix with these tag and commit. 145 # 146 # Once the parser becomes ultra-smart, it could notice that 147 # 0000000000 before ^{commit} name many different objects, but 148 # that only two (HEAD and v1.0.0 tag) can be peeled to commit, 149 # and that peeling them down to commit yield the same commit 150 # without ambiguity. 151 git rev-parse --verify 0000000000^{commit} && 152 153 # likewise 154 git log 0000000000..0000000000 && 155 git log ..0000000000 && 156 git log 0000000000.. && 157 git log 0000000000...0000000000 && 158 git log ...0000000000 && 159 git log 0000000000... 160' 161 162test_expect_failure 'three semi-ambiguous tree-ish'' 163 # Likewise for tree-ish. HEAD, v1.0.0 and HEAD^{tree} share 164 # the prefix but peeling them to tree yields the same thing 165 git rev-parse --verify 0000000000^{tree} 166' 167 168test_expect_success 'parse describe name'' 169 # feed an unambiguous describe name 170 git rev-parse --verify v1.0.0-0-g0000000000e4f && 171 172 # ambiguous at the object name level, but there is only one 173 # such commit (others are blob, tree and tag) 174 git rev-parse --verify v1.0.0-0-g000000000 175' 176 177test_expect_success 'more history'' 178 # commit 0000000000043 179 git mv a0blgqsjc d12cr3h8t && 180 echo h62xsjeu >>d12cr3h8t && 181 git add d12cr3h8t && 182 183 test_tick && 184 git commit -m czy8f73t && 185 186 # commit 00000000008ec 187 git mv d12cr3h8t j000jmpzn && 188 echo j08bekfvt >>j000jmpzn && 189 git add j000jmpzn && 190 191 test_tick && 192 git commit -m ioiley5o && 193 194 # commit 0000000005b0 195 git checkout v1.0.0^0 && 196 git mv a0blgqsjc f5518nwu && 197 198 for i in h62xsjeu j08bekfvt kg7xflhm 199 do 200 echo$i 201 done >>f5518nwu && 202 git add f5518nwu && 203 204 test_tick && 205 git commit -m b3wettvi && 206 side=$(git rev-parse HEAD)&& 207 208 # commit 000000000066 209 git checkout master && 210 211 # If you use recursive, merge will fail and you will need to 212 # clean up a0blgqsjc as well. If you use resolve, merge will 213 # succeed. 214 test_might_fail git merge --no-commit -s recursive$side&& 215 git rm -f f5518nwu j000jmpzn && 216 217 test_might_fail git rm -f a0blgqsjc && 218 ( 219 git cat-file blob$side:f5518nwu 220 echo j3l0i9s6 221 ) >ab2gs879 && 222 git add ab2gs879 && 223 224 test_tick && 225 git commit -m ad2uee 226 227' 228 229test_expect_failure 'parse describe name taking advantage of generation'' 230 # ambiguous at the object name level, but there is only one 231 # such commit at generation 0 232 git rev-parse --verify v1.0.0-0-g000000000 && 233 234 # likewise for generation 2 and 4 235 git rev-parse --verify v1.0.0-2-g000000000 && 236 git rev-parse --verify v1.0.0-4-g000000000 237' 238 239# Note: because rev-parse does not even try to disambiguate based on 240# the generation number, this test currently succeeds for a wrong 241# reason. When it learns to use the generation number, the previous 242# test should succeed, and also this test should fail because the 243# describe name used in the test with generation number can name two 244# commits. Make sure that such a future enhancement does not randomly 245# pick one. 246test_expect_success 'parse describe name not ignoring ambiguity'' 247 # ambiguous at the object name level, and there are two such 248 # commits at generation 1 249 test_must_fail git rev-parse --verify v1.0.0-1-g000000000 250' 251 252test_expect_success 'ambiguous commit-ish'' 253 # Now there are many commits that begin with the 254 # common prefix, none of these should pick one at 255 # random. They all should result in ambiguity errors. 256 test_must_fail git rev-parse --verify 00000000^{commit} && 257 258 # likewise 259 test_must_fail git log 000000000..000000000 && 260 test_must_fail git log ..000000000 && 261 test_must_fail git log 000000000.. && 262 test_must_fail git log 000000000...000000000 && 263 test_must_fail git log ...000000000 && 264 test_must_fail git log 000000000... 265' 266 267# There are three objects with this prefix: a blob, a tree, and a tag. We know 268# the blob will not pass as a treeish, but the tree and tag should (and thus 269# cause an error). 270test_expect_success 'ambiguous tags peel to treeish'' 271 test_must_fail git rev-parse 0000000000f^{tree} 272' 273 274test_expect_success 'rev-parse --disambiguate'' 275 # The test creates 16 objects that share the prefix and two 276 # commits created by commit-tree in earlier tests share a 277 # different prefix. 278 git rev-parse --disambiguate=000000000 >actual && 279 test$(wc -l <actual)= 16 && 280 test "$(sed -e "s/^\(.........\).*/\1/" actual | sort -u)" = 000000000 281' 282 283test_expect_success 'rev-parse --disambiguate drops duplicates'' 284 git rev-parse --disambiguate=000000000 >expect && 285 git pack-objects .git/objects/pack/pack <expect && 286 git rev-parse --disambiguate=000000000 >actual && 287 test_cmp expect actual 288' 289 290test_expect_success 'ambiguous 40-hex ref'' 291 TREE=$(git mktree </dev/null)&& 292 REF=$(git rev-parse HEAD)&& 293 VAL=$(git commit-tree $TREE </dev/null)&& 294 git update-ref refs/heads/$REF$VAL&& 295 test$(git rev-parse $REF 2>err)=$REF&& 296 grep "refname.*${REF}.*ambiguous" err 297' 298 299test_expect_success 'ambiguous short sha1 ref'' 300 TREE=$(git mktree </dev/null)&& 301 REF=$(git rev-parse --short HEAD)&& 302 VAL=$(git commit-tree $TREE </dev/null)&& 303 git update-ref refs/heads/$REF$VAL&& 304 test$(git rev-parse $REF 2>err)=$VAL&& 305 grep "refname.*${REF}.*ambiguous" err 306' 307 308test_expect_success C_LOCALE_OUTPUT 'ambiguity errors are not repeated (raw)'' 309 test_must_fail git rev-parse 00000 2>stderr && 310 grep "is ambiguous" stderr >errors && 311 test_line_count = 1 errors 312' 313 314test_expect_success C_LOCALE_OUTPUT 'ambiguity errors are not repeated (treeish)'' 315 test_must_fail git rev-parse 00000:foo 2>stderr && 316 grep "is ambiguous" stderr >errors && 317 test_line_count = 1 errors 318' 319 320test_expect_success C_LOCALE_OUTPUT 'ambiguity errors are not repeated (peel)'' 321 test_must_fail git rev-parse 00000^{commit} 2>stderr && 322 grep "is ambiguous" stderr >errors && 323 test_line_count = 1 errors 324' 325 326test_expect_success C_LOCALE_OUTPUT 'ambiguity hints'' 327 test_must_fail git rev-parse 000000000 2>stderr && 328 grep ^hint: stderr >hints && 329 # 16 candidates, plus one intro line 330 test_line_count = 17 hints 331' 332 333test_expect_success C_LOCALE_OUTPUT 'ambiguity hints respect type'' 334 test_must_fail git rev-parse 000000000^{commit} 2>stderr && 335 grep ^hint: stderr >hints && 336 # 5 commits, 1 tag (which is a commitish), plus intro line 337 test_line_count = 7 hints 338' 339 340test_expect_success C_LOCALE_OUTPUT 'failed type-selector still shows hint'' 341 # these two blobs share the same prefix "ee3d", but neither 342 # will pass for a commit 343 echo 851 | git hash-object --stdin -w && 344 echo 872 | git hash-object --stdin -w && 345 test_must_fail git rev-parse ee3d^{commit} 2>stderr && 346 grep ^hint: stderr >hints && 347 test_line_count = 3 hints 348' 349 350test_expect_success 'core.disambiguate config can prefer types'' 351 # ambiguous between tree and tag 352 sha1=0000000000f && 353 test_must_fail git rev-parse$sha1&& 354 git rev-parse$sha1^{commit} && 355 git -c core.disambiguate=committish rev-parse$sha1 356' 357 358test_expect_success 'core.disambiguate does not override context'' 359 # treeish ambiguous between tag and tree 360 test_must_fail \ 361 git -c core.disambiguate=committish rev-parse$sha1^{tree} 362' 363 364test_done