Git fork
at reftables-rust 585 lines 15 kB view raw
1#!/bin/sh 2 3test_description='exercise basic multi-pack bitmap functionality' 4 5. ./test-lib.sh 6. "${TEST_DIRECTORY}/lib-bitmap.sh" 7 8# We'll be writing our own MIDX, so avoid getting confused by the 9# automatic ones. 10GIT_TEST_MULTI_PACK_INDEX=0 11GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0 12 13# This test exercise multi-pack bitmap functionality where the object order is 14# stored and read from a special chunk within the MIDX, so use the default 15# behavior here. 16sane_unset GIT_TEST_MIDX_WRITE_REV 17sane_unset GIT_TEST_MIDX_READ_RIDX 18 19bitmap_reuse_tests() { 20 from=$1 21 to=$2 22 writeLookupTable=false 23 24 for i in $3-${$#} 25 do 26 case $i in 27 "pack.writeBitmapLookupTable") writeLookupTable=true;; 28 esac 29 done 30 31 test_expect_success "setup pack reuse tests ($from -> $to)" ' 32 rm -fr repo && 33 git init repo && 34 ( 35 cd repo && 36 git config pack.writeBitmapLookupTable '"$writeLookupTable"' && 37 test_commit_bulk 16 && 38 git tag old-tip && 39 40 git config core.multiPackIndex true && 41 if test "MIDX" = "$from" 42 then 43 git repack -Ad && 44 git multi-pack-index write --bitmap 45 else 46 git repack -Adb 47 fi 48 ) 49 ' 50 51 test_expect_success "build bitmap from existing ($from -> $to)" ' 52 ( 53 cd repo && 54 git config pack.writeBitmapLookupTable '"$writeLookupTable"' && 55 test_commit_bulk --id=further 16 && 56 git tag new-tip && 57 58 if test "MIDX" = "$to" 59 then 60 git repack -d && 61 git multi-pack-index write --bitmap 62 else 63 git repack -Adb 64 fi 65 ) 66 ' 67 68 test_expect_success "verify resulting bitmaps ($from -> $to)" ' 69 ( 70 cd repo && 71 git config pack.writeBitmapLookupTable '"$writeLookupTable"' && 72 git for-each-ref && 73 git rev-list --test-bitmap refs/tags/old-tip && 74 git rev-list --test-bitmap refs/tags/new-tip 75 ) 76 ' 77} 78 79test_midx_bitmap_cases () { 80 writeLookupTable=false 81 writeBitmapLookupTable= 82 83 for i in "$@" 84 do 85 case $i in 86 "pack.writeBitmapLookupTable") 87 writeLookupTable=true 88 writeBitmapLookupTable="$i" 89 ;; 90 esac 91 done 92 93 test_expect_success 'setup test_repository' ' 94 rm -rf * .git && 95 git init && 96 git config pack.writeBitmapLookupTable '"$writeLookupTable"' 97 ' 98 99 midx_bitmap_core 100 101 bitmap_reuse_tests 'pack' 'MIDX' "$writeBitmapLookupTable" 102 bitmap_reuse_tests 'MIDX' 'pack' "$writeBitmapLookupTable" 103 bitmap_reuse_tests 'MIDX' 'MIDX' "$writeBitmapLookupTable" 104 105 test_expect_success 'missing object closure fails gracefully' ' 106 rm -fr repo && 107 git init repo && 108 test_when_finished "rm -fr repo" && 109 ( 110 cd repo && 111 git config pack.writeBitmapLookupTable '"$writeLookupTable"' && 112 113 test_commit loose && 114 test_commit packed && 115 116 # Do not pass "--revs"; we want a pack without the "loose" 117 # commit. 118 git pack-objects $objdir/pack/pack <<-EOF && 119 $(git rev-parse packed) 120 EOF 121 122 test_must_fail git multi-pack-index write --bitmap 2>err && 123 grep "doesn.t have full closure" err && 124 test_path_is_missing $midx 125 ) 126 ' 127 128 midx_bitmap_partial_tests 129 130 test_expect_success 'removing a MIDX clears stale bitmaps' ' 131 rm -fr repo && 132 git init repo && 133 test_when_finished "rm -fr repo" && 134 ( 135 cd repo && 136 git config pack.writeBitmapLookupTable '"$writeLookupTable"' && 137 test_commit base && 138 git repack && 139 git multi-pack-index write --bitmap && 140 141 # Write a MIDX and bitmap; remove the MIDX but leave the bitmap. 142 stale_bitmap=$midx-$(midx_checksum $objdir).bitmap && 143 rm $midx && 144 145 # Then write a new MIDX. 146 test_commit new && 147 git repack && 148 git multi-pack-index write --bitmap && 149 150 test_path_is_file $midx && 151 test_path_is_file $midx-$(midx_checksum $objdir).bitmap && 152 test_path_is_missing $stale_bitmap 153 ) 154 ' 155 156 test_expect_success 'pack.preferBitmapTips' ' 157 git init repo && 158 test_when_finished "rm -fr repo" && 159 ( 160 cd repo && 161 git config pack.writeBitmapLookupTable '"$writeLookupTable"' && 162 163 test_commit_bulk --message="%s" 103 && 164 165 git log --format="%H" >commits.raw && 166 sort <commits.raw >commits && 167 168 git log --format="create refs/tags/%s %H" HEAD >refs && 169 git update-ref --stdin <refs && 170 171 git multi-pack-index write --bitmap && 172 test_path_is_file $midx && 173 test_path_is_file $midx-$(midx_checksum $objdir).bitmap && 174 175 test-tool bitmap list-commits | sort >bitmaps && 176 comm -13 bitmaps commits >before && 177 test_line_count = 1 before && 178 179 sed "s|\(.*\)|create refs/tags/include/\1 \1|" before | 180 git update-ref --stdin && 181 182 rm -fr $midx-$(midx_checksum $objdir).bitmap && 183 rm -fr $midx && 184 185 git -c pack.preferBitmapTips=refs/tags/include \ 186 multi-pack-index write --bitmap && 187 test-tool bitmap list-commits | sort >bitmaps && 188 comm -13 bitmaps commits >after && 189 190 ! test_cmp before after 191 ) 192 ' 193 194 test_expect_success 'writing a bitmap with --refs-snapshot' ' 195 git init repo && 196 test_when_finished "rm -fr repo" && 197 ( 198 cd repo && 199 git config pack.writeBitmapLookupTable '"$writeLookupTable"' && 200 201 test_commit one && 202 test_commit two && 203 204 git rev-parse one >snapshot && 205 206 git repack -ad && 207 208 # First, write a MIDX which see both refs/tags/one and 209 # refs/tags/two (causing both of those commits to receive 210 # bitmaps). 211 git multi-pack-index write --bitmap && 212 213 test_path_is_file $midx && 214 test_path_is_file $midx-$(midx_checksum $objdir).bitmap && 215 216 test-tool bitmap list-commits | sort >bitmaps && 217 grep "$(git rev-parse one)" bitmaps && 218 grep "$(git rev-parse two)" bitmaps && 219 220 rm -fr $midx-$(midx_checksum $objdir).bitmap && 221 rm -fr $midx && 222 223 # Then again, but with a refs snapshot which only sees 224 # refs/tags/one. 225 git multi-pack-index write --bitmap --refs-snapshot=snapshot && 226 227 test_path_is_file $midx && 228 test_path_is_file $midx-$(midx_checksum $objdir).bitmap && 229 230 test-tool bitmap list-commits | sort >bitmaps && 231 grep "$(git rev-parse one)" bitmaps && 232 ! grep "$(git rev-parse two)" bitmaps 233 ) 234 ' 235 236 test_expect_success 'write a bitmap with --refs-snapshot (preferred tips)' ' 237 git init repo && 238 test_when_finished "rm -fr repo" && 239 ( 240 cd repo && 241 git config pack.writeBitmapLookupTable '"$writeLookupTable"' && 242 243 test_commit_bulk --message="%s" 103 && 244 245 git log --format="%H" >commits.raw && 246 sort <commits.raw >commits && 247 248 git log --format="create refs/tags/%s %H" HEAD >refs && 249 git update-ref --stdin <refs && 250 251 git multi-pack-index write --bitmap && 252 test_path_is_file $midx && 253 test_path_is_file $midx-$(midx_checksum $objdir).bitmap && 254 255 test-tool bitmap list-commits | sort >bitmaps && 256 comm -13 bitmaps commits >before && 257 test_line_count = 1 before && 258 259 ( 260 grep -vf before commits.raw && 261 # mark missing commits as preferred 262 sed "s/^/+/" before 263 ) >snapshot && 264 265 rm -fr $midx-$(midx_checksum $objdir).bitmap && 266 rm -fr $midx && 267 268 git multi-pack-index write --bitmap --refs-snapshot=snapshot && 269 test-tool bitmap list-commits | sort >bitmaps && 270 comm -13 bitmaps commits >after && 271 272 ! test_cmp before after 273 ) 274 ' 275 276 test_expect_success 'hash-cache values are propagated from pack bitmaps' ' 277 rm -fr repo && 278 git init repo && 279 test_when_finished "rm -fr repo" && 280 ( 281 cd repo && 282 git config pack.writeBitmapLookupTable '"$writeLookupTable"' && 283 284 test_commit base && 285 test_commit base2 && 286 git repack -adb && 287 288 test-tool bitmap dump-hashes >pack.raw && 289 test_file_not_empty pack.raw && 290 sort pack.raw >pack.hashes && 291 292 test_commit new && 293 git repack && 294 git multi-pack-index write --bitmap && 295 296 test-tool bitmap dump-hashes >midx.raw && 297 sort midx.raw >midx.hashes && 298 299 # ensure that every namehash in the pack bitmap can be found in 300 # the midx bitmap (i.e., that there are no oid-namehash pairs 301 # unique to the pack bitmap). 302 comm -23 pack.hashes midx.hashes >dropped.hashes && 303 test_must_be_empty dropped.hashes 304 ) 305 ' 306 307 test_expect_success 'no .bitmap is written without any objects' ' 308 rm -fr repo && 309 git init repo && 310 test_when_finished "rm -fr repo" && 311 ( 312 cd repo && 313 git config pack.writeBitmapLookupTable '"$writeLookupTable"' && 314 315 empty="$(git pack-objects $objdir/pack/pack </dev/null)" && 316 cat >packs <<-EOF && 317 pack-$empty.idx 318 EOF 319 320 git multi-pack-index write --bitmap --stdin-packs \ 321 <packs 2>err && 322 323 grep "bitmap without any objects" err && 324 325 test_path_is_file $midx && 326 test_path_is_missing $midx-$(midx_checksum $objdir).bitmap 327 ) 328 ' 329 330 test_expect_success 'graceful fallback when missing reverse index' ' 331 rm -fr repo && 332 git init repo && 333 test_when_finished "rm -fr repo" && 334 ( 335 cd repo && 336 git config pack.writeBitmapLookupTable '"$writeLookupTable"' && 337 338 test_commit base && 339 340 # write a pack and MIDX bitmap containing base 341 git repack -adb && 342 git multi-pack-index write --bitmap && 343 344 GIT_TEST_MIDX_READ_RIDX=0 \ 345 git rev-list --use-bitmap-index HEAD 2>err && 346 ! grep "ignoring extra bitmap file" err 347 ) 348 ' 349} 350 351test_midx_bitmap_cases 352 353test_midx_bitmap_cases "pack.writeBitmapLookupTable" 354 355test_expect_success 'multi-pack-index write writes lookup table if enabled' ' 356 rm -fr repo && 357 git init repo && 358 test_when_finished "rm -fr repo" && 359 ( 360 cd repo && 361 test_commit base && 362 git config pack.writeBitmapLookupTable true && 363 git repack -ad && 364 GIT_TRACE2_EVENT="$(pwd)/trace" \ 365 git multi-pack-index write --bitmap && 366 grep "\"label\":\"writing_lookup_table\"" trace 367 ) 368' 369 370test_expect_success 'preferred pack change with existing MIDX bitmap' ' 371 git init preferred-pack-with-existing && 372 ( 373 cd preferred-pack-with-existing && 374 375 test_commit base && 376 test_commit other && 377 378 git rev-list --objects --no-object-names base >p1.objects && 379 git rev-list --objects --no-object-names other >p2.objects && 380 381 p1="$(git pack-objects "$objdir/pack/pack" \ 382 --delta-base-offset <p1.objects)" && 383 p2="$(git pack-objects "$objdir/pack/pack" \ 384 --delta-base-offset <p2.objects)" && 385 386 # Generate a MIDX containing the first two packs, 387 # marking p1 as preferred, and ensure that it can be 388 # successfully cloned. 389 git multi-pack-index write --bitmap \ 390 --preferred-pack="pack-$p1.pack" && 391 test_path_is_file $midx && 392 test_path_is_file $midx-$(midx_checksum $objdir).bitmap && 393 git clone --no-local . clone1 && 394 395 # Then generate a new pack which sorts ahead of any 396 # existing pack (by tweaking the pack prefix). 397 test_commit foo && 398 git pack-objects --all --unpacked $objdir/pack/pack0 && 399 400 # Generate a new MIDX which changes the preferred pack 401 # to a pack contained in the existing MIDX. 402 git multi-pack-index write --bitmap \ 403 --preferred-pack="pack-$p2.pack" && 404 test_path_is_file $midx && 405 test_path_is_file $midx-$(midx_checksum $objdir).bitmap && 406 407 # When the above circumstances are met, the preferred 408 # pack should change appropriately and clones should 409 # (still) succeed. 410 git clone --no-local . clone2 411 ) 412' 413 414test_expect_success 'tagged commits are selected for bitmapping' ' 415 rm -fr repo && 416 git init repo && 417 test_when_finished "rm -fr repo" && 418 ( 419 cd repo && 420 421 test_commit --annotate base && 422 git repack -d && 423 424 # Remove refs/heads/main which points at the commit directly, 425 # leaving only a reference to the annotated tag. 426 git branch -M main && 427 git checkout base && 428 git branch -d main && 429 430 git multi-pack-index write --bitmap && 431 432 git rev-parse HEAD >want && 433 test-tool bitmap list-commits >actual && 434 grep $(cat want) actual 435 ) 436' 437 438test_expect_success 'do not follow replace objects for MIDX bitmap' ' 439 rm -fr repo && 440 git init repo && 441 test_when_finished "rm -fr repo" && 442 ( 443 cd repo && 444 445 test_commit A && 446 test_commit B && 447 git checkout --orphan=orphan A && 448 test_commit orphan && 449 450 git replace A HEAD && 451 git repack -ad --write-midx --write-bitmap-index && 452 453 # generating reachability bitmaps with replace refs 454 # enabled will result in broken clones 455 git clone --no-local --bare . clone.git 456 ) 457' 458 459corrupt_file () { 460 chmod a+w "$1" && 461 printf "bogus" | dd of="$1" bs=1 seek="12" conv=notrunc 462} 463 464test_expect_success 'git fsck correctly identifies good and bad bitmaps' ' 465 git init valid && 466 test_when_finished rm -rf valid && 467 468 test_commit_bulk 20 && 469 git repack -adbf && 470 471 # Move pack-bitmap aside so it is not deleted 472 # in next repack. 473 packbitmap=$(ls .git/objects/pack/pack-*.bitmap) && 474 mv "$packbitmap" "$packbitmap.bak" && 475 476 test_commit_bulk 10 && 477 git repack -b --write-midx && 478 midxbitmap=$(ls .git/objects/pack/multi-pack-index-*.bitmap) && 479 480 # Copy MIDX bitmap to backup. Copy pack bitmap from backup. 481 cp "$midxbitmap" "$midxbitmap.bak" && 482 cp "$packbitmap.bak" "$packbitmap" && 483 484 # fsck works at first 485 git fsck 2>err && 486 test_must_be_empty err && 487 488 corrupt_file "$packbitmap" && 489 test_must_fail git fsck 2>err && 490 grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err && 491 492 cp "$packbitmap.bak" "$packbitmap" && 493 corrupt_file "$midxbitmap" && 494 test_must_fail git fsck 2>err && 495 grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err && 496 497 corrupt_file "$packbitmap" && 498 test_must_fail git fsck 2>err && 499 grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err && 500 grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err 501' 502 503test_expect_success 'corrupt MIDX with bitmap causes fallback' ' 504 git init corrupt-midx-bitmap && 505 ( 506 cd corrupt-midx-bitmap && 507 508 test_commit first && 509 git repack -d && 510 test_commit second && 511 git repack -d && 512 513 git multi-pack-index write --bitmap && 514 checksum=$(midx_checksum $objdir) && 515 for f in $midx $midx-$checksum.bitmap 516 do 517 mv $f $f.bak || return 1 518 done && 519 520 # pack everything together, invalidating the MIDX 521 git repack -ad && 522 # then restore the now-stale MIDX 523 for f in $midx $midx-$checksum.bitmap 524 do 525 mv $f.bak $f || return 1 526 done && 527 528 git rev-list --count --objects --use-bitmap-index HEAD >out 2>err && 529 # should attempt opening the broken pack twice (once 530 # from the attempt to load it via the stale bitmap, and 531 # again when attempting to load it from the stale MIDX) 532 # before falling back to the non-MIDX case 533 test 2 -eq $(grep -c "could not open pack" err) && 534 test 6 -eq $(cat out) 535 ) 536' 537 538for allow_pack_reuse in single multi 539do 540 test_expect_success "reading MIDX without BTMP chunk does not complain with $allow_pack_reuse pack reuse" ' 541 test_when_finished "rm -rf midx-without-btmp" && 542 git init midx-without-btmp && 543 ( 544 cd midx-without-btmp && 545 test_commit initial && 546 547 git repack -Adbl --write-bitmap-index --write-midx && 548 GIT_TEST_MIDX_READ_BTMP=false git -c pack.allowPackReuse=$allow_pack_reuse \ 549 pack-objects --all --use-bitmap-index --stdout </dev/null >/dev/null 2>err && 550 test_must_be_empty err 551 ) 552 ' 553done 554 555test_expect_success 'remove one packfile between MIDX bitmap writes' ' 556 git init remove-pack-between-writes && 557 ( 558 cd remove-pack-between-writes && 559 560 test_commit A && 561 test_commit B && 562 test_commit C && 563 564 # Create packs with the prefix "pack-A", "pack-B", 565 # "pack-C" to impose a lexicographic order on these 566 # packs so the pack being removed is always from the 567 # middle. 568 packdir=.git/objects/pack && 569 A="$(echo A | git pack-objects $packdir/pack-A --revs)" && 570 B="$(echo B | git pack-objects $packdir/pack-B --revs)" && 571 C="$(echo C | git pack-objects $packdir/pack-C --revs)" && 572 573 git multi-pack-index write --bitmap && 574 575 cat >in <<-EOF && 576 pack-A-$A.idx 577 pack-C-$C.idx 578 EOF 579 git multi-pack-index write --bitmap --stdin-packs <in && 580 581 git rev-list --test-bitmap HEAD 582 ) 583' 584 585test_done