Git fork
at reftables-rust 750 lines 20 kB view raw
1#!/bin/sh 2 3test_description='cruft pack related pack-objects tests' 4 5. ./test-lib.sh 6 7objdir=.git/objects 8packdir=$objdir/pack 9 10basic_cruft_pack_tests () { 11 expire="$1" 12 13 test_expect_success "unreachable loose objects are packed (expire $expire)" ' 14 git init repo && 15 test_when_finished "rm -fr repo" && 16 ( 17 cd repo && 18 19 test_commit base && 20 git repack -Ad && 21 test_commit loose && 22 23 test-tool chmtime +2000 "$objdir/$(test_oid_to_path \ 24 $(git rev-parse loose:loose.t))" && 25 test-tool chmtime +1000 "$objdir/$(test_oid_to_path \ 26 $(git rev-parse loose^{tree}))" && 27 28 ( 29 git rev-list --objects --no-object-names base..loose | 30 while read oid 31 do 32 path="$objdir/$(test_oid_to_path "$oid")" && 33 printf "%s %d\n" "$oid" "$(test-tool chmtime --get "$path")" || 34 echo "object list generation failed for $oid" 35 done | 36 sort -k1 37 ) >expect && 38 39 keep="$(basename "$(ls $packdir/pack-*.pack)")" && 40 cruft="$(echo $keep | git pack-objects --cruft \ 41 --cruft-expiration="$expire" $packdir/pack)" && 42 test-tool pack-mtimes "pack-$cruft.mtimes" >actual && 43 44 test_cmp expect actual 45 ) 46 ' 47 48 test_expect_success "unreachable packed objects are packed (expire $expire)" ' 49 git init repo && 50 test_when_finished "rm -fr repo" && 51 ( 52 cd repo && 53 54 test_commit packed && 55 git repack -Ad && 56 test_commit other && 57 58 git rev-list --objects --no-object-names packed.. >objects && 59 keep="$(basename "$(ls $packdir/pack-*.pack)")" && 60 other="$(git pack-objects --delta-base-offset \ 61 $packdir/pack <objects)" && 62 git prune-packed && 63 64 test-tool chmtime --get -100 "$packdir/pack-$other.pack" >expect && 65 66 cruft="$(git pack-objects --cruft --cruft-expiration="$expire" $packdir/pack <<-EOF 67 $keep 68 -pack-$other.pack 69 EOF 70 )" && 71 test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw && 72 73 cut -d" " -f2 <actual.raw | sort -u >actual && 74 75 test_cmp expect actual 76 ) 77 ' 78 79 test_expect_success "unreachable cruft objects are repacked (expire $expire)" ' 80 git init repo && 81 test_when_finished "rm -fr repo" && 82 ( 83 cd repo && 84 85 test_commit packed && 86 git repack -Ad && 87 test_commit other && 88 89 git rev-list --objects --no-object-names packed.. >objects && 90 keep="$(basename "$(ls $packdir/pack-*.pack)")" && 91 92 cruft_a="$(echo $keep | git pack-objects --cruft --cruft-expiration="$expire" $packdir/pack)" && 93 git prune-packed && 94 cruft_b="$(git pack-objects --cruft --cruft-expiration="$expire" $packdir/pack <<-EOF 95 $keep 96 -pack-$cruft_a.pack 97 EOF 98 )" && 99 100 test-tool pack-mtimes "pack-$cruft_a.mtimes" >expect.raw && 101 test-tool pack-mtimes "pack-$cruft_b.mtimes" >actual.raw && 102 103 sort <expect.raw >expect && 104 sort <actual.raw >actual && 105 106 test_cmp expect actual 107 ) 108 ' 109 110 test_expect_success "multiple cruft packs (expire $expire)" ' 111 git init repo && 112 test_when_finished "rm -fr repo" && 113 ( 114 cd repo && 115 116 test_commit reachable && 117 git repack -Ad && 118 keep="$(basename "$(ls $packdir/pack-*.pack)")" && 119 120 test_commit cruft && 121 loose="$objdir/$(test_oid_to_path $(git rev-parse cruft))" && 122 123 # generate three copies of the cruft object in different 124 # cruft packs, each with a unique mtime: 125 # - one expired (1000 seconds ago) 126 # - two non-expired (one 1000 seconds in the future, 127 # one 1500 seconds in the future) 128 test-tool chmtime =-1000 "$loose" && 129 git pack-objects --cruft $packdir/pack-A <<-EOF && 130 $keep 131 EOF 132 test-tool chmtime =+1000 "$loose" && 133 git pack-objects --cruft $packdir/pack-B <<-EOF && 134 $keep 135 -$(basename $(ls $packdir/pack-A-*.pack)) 136 EOF 137 test-tool chmtime =+1500 "$loose" && 138 git pack-objects --cruft $packdir/pack-C <<-EOF && 139 $keep 140 -$(basename $(ls $packdir/pack-A-*.pack)) 141 -$(basename $(ls $packdir/pack-B-*.pack)) 142 EOF 143 144 # ensure the resulting cruft pack takes the most recent 145 # mtime among all copies 146 cruft="$(git pack-objects --cruft \ 147 --cruft-expiration="$expire" \ 148 $packdir/pack <<-EOF 149 $keep 150 -$(basename $(ls $packdir/pack-A-*.pack)) 151 -$(basename $(ls $packdir/pack-B-*.pack)) 152 -$(basename $(ls $packdir/pack-C-*.pack)) 153 EOF 154 )" && 155 156 test-tool pack-mtimes "$(basename $(ls $packdir/pack-C-*.mtimes))" >expect.raw && 157 test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw && 158 159 sort expect.raw >expect && 160 sort actual.raw >actual && 161 test_cmp expect actual 162 ) 163 ' 164 165 test_expect_success "cruft packs tolerate missing trees (expire $expire)" ' 166 git init repo && 167 test_when_finished "rm -fr repo" && 168 ( 169 cd repo && 170 171 test_commit reachable && 172 test_commit cruft && 173 174 tree="$(git rev-parse cruft^{tree})" && 175 176 git reset --hard reachable && 177 git tag -d cruft && 178 git reflog expire --all --expire=all && 179 180 # remove the unreachable tree, but leave the commit 181 # which has it as its root tree intact 182 rm -fr "$objdir/$(test_oid_to_path "$tree")" && 183 184 git repack -Ad && 185 basename $(ls $packdir/pack-*.pack) >in && 186 git pack-objects --cruft --cruft-expiration="$expire" \ 187 $packdir/pack <in 188 ) 189 ' 190 191 test_expect_success "cruft packs tolerate missing blobs (expire $expire)" ' 192 git init repo && 193 test_when_finished "rm -fr repo" && 194 ( 195 cd repo && 196 197 test_commit reachable && 198 test_commit cruft && 199 200 blob="$(git rev-parse cruft:cruft.t)" && 201 202 git reset --hard reachable && 203 git tag -d cruft && 204 git reflog expire --all --expire=all && 205 206 # remove the unreachable blob, but leave the commit (and 207 # the root tree of that commit) intact 208 rm -fr "$objdir/$(test_oid_to_path "$blob")" && 209 210 git repack -Ad && 211 basename $(ls $packdir/pack-*.pack) >in && 212 git pack-objects --cruft --cruft-expiration="$expire" \ 213 $packdir/pack <in 214 ) 215 ' 216} 217 218basic_cruft_pack_tests never 219basic_cruft_pack_tests 2.weeks.ago 220 221test_expect_success 'cruft tags rescue tagged objects' ' 222 git init repo && 223 test_when_finished "rm -fr repo" && 224 ( 225 cd repo && 226 227 test_commit packed && 228 git repack -Ad && 229 230 test_commit tagged && 231 git tag -a annotated -m tag && 232 233 git rev-list --objects --no-object-names packed.. >objects && 234 while read oid 235 do 236 test-tool chmtime -1000 \ 237 "$objdir/$(test_oid_to_path $oid)" || exit 1 238 done <objects && 239 240 test-tool chmtime -500 \ 241 "$objdir/$(test_oid_to_path $(git rev-parse annotated))" && 242 243 keep="$(basename "$(ls $packdir/pack-*.pack)")" && 244 cruft="$(echo $keep | git pack-objects --cruft \ 245 --cruft-expiration=750.seconds.ago \ 246 $packdir/pack)" && 247 test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw && 248 cut -f1 -d" " <actual.raw | sort >actual && 249 250 ( 251 cat objects && 252 git rev-parse annotated 253 ) >expect.raw && 254 sort <expect.raw >expect && 255 256 test_cmp expect actual && 257 cat actual 258 ) 259' 260 261test_expect_success 'cruft commits rescue parents, trees' ' 262 git init repo && 263 test_when_finished "rm -fr repo" && 264 ( 265 cd repo && 266 267 test_commit packed && 268 git repack -Ad && 269 270 test_commit old && 271 test_commit new && 272 273 git rev-list --objects --no-object-names packed..new >objects && 274 while read object 275 do 276 test-tool chmtime -1000 \ 277 "$objdir/$(test_oid_to_path $object)" || exit 1 278 done <objects && 279 test-tool chmtime +500 "$objdir/$(test_oid_to_path \ 280 $(git rev-parse HEAD))" && 281 282 keep="$(basename "$(ls $packdir/pack-*.pack)")" && 283 cruft="$(echo $keep | git pack-objects --cruft \ 284 --cruft-expiration=750.seconds.ago \ 285 $packdir/pack)" && 286 test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw && 287 288 cut -d" " -f1 <actual.raw | sort >actual && 289 sort <objects >expect && 290 291 test_cmp expect actual 292 ) 293' 294 295test_expect_success 'cruft trees rescue sub-trees, blobs' ' 296 git init repo && 297 test_when_finished "rm -fr repo" && 298 ( 299 cd repo && 300 301 test_commit packed && 302 git repack -Ad && 303 304 mkdir -p dir/sub && 305 echo foo >foo && 306 echo bar >dir/bar && 307 echo baz >dir/sub/baz && 308 309 test_tick && 310 git add . && 311 git commit -m "pruned" && 312 313 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD))" && 314 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD^{tree}))" && 315 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD:foo))" && 316 test-tool chmtime -500 "$objdir/$(test_oid_to_path $(git rev-parse HEAD:dir))" && 317 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD:dir/bar))" && 318 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD:dir/sub))" && 319 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD:dir/sub/baz))" && 320 321 keep="$(basename "$(ls $packdir/pack-*.pack)")" && 322 cruft="$(echo $keep | git pack-objects --cruft \ 323 --cruft-expiration=750.seconds.ago \ 324 $packdir/pack)" && 325 test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw && 326 cut -f1 -d" " <actual.raw | sort >actual && 327 328 git rev-parse HEAD:dir HEAD:dir/bar HEAD:dir/sub HEAD:dir/sub/baz >expect.raw && 329 sort <expect.raw >expect && 330 331 test_cmp expect actual 332 ) 333' 334 335test_expect_success 'expired objects are pruned' ' 336 git init repo && 337 test_when_finished "rm -fr repo" && 338 ( 339 cd repo && 340 341 test_commit packed && 342 git repack -Ad && 343 344 test_commit pruned && 345 346 git rev-list --objects --no-object-names packed..pruned >objects && 347 while read object 348 do 349 test-tool chmtime -1000 \ 350 "$objdir/$(test_oid_to_path $object)" || exit 1 351 done <objects && 352 353 keep="$(basename "$(ls $packdir/pack-*.pack)")" && 354 cruft="$(echo $keep | git pack-objects --cruft \ 355 --cruft-expiration=750.seconds.ago \ 356 $packdir/pack)" && 357 358 test-tool pack-mtimes "pack-$cruft.mtimes" >actual && 359 test_must_be_empty actual 360 ) 361' 362 363test_expect_success 'loose objects mtimes upsert others' ' 364 git init repo && 365 test_when_finished "rm -fr repo" && 366 ( 367 cd repo && 368 369 test_commit reachable && 370 git repack -Ad && 371 git branch -M main && 372 373 git checkout --orphan other && 374 test_commit cruft && 375 # incremental repack, leaving existing objects loose (so 376 # they can be "freshened") 377 git repack && 378 379 tip="$(git rev-parse cruft)" && 380 path="$objdir/$(test_oid_to_path "$tip")" && 381 test-tool chmtime --get +1000 "$path" >expect && 382 383 git checkout main && 384 git branch -D other && 385 git tag -d cruft && 386 git reflog expire --all --expire=all && 387 388 git repack --cruft -d && 389 390 mtimes="$(basename $(ls $packdir/pack-*.mtimes))" && 391 test-tool pack-mtimes "$mtimes" >actual.raw && 392 grep "$tip" actual.raw | cut -d" " -f2 >actual && 393 test_cmp expect actual 394 ) 395' 396 397test_expect_success 'expiring cruft objects with git gc' ' 398 git init repo && 399 test_when_finished "rm -fr repo" && 400 ( 401 cd repo && 402 403 test_commit reachable && 404 git branch -M main && 405 git checkout --orphan other && 406 test_commit unreachable && 407 408 git checkout main && 409 git branch -D other && 410 git tag -d unreachable && 411 # objects are not cruft if they are contained in the reflogs 412 git reflog expire --all --expire=all && 413 414 git rev-list --objects --all --no-object-names >reachable.raw && 415 git cat-file --batch-all-objects --batch-check="%(objectname)" >objects && 416 sort <reachable.raw >reachable && 417 comm -13 reachable objects >unreachable && 418 419 # Write a cruft pack containing all unreachable objects. 420 git gc --cruft --prune="01-01-1980" && 421 422 mtimes=$(ls .git/objects/pack/pack-*.mtimes) && 423 test_path_is_file $mtimes && 424 425 # Prune all unreachable objects from the cruft pack. 426 git gc --cruft --prune=now && 427 428 git cat-file --batch-all-objects --batch-check="%(objectname)" >objects && 429 430 comm -23 unreachable objects >removed && 431 test_cmp unreachable removed && 432 test_path_is_missing $mtimes 433 ) 434' 435 436test_expect_success 'cruft --local drops unreachable objects' ' 437 git init alternate && 438 git init repo && 439 test_when_finished "rm -fr alternate repo" && 440 441 test_commit -C alternate base && 442 # Pack all objects in alternate so that the cruft repack in "repo" sees 443 # the object it dropped due to `--local` as packed. Otherwise this 444 # object would not appear packed anywhere (since it is not packed in 445 # alternate and likewise not part of the cruft pack in the other repo 446 # because of `--local`). 447 git -C alternate repack -ad && 448 449 ( 450 cd repo && 451 452 object="$(git -C ../alternate rev-parse HEAD:base.t)" && 453 git -C ../alternate cat-file -p $object >contents && 454 455 # Write some reachable objects and two unreachable ones: one 456 # that the alternate has and another that is unique. 457 test_commit other && 458 git hash-object -w -t blob contents && 459 cruft="$(echo cruft | git hash-object -w -t blob --stdin)" && 460 461 ( cd ../alternate/.git/objects && pwd ) \ 462 >.git/objects/info/alternates && 463 464 test_path_is_file $objdir/$(test_oid_to_path $cruft) && 465 test_path_is_file $objdir/$(test_oid_to_path $object) && 466 467 git repack -d --cruft --local && 468 469 test-tool pack-mtimes "$(basename $(ls $packdir/pack-*.mtimes))" \ 470 >objects && 471 ! grep $object objects && 472 grep $cruft objects 473 ) 474' 475 476test_expect_success 'MIDX bitmaps tolerate reachable cruft objects' ' 477 git init repo && 478 test_when_finished "rm -fr repo" && 479 ( 480 cd repo && 481 482 test_commit reachable && 483 test_commit cruft && 484 unreachable="$(git rev-parse cruft)" && 485 486 git reset --hard $unreachable^ && 487 git tag -d cruft && 488 git reflog expire --all --expire=all && 489 490 git repack --cruft -d && 491 492 # resurrect the unreachable object via a new commit. the 493 # new commit will get selected for a bitmap, but be 494 # missing one of its parents from the selected packs. 495 git reset --hard $unreachable && 496 test_commit resurrect && 497 498 git repack --write-midx --write-bitmap-index --geometric=2 -d 499 ) 500' 501 502test_expect_success 'cruft objects are freshend via loose' ' 503 git init repo && 504 test_when_finished "rm -fr repo" && 505 ( 506 cd repo && 507 508 echo "cruft" >contents && 509 blob="$(git hash-object -w -t blob contents)" && 510 loose="$objdir/$(test_oid_to_path $blob)" && 511 512 test_commit base && 513 514 git repack --cruft -d && 515 516 test_path_is_missing "$loose" && 517 test-tool pack-mtimes "$(basename "$(ls $packdir/pack-*.mtimes)")" >cruft && 518 grep "$blob" cruft && 519 520 # write the same object again 521 git hash-object -w -t blob contents && 522 523 test_path_is_file "$loose" 524 ) 525' 526 527test_expect_success 'gc.recentObjectsHook' ' 528 git init repo && 529 test_when_finished "rm -fr repo" && 530 ( 531 cd repo && 532 533 # Create a handful of objects. 534 # 535 # - one reachable commit, "base", designated for the reachable 536 # pack 537 # - one unreachable commit, "cruft.discard", which is marked 538 # for deletion 539 # - one unreachable commit, "cruft.old", which would be marked 540 # for deletion, but is rescued as an extra cruft tip 541 # - one unreachable commit, "cruft.new", which is not marked 542 # for deletion 543 test_commit base && 544 git branch -M main && 545 546 git checkout --orphan discard && 547 git rm -fr . && 548 test_commit --no-tag cruft.discard && 549 550 git checkout --orphan old && 551 git rm -fr . && 552 test_commit --no-tag cruft.old && 553 cruft_old="$(git rev-parse HEAD)" && 554 555 git checkout --orphan new && 556 git rm -fr . && 557 test_commit --no-tag cruft.new && 558 cruft_new="$(git rev-parse HEAD)" && 559 560 git checkout main && 561 git branch -D discard old new && 562 git reflog expire --all --expire=all && 563 564 # mark cruft.old with an mtime that is many minutes 565 # older than the expiration period, and mark cruft.new 566 # with an mtime that is in the future (and thus not 567 # eligible for pruning). 568 test-tool chmtime -2000 "$objdir/$(test_oid_to_path $cruft_old)" && 569 test-tool chmtime +1000 "$objdir/$(test_oid_to_path $cruft_new)" && 570 571 # Write the list of cruft objects we expect to 572 # accumulate, which is comprised of everything reachable 573 # from cruft.old and cruft.new, but not cruft.discard. 574 git rev-list --objects --no-object-names \ 575 $cruft_old $cruft_new >cruft.raw && 576 sort cruft.raw >cruft.expect && 577 578 # Write the script to list extra tips, which are limited 579 # to cruft.old, in this case. 580 write_script extra-tips <<-EOF && 581 echo $cruft_old 582 EOF 583 git config gc.recentObjectsHook ./extra-tips && 584 585 git repack --cruft --cruft-expiration=now -d && 586 587 mtimes="$(ls .git/objects/pack/pack-*.mtimes)" && 588 git show-index <${mtimes%.mtimes}.idx >cruft && 589 cut -d" " -f2 cruft | sort >cruft.actual && 590 test_cmp cruft.expect cruft.actual && 591 592 # Ensure that the "old" objects are removed after 593 # dropping the gc.recentObjectsHook hook. 594 git config --unset gc.recentObjectsHook && 595 git repack --cruft --cruft-expiration=now -d && 596 597 mtimes="$(ls .git/objects/pack/pack-*.mtimes)" && 598 git show-index <${mtimes%.mtimes}.idx >cruft && 599 cut -d" " -f2 cruft | sort >cruft.actual && 600 601 git rev-list --objects --no-object-names $cruft_new >cruft.raw && 602 cp cruft.expect cruft.old && 603 sort cruft.raw >cruft.expect && 604 test_cmp cruft.expect cruft.actual && 605 606 # ensure objects which are no longer in the cruft pack were 607 # removed from the repository 608 for object in $(comm -13 cruft.expect cruft.old) 609 do 610 test_must_fail git cat-file -t $object || return 1 611 done 612 ) 613' 614 615test_expect_success 'multi-valued gc.recentObjectsHook' ' 616 git init repo && 617 test_when_finished "rm -fr repo" && 618 ( 619 cd repo && 620 621 test_commit base && 622 git branch -M main && 623 624 git checkout --orphan cruft.a && 625 git rm -fr . && 626 test_commit --no-tag cruft.a && 627 cruft_a="$(git rev-parse HEAD)" && 628 629 git checkout --orphan cruft.b && 630 git rm -fr . && 631 test_commit --no-tag cruft.b && 632 cruft_b="$(git rev-parse HEAD)" && 633 634 git checkout main && 635 git branch -D cruft.a cruft.b && 636 git reflog expire --all --expire=all && 637 638 echo "echo $cruft_a" | write_script extra-tips.a && 639 echo "echo $cruft_b" | write_script extra-tips.b && 640 echo "false" | write_script extra-tips.c && 641 642 git rev-list --objects --no-object-names $cruft_a $cruft_b \ 643 >cruft.raw && 644 sort cruft.raw >cruft.expect && 645 646 # ensure that each extra cruft tip is saved by its 647 # respective hook 648 git config --add gc.recentObjectsHook ./extra-tips.a && 649 git config --add gc.recentObjectsHook ./extra-tips.b && 650 git repack --cruft --cruft-expiration=now -d && 651 652 mtimes="$(ls .git/objects/pack/pack-*.mtimes)" && 653 git show-index <${mtimes%.mtimes}.idx >cruft && 654 cut -d" " -f2 cruft | sort >cruft.actual && 655 test_cmp cruft.expect cruft.actual && 656 657 # ensure that a dirty exit halts cruft pack generation 658 git config --add gc.recentObjectsHook ./extra-tips.c && 659 test_must_fail git repack --cruft --cruft-expiration=now -d 2>err && 660 grep "unable to enumerate additional recent objects" err && 661 662 # and that the existing cruft pack is left alone 663 test_path_is_file "$mtimes" 664 ) 665' 666 667test_expect_success 'additional cruft blobs via gc.recentObjectsHook' ' 668 git init repo && 669 test_when_finished "rm -fr repo" && 670 ( 671 cd repo && 672 673 test_commit base && 674 675 blob=$(echo "unreachable" | git hash-object -w --stdin) && 676 677 # mark the unreachable blob we wrote above as having 678 # aged out of the retention period 679 test-tool chmtime -2000 "$objdir/$(test_oid_to_path $blob)" && 680 681 # Write the script to list extra tips, which is just the 682 # extra blob as above. 683 write_script extra-tips <<-EOF && 684 echo $blob 685 EOF 686 git config gc.recentObjectsHook ./extra-tips && 687 688 git repack --cruft --cruft-expiration=now -d && 689 690 mtimes="$(ls .git/objects/pack/pack-*.mtimes)" && 691 git show-index <${mtimes%.mtimes}.idx >cruft && 692 cut -d" " -f2 cruft >actual && 693 echo $blob >expect && 694 test_cmp expect actual 695 ) 696' 697 698test_expect_success 'split cruft packs with --max-cruft-size' ' 699 repo=cruft-with--max-cruft-size && 700 test_when_finished "rm -fr $repo" && 701 702 git init "$repo" && 703 704 ( 705 cd "$repo" && 706 707 git config core.compression 0 && 708 709 sz=$((1024 * 1024)) && # 1MiB 710 test-tool genrandom foo $sz >foo && 711 test-tool genrandom bar $sz >bar && 712 foo="$(git hash-object -w -t blob foo)" && 713 bar="$(git hash-object -w -t blob bar)" && 714 715 to=$packdir/pack && 716 # Pack together foo and bar into a single 2MiB pack. 717 pack="$(git pack-objects $to <<-EOF 718 $foo 719 $bar 720 EOF 721 )" && 722 723 # Then generate a cruft pack containing foo and bar. 724 # 725 # Generate the pack with --max-pack-size equal to the 726 # size of one object, forcing us to write two cruft 727 # packs. 728 git pack-objects --cruft --max-pack-size=$sz $to <<-EOF && 729 -pack-$pack.pack 730 EOF 731 732 ls $packdir/pack-*.mtimes >crufts && 733 test_line_count = 2 crufts && 734 735 for cruft in $(cat crufts) 736 do 737 test-tool pack-mtimes "$(basename "$cruft")" || return 1 738 done >actual.raw && 739 740 cut -d" " -f1 <actual.raw | sort >actual && 741 sort >expect <<-EOF && 742 $foo 743 $bar 744 EOF 745 746 test_cmp expect actual 747 ) 748' 749 750test_done