Git fork
at reftables-rust 480 lines 14 kB view raw
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 23GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 24export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 25 26. ./test-lib.sh 27. "$TEST_DIRECTORY/lib-loose.sh" 28 29test_cmp_failed_rev_parse () { 30 dir=$1 31 rev=$2 32 33 cat >expect && 34 test_must_fail git -C "$dir" rev-parse "$rev" 2>actual.raw && 35 sed "s/\($rev\)[0-9a-f]*/\1.../" <actual.raw >actual && 36 test_cmp expect actual 37} 38 39test_expect_success 'ambiguous blob output' ' 40 git init --bare blob.prefix && 41 ( 42 cd blob.prefix && 43 44 # Both start with "dead..", under both SHA-1 and SHA-256 45 echo brocdnra | git hash-object -w --stdin && 46 echo brigddsv | git hash-object -w --stdin && 47 48 # Both start with "beef.." 49 echo 1agllotbh | git hash-object -w --stdin && 50 echo 1bbfctrkc | git hash-object -w --stdin 51 ) && 52 53 test_must_fail git -C blob.prefix rev-parse dead && 54 test_cmp_failed_rev_parse blob.prefix beef <<-\EOF 55 error: short object ID beef... is ambiguous 56 hint: The candidates are: 57 hint: beef... blob 58 hint: beef... blob 59 fatal: ambiguous argument '\''beef...'\'': unknown revision or path not in the working tree. 60 Use '\''--'\'' to separate paths from revisions, like this: 61 '\''git <command> [<revision>...] -- [<file>...]'\'' 62 EOF 63' 64 65test_expect_success 'ambiguous loose bad object parsed as OBJ_BAD' ' 66 git init --bare blob.bad && 67 ( 68 cd blob.bad && 69 70 # Both have the prefix "bad0" 71 echo xyzfaowcoh | loose_obj objects bad && 72 echo xyzhjpyvwl | loose_obj objects bad 73 ) && 74 75 test_cmp_failed_rev_parse blob.bad bad0 <<-\EOF 76 error: short object ID bad0... is ambiguous 77 fatal: invalid object type 78 EOF 79' 80 81test_expect_success POSIXPERM 'ambigous zlib corrupt loose blob' ' 82 git init --bare blob.corrupt && 83 ( 84 cd blob.corrupt && 85 86 # Both have the prefix "cafe" 87 echo bnkxmdwz | git hash-object -w --stdin && 88 oid=$(echo bmwsjxzi | git hash-object -w --stdin) && 89 90 oidf=objects/$(test_oid_to_path "$oid") && 91 chmod 755 $oidf && 92 echo broken >$oidf 93 ) && 94 95 test_cmp_failed_rev_parse blob.corrupt cafe <<-\EOF 96 error: short object ID cafe... is ambiguous 97 error: inflate: data stream error (incorrect header check) 98 error: unable to unpack cafe... header 99 error: inflate: data stream error (incorrect header check) 100 error: unable to unpack cafe... header 101 hint: The candidates are: 102 hint: cafe... [bad object] 103 hint: cafe... blob 104 fatal: ambiguous argument '\''cafe...'\'': unknown revision or path not in the working tree. 105 Use '\''--'\'' to separate paths from revisions, like this: 106 '\''git <command> [<revision>...] -- [<file>...]'\'' 107 EOF 108' 109 110if ! test_have_prereq SHA1 111then 112 skip_all='not using SHA-1 for objects' 113 test_done 114fi 115 116test_expect_success 'blob and tree' ' 117 test_tick && 118 ( 119 test_write_lines 0 1 2 3 4 5 6 7 8 9 && 120 echo && 121 echo b1rwzyc3 122 ) >a0blgqsjc && 123 124 # create one blob 0000000000b36 125 git add a0blgqsjc && 126 127 # create one tree 0000000000cdc 128 git write-tree 129' 130 131test_expect_success 'warn ambiguity when no candidate matches type hint' ' 132 test_must_fail git rev-parse --verify 000000000^{commit} 2>actual && 133 test_grep "short object ID 000000000 is ambiguous" actual 134' 135 136test_expect_success 'disambiguate tree-ish' ' 137 # feed tree-ish in an unambiguous way 138 git rev-parse --verify 0000000000cdc:a0blgqsjc && 139 140 # ambiguous at the object name level, but there is only one 141 # such tree-ish (the other is a blob) 142 git rev-parse --verify 000000000:a0blgqsjc 143' 144 145test_expect_success 'disambiguate blob' ' 146 sed -e "s/|$//" >patch <<-EOF && 147 diff --git a/frotz b/frotz 148 index 000000000..ffffff 100644 149 --- a/frotz 150 +++ b/frotz 151 @@ -10,3 +10,4 @@ 152 9 153 | 154 b1rwzyc3 155 +irwry 156 EOF 157 ( 158 GIT_INDEX_FILE=frotz && 159 export GIT_INDEX_FILE && 160 git apply --build-fake-ancestor frotz patch && 161 git cat-file blob :frotz >actual 162 ) && 163 test_cmp a0blgqsjc actual 164' 165 166test_expect_success 'disambiguate tree' ' 167 commit=$(echo "d7xm" | git commit-tree 000000000) && 168 # this commit is fffff2e and not ambiguous with the 00000* objects 169 test $(git rev-parse $commit^{tree}) = $(git rev-parse 0000000000cdc) 170' 171 172test_expect_success 'first commit' ' 173 # create one commit 0000000000e4f 174 git commit -m a2onsxbvj 175' 176 177test_expect_success 'disambiguate commit-ish' ' 178 # feed commit-ish in an unambiguous way 179 git rev-parse --verify 0000000000e4f^{commit} && 180 181 # ambiguous at the object name level, but there is only one 182 # such commit (the others are tree and blob) 183 git rev-parse --verify 000000000^{commit} && 184 185 # likewise 186 git rev-parse --verify 000000000^0 187' 188 189test_expect_success 'disambiguate commit' ' 190 commit=$(echo "hoaxj" | git commit-tree 0000000000cdc -p 000000000) && 191 # this commit is ffffffd8 and not ambiguous with the 00000* objects 192 test $(git rev-parse $commit^) = $(git rev-parse 0000000000e4f) 193' 194 195test_expect_success 'log name1..name2 takes only commit-ishes on both ends' ' 196 # These are underspecified from the prefix-length point of view 197 # to disambiguate the commit with other objects, but there is only 198 # one commit that has 00000* prefix at this point. 199 git log 000000000..000000000 && 200 git log ..000000000 && 201 git log 000000000.. && 202 git log 000000000...000000000 && 203 git log ...000000000 && 204 git log 000000000... 205' 206 207test_expect_success 'rev-parse name1..name2 takes only commit-ishes on both ends' ' 208 # Likewise. 209 git rev-parse 000000000..000000000 && 210 git rev-parse ..000000000 && 211 git rev-parse 000000000.. 212' 213 214test_expect_success 'git log takes only commit-ish' ' 215 # Likewise. 216 git log 000000000 217' 218 219test_expect_success 'git reset takes only commit-ish' ' 220 # Likewise. 221 git reset 000000000 222' 223 224test_expect_success 'first tag' ' 225 # create one tag 0000000000f8f 226 git tag -a -m j7cp83um v1.0.0 227' 228 229test_expect_failure 'two semi-ambiguous commit-ish' ' 230 # At this point, we have a tag 0000000000f8f that points 231 # at a commit 0000000000e4f, and a tree and a blob that 232 # share 0000000000 prefix with these tag and commit. 233 # 234 # Once the parser becomes ultra-smart, it could notice that 235 # 0000000000 before ^{commit} name many different objects, but 236 # that only two (HEAD and v1.0.0 tag) can be peeled to commit, 237 # and that peeling them down to commit yield the same commit 238 # without ambiguity. 239 git rev-parse --verify 0000000000^{commit} && 240 241 # likewise 242 git log 0000000000..0000000000 && 243 git log ..0000000000 && 244 git log 0000000000.. && 245 git log 0000000000...0000000000 && 246 git log ...0000000000 && 247 git log 0000000000... 248' 249 250test_expect_failure 'three semi-ambiguous tree-ish' ' 251 # Likewise for tree-ish. HEAD, v1.0.0 and HEAD^{tree} share 252 # the prefix but peeling them to tree yields the same thing 253 git rev-parse --verify 0000000000^{tree} 254' 255 256test_expect_success 'parse describe name' ' 257 # feed an unambiguous describe name 258 git rev-parse --verify v1.0.0-0-g0000000000e4f && 259 260 # ambiguous at the object name level, but there is only one 261 # such commit (others are blob, tree and tag) 262 git rev-parse --verify v1.0.0-0-g000000000 263' 264 265test_expect_success 'more history' ' 266 # commit 0000000000043 267 git mv a0blgqsjc d12cr3h8t && 268 echo h62xsjeu >>d12cr3h8t && 269 git add d12cr3h8t && 270 271 test_tick && 272 git commit -m czy8f73t && 273 274 # commit 00000000008ec 275 git mv d12cr3h8t j000jmpzn && 276 echo j08bekfvt >>j000jmpzn && 277 git add j000jmpzn && 278 279 test_tick && 280 git commit -m ioiley5o && 281 282 # commit 0000000005b0 283 git checkout v1.0.0^0 && 284 git mv a0blgqsjc f5518nwu && 285 286 test_write_lines h62xsjeu j08bekfvt kg7xflhm >>f5518nwu && 287 git add f5518nwu && 288 289 test_tick && 290 git commit -m b3wettvi && 291 side=$(git rev-parse HEAD) && 292 293 # commit 000000000066 294 git checkout main && 295 296 # If you use recursive, merge will fail and you will need to 297 # clean up a0blgqsjc as well. If you use resolve, merge will 298 # succeed. 299 test_might_fail git merge --no-commit -s recursive $side && 300 git rm -f f5518nwu j000jmpzn && 301 302 test_might_fail git rm -f a0blgqsjc && 303 ( 304 git cat-file blob $side:f5518nwu && 305 echo j3l0i9s6 306 ) >ab2gs879 && 307 git add ab2gs879 && 308 309 test_tick && 310 git commit -m ad2uee 311 312' 313 314test_expect_failure 'parse describe name taking advantage of generation' ' 315 # ambiguous at the object name level, but there is only one 316 # such commit at generation 0 317 git rev-parse --verify v1.0.0-0-g000000000 && 318 319 # likewise for generation 2 and 4 320 git rev-parse --verify v1.0.0-2-g000000000 && 321 git rev-parse --verify v1.0.0-4-g000000000 322' 323 324# Note: because rev-parse does not even try to disambiguate based on 325# the generation number, this test currently succeeds for a wrong 326# reason. When it learns to use the generation number, the previous 327# test should succeed, and also this test should fail because the 328# describe name used in the test with generation number can name two 329# commits. Make sure that such a future enhancement does not randomly 330# pick one. 331test_expect_success 'parse describe name not ignoring ambiguity' ' 332 # ambiguous at the object name level, and there are two such 333 # commits at generation 1 334 test_must_fail git rev-parse --verify v1.0.0-1-g000000000 335' 336 337test_expect_success 'ambiguous commit-ish' ' 338 # Now there are many commits that begin with the 339 # common prefix, none of these should pick one at 340 # random. They all should result in ambiguity errors. 341 test_must_fail git rev-parse --verify 00000000^{commit} && 342 343 # likewise 344 test_must_fail git log 000000000..000000000 && 345 test_must_fail git log ..000000000 && 346 test_must_fail git log 000000000.. && 347 test_must_fail git log 000000000...000000000 && 348 test_must_fail git log ...000000000 && 349 test_must_fail git log 000000000... 350' 351 352# There are three objects with this prefix: a blob, a tree, and a tag. We know 353# the blob will not pass as a treeish, but the tree and tag should (and thus 354# cause an error). 355test_expect_success 'ambiguous tags peel to treeish' ' 356 test_must_fail git rev-parse 0000000000f^{tree} 357' 358 359test_expect_success 'rev-parse --disambiguate' ' 360 # The test creates 16 objects that share the prefix and two 361 # commits created by commit-tree in earlier tests share a 362 # different prefix. 363 git rev-parse --disambiguate=000000000 >actual && 364 test_line_count = 16 actual && 365 test "$(sed -e "s/^\(.........\).*/\1/" actual | sort -u)" = 000000000 366' 367 368test_expect_success 'rev-parse --disambiguate drops duplicates' ' 369 git rev-parse --disambiguate=000000000 >expect && 370 git pack-objects .git/objects/pack/pack <expect && 371 git rev-parse --disambiguate=000000000 >actual && 372 test_cmp expect actual 373' 374 375test_expect_success 'ambiguous 40-hex ref' ' 376 TREE=$(git mktree </dev/null) && 377 REF=$(git rev-parse HEAD) && 378 VAL=$(git commit-tree $TREE </dev/null) && 379 git update-ref refs/heads/$REF $VAL && 380 test $(git rev-parse $REF 2>err) = $REF && 381 grep "refname.*${REF}.*ambiguous" err 382' 383 384test_expect_success 'ambiguous short sha1 ref' ' 385 TREE=$(git mktree </dev/null) && 386 REF=$(git rev-parse --short HEAD) && 387 VAL=$(git commit-tree $TREE </dev/null) && 388 git update-ref refs/heads/$REF $VAL && 389 test $(git rev-parse $REF 2>err) = $VAL && 390 grep "refname.*${REF}.*ambiguous" err 391' 392 393test_expect_success 'ambiguity errors are not repeated (raw)' ' 394 test_must_fail git rev-parse 00000 2>stderr && 395 grep "is ambiguous" stderr >errors && 396 test_line_count = 1 errors 397' 398 399test_expect_success 'ambiguity errors are not repeated (treeish)' ' 400 test_must_fail git rev-parse 00000:foo 2>stderr && 401 grep "is ambiguous" stderr >errors && 402 test_line_count = 1 errors 403' 404 405test_expect_success 'ambiguity errors are not repeated (peel)' ' 406 test_must_fail git rev-parse 00000^{commit} 2>stderr && 407 grep "is ambiguous" stderr >errors && 408 test_line_count = 1 errors 409' 410 411test_expect_success 'ambiguity hints' ' 412 test_must_fail git rev-parse 000000000 2>stderr && 413 grep ^hint: stderr >hints && 414 # 16 candidates, plus one intro line 415 test_line_count = 17 hints 416' 417 418test_expect_success 'ambiguity hints respect type' ' 419 test_must_fail git rev-parse 000000000^{commit} 2>stderr && 420 grep ^hint: stderr >hints && 421 # 5 commits, 1 tag (which is a committish), plus intro line 422 test_line_count = 7 hints 423' 424 425test_expect_success 'failed type-selector still shows hint' ' 426 # these two blobs share the same prefix "ee3d", but neither 427 # will pass for a commit 428 echo 851 | git hash-object --stdin -w && 429 echo 872 | git hash-object --stdin -w && 430 test_must_fail git rev-parse ee3d^{commit} 2>stderr && 431 grep ^hint: stderr >hints && 432 test_line_count = 3 hints 433' 434 435test_expect_success 'core.disambiguate config can prefer types' ' 436 # ambiguous between tree and tag 437 sha1=0000000000f && 438 test_must_fail git rev-parse $sha1 && 439 git rev-parse $sha1^{commit} && 440 git -c core.disambiguate=committish rev-parse $sha1 441' 442 443test_expect_success 'core.disambiguate does not override context' ' 444 # treeish ambiguous between tag and tree 445 test_must_fail \ 446 git -c core.disambiguate=committish rev-parse $sha1^{tree} 447' 448 449test_expect_success 'ambiguous commits are printed by type first, then hash order' ' 450 test_must_fail git rev-parse 0000 2>stderr && 451 grep ^hint: stderr >hints && 452 grep 0000 hints >objects && 453 cat >expected <<-\EOF && 454 tag 455 commit 456 tree 457 blob 458 EOF 459 awk "{print \$3}" <objects >objects.types && 460 uniq <objects.types >objects.types.uniq && 461 test_cmp expected objects.types.uniq && 462 for type in tag commit tree blob 463 do 464 grep $type objects >$type.objects && 465 sort $type.objects >$type.objects.sorted && 466 test_cmp $type.objects.sorted $type.objects || return 1 467 done 468' 469 470test_expect_success 'cat-file --batch and --batch-check show ambiguous' ' 471 echo "0000 ambiguous" >expect && 472 echo 0000 | git cat-file --batch-check >actual 2>err && 473 test_cmp expect actual && 474 test_grep hint: err && 475 echo 0000 | git cat-file --batch >actual 2>err && 476 test_cmp expect actual && 477 test_grep hint: err 478' 479 480test_done