| 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='git repack works correctly' |
| 4 | |
| 5 | . ./test-lib.sh |
| 6 | |
| 7 | objdir=.git/objects |
| 8 | packdir=$objdir/pack |
| 9 | |
| 10 | test_expect_success '--expire-to stores pruned objects (now)' ' |
| 11 | git init expire-to-now && |
| 12 | ( |
| 13 | cd expire-to-now && |
| 14 | |
| 15 | git branch -M main && |
| 16 | |
| 17 | test_commit base && |
| 18 | |
| 19 | git checkout -b cruft && |
| 20 | test_commit --no-tag cruft && |
| 21 | |
| 22 | git rev-list --objects --no-object-names main..cruft >moved.raw && |
| 23 | sort moved.raw >moved.want && |
| 24 | |
| 25 | git rev-list --all --objects --no-object-names >expect.raw && |
| 26 | sort expect.raw >expect && |
| 27 | |
| 28 | git checkout main && |
| 29 | git branch -D cruft && |
| 30 | git reflog expire --all --expire=all && |
| 31 | |
| 32 | git init --bare expired.git && |
| 33 | git repack -d \ |
| 34 | --cruft --cruft-expiration="now" \ |
| 35 | --expire-to="expired.git/objects/pack/pack" && |
| 36 | |
| 37 | expired="$(ls expired.git/objects/pack/pack-*.idx)" && |
| 38 | test_path_is_file "${expired%.idx}.mtimes" && |
| 39 | |
| 40 | # Since the `--cruft-expiration` is "now", the effective |
| 41 | # behavior is to move _all_ unreachable objects out to |
| 42 | # the location in `--expire-to`. |
| 43 | git show-index <$expired >expired.raw && |
| 44 | cut -d" " -f2 expired.raw | sort >expired.objects && |
| 45 | git rev-list --all --objects --no-object-names \ |
| 46 | >remaining.objects && |
| 47 | |
| 48 | # ...in other words, the combined contents of this |
| 49 | # repository and expired.git should be the same as the |
| 50 | # set of objects we started with. |
| 51 | sort expired.objects remaining.objects >actual && |
| 52 | test_cmp expect actual && |
| 53 | |
| 54 | # The "moved" objects (i.e., those in expired.git) |
| 55 | # should be the same as the cruft objects which were |
| 56 | # expired in the previous step. |
| 57 | test_cmp moved.want expired.objects |
| 58 | ) |
| 59 | ' |
| 60 | |
| 61 | test_expect_success '--expire-to stores pruned objects (5.minutes.ago)' ' |
| 62 | git init expire-to-5.minutes.ago && |
| 63 | ( |
| 64 | cd expire-to-5.minutes.ago && |
| 65 | |
| 66 | git branch -M main && |
| 67 | |
| 68 | test_commit base && |
| 69 | |
| 70 | # Create two classes of unreachable objects, one which |
| 71 | # is older than 5 minutes (stale), and another which is |
| 72 | # newer (recent). |
| 73 | for kind in stale recent |
| 74 | do |
| 75 | git checkout -b $kind main && |
| 76 | test_commit --no-tag $kind || return 1 |
| 77 | done && |
| 78 | |
| 79 | git rev-list --objects --no-object-names main..stale >in && |
| 80 | stale="$(git pack-objects $objdir/pack/pack <in)" && |
| 81 | mtime="$(test-tool chmtime --get =-600 $objdir/pack/pack-$stale.pack)" && |
| 82 | |
| 83 | # expect holds the set of objects we expect to find in |
| 84 | # this repository after repacking |
| 85 | git rev-list --objects --no-object-names recent >expect.raw && |
| 86 | sort expect.raw >expect && |
| 87 | |
| 88 | # moved.want holds the set of objects we expect to find |
| 89 | # in expired.git |
| 90 | git rev-list --objects --no-object-names main..stale >out && |
| 91 | sort out >moved.want && |
| 92 | |
| 93 | git checkout main && |
| 94 | git branch -D stale recent && |
| 95 | git reflog expire --all --expire=all && |
| 96 | git prune-packed && |
| 97 | |
| 98 | git init --bare expired.git && |
| 99 | git repack -d \ |
| 100 | --cruft --cruft-expiration=5.minutes.ago \ |
| 101 | --expire-to="expired.git/objects/pack/pack" && |
| 102 | |
| 103 | # Some of the remaining objects in this repository are |
| 104 | # unreachable, so use `cat-file --batch-all-objects` |
| 105 | # instead of `rev-list` to get their names |
| 106 | git cat-file --batch-all-objects --batch-check="%(objectname)" \ |
| 107 | >remaining.objects && |
| 108 | sort remaining.objects >actual && |
| 109 | test_cmp expect actual && |
| 110 | |
| 111 | ( |
| 112 | cd expired.git && |
| 113 | |
| 114 | expired="$(ls objects/pack/pack-*.mtimes)" && |
| 115 | test-tool pack-mtimes $(basename $expired) >out && |
| 116 | cut -d" " -f1 out | sort >../moved.got && |
| 117 | |
| 118 | # Ensure that there are as many objects with the |
| 119 | # expected mtime as were moved to expired.git. |
| 120 | # |
| 121 | # In other words, ensure that the recorded |
| 122 | # mtimes of any moved objects was written |
| 123 | # correctly. |
| 124 | grep " $mtime$" out >matching && |
| 125 | test_line_count = $(wc -l <../moved.want) matching |
| 126 | ) && |
| 127 | test_cmp moved.want moved.got |
| 128 | ) |
| 129 | ' |
| 130 | |
| 131 | generate_random_blob() { |
| 132 | test-tool genrandom "$@" >blob && |
| 133 | git hash-object -w -t blob blob && |
| 134 | rm blob |
| 135 | } |
| 136 | |
| 137 | pack_random_blob () { |
| 138 | generate_random_blob "$@" && |
| 139 | git repack -d -q >/dev/null |
| 140 | } |
| 141 | |
| 142 | generate_cruft_pack () { |
| 143 | pack_random_blob "$@" >/dev/null && |
| 144 | |
| 145 | ls $packdir/pack-*.pack | xargs -n 1 basename >in && |
| 146 | pack="$(git pack-objects --cruft $packdir/pack <in)" && |
| 147 | git prune-packed && |
| 148 | |
| 149 | echo "$packdir/pack-$pack.mtimes" |
| 150 | } |
| 151 | |
| 152 | test_expect_success '--max-cruft-size creates new packs when too large' ' |
| 153 | git init max-cruft-size-large && |
| 154 | ( |
| 155 | cd max-cruft-size-large && |
| 156 | test_commit base && |
| 157 | |
| 158 | foo="$(pack_random_blob foo $((1*1024*1024)))" && |
| 159 | git repack --cruft -d && |
| 160 | cruft_foo="$(ls $packdir/pack-*.mtimes)" && |
| 161 | |
| 162 | bar="$(pack_random_blob bar $((1*1024*1024)))" && |
| 163 | git repack --cruft -d --max-cruft-size=1M && |
| 164 | cruft_bar="$(ls $packdir/pack-*.mtimes | grep -v $cruft_foo)" && |
| 165 | |
| 166 | test-tool pack-mtimes $(basename "$cruft_foo") >foo.objects && |
| 167 | test-tool pack-mtimes $(basename "$cruft_bar") >bar.objects && |
| 168 | |
| 169 | test_grep "^$foo" foo.objects && |
| 170 | test_line_count = 1 foo.objects && |
| 171 | test_grep "^$bar" bar.objects && |
| 172 | test_line_count = 1 bar.objects |
| 173 | ) |
| 174 | ' |
| 175 | |
| 176 | test_expect_success '--max-cruft-size combines existing packs when not too large' ' |
| 177 | git init max-cruft-size-small && |
| 178 | ( |
| 179 | cd max-cruft-size-small && |
| 180 | test_commit base && |
| 181 | |
| 182 | foo="$(pack_random_blob foo $((1*1024*1024)))" && |
| 183 | git repack --cruft -d && |
| 184 | |
| 185 | bar="$(pack_random_blob bar $((1*1024*1024)))" && |
| 186 | git repack --cruft -d --max-cruft-size=10M && |
| 187 | |
| 188 | cruft=$(ls $packdir/pack-*.mtimes) && |
| 189 | test-tool pack-mtimes $(basename "$cruft") >cruft.objects && |
| 190 | |
| 191 | test_grep "^$foo" cruft.objects && |
| 192 | test_grep "^$bar" cruft.objects && |
| 193 | test_line_count = 2 cruft.objects |
| 194 | ) |
| 195 | ' |
| 196 | |
| 197 | test_expect_success '--combine-cruft-below-size combines packs' ' |
| 198 | repo=combine-cruft-below-size && |
| 199 | test_when_finished "rm -fr $repo" && |
| 200 | |
| 201 | git init "$repo" && |
| 202 | ( |
| 203 | cd "$repo" && |
| 204 | |
| 205 | test_commit base && |
| 206 | git repack -ad && |
| 207 | |
| 208 | cruft_foo="$(generate_cruft_pack foo 524288)" && # 0.5 MiB |
| 209 | cruft_bar="$(generate_cruft_pack bar 524288)" && # 0.5 MiB |
| 210 | cruft_baz="$(generate_cruft_pack baz 1048576)" && # 1.0 MiB |
| 211 | cruft_quux="$(generate_cruft_pack quux 1572864)" && # 1.5 MiB |
| 212 | |
| 213 | test-tool pack-mtimes "$(basename $cruft_foo)" >expect.raw && |
| 214 | test-tool pack-mtimes "$(basename $cruft_bar)" >>expect.raw && |
| 215 | sort expect.raw >expect.objects && |
| 216 | |
| 217 | # Repacking with `--combine-cruft-below-size=1M` |
| 218 | # should combine both 0.5 MiB packs together, but |
| 219 | # ignore the two packs which are >= 1.0 MiB. |
| 220 | ls $packdir/pack-*.mtimes | sort >cruft.before && |
| 221 | git repack -d --cruft --combine-cruft-below-size=1M && |
| 222 | ls $packdir/pack-*.mtimes | sort >cruft.after && |
| 223 | |
| 224 | comm -13 cruft.before cruft.after >cruft.new && |
| 225 | comm -23 cruft.before cruft.after >cruft.removed && |
| 226 | |
| 227 | test_line_count = 1 cruft.new && |
| 228 | test_line_count = 2 cruft.removed && |
| 229 | |
| 230 | # The two packs smaller than 1.0MiB should be repacked |
| 231 | # together. |
| 232 | printf "%s\n" $cruft_foo $cruft_bar | sort >expect.removed && |
| 233 | test_cmp expect.removed cruft.removed && |
| 234 | |
| 235 | # ...and contain the set of objects rolled up. |
| 236 | test-tool pack-mtimes "$(basename $(cat cruft.new))" >actual.raw && |
| 237 | sort actual.raw >actual.objects && |
| 238 | |
| 239 | test_cmp expect.objects actual.objects |
| 240 | ) |
| 241 | ' |
| 242 | |
| 243 | test_expect_success 'setup cruft with freshened objects' ' |
| 244 | git init cruft-freshen && |
| 245 | ( |
| 246 | cd cruft-freshen && |
| 247 | |
| 248 | test_commit base && |
| 249 | git repack -ad && |
| 250 | |
| 251 | foo="$(generate_random_blob foo 64)" && |
| 252 | test-tool chmtime --get -10000 \ |
| 253 | "$objdir/$(test_oid_to_path "$foo")" >foo.mtime && |
| 254 | |
| 255 | git repack --cruft -d && |
| 256 | |
| 257 | cruft="$(ls $packdir/pack-*.mtimes)" && |
| 258 | test-tool pack-mtimes "$(basename $cruft)" >actual && |
| 259 | echo "$foo $(cat foo.mtime)" >expect && |
| 260 | test_cmp expect actual |
| 261 | ) |
| 262 | ' |
| 263 | |
| 264 | test_expect_success 'cruft with freshened objects (loose)' ' |
| 265 | ( |
| 266 | cd cruft-freshen && |
| 267 | |
| 268 | # regenerate the object, setting its mtime to be more recent |
| 269 | foo="$(generate_random_blob foo 64)" && |
| 270 | test-tool chmtime --get -100 \ |
| 271 | "$objdir/$(test_oid_to_path "$foo")" >foo.mtime && |
| 272 | |
| 273 | git repack --cruft -d && |
| 274 | |
| 275 | cruft="$(ls $packdir/pack-*.mtimes)" && |
| 276 | test-tool pack-mtimes "$(basename $cruft)" >actual && |
| 277 | echo "$foo $(cat foo.mtime)" >expect && |
| 278 | test_cmp expect actual |
| 279 | ) |
| 280 | ' |
| 281 | |
| 282 | test_expect_success 'cruft with freshened objects (packed)' ' |
| 283 | ( |
| 284 | cd cruft-freshen && |
| 285 | |
| 286 | # regenerate the object and store it in a packfile, |
| 287 | # setting its mtime to be more recent |
| 288 | # |
| 289 | # store it alongside another cruft object so that we |
| 290 | # do not create an identical copy of the existing |
| 291 | # cruft pack (which contains $foo). |
| 292 | foo="$(generate_random_blob foo 64)" && |
| 293 | bar="$(generate_random_blob bar 64)" && |
| 294 | foo_pack="$(printf "%s\n" $foo $bar | git pack-objects $packdir/pack)" && |
| 295 | git prune-packed && |
| 296 | |
| 297 | test-tool chmtime --get -10 \ |
| 298 | "$packdir/pack-$foo_pack.pack" >foo.mtime && |
| 299 | |
| 300 | git repack --cruft -d && |
| 301 | |
| 302 | cruft="$(ls $packdir/pack-*.mtimes)" && |
| 303 | test-tool pack-mtimes "$(basename $cruft)" >actual && |
| 304 | echo "$foo $(cat foo.mtime)" >expect.raw && |
| 305 | echo "$bar $(cat foo.mtime)" >>expect.raw && |
| 306 | sort expect.raw >expect && |
| 307 | test_cmp expect actual |
| 308 | ) |
| 309 | ' |
| 310 | |
| 311 | test_expect_success 'multi-cruft with freshened objects (previously cruft)' ' |
| 312 | repo="max-cruft-size-threshold" && |
| 313 | |
| 314 | test_when_finished "rm -fr $repo" && |
| 315 | git init "$repo" && |
| 316 | ( |
| 317 | cd "$repo" && |
| 318 | |
| 319 | test_commit base && |
| 320 | foo="$(generate_random_blob foo $((2*1024*1024)))" && |
| 321 | bar="$(generate_random_blob bar $((2*1024*1024)))" && |
| 322 | baz="$(generate_random_blob baz $((2*1024*1024)))" && |
| 323 | |
| 324 | test-tool chmtime --get -100000 \ |
| 325 | "$objdir/$(test_oid_to_path "$foo")" >foo.old && |
| 326 | test-tool chmtime --get -100000 \ |
| 327 | "$objdir/$(test_oid_to_path "$bar")" >bar.old && |
| 328 | test-tool chmtime --get -100000 \ |
| 329 | "$objdir/$(test_oid_to_path "$baz")" >baz.old && |
| 330 | |
| 331 | git repack --cruft -d && |
| 332 | |
| 333 | # Make an identical copy of foo stored in a pack with a more |
| 334 | # recent mtime. |
| 335 | foo="$(generate_random_blob foo $((2*1024*1024)))" && |
| 336 | foo_pack="$(echo "$foo" | git pack-objects $packdir/pack)" && |
| 337 | test-tool chmtime --get -100 \ |
| 338 | "$packdir/pack-$foo_pack.pack" >foo.new && |
| 339 | git prune-packed && |
| 340 | |
| 341 | # Make a loose copy of bar, also with a more recent mtime. |
| 342 | bar="$(generate_random_blob bar $((2*1024*1024)))" && |
| 343 | test-tool chmtime --get -100 \ |
| 344 | "$objdir/$(test_oid_to_path "$bar")" >bar.new && |
| 345 | |
| 346 | # Make a new cruft object $quux to ensure we do not |
| 347 | # generate an identical pack to the existing cruft |
| 348 | # pack. |
| 349 | quux="$(generate_random_blob quux $((1024)))" && |
| 350 | test-tool chmtime --get -100 \ |
| 351 | "$objdir/$(test_oid_to_path "$quux")" >quux.new && |
| 352 | |
| 353 | git repack --cruft --max-cruft-size=3M -d && |
| 354 | |
| 355 | for p in $packdir/pack-*.mtimes |
| 356 | do |
| 357 | test-tool pack-mtimes "$(basename "$p")" || return 1 |
| 358 | done >actual.raw && |
| 359 | sort actual.raw >actual && |
| 360 | |
| 361 | # Among the set of all cruft packs, we should see the |
| 362 | # new mtimes for object $foo and $bar, as well as the |
| 363 | # single new copy of $baz. |
| 364 | sort >expect <<-EOF && |
| 365 | $foo $(cat foo.new) |
| 366 | $bar $(cat bar.new) |
| 367 | $baz $(cat baz.old) |
| 368 | $quux $(cat quux.new) |
| 369 | EOF |
| 370 | |
| 371 | test_cmp expect actual |
| 372 | ) |
| 373 | ' |
| 374 | |
| 375 | test_expect_success '--max-cruft-size with pruning' ' |
| 376 | git init max-cruft-size-prune && |
| 377 | ( |
| 378 | cd max-cruft-size-prune && |
| 379 | |
| 380 | test_commit base && |
| 381 | foo="$(generate_random_blob foo $((1024*1024)))" && |
| 382 | bar="$(generate_random_blob bar $((1024*1024)))" && |
| 383 | baz="$(generate_random_blob baz $((1024*1024)))" && |
| 384 | |
| 385 | test-tool chmtime -10000 "$objdir/$(test_oid_to_path "$foo")" && |
| 386 | |
| 387 | git repack -d --cruft --max-cruft-size=1M && |
| 388 | |
| 389 | # backdate the mtimes of all cruft packs to validate |
| 390 | # that they were rewritten as a result of pruning |
| 391 | ls $packdir/pack-*.mtimes | sort >cruft.before && |
| 392 | for cruft in $(cat cruft.before) |
| 393 | do |
| 394 | mtime="$(test-tool chmtime --get -10000 "$cruft")" && |
| 395 | echo $cruft $mtime >>mtimes || return 1 |
| 396 | done && |
| 397 | |
| 398 | # repack (and prune) with a --max-cruft-size to ensure |
| 399 | # that we appropriately split the resulting set of packs |
| 400 | git repack -d --cruft --max-cruft-size=1M \ |
| 401 | --cruft-expiration=1000.seconds.ago && |
| 402 | ls $packdir/pack-*.mtimes | sort >cruft.after && |
| 403 | |
| 404 | for cruft in $(cat cruft.after) |
| 405 | do |
| 406 | old_mtime="$(grep $cruft mtimes | cut -d" " -f2)" && |
| 407 | new_mtime="$(test-tool chmtime --get $cruft)" && |
| 408 | test $old_mtime -lt $new_mtime || return 1 |
| 409 | done && |
| 410 | |
| 411 | test_line_count = 3 cruft.before && |
| 412 | test_line_count = 2 cruft.after && |
| 413 | test_must_fail git cat-file -e $foo && |
| 414 | git cat-file -e $bar && |
| 415 | git cat-file -e $baz |
| 416 | ) |
| 417 | ' |
| 418 | |
| 419 | test_expect_success '--max-cruft-size ignores non-local packs' ' |
| 420 | repo="max-cruft-size-non-local" && |
| 421 | git init $repo && |
| 422 | ( |
| 423 | cd $repo && |
| 424 | test_commit base && |
| 425 | generate_random_blob foo 64 && |
| 426 | git repack --cruft -d |
| 427 | ) && |
| 428 | |
| 429 | git clone --reference=$repo $repo $repo-alt && |
| 430 | ( |
| 431 | cd $repo-alt && |
| 432 | |
| 433 | test_commit other && |
| 434 | generate_random_blob bar 64 && |
| 435 | |
| 436 | # ensure that we do not attempt to pick up packs from |
| 437 | # the non-alternated repository, which would result in a |
| 438 | # crash |
| 439 | git repack --cruft --max-cruft-size=1M -d |
| 440 | ) |
| 441 | ' |
| 442 | |
| 443 | test_expect_success 'reachable packs are preferred over cruft ones' ' |
| 444 | repo="cruft-preferred-packs" && |
| 445 | git init "$repo" && |
| 446 | ( |
| 447 | cd "$repo" && |
| 448 | |
| 449 | # This test needs to exercise careful control over when a MIDX |
| 450 | # is and is not written. Unset the corresponding TEST variable |
| 451 | # accordingly. |
| 452 | sane_unset GIT_TEST_MULTI_PACK_INDEX && |
| 453 | |
| 454 | test_commit base && |
| 455 | test_commit --no-tag cruft && |
| 456 | |
| 457 | non_cruft="$(echo base | git pack-objects --revs $packdir/pack)" && |
| 458 | # Write a cruft pack which both (a) sorts ahead of the non-cruft |
| 459 | # pack in lexical order, and (b) has an older mtime to appease |
| 460 | # the MIDX preferred pack selection routine. |
| 461 | cruft="$(echo pack-$non_cruft.pack | git pack-objects --cruft $packdir/pack-A)" && |
| 462 | test-tool chmtime -1000 $packdir/pack-A-$cruft.pack && |
| 463 | |
| 464 | test_commit other && |
| 465 | git repack -d && |
| 466 | |
| 467 | git repack --geometric 2 -d --write-midx --write-bitmap-index && |
| 468 | |
| 469 | # After repacking, there are two packs left: one reachable one |
| 470 | # (which is the result of combining both of the existing two |
| 471 | # non-cruft packs), and one cruft pack. |
| 472 | find .git/objects/pack -type f -name "*.pack" >packs && |
| 473 | test_line_count = 2 packs && |
| 474 | |
| 475 | # Make sure that the pack we just wrote is marked as preferred, |
| 476 | # not the cruft one. |
| 477 | pack="$(test-tool read-midx --preferred-pack $objdir)" && |
| 478 | test_path_is_missing "$packdir/$(basename "$pack" ".idx").mtimes" |
| 479 | ) |
| 480 | ' |
| 481 | |
| 482 | test_expect_success 'repack --cruft generates a cruft pack' ' |
| 483 | git init repo && |
| 484 | test_when_finished "rm -fr repo" && |
| 485 | ( |
| 486 | cd repo && |
| 487 | |
| 488 | test_commit reachable && |
| 489 | git branch -M main && |
| 490 | git checkout --orphan other && |
| 491 | test_commit unreachable && |
| 492 | |
| 493 | git checkout main && |
| 494 | git branch -D other && |
| 495 | git tag -d unreachable && |
| 496 | # objects are not cruft if they are contained in the reflogs |
| 497 | git reflog expire --all --expire=all && |
| 498 | |
| 499 | git rev-list --objects --all --no-object-names >reachable.raw && |
| 500 | git cat-file --batch-all-objects --batch-check="%(objectname)" >objects && |
| 501 | sort <reachable.raw >reachable && |
| 502 | comm -13 reachable objects >unreachable && |
| 503 | |
| 504 | git repack --cruft -d && |
| 505 | |
| 506 | cruft=$(basename $(ls $packdir/pack-*.mtimes) .mtimes) && |
| 507 | pack=$(basename $(ls $packdir/pack-*.pack | grep -v $cruft) .pack) && |
| 508 | |
| 509 | git show-index <$packdir/$pack.idx >actual.raw && |
| 510 | cut -f2 -d" " actual.raw | sort >actual && |
| 511 | test_cmp reachable actual && |
| 512 | |
| 513 | git show-index <$packdir/$cruft.idx >actual.raw && |
| 514 | cut -f2 -d" " actual.raw | sort >actual && |
| 515 | test_cmp unreachable actual |
| 516 | ) |
| 517 | ' |
| 518 | |
| 519 | test_expect_success 'cruft packs are not included in geometric repack' ' |
| 520 | git init repo && |
| 521 | test_when_finished "rm -fr repo" && |
| 522 | ( |
| 523 | cd repo && |
| 524 | |
| 525 | test_commit reachable && |
| 526 | git repack -Ad && |
| 527 | git branch -M main && |
| 528 | |
| 529 | git checkout --orphan other && |
| 530 | test_commit cruft && |
| 531 | git repack -d && |
| 532 | |
| 533 | git checkout main && |
| 534 | git branch -D other && |
| 535 | git tag -d cruft && |
| 536 | git reflog expire --all --expire=all && |
| 537 | |
| 538 | git repack --cruft && |
| 539 | |
| 540 | find $packdir -type f | sort >before && |
| 541 | git repack --geometric=2 -d && |
| 542 | find $packdir -type f | sort >after && |
| 543 | |
| 544 | test_cmp before after |
| 545 | ) |
| 546 | ' |
| 547 | |
| 548 | test_expect_success 'repack --geometric collects once-cruft objects' ' |
| 549 | git init repo && |
| 550 | test_when_finished "rm -fr repo" && |
| 551 | ( |
| 552 | cd repo && |
| 553 | |
| 554 | test_commit reachable && |
| 555 | git repack -Ad && |
| 556 | git branch -M main && |
| 557 | |
| 558 | git checkout --orphan other && |
| 559 | git rm -rf . && |
| 560 | test_commit --no-tag cruft && |
| 561 | cruft="$(git rev-parse HEAD)" && |
| 562 | |
| 563 | git checkout main && |
| 564 | git branch -D other && |
| 565 | git reflog expire --all --expire=all && |
| 566 | |
| 567 | # Pack the objects created in the previous step into a cruft |
| 568 | # pack. Intentionally leave loose copies of those objects |
| 569 | # around so we can pick them up in a subsequent --geometric |
| 570 | # reapack. |
| 571 | git repack --cruft && |
| 572 | |
| 573 | # Now make those objects reachable, and ensure that they are |
| 574 | # packed into the new pack created via a --geometric repack. |
| 575 | git update-ref refs/heads/other $cruft && |
| 576 | |
| 577 | # Without this object, the set of unpacked objects is exactly |
| 578 | # the set of objects already in the cruft pack. Tweak that set |
| 579 | # to ensure we do not overwrite the cruft pack entirely. |
| 580 | test_commit reachable2 && |
| 581 | |
| 582 | find $packdir -name "pack-*.idx" | sort >before && |
| 583 | git repack --geometric=2 -d && |
| 584 | find $packdir -name "pack-*.idx" | sort >after && |
| 585 | |
| 586 | { |
| 587 | git rev-list --objects --no-object-names $cruft && |
| 588 | git rev-list --objects --no-object-names reachable..reachable2 |
| 589 | } >want.raw && |
| 590 | sort want.raw >want && |
| 591 | |
| 592 | pack=$(comm -13 before after) && |
| 593 | git show-index <$pack >objects.raw && |
| 594 | |
| 595 | cut -d" " -f2 objects.raw | sort >got && |
| 596 | |
| 597 | test_cmp want got |
| 598 | ) |
| 599 | ' |
| 600 | |
| 601 | test_expect_success 'cruft repack with no reachable objects' ' |
| 602 | git init repo && |
| 603 | test_when_finished "rm -fr repo" && |
| 604 | ( |
| 605 | cd repo && |
| 606 | |
| 607 | test_commit base && |
| 608 | git repack -ad && |
| 609 | |
| 610 | base="$(git rev-parse base)" && |
| 611 | |
| 612 | git for-each-ref --format="delete %(refname)" >in && |
| 613 | git update-ref --stdin <in && |
| 614 | git reflog expire --all --expire=all && |
| 615 | rm -fr .git/index && |
| 616 | |
| 617 | git repack --cruft -d && |
| 618 | |
| 619 | git cat-file -t $base |
| 620 | ) |
| 621 | ' |
| 622 | |
| 623 | find_pack () { |
| 624 | for idx in $(ls $packdir/pack-*.idx) |
| 625 | do |
| 626 | git show-index <$idx >out && |
| 627 | if grep -q "$1" out |
| 628 | then |
| 629 | echo $idx |
| 630 | fi || return 1 |
| 631 | done |
| 632 | } |
| 633 | |
| 634 | test_expect_success 'cruft repack with --max-pack-size' ' |
| 635 | git init max-pack-size && |
| 636 | ( |
| 637 | cd max-pack-size && |
| 638 | test_commit base && |
| 639 | |
| 640 | # two cruft objects which exceed the maximum pack size |
| 641 | foo=$(generate_random_blob foo 1048576) && |
| 642 | bar=$(generate_random_blob bar 1048576) && |
| 643 | test-tool chmtime --get -1000 \ |
| 644 | "$objdir/$(test_oid_to_path $foo)" >foo.mtime && |
| 645 | test-tool chmtime --get -2000 \ |
| 646 | "$objdir/$(test_oid_to_path $bar)" >bar.mtime && |
| 647 | git repack --cruft --max-pack-size=1M && |
| 648 | find $packdir -name "*.mtimes" >cruft && |
| 649 | test_line_count = 2 cruft && |
| 650 | |
| 651 | foo_mtimes="$(basename $(find_pack $foo) .idx).mtimes" && |
| 652 | bar_mtimes="$(basename $(find_pack $bar) .idx).mtimes" && |
| 653 | test-tool pack-mtimes $foo_mtimes >foo.actual && |
| 654 | test-tool pack-mtimes $bar_mtimes >bar.actual && |
| 655 | |
| 656 | echo "$foo $(cat foo.mtime)" >foo.expect && |
| 657 | echo "$bar $(cat bar.mtime)" >bar.expect && |
| 658 | |
| 659 | test_cmp foo.expect foo.actual && |
| 660 | test_cmp bar.expect bar.actual && |
| 661 | test "$foo_mtimes" != "$bar_mtimes" |
| 662 | ) |
| 663 | ' |
| 664 | |
| 665 | test_expect_success 'cruft repack with pack.packSizeLimit' ' |
| 666 | ( |
| 667 | cd max-pack-size && |
| 668 | # repack everything back together to remove the existing cruft |
| 669 | # pack (but to keep its objects) |
| 670 | git repack -adk && |
| 671 | git -c pack.packSizeLimit=1M repack --cruft && |
| 672 | # ensure the same post condition is met when --max-pack-size |
| 673 | # would otherwise be inferred from the configuration |
| 674 | find $packdir -name "*.mtimes" >cruft && |
| 675 | test_line_count = 2 cruft && |
| 676 | for pack in $(cat cruft) |
| 677 | do |
| 678 | test-tool pack-mtimes "$(basename $pack)" >objects && |
| 679 | test_line_count = 1 objects || return 1 |
| 680 | done |
| 681 | ) |
| 682 | ' |
| 683 | |
| 684 | test_expect_success 'cruft repack respects repack.cruftWindow' ' |
| 685 | git init repo && |
| 686 | test_when_finished "rm -fr repo" && |
| 687 | ( |
| 688 | cd repo && |
| 689 | |
| 690 | test_commit base && |
| 691 | |
| 692 | GIT_TRACE2_EVENT=$(pwd)/event.trace \ |
| 693 | git -c pack.window=1 -c repack.cruftWindow=2 repack \ |
| 694 | --cruft --window=3 && |
| 695 | |
| 696 | test_grep "pack-objects.*--window=2.*--cruft" event.trace |
| 697 | ) |
| 698 | ' |
| 699 | |
| 700 | test_expect_success 'cruft repack respects --window by default' ' |
| 701 | git init repo && |
| 702 | test_when_finished "rm -fr repo" && |
| 703 | ( |
| 704 | cd repo && |
| 705 | |
| 706 | test_commit base && |
| 707 | |
| 708 | GIT_TRACE2_EVENT=$(pwd)/event.trace \ |
| 709 | git -c pack.window=2 repack --cruft --window=3 && |
| 710 | |
| 711 | test_grep "pack-objects.*--window=3.*--cruft" event.trace |
| 712 | ) |
| 713 | ' |
| 714 | |
| 715 | test_expect_success 'cruft repack respects --quiet' ' |
| 716 | git init repo && |
| 717 | test_when_finished "rm -fr repo" && |
| 718 | ( |
| 719 | cd repo && |
| 720 | |
| 721 | test_commit base && |
| 722 | GIT_PROGRESS_DELAY=0 git repack --cruft --quiet 2>err && |
| 723 | test_must_be_empty err |
| 724 | ) |
| 725 | ' |
| 726 | |
| 727 | setup_cruft_exclude_tests() { |
| 728 | git init "$1" && |
| 729 | ( |
| 730 | cd "$1" && |
| 731 | |
| 732 | git config repack.midxMustContainCruft false && |
| 733 | |
| 734 | test_commit one && |
| 735 | |
| 736 | test_commit --no-tag two && |
| 737 | two="$(git rev-parse HEAD)" && |
| 738 | test_commit --no-tag three && |
| 739 | three="$(git rev-parse HEAD)" && |
| 740 | git reset --hard one && |
| 741 | git reflog expire --all --expire=all && |
| 742 | |
| 743 | GIT_TEST_MULTI_PACK_INDEX=0 git repack --cruft -d && |
| 744 | |
| 745 | git merge $two && |
| 746 | test_commit four |
| 747 | ) |
| 748 | } |
| 749 | |
| 750 | test_expect_success 'repack --write-midx excludes cruft where possible' ' |
| 751 | setup_cruft_exclude_tests exclude-cruft-when-possible && |
| 752 | ( |
| 753 | cd exclude-cruft-when-possible && |
| 754 | |
| 755 | GIT_TEST_MULTI_PACK_INDEX=0 \ |
| 756 | git repack -d --geometric=2 --write-midx --write-bitmap-index && |
| 757 | |
| 758 | test-tool read-midx --show-objects $objdir >midx && |
| 759 | cruft="$(ls $packdir/*.mtimes)" && |
| 760 | test_grep ! "$(basename "$cruft" .mtimes).idx" midx && |
| 761 | |
| 762 | git rev-list --all --objects --no-object-names >reachable.raw && |
| 763 | sort reachable.raw >reachable.objects && |
| 764 | awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects && |
| 765 | |
| 766 | test_cmp reachable.objects midx.objects |
| 767 | ) |
| 768 | ' |
| 769 | |
| 770 | test_expect_success 'repack --write-midx includes cruft when instructed' ' |
| 771 | setup_cruft_exclude_tests exclude-cruft-when-instructed && |
| 772 | ( |
| 773 | cd exclude-cruft-when-instructed && |
| 774 | |
| 775 | GIT_TEST_MULTI_PACK_INDEX=0 \ |
| 776 | git -c repack.midxMustContainCruft=true repack \ |
| 777 | -d --geometric=2 --write-midx --write-bitmap-index && |
| 778 | |
| 779 | test-tool read-midx --show-objects $objdir >midx && |
| 780 | cruft="$(ls $packdir/*.mtimes)" && |
| 781 | test_grep "$(basename "$cruft" .mtimes).idx" midx && |
| 782 | |
| 783 | git cat-file --batch-check="%(objectname)" --batch-all-objects \ |
| 784 | >all.objects && |
| 785 | awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects && |
| 786 | |
| 787 | test_cmp all.objects midx.objects |
| 788 | ) |
| 789 | ' |
| 790 | |
| 791 | test_expect_success 'repack --write-midx includes cruft when necessary' ' |
| 792 | setup_cruft_exclude_tests exclude-cruft-when-necessary && |
| 793 | ( |
| 794 | cd exclude-cruft-when-necessary && |
| 795 | |
| 796 | test_path_is_file $(ls $packdir/pack-*.mtimes) && |
| 797 | ( cd $packdir && ls pack-*.idx ) | sort >packs.all && |
| 798 | git multi-pack-index write --stdin-packs --bitmap <packs.all && |
| 799 | |
| 800 | test_commit five && |
| 801 | GIT_TEST_MULTI_PACK_INDEX=0 \ |
| 802 | git repack -d --geometric=2 --write-midx --write-bitmap-index && |
| 803 | |
| 804 | test-tool read-midx --show-objects $objdir >midx && |
| 805 | awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects && |
| 806 | git cat-file --batch-all-objects --batch-check="%(objectname)" \ |
| 807 | >expect.objects && |
| 808 | test_cmp expect.objects midx.objects && |
| 809 | |
| 810 | grep "^pack-" midx >midx.packs && |
| 811 | test_line_count = "$(($(wc -l <packs.all) + 1))" midx.packs |
| 812 | ) |
| 813 | ' |
| 814 | |
| 815 | test_expect_success 'repack --write-midx includes cruft when already geometric' ' |
| 816 | git init repack--write-midx-geometric-noop && |
| 817 | ( |
| 818 | cd repack--write-midx-geometric-noop && |
| 819 | |
| 820 | git branch -M main && |
| 821 | test_commit A && |
| 822 | test_commit B && |
| 823 | |
| 824 | git checkout -B side && |
| 825 | test_commit --no-tag C && |
| 826 | C="$(git rev-parse HEAD)" && |
| 827 | |
| 828 | git checkout main && |
| 829 | git branch -D side && |
| 830 | git reflog expire --all --expire=all && |
| 831 | |
| 832 | # At this point we have two packs: one containing the |
| 833 | # objects belonging to commits A and B, and another |
| 834 | # (cruft) pack containing the objects belonging to |
| 835 | # commit C. |
| 836 | git repack --cruft -d && |
| 837 | |
| 838 | # Create a third pack which contains a merge commit |
| 839 | # making commit C reachable again. |
| 840 | # |
| 841 | # --no-ff is important here, as it ensures that we |
| 842 | # actually write a new object and subsequently a new |
| 843 | # pack to contain it. |
| 844 | git merge --no-ff $C && |
| 845 | git repack -d && |
| 846 | |
| 847 | ls $packdir/pack-*.idx | sort >packs.all && |
| 848 | cruft="$(ls $packdir/pack-*.mtimes)" && |
| 849 | cruft="${cruft%.mtimes}.idx" && |
| 850 | |
| 851 | for idx in $(grep -v $cruft <packs.all) |
| 852 | do |
| 853 | git show-index <$idx >out && |
| 854 | wc -l <out || return 1 |
| 855 | done >sizes.raw && |
| 856 | |
| 857 | # Make sure that there are two non-cruft packs, and |
| 858 | # that one of them contains at least twice as many |
| 859 | # objects as the other, ensuring that they are already |
| 860 | # in a geometric progression. |
| 861 | sort -n sizes.raw >sizes && |
| 862 | test_line_count = 2 sizes && |
| 863 | s1=$(head -n 1 sizes) && |
| 864 | s2=$(tail -n 1 sizes) && |
| 865 | test "$s2" -gt "$((2 * $s1))" && |
| 866 | |
| 867 | git -c repack.midxMustContainCruft=false repack --geometric=2 \ |
| 868 | --write-midx --write-bitmap-index |
| 869 | ) |
| 870 | ' |
| 871 | |
| 872 | test_expect_success 'repack rescues once-cruft objects above geometric split' ' |
| 873 | git config repack.midxMustContainCruft false && |
| 874 | |
| 875 | test_commit reachable && |
| 876 | test_commit unreachable && |
| 877 | |
| 878 | unreachable="$(git rev-parse HEAD)" && |
| 879 | |
| 880 | git reset --hard HEAD^ && |
| 881 | git tag -d unreachable && |
| 882 | git reflog expire --all --expire=all && |
| 883 | |
| 884 | git repack --cruft -d && |
| 885 | |
| 886 | echo $unreachable | git pack-objects .git/objects/pack/pack && |
| 887 | |
| 888 | test_commit new && |
| 889 | |
| 890 | git update-ref refs/heads/other $unreachable && |
| 891 | git repack --geometric=2 -d --write-midx --write-bitmap-index |
| 892 | ' |
| 893 | |
| 894 | test_expect_success 'repack --geometric --cruft combines packs and writes cruft' ' |
| 895 | git init geometric-cruft-basic && |
| 896 | ( |
| 897 | cd geometric-cruft-basic && |
| 898 | |
| 899 | test_commit A && |
| 900 | test_commit B && |
| 901 | |
| 902 | B="$(git rev-parse B)" && |
| 903 | |
| 904 | git reset --hard $B^ && |
| 905 | git tag -d B && |
| 906 | git reflog expire --all --expire=all && |
| 907 | |
| 908 | # Initial state: one non-cruft pack, one cruft pack. |
| 909 | git repack -d --cruft && |
| 910 | |
| 911 | ls $packdir/pack-*.mtimes >cruft.before && |
| 912 | test_line_count = 1 cruft.before && |
| 913 | |
| 914 | test_commit C && |
| 915 | git repack && |
| 916 | |
| 917 | # At this point we have three packs: |
| 918 | # - the non-cruft pack from A |
| 919 | # - the cruft pack from B |
| 920 | # - a new non-cruft pack from C |
| 921 | # |
| 922 | # The two non-cruft packs are not in a geometric |
| 923 | # progression, so they should be rolled up. |
| 924 | git repack -d --geometric=2 --cruft && |
| 925 | |
| 926 | # The old cruft pack for B is retained, since the |
| 927 | # geometric repack does not touch cruft packs. |
| 928 | ls $packdir/pack-*.mtimes >cruft.after && |
| 929 | test_line_count = 1 cruft.after && |
| 930 | |
| 931 | # Ensure that all reachable objects are present. |
| 932 | git fsck |
| 933 | ) |
| 934 | ' |
| 935 | |
| 936 | test_expect_success 'repack --geometric --cruft writes new cruft for loose unreachable' ' |
| 937 | git init geometric-cruft-new-cruft && |
| 938 | ( |
| 939 | cd geometric-cruft-new-cruft && |
| 940 | |
| 941 | git config set maintenance.auto false && |
| 942 | |
| 943 | test_commit A && |
| 944 | git repack && |
| 945 | |
| 946 | test_commit B && |
| 947 | git repack && |
| 948 | |
| 949 | # Create an unreachable commit whose objects are |
| 950 | # still loose (never packed). |
| 951 | test_commit C && |
| 952 | C="$(git rev-parse C)" && |
| 953 | git reset --hard $C^ && |
| 954 | git tag -d C && |
| 955 | git reflog expire --all --expire=all && |
| 956 | |
| 957 | # At this point we have two non-cruft packs of |
| 958 | # similar size that are not in geometric progression, |
| 959 | # and loose unreachable objects from commit C. |
| 960 | ls $packdir/pack-*.idx >packs.before && |
| 961 | test_line_count = 2 packs.before && |
| 962 | |
| 963 | # Geometric+cruft repack should roll up the two |
| 964 | # non-cruft packs and write a new cruft pack for C |
| 965 | # (whose objects are loose and unreachable). |
| 966 | git repack -d --geometric=2 --cruft && |
| 967 | |
| 968 | ls $packdir/pack-*.mtimes >cruft.after && |
| 969 | test_line_count = 1 cruft.after && |
| 970 | |
| 971 | git fsck |
| 972 | ) |
| 973 | ' |
| 974 | |
| 975 | test_expect_success 'repack --geometric --cruft -d deletes rolled-up packs' ' |
| 976 | git init geometric-cruft-delete && |
| 977 | ( |
| 978 | cd geometric-cruft-delete && |
| 979 | |
| 980 | test_commit A && |
| 981 | git repack -d && |
| 982 | |
| 983 | test_commit B && |
| 984 | git repack -d && |
| 985 | |
| 986 | ls $packdir/pack-*.idx >before && |
| 987 | |
| 988 | git repack -d --geometric=2 --cruft && |
| 989 | |
| 990 | # Two packs should have been rolled into one. No cruft |
| 991 | # pack is written because there are no unreachable objects. |
| 992 | ls $packdir/pack-*.idx >after && |
| 993 | test_line_count = 1 after && |
| 994 | |
| 995 | # The rolled-up packs should be gone. |
| 996 | ! test_cmp before after |
| 997 | ) |
| 998 | ' |
| 999 | |
| 1000 | test_expect_success 'repack --geometric --cruft collects loose unreachable objects' ' |
| 1001 | git init geometric-cruft-loose && |
| 1002 | ( |
| 1003 | cd geometric-cruft-loose && |
| 1004 | |
| 1005 | test_commit A && |
| 1006 | git repack -d && |
| 1007 | |
| 1008 | test_commit B && |
| 1009 | git repack && |
| 1010 | |
| 1011 | # Create a loose unreachable object by making it |
| 1012 | # orphaned (not in any pack). |
| 1013 | loose="$(echo "cruft object" | git hash-object -w --stdin)" && |
| 1014 | |
| 1015 | # We have two non-cruft packs and a loose unreachable |
| 1016 | # object. The geometric+cruft repack should roll up |
| 1017 | # the packs AND write a cruft pack for the loose |
| 1018 | # unreachable object. |
| 1019 | git repack -d --geometric=2 --cruft && |
| 1020 | |
| 1021 | ls $packdir/pack-*.mtimes >cruft.packs && |
| 1022 | test_line_count = 1 cruft.packs && |
| 1023 | |
| 1024 | git fsck |
| 1025 | ) |
| 1026 | ' |
| 1027 | |
| 1028 | test_expect_success 'repack --geometric --cruft accumulates cruft packs' ' |
| 1029 | git init geometric-cruft-accumulate && |
| 1030 | ( |
| 1031 | cd geometric-cruft-accumulate && |
| 1032 | |
| 1033 | git config set maintenance.auto false && |
| 1034 | |
| 1035 | test_commit A && |
| 1036 | git repack && |
| 1037 | |
| 1038 | # First round: create unreachable objects and do a |
| 1039 | # geometric+cruft repack. |
| 1040 | unreachable_1="$(echo "cruft 1" | git hash-object -w --stdin)" && |
| 1041 | git repack -d --geometric=2 --cruft && |
| 1042 | |
| 1043 | ls $packdir/pack-*.mtimes >cruft.1 && |
| 1044 | test_line_count = 1 cruft.1 && |
| 1045 | |
| 1046 | test_commit B && |
| 1047 | git repack && |
| 1048 | |
| 1049 | # Second round: create more unreachable objects and |
| 1050 | # repack again. The old cruft pack should be retained |
| 1051 | # and a new one written. |
| 1052 | unreachable_2="$(echo "cruft 2" | git hash-object -w --stdin)" && |
| 1053 | git repack -d --geometric=2 --cruft && |
| 1054 | |
| 1055 | ls $packdir/pack-*.mtimes >cruft.2 && |
| 1056 | test_line_count = 2 cruft.2 && |
| 1057 | |
| 1058 | git fsck |
| 1059 | ) |
| 1060 | ' |
| 1061 | |
| 1062 | test_expect_success 'repack --geometric --cruft --combine-cruft-below-size' ' |
| 1063 | git init geometric-cruft-combine && |
| 1064 | ( |
| 1065 | cd geometric-cruft-combine && |
| 1066 | |
| 1067 | git config set maintenance.auto false && |
| 1068 | |
| 1069 | test_commit A && |
| 1070 | git repack && |
| 1071 | |
| 1072 | # Create a small cruft pack. |
| 1073 | unreachable_1="$(echo "cruft 1" | git hash-object -w --stdin)" && |
| 1074 | git repack -d --geometric=2 --cruft && |
| 1075 | |
| 1076 | ls $packdir/pack-*.mtimes >cruft.before && |
| 1077 | test_line_count = 1 cruft.before && |
| 1078 | |
| 1079 | test_commit B && |
| 1080 | git repack && |
| 1081 | |
| 1082 | # Create another small cruft pack. |
| 1083 | unreachable_2="$(echo "cruft 2" | git hash-object -w --stdin)" && |
| 1084 | git repack -d --geometric=2 --cruft && |
| 1085 | |
| 1086 | ls $packdir/pack-*.mtimes >cruft.mid && |
| 1087 | test_line_count = 2 cruft.mid && |
| 1088 | |
| 1089 | test_commit C && |
| 1090 | git repack && |
| 1091 | |
| 1092 | # With --combine-cruft-below-size, the two small cruft |
| 1093 | # packs should be combined into one. |
| 1094 | unreachable_3="$(echo "cruft 3" | git hash-object -w --stdin)" && |
| 1095 | git repack -d --geometric=2 --cruft \ |
| 1096 | --combine-cruft-below-size=10M && |
| 1097 | |
| 1098 | ls $packdir/pack-*.mtimes >cruft.after && |
| 1099 | test_line_count = 1 cruft.after && |
| 1100 | |
| 1101 | git fsck |
| 1102 | ) |
| 1103 | ' |
| 1104 | |
| 1105 | test_expect_success 'repack --geometric --cruft --expire-to' ' |
| 1106 | git init geometric-cruft-expire-to && |
| 1107 | ( |
| 1108 | cd geometric-cruft-expire-to && |
| 1109 | |
| 1110 | git config set maintenance.auto false && |
| 1111 | |
| 1112 | test_commit A && |
| 1113 | git repack && |
| 1114 | |
| 1115 | test_commit B && |
| 1116 | git repack && |
| 1117 | |
| 1118 | # Create unreachable objects and record them. |
| 1119 | test_commit C && |
| 1120 | C="$(git rev-parse C)" && |
| 1121 | git rev-list --objects --no-object-names B..C >unreachable.raw && |
| 1122 | sort unreachable.raw >unreachable.want && |
| 1123 | |
| 1124 | git reset --hard $C^ && |
| 1125 | git tag -d C && |
| 1126 | git reflog expire --all --expire=all && |
| 1127 | |
| 1128 | git init --bare expired.git && |
| 1129 | git repack -d --geometric=2 --cruft \ |
| 1130 | --cruft-expiration=now \ |
| 1131 | --expire-to="expired.git/objects/pack/pack" && |
| 1132 | |
| 1133 | # The expired objects should appear in the |
| 1134 | # expire-to location. |
| 1135 | expired="$(ls expired.git/objects/pack/pack-*.idx)" && |
| 1136 | test_path_is_file "${expired%.idx}.mtimes" && |
| 1137 | git show-index <"$expired" >expired.raw && |
| 1138 | cut -d" " -f2 expired.raw | sort >expired.objects && |
| 1139 | test_cmp unreachable.want expired.objects && |
| 1140 | |
| 1141 | git fsck |
| 1142 | ) |
| 1143 | ' |
| 1144 | |
| 1145 | test_done |