| 1 | #!/bin/sh |
| 2 | # |
| 3 | # Copyright (c) 2005 Junio C Hamano |
| 4 | # |
| 5 | |
| 6 | test_description='git pack-object' |
| 7 | |
| 8 | . ./test-lib.sh |
| 9 | |
| 10 | test_expect_success 'setup' ' |
| 11 | rm -f .git/index* && |
| 12 | test-tool genzeros 4096 | tr "\000" "a" >a && |
| 13 | test-tool genzeros 4096 | tr "\000" "b" >b && |
| 14 | test-tool genzeros 4096 | tr "\000" "c" >c && |
| 15 | test-tool genrandom "seed a" 2097152 >a_big && |
| 16 | test-tool genrandom "seed b" 2097152 >b_big && |
| 17 | git update-index --add a a_big b b_big c && |
| 18 | cat c >d && echo foo >>d && git update-index --add d && |
| 19 | tree=$(git write-tree) && |
| 20 | commit=$(git commit-tree $tree </dev/null) && |
| 21 | { |
| 22 | echo $tree && |
| 23 | echo $commit && |
| 24 | git ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\) .*/\\1/" |
| 25 | } >obj-list && |
| 26 | { |
| 27 | git diff-tree --root -p $commit && |
| 28 | while read object |
| 29 | do |
| 30 | t=$(git cat-file -t $object) && |
| 31 | git cat-file $t $object || return 1 |
| 32 | done <obj-list |
| 33 | } >expect |
| 34 | ' |
| 35 | |
| 36 | test_expect_success 'setup pack-object <stdin' ' |
| 37 | git init pack-object-stdin && |
| 38 | test_commit -C pack-object-stdin one && |
| 39 | test_commit -C pack-object-stdin two |
| 40 | |
| 41 | ' |
| 42 | |
| 43 | test_expect_success 'pack-object <stdin parsing: basic [|--revs]' ' |
| 44 | cat >in <<-EOF && |
| 45 | $(git -C pack-object-stdin rev-parse one) |
| 46 | EOF |
| 47 | |
| 48 | git -C pack-object-stdin pack-objects basic-stdin <in && |
| 49 | idx=$(echo pack-object-stdin/basic-stdin-*.idx) && |
| 50 | git show-index <"$idx" >actual && |
| 51 | test_line_count = 1 actual && |
| 52 | |
| 53 | git -C pack-object-stdin pack-objects --revs basic-stdin-revs <in && |
| 54 | idx=$(echo pack-object-stdin/basic-stdin-revs-*.idx) && |
| 55 | git show-index <"$idx" >actual && |
| 56 | test_line_count = 3 actual |
| 57 | ' |
| 58 | |
| 59 | test_expect_success 'pack-object <stdin parsing: [|--revs] bad line' ' |
| 60 | cat >in <<-EOF && |
| 61 | $(git -C pack-object-stdin rev-parse one) |
| 62 | garbage |
| 63 | $(git -C pack-object-stdin rev-parse two) |
| 64 | EOF |
| 65 | |
| 66 | sed "s/^> //g" >err.expect <<-EOF && |
| 67 | fatal: expected object ID, got garbage: |
| 68 | > garbage |
| 69 | |
| 70 | EOF |
| 71 | test_must_fail git -C pack-object-stdin pack-objects bad-line-stdin <in 2>err.actual && |
| 72 | test_cmp err.expect err.actual && |
| 73 | |
| 74 | cat >err.expect <<-EOF && |
| 75 | fatal: bad revision '"'"'garbage'"'"' |
| 76 | EOF |
| 77 | test_must_fail git -C pack-object-stdin pack-objects --revs bad-line-stdin-revs <in 2>err.actual && |
| 78 | test_cmp err.expect err.actual |
| 79 | ' |
| 80 | |
| 81 | test_expect_success 'pack-object <stdin parsing: [|--revs] empty line' ' |
| 82 | cat >in <<-EOF && |
| 83 | $(git -C pack-object-stdin rev-parse one) |
| 84 | |
| 85 | $(git -C pack-object-stdin rev-parse two) |
| 86 | EOF |
| 87 | |
| 88 | sed -e "s/^> //g" -e "s/Z$//g" >err.expect <<-EOF && |
| 89 | fatal: expected object ID, got garbage: |
| 90 | > Z |
| 91 | |
| 92 | EOF |
| 93 | test_must_fail git -C pack-object-stdin pack-objects empty-line-stdin <in 2>err.actual && |
| 94 | test_cmp err.expect err.actual && |
| 95 | |
| 96 | git -C pack-object-stdin pack-objects --revs empty-line-stdin-revs <in && |
| 97 | idx=$(echo pack-object-stdin/empty-line-stdin-revs-*.idx) && |
| 98 | git show-index <"$idx" >actual && |
| 99 | test_line_count = 3 actual |
| 100 | ' |
| 101 | |
| 102 | test_expect_success 'pack-object <stdin parsing: [|--revs] with --stdin' ' |
| 103 | cat >in <<-EOF && |
| 104 | $(git -C pack-object-stdin rev-parse one) |
| 105 | $(git -C pack-object-stdin rev-parse two) |
| 106 | EOF |
| 107 | |
| 108 | # There is the "--stdin-packs is incompatible with --revs" |
| 109 | # test below, but we should make sure that the revision.c |
| 110 | # --stdin is not picked up |
| 111 | cat >err.expect <<-EOF && |
| 112 | fatal: disallowed abbreviated or ambiguous option '"'"'stdin'"'"' |
| 113 | EOF |
| 114 | test_must_fail git -C pack-object-stdin pack-objects stdin-with-stdin-option --stdin <in 2>err.actual && |
| 115 | test_cmp err.expect err.actual && |
| 116 | |
| 117 | test_must_fail git -C pack-object-stdin pack-objects --stdin --revs stdin-with-stdin-option-revs 2>err.actual <in && |
| 118 | test_cmp err.expect err.actual |
| 119 | ' |
| 120 | |
| 121 | test_expect_success 'pack-object <stdin parsing: --stdin-packs handles garbage' ' |
| 122 | cat >in <<-EOF && |
| 123 | $(git -C pack-object-stdin rev-parse one) |
| 124 | $(git -C pack-object-stdin rev-parse two) |
| 125 | EOF |
| 126 | |
| 127 | # That we get "two" and not "one" has to do with OID |
| 128 | # ordering. It happens to be the same here under SHA-1 and |
| 129 | # SHA-256. See commentary in pack-objects.c |
| 130 | cat >err.expect <<-EOF && |
| 131 | fatal: could not find pack '"'"'$(git -C pack-object-stdin rev-parse two)'"'"' |
| 132 | EOF |
| 133 | test_must_fail git \ |
| 134 | -C pack-object-stdin \ |
| 135 | pack-objects stdin-with-stdin-option --stdin-packs \ |
| 136 | <in 2>err.actual && |
| 137 | test_cmp err.expect err.actual |
| 138 | ' |
| 139 | |
| 140 | # usage: check_deltas <stderr_from_pack_objects> <cmp_op> <nr_deltas> |
| 141 | # e.g.: check_deltas stderr -gt 0 |
| 142 | check_deltas() { |
| 143 | deltas=$(sed -n 's/Total [0-9][0-9]* (delta \([0-9][0-9]*\)).*/\1/p' "$1") && |
| 144 | shift && |
| 145 | if ! test "$deltas" "$@" |
| 146 | then |
| 147 | echo >&2 "unexpected number of deltas (compared $delta $*)" |
| 148 | return 1 |
| 149 | fi |
| 150 | } |
| 151 | |
| 152 | test_expect_success 'pack without delta' ' |
| 153 | packname_1=$(git pack-objects --progress --window=0 test-1 \ |
| 154 | <obj-list 2>stderr) && |
| 155 | check_deltas stderr = 0 |
| 156 | ' |
| 157 | |
| 158 | test_expect_success 'negative window clamps to 0' ' |
| 159 | git pack-objects --progress --window=-1 neg-window <obj-list 2>stderr && |
| 160 | check_deltas stderr = 0 |
| 161 | ' |
| 162 | |
| 163 | test_expect_success 'pack-objects with bogus arguments' ' |
| 164 | test_must_fail git pack-objects --window=0 test-1 blah blah <obj-list |
| 165 | ' |
| 166 | |
| 167 | check_unpack () { |
| 168 | local packname="$1" && |
| 169 | local object_list="$2" && |
| 170 | local git_config="$3" && |
| 171 | test_when_finished "rm -rf git2" && |
| 172 | git $git_config init --bare git2 && |
| 173 | ( |
| 174 | git $git_config -C git2 unpack-objects -n <"$packname".pack && |
| 175 | git $git_config -C git2 unpack-objects <"$packname".pack && |
| 176 | git $git_config -C git2 cat-file --batch-check="%(objectname)" |
| 177 | ) <"$object_list" >current && |
| 178 | cmp "$object_list" current |
| 179 | } |
| 180 | |
| 181 | test_expect_success 'unpack without delta' ' |
| 182 | check_unpack test-1-${packname_1} obj-list |
| 183 | ' |
| 184 | |
| 185 | BATCH_CONFIGURATION='-c core.fsync=loose-object -c core.fsyncmethod=batch' |
| 186 | |
| 187 | test_expect_success 'unpack without delta (core.fsyncmethod=batch)' ' |
| 188 | check_unpack test-1-${packname_1} obj-list "$BATCH_CONFIGURATION" |
| 189 | ' |
| 190 | |
| 191 | test_expect_success 'pack with REF_DELTA' ' |
| 192 | packname_2=$(git pack-objects --progress test-2 <obj-list 2>stderr) && |
| 193 | check_deltas stderr -gt 0 && |
| 194 | test-tool pack-deltas --list-deltas test-2-$packname_2.idx >deltas && |
| 195 | test_grep " REF_DELTA " deltas |
| 196 | ' |
| 197 | |
| 198 | test_expect_success 'unpack with REF_DELTA' ' |
| 199 | check_unpack test-2-${packname_2} obj-list |
| 200 | ' |
| 201 | |
| 202 | test_expect_success 'unpack with REF_DELTA (core.fsyncmethod=batch)' ' |
| 203 | check_unpack test-2-${packname_2} obj-list "$BATCH_CONFIGURATION" |
| 204 | ' |
| 205 | |
| 206 | test_expect_success 'pack with OFS_DELTA' ' |
| 207 | packname_3=$(git pack-objects --progress --delta-base-offset test-3 \ |
| 208 | <obj-list 2>stderr) && |
| 209 | check_deltas stderr -gt 0 && |
| 210 | test-tool pack-deltas --list-deltas test-3-$packname_3.idx >deltas && |
| 211 | test_grep " OFS_DELTA " deltas |
| 212 | ' |
| 213 | |
| 214 | test_expect_success 'pack without REF_DELTA' ' |
| 215 | git pack-objects --no-ref-delta --stdout <obj-list >no-ref.pack && |
| 216 | git index-pack -o no-ref.idx no-ref.pack && |
| 217 | |
| 218 | test-tool pack-deltas --list-deltas no-ref.idx >deltas && |
| 219 | test_must_be_empty deltas |
| 220 | ' |
| 221 | |
| 222 | test_expect_success 'pack without REF_DELTA with OFS_DELTA' ' |
| 223 | git pack-objects --delta-base-offset --no-ref-delta --stdout \ |
| 224 | <obj-list >no-ref-ofs.pack && |
| 225 | git index-pack -o no-ref-ofs.idx no-ref-ofs.pack && |
| 226 | |
| 227 | test-tool pack-deltas --list-deltas no-ref-ofs.idx >deltas && |
| 228 | test_grep " OFS_DELTA " deltas && |
| 229 | test_grep ! " REF_DELTA " deltas |
| 230 | ' |
| 231 | |
| 232 | test_expect_success 'pack without REF_DELTA reuses deltas as OFS_DELTA' ' |
| 233 | # Install the REF_DELTA pack above and disable delta search, so any |
| 234 | # output delta must be a reused REF_DELTA rewritten as OFS_DELTA. |
| 235 | test_when_finished "rm -f .git/objects/pack/pack-$packname_2.*" && |
| 236 | git index-pack --stdin <test-2-${packname_2}.pack >/dev/null && |
| 237 | |
| 238 | git pack-objects --window=0 --delta-base-offset \ |
| 239 | --no-ref-delta --stdout <obj-list >reused.pack && |
| 240 | git index-pack -o reused.idx reused.pack && |
| 241 | test-tool pack-deltas --list-deltas reused.idx >deltas && |
| 242 | test_grep " OFS_DELTA " deltas && |
| 243 | test_grep ! " REF_DELTA " deltas |
| 244 | ' |
| 245 | |
| 246 | test_expect_success 'pack without REF_DELTA skips excluded delta bases' ' |
| 247 | test_when_finished "git read-tree $tree" && |
| 248 | |
| 249 | echo bar >>d && |
| 250 | git update-index --add d && |
| 251 | thin_tree=$(git write-tree) && |
| 252 | thin_commit=$(git commit-tree $thin_tree -p $commit </dev/null) && |
| 253 | |
| 254 | { |
| 255 | echo $thin_commit && |
| 256 | echo ^$commit |
| 257 | } >thin-revs && |
| 258 | |
| 259 | # Each type appears only once in the output, so any delta must |
| 260 | # use an excluded base and therefore be a REF_DELTA. |
| 261 | git pack-objects --thin --stdout --revs \ |
| 262 | <thin-revs >thin.pack && |
| 263 | git index-pack --fix-thin --stdin thin-fixed.pack \ |
| 264 | <thin.pack >/dev/null && |
| 265 | |
| 266 | test-tool pack-deltas --list-deltas thin-fixed.idx >deltas && |
| 267 | test_grep ! " OFS_DELTA " deltas && |
| 268 | test_grep " REF_DELTA " deltas && |
| 269 | |
| 270 | # Store the REF_DELTA entries above and disable delta search below, |
| 271 | # so any output delta would have to reuse an excluded-base |
| 272 | # REF_DELTA. |
| 273 | git index-pack --stdin <thin-fixed.pack >/dev/null && |
| 274 | |
| 275 | git pack-objects --thin --window=0 --stdout --revs \ |
| 276 | --delta-base-offset --no-ref-delta \ |
| 277 | <thin-revs >no-ref-thin.pack && |
| 278 | git index-pack --fix-thin --stdin no-ref-thin-fixed.pack \ |
| 279 | <no-ref-thin.pack >/dev/null && |
| 280 | |
| 281 | test-tool pack-deltas --list-deltas no-ref-thin-fixed.idx >deltas && |
| 282 | test_must_be_empty deltas |
| 283 | ' |
| 284 | |
| 285 | test_expect_success 'unpack with OFS_DELTA' ' |
| 286 | check_unpack test-3-${packname_3} obj-list |
| 287 | ' |
| 288 | |
| 289 | test_expect_success 'unpack with OFS_DELTA (core.fsyncmethod=batch)' ' |
| 290 | check_unpack test-3-${packname_3} obj-list "$BATCH_CONFIGURATION" |
| 291 | ' |
| 292 | |
| 293 | test_expect_success PERL_TEST_HELPERS 'compare delta flavors' ' |
| 294 | perl -e '\'' |
| 295 | defined($_ = -s $_) or die for @ARGV; |
| 296 | exit 1 if $ARGV[0] <= $ARGV[1]; |
| 297 | '\'' test-2-$packname_2.pack test-3-$packname_3.pack |
| 298 | ' |
| 299 | |
| 300 | check_use_objects () { |
| 301 | test_when_finished "rm -rf git2" && |
| 302 | git init --bare git2 && |
| 303 | cp "$1".pack "$1".idx git2/objects/pack && |
| 304 | ( |
| 305 | cd git2 && |
| 306 | git diff-tree --root -p $commit && |
| 307 | while read object |
| 308 | do |
| 309 | t=$(git cat-file -t $object) && |
| 310 | git cat-file $t $object || exit 1 |
| 311 | done |
| 312 | ) <obj-list >current && |
| 313 | cmp expect current |
| 314 | } |
| 315 | |
| 316 | test_expect_success 'use packed objects' ' |
| 317 | check_use_objects test-1-${packname_1} |
| 318 | ' |
| 319 | |
| 320 | test_expect_success 'use packed deltified (REF_DELTA) objects' ' |
| 321 | check_use_objects test-2-${packname_2} |
| 322 | ' |
| 323 | |
| 324 | test_expect_success 'use packed deltified (OFS_DELTA) objects' ' |
| 325 | check_use_objects test-3-${packname_3} |
| 326 | ' |
| 327 | |
| 328 | test_expect_success 'survive missing objects/pack directory' ' |
| 329 | ( |
| 330 | rm -fr missing-pack && |
| 331 | mkdir missing-pack && |
| 332 | cd missing-pack && |
| 333 | git init && |
| 334 | GOP=.git/objects/pack && |
| 335 | rm -fr $GOP && |
| 336 | git index-pack --stdin --keep=test <../test-3-${packname_3}.pack && |
| 337 | test -f $GOP/pack-${packname_3}.pack && |
| 338 | cmp $GOP/pack-${packname_3}.pack ../test-3-${packname_3}.pack && |
| 339 | test -f $GOP/pack-${packname_3}.idx && |
| 340 | cmp $GOP/pack-${packname_3}.idx ../test-3-${packname_3}.idx && |
| 341 | test -f $GOP/pack-${packname_3}.keep |
| 342 | ) |
| 343 | ' |
| 344 | |
| 345 | test_expect_success 'verify pack' ' |
| 346 | git verify-pack test-1-${packname_1}.idx \ |
| 347 | test-2-${packname_2}.idx \ |
| 348 | test-3-${packname_3}.idx |
| 349 | ' |
| 350 | |
| 351 | test_expect_success 'verify pack -v' ' |
| 352 | git verify-pack -v test-1-${packname_1}.idx \ |
| 353 | test-2-${packname_2}.idx \ |
| 354 | test-3-${packname_3}.idx |
| 355 | ' |
| 356 | |
| 357 | test_expect_success 'verify-pack catches mismatched .idx and .pack files' ' |
| 358 | cat test-1-${packname_1}.idx >test-3.idx && |
| 359 | cat test-2-${packname_2}.pack >test-3.pack && |
| 360 | if git verify-pack test-3.idx |
| 361 | then false |
| 362 | else :; |
| 363 | fi |
| 364 | ' |
| 365 | |
| 366 | test_expect_success 'verify-pack catches a corrupted pack signature' ' |
| 367 | cat test-1-${packname_1}.pack >test-3.pack && |
| 368 | echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=2 && |
| 369 | if git verify-pack test-3.idx |
| 370 | then false |
| 371 | else :; |
| 372 | fi |
| 373 | ' |
| 374 | |
| 375 | test_expect_success 'verify-pack catches a corrupted pack version' ' |
| 376 | cat test-1-${packname_1}.pack >test-3.pack && |
| 377 | echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=7 && |
| 378 | if git verify-pack test-3.idx |
| 379 | then false |
| 380 | else :; |
| 381 | fi |
| 382 | ' |
| 383 | |
| 384 | test_expect_success 'verify-pack catches a corrupted type/size of the 1st packed object data' ' |
| 385 | cat test-1-${packname_1}.pack >test-3.pack && |
| 386 | echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=12 && |
| 387 | if git verify-pack test-3.idx |
| 388 | then false |
| 389 | else :; |
| 390 | fi |
| 391 | ' |
| 392 | |
| 393 | test_expect_success 'verify-pack catches a corrupted sum of the index file itself' ' |
| 394 | l=$(wc -c <test-3.idx) && |
| 395 | l=$(expr $l - 20) && |
| 396 | cat test-1-${packname_1}.pack >test-3.pack && |
| 397 | printf "%20s" "" | dd of=test-3.idx count=20 bs=1 conv=notrunc seek=$l && |
| 398 | if git verify-pack test-3.pack |
| 399 | then false |
| 400 | else :; |
| 401 | fi |
| 402 | ' |
| 403 | |
| 404 | test_expect_success 'build pack index for an existing pack' ' |
| 405 | cat test-1-${packname_1}.pack >test-3.pack && |
| 406 | git index-pack -o tmp.idx test-3.pack && |
| 407 | cmp tmp.idx test-1-${packname_1}.idx && |
| 408 | |
| 409 | git index-pack test-3.pack && |
| 410 | cmp test-3.idx test-1-${packname_1}.idx && |
| 411 | |
| 412 | cat test-2-${packname_2}.pack >test-3.pack && |
| 413 | git index-pack -o tmp.idx test-2-${packname_2}.pack && |
| 414 | cmp tmp.idx test-2-${packname_2}.idx && |
| 415 | |
| 416 | git index-pack test-3.pack && |
| 417 | cmp test-3.idx test-2-${packname_2}.idx && |
| 418 | |
| 419 | cat test-3-${packname_3}.pack >test-3.pack && |
| 420 | git index-pack -o tmp.idx test-3-${packname_3}.pack && |
| 421 | cmp tmp.idx test-3-${packname_3}.idx && |
| 422 | |
| 423 | git index-pack test-3.pack && |
| 424 | cmp test-3.idx test-3-${packname_3}.idx && |
| 425 | |
| 426 | cat test-1-${packname_1}.pack >test-4.pack && |
| 427 | rm -f test-4.keep && |
| 428 | git index-pack --keep=why test-4.pack && |
| 429 | cmp test-1-${packname_1}.idx test-4.idx && |
| 430 | test -f test-4.keep && |
| 431 | |
| 432 | : |
| 433 | ' |
| 434 | |
| 435 | test_expect_success 'unpacking with --strict' ' |
| 436 | |
| 437 | for j in a b c d e f g |
| 438 | do |
| 439 | for i in 0 1 2 3 4 5 6 7 8 9 |
| 440 | do |
| 441 | o=$(echo $j$i | git hash-object -w --stdin) && |
| 442 | echo "100644 $o 0 $j$i" || return 1 |
| 443 | done |
| 444 | done >LIST && |
| 445 | rm -f .git/index && |
| 446 | git update-index --index-info <LIST && |
| 447 | LIST=$(git write-tree) && |
| 448 | rm -f .git/index && |
| 449 | head -n 10 LIST | git update-index --index-info && |
| 450 | LI=$(git write-tree) && |
| 451 | rm -f .git/index && |
| 452 | tail -n 10 LIST | git update-index --index-info && |
| 453 | ST=$(git write-tree) && |
| 454 | git rev-list --objects "$LIST" "$LI" "$ST" >actual && |
| 455 | PACK5=$( git pack-objects test-5 <actual ) && |
| 456 | PACK6=$( test_write_lines "$LIST" "$LI" "$ST" | git pack-objects test-6 ) && |
| 457 | test_create_repo test-5 && |
| 458 | ( |
| 459 | cd test-5 && |
| 460 | git unpack-objects --strict <../test-5-$PACK5.pack && |
| 461 | git ls-tree -r $LIST && |
| 462 | git ls-tree -r $LI && |
| 463 | git ls-tree -r $ST |
| 464 | ) && |
| 465 | test_create_repo test-6 && |
| 466 | ( |
| 467 | # tree-only into empty repo -- many unreachables |
| 468 | cd test-6 && |
| 469 | test_must_fail git unpack-objects --strict <../test-6-$PACK6.pack |
| 470 | ) && |
| 471 | ( |
| 472 | # already populated -- no unreachables |
| 473 | cd test-5 && |
| 474 | git unpack-objects --strict <../test-6-$PACK6.pack |
| 475 | ) |
| 476 | ' |
| 477 | |
| 478 | test_expect_success 'index-pack with --strict' ' |
| 479 | |
| 480 | for j in a b c d e f g |
| 481 | do |
| 482 | for i in 0 1 2 3 4 5 6 7 8 9 |
| 483 | do |
| 484 | o=$(echo $j$i | git hash-object -w --stdin) && |
| 485 | echo "100644 $o 0 $j$i" || return 1 |
| 486 | done |
| 487 | done >LIST && |
| 488 | rm -f .git/index && |
| 489 | git update-index --index-info <LIST && |
| 490 | LIST=$(git write-tree) && |
| 491 | rm -f .git/index && |
| 492 | head -n 10 LIST | git update-index --index-info && |
| 493 | LI=$(git write-tree) && |
| 494 | rm -f .git/index && |
| 495 | tail -n 10 LIST | git update-index --index-info && |
| 496 | ST=$(git write-tree) && |
| 497 | git rev-list --objects "$LIST" "$LI" "$ST" >actual && |
| 498 | PACK5=$( git pack-objects test-5 <actual ) && |
| 499 | PACK6=$( test_write_lines "$LIST" "$LI" "$ST" | git pack-objects test-6 ) && |
| 500 | test_create_repo test-7 && |
| 501 | ( |
| 502 | cd test-7 && |
| 503 | git index-pack --strict --stdin <../test-5-$PACK5.pack && |
| 504 | git ls-tree -r $LIST && |
| 505 | git ls-tree -r $LI && |
| 506 | git ls-tree -r $ST |
| 507 | ) && |
| 508 | test_create_repo test-8 && |
| 509 | ( |
| 510 | # tree-only into empty repo -- many unreachables |
| 511 | cd test-8 && |
| 512 | test_must_fail git index-pack --strict --stdin <../test-6-$PACK6.pack |
| 513 | ) && |
| 514 | ( |
| 515 | # already populated -- no unreachables |
| 516 | cd test-7 && |
| 517 | git index-pack --strict --stdin <../test-6-$PACK6.pack |
| 518 | ) |
| 519 | ' |
| 520 | |
| 521 | test_expect_success 'setup for --strict and --fsck-objects downgrading fsck msgs' ' |
| 522 | git init strict && |
| 523 | ( |
| 524 | cd strict && |
| 525 | test_commit first hello && |
| 526 | cat >commit <<-EOF && |
| 527 | tree $(git rev-parse HEAD^{tree}) |
| 528 | parent $(git rev-parse HEAD) |
| 529 | author A U Thor |
| 530 | committer A U Thor |
| 531 | |
| 532 | commit: this is a commit with bad emails |
| 533 | |
| 534 | EOF |
| 535 | git hash-object --literally -t commit -w --stdin <commit >commit_list && |
| 536 | git pack-objects test <commit_list >pack-name |
| 537 | ) |
| 538 | ' |
| 539 | |
| 540 | test_with_bad_commit () { |
| 541 | must_fail_arg="$1" && |
| 542 | must_pass_arg="$2" && |
| 543 | ( |
| 544 | cd strict && |
| 545 | test_must_fail git index-pack "$must_fail_arg" "test-$(cat pack-name).pack" && |
| 546 | git index-pack "$must_pass_arg" "test-$(cat pack-name).pack" |
| 547 | ) |
| 548 | } |
| 549 | |
| 550 | test_expect_success 'index-pack with --strict downgrading fsck msgs' ' |
| 551 | test_with_bad_commit --strict --strict="missingEmail=ignore" |
| 552 | ' |
| 553 | |
| 554 | test_expect_success 'index-pack with --fsck-objects downgrading fsck msgs' ' |
| 555 | test_with_bad_commit --fsck-objects --fsck-objects="missingEmail=ignore" |
| 556 | ' |
| 557 | |
| 558 | test_expect_success 'cleanup for --strict and --fsck-objects downgrading fsck msgs' ' |
| 559 | rm -rf strict |
| 560 | ' |
| 561 | |
| 562 | test_expect_success 'honor pack.packSizeLimit' ' |
| 563 | git config pack.packSizeLimit 3m && |
| 564 | packname_10=$(git pack-objects test-10 <obj-list) && |
| 565 | test 2 = $(ls test-10-*.pack | wc -l) |
| 566 | ' |
| 567 | |
| 568 | test_expect_success 'verify resulting packs' ' |
| 569 | git verify-pack test-10-*.pack |
| 570 | ' |
| 571 | |
| 572 | test_expect_success 'tolerate packsizelimit smaller than biggest object' ' |
| 573 | git config pack.packSizeLimit 1 && |
| 574 | packname_11=$(git pack-objects test-11 <obj-list) && |
| 575 | test 5 = $(ls test-11-*.pack | wc -l) |
| 576 | ' |
| 577 | |
| 578 | test_expect_success 'verify resulting packs' ' |
| 579 | git verify-pack test-11-*.pack |
| 580 | ' |
| 581 | |
| 582 | test_expect_success 'set up pack for non-repo tests' ' |
| 583 | # make sure we have a pack with no matching index file |
| 584 | cp test-1-*.pack foo.pack |
| 585 | ' |
| 586 | |
| 587 | test_expect_success 'index-pack --stdin complains of non-repo' ' |
| 588 | nongit test_must_fail git index-pack --object-format=$(test_oid algo) --stdin <foo.pack && |
| 589 | test_path_is_missing non-repo/.git |
| 590 | ' |
| 591 | |
| 592 | test_expect_success 'index-pack <pack> works in non-repo' ' |
| 593 | nongit git index-pack --object-format=$(test_oid algo) ../foo.pack && |
| 594 | test_path_is_file foo.idx |
| 595 | ' |
| 596 | |
| 597 | test_expect_success 'index-pack --strict <pack> works in non-repo' ' |
| 598 | rm -f foo.idx && |
| 599 | nongit git index-pack --strict --object-format=$(test_oid algo) ../foo.pack && |
| 600 | test_path_is_file foo.idx |
| 601 | ' |
| 602 | |
| 603 | test_expect_success DEFAULT_HASH_ALGORITHM 'show-index works OK outside a repository' ' |
| 604 | nongit git show-index <foo.idx |
| 605 | ' |
| 606 | |
| 607 | for hash in sha1 sha256 |
| 608 | do |
| 609 | test_expect_success 'show-index works OK outside a repository with hash algo passed in via --object-format' ' |
| 610 | test_when_finished "rm -rf explicit-hash-$hash" && |
| 611 | git init --object-format=$hash explicit-hash-$hash && |
| 612 | test_commit -C explicit-hash-$hash one && |
| 613 | git -C explicit-hash-$hash rev-parse one >in && |
| 614 | git -C explicit-hash-$hash pack-objects explicit-hash-$hash <in && |
| 615 | idx=$(echo explicit-hash-$hash/explicit-hash-$hash*.idx) && |
| 616 | nongit git show-index --object-format=$hash <"$idx" >actual && |
| 617 | test_line_count = 1 actual |
| 618 | ' |
| 619 | done |
| 620 | |
| 621 | test_expect_success !PTHREADS,!FAIL_PREREQS \ |
| 622 | 'index-pack --threads=N or pack.threads=N warns when no pthreads' ' |
| 623 | test_must_fail git index-pack --threads=2 2>err && |
| 624 | grep ^warning: err >warnings && |
| 625 | test_line_count = 1 warnings && |
| 626 | test_grep -F "no threads support, ignoring --threads=2" err && |
| 627 | |
| 628 | test_must_fail git -c pack.threads=2 index-pack 2>err && |
| 629 | grep ^warning: err >warnings && |
| 630 | test_line_count = 1 warnings && |
| 631 | test_grep -F "no threads support, ignoring pack.threads" err && |
| 632 | |
| 633 | test_must_fail git -c pack.threads=2 index-pack --threads=4 2>err && |
| 634 | grep ^warning: err >warnings && |
| 635 | test_line_count = 2 warnings && |
| 636 | test_grep -F "no threads support, ignoring --threads=4" err && |
| 637 | test_grep -F "no threads support, ignoring pack.threads" err |
| 638 | ' |
| 639 | |
| 640 | test_expect_success !PTHREADS,!FAIL_PREREQS \ |
| 641 | 'pack-objects --threads=N or pack.threads=N warns when no pthreads' ' |
| 642 | git pack-objects --threads=2 --stdout --all </dev/null >/dev/null 2>err && |
| 643 | grep ^warning: err >warnings && |
| 644 | test_line_count = 1 warnings && |
| 645 | test_grep -F "no threads support, ignoring --threads" err && |
| 646 | |
| 647 | git -c pack.threads=2 pack-objects --stdout --all </dev/null >/dev/null 2>err && |
| 648 | grep ^warning: err >warnings && |
| 649 | test_line_count = 1 warnings && |
| 650 | test_grep -F "no threads support, ignoring pack.threads" err && |
| 651 | |
| 652 | git -c pack.threads=2 pack-objects --threads=4 --stdout --all </dev/null >/dev/null 2>err && |
| 653 | grep ^warning: err >warnings && |
| 654 | test_line_count = 2 warnings && |
| 655 | test_grep -F "no threads support, ignoring --threads" err && |
| 656 | test_grep -F "no threads support, ignoring pack.threads" err |
| 657 | ' |
| 658 | |
| 659 | test_expect_success 'pack-objects in too-many-packs mode' ' |
| 660 | GIT_TEST_FULL_IN_PACK_ARRAY=1 git repack -ad && |
| 661 | git fsck |
| 662 | ' |
| 663 | |
| 664 | test_expect_success 'setup: fake a SHA1 hash collision' ' |
| 665 | git init corrupt && |
| 666 | ( |
| 667 | cd corrupt && |
| 668 | long_a=$(git hash-object -w ../a | sed -e "s!^..!&/!") && |
| 669 | long_b=$(git hash-object -w ../b | sed -e "s!^..!&/!") && |
| 670 | test -f .git/objects/$long_b && |
| 671 | cp -f .git/objects/$long_a \ |
| 672 | .git/objects/$long_b |
| 673 | ) |
| 674 | ' |
| 675 | |
| 676 | test_expect_success 'make sure index-pack detects the SHA1 collision' ' |
| 677 | ( |
| 678 | cd corrupt && |
| 679 | test_must_fail git index-pack -o ../bad.idx ../test-3.pack 2>msg && |
| 680 | test_grep "SHA1 COLLISION FOUND" msg |
| 681 | ) |
| 682 | ' |
| 683 | |
| 684 | test_expect_success 'make sure index-pack detects the SHA1 collision (large blobs)' ' |
| 685 | ( |
| 686 | cd corrupt && |
| 687 | test_must_fail git -c core.bigfilethreshold=1 index-pack -o ../bad.idx ../test-3.pack 2>msg && |
| 688 | test_grep "SHA1 COLLISION FOUND" msg |
| 689 | ) |
| 690 | ' |
| 691 | |
| 692 | test_expect_success 'prefetch objects' ' |
| 693 | rm -rf server client && |
| 694 | |
| 695 | git init server && |
| 696 | test_config -C server uploadpack.allowanysha1inwant 1 && |
| 697 | test_config -C server uploadpack.allowfilter 1 && |
| 698 | test_config -C server protocol.version 2 && |
| 699 | |
| 700 | echo one >server/one && |
| 701 | git -C server add one && |
| 702 | git -C server commit -m one && |
| 703 | git -C server branch one_branch && |
| 704 | |
| 705 | echo two_a >server/two_a && |
| 706 | echo two_b >server/two_b && |
| 707 | git -C server add two_a two_b && |
| 708 | git -C server commit -m two && |
| 709 | |
| 710 | echo three >server/three && |
| 711 | git -C server add three && |
| 712 | git -C server commit -m three && |
| 713 | git -C server branch three_branch && |
| 714 | |
| 715 | # Clone, fetch "two" with blobs excluded, and re-push it. This requires |
| 716 | # the client to have the blobs of "two" - verify that these are |
| 717 | # prefetched in one batch. |
| 718 | git clone --filter=blob:none --single-branch -b one_branch \ |
| 719 | "file://$(pwd)/server" client && |
| 720 | test_config -C client protocol.version 2 && |
| 721 | TWO=$(git -C server rev-parse three_branch^) && |
| 722 | git -C client fetch --filter=blob:none origin "$TWO" && |
| 723 | GIT_TRACE_PACKET=$(pwd)/trace git -C client push origin "$TWO":refs/heads/two_branch && |
| 724 | grep "fetch> done" trace >donelines && |
| 725 | test_line_count = 1 donelines |
| 726 | ' |
| 727 | |
| 728 | for hash in sha1 sha256 |
| 729 | do |
| 730 | test_expect_success "verify-pack with $hash packfile" ' |
| 731 | test_when_finished "rm -rf repo" && |
| 732 | git init --object-format=$hash repo && |
| 733 | test_commit -C repo initial && |
| 734 | git -C repo repack -ad && |
| 735 | git -C repo verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx && |
| 736 | if test $hash = $GIT_TEST_BUILTIN_HASH |
| 737 | then |
| 738 | nongit git verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx |
| 739 | else |
| 740 | # We have no way to identify the hash used by packfiles |
| 741 | # or indices, so we always fall back to SHA1. |
| 742 | nongit test_must_fail git verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx && |
| 743 | # But with an explicit object format we should succeed. |
| 744 | nongit git verify-pack --object-format=$hash "$(pwd)"/repo/.git/objects/pack/*.idx |
| 745 | fi |
| 746 | ' |
| 747 | |
| 748 | test_expect_success "index-pack outside of a $hash repository" ' |
| 749 | test_when_finished "rm -rf repo" && |
| 750 | git init --object-format=$hash repo && |
| 751 | test_commit -C repo initial && |
| 752 | git -C repo repack -ad && |
| 753 | git -C repo index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack && |
| 754 | if test $hash = $GIT_TEST_BUILTIN_HASH |
| 755 | then |
| 756 | nongit git index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack |
| 757 | else |
| 758 | # We have no way to identify the hash used by packfiles |
| 759 | # or indices, so we always fall back to SHA1. |
| 760 | nongit test_must_fail git index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack 2>err && |
| 761 | # But with an explicit object format we should succeed. |
| 762 | nongit git index-pack --object-format=$hash --verify "$(pwd)"/repo/.git/objects/pack/*.pack |
| 763 | fi |
| 764 | ' |
| 765 | done |
| 766 | |
| 767 | test_expect_success 'valid and invalid --name-hash-versions' ' |
| 768 | sane_unset GIT_TEST_NAME_HASH_VERSION && |
| 769 | |
| 770 | # Valid values are hard to verify other than "do not fail". |
| 771 | # Performance tests will be more valuable to validate these versions. |
| 772 | # Negative values are converted to version 1. |
| 773 | for value in -1 1 2 |
| 774 | do |
| 775 | git pack-objects base --all --name-hash-version=$value || return 1 |
| 776 | done && |
| 777 | |
| 778 | # Invalid values have clear post-conditions. |
| 779 | for value in 0 3 |
| 780 | do |
| 781 | test_must_fail git pack-objects base --all --name-hash-version=$value 2>err && |
| 782 | test_grep "invalid --name-hash-version option" err || return 1 |
| 783 | done |
| 784 | ' |
| 785 | |
| 786 | # The following test is not necessarily a permanent choice, but since we do not |
| 787 | # have a "name hash version" bit in the .bitmap file format, we cannot write the |
| 788 | # hash values into the .bitmap file without risking breakage later. |
| 789 | # |
| 790 | # TODO: Make these compatible in the future and replace this test with the |
| 791 | # expected behavior when both are specified. |
| 792 | test_expect_success '--name-hash-version=2 and --write-bitmap-index are incompatible' ' |
| 793 | git pack-objects base --all --name-hash-version=2 --write-bitmap-index 2>err && |
| 794 | test_grep "currently, --write-bitmap-index requires --name-hash-version=1" err && |
| 795 | |
| 796 | # --stdout option silently removes --write-bitmap-index |
| 797 | git pack-objects --stdout --all --name-hash-version=2 --write-bitmap-index >out 2>err && |
| 798 | test_grep ! "currently, --write-bitmap-index requires --name-hash-version=1" err |
| 799 | ' |
| 800 | |
| 801 | test_expect_success '--path-walk pack everything' ' |
| 802 | git -C server rev-parse HEAD >in && |
| 803 | GIT_PROGRESS_DELAY=0 git -C server pack-objects \ |
| 804 | --stdout --revs --path-walk --progress <in >out.pack 2>err && |
| 805 | test_grep "Compressing objects by path" err && |
| 806 | git -C server index-pack --stdin <out.pack |
| 807 | ' |
| 808 | |
| 809 | test_expect_success '--path-walk thin pack' ' |
| 810 | cat >in <<-EOF && |
| 811 | $(git -C server rev-parse HEAD) |
| 812 | ^$(git -C server rev-parse HEAD~2) |
| 813 | EOF |
| 814 | GIT_PROGRESS_DELAY=0 git -C server pack-objects \ |
| 815 | --thin --stdout --revs --path-walk --progress <in >out.pack 2>err && |
| 816 | test_grep "Compressing objects by path" err && |
| 817 | git -C server index-pack --fix-thin --stdin <out.pack |
| 818 | ' |
| 819 | |
| 820 | test_done |