3 test_description='multi-pack-indexes'
 
  16                 header: 4d494458 1 $NUM_CHUNKS $NUM_PACKS
 
  17                 chunks: pack-names oid-fanout oid-lookup object-offsets$EXTRA_CHUNKS
 
  18                 num_objects: $NUM_OBJECTS
 
  21                 if test $NUM_PACKS -ge 1
 
  23                         ls $OBJECT_DIR/pack/ | grep idx | sort
 
  25                 printf "object-dir: $OBJECT_DIR\n"
 
  27         test-tool read-midx $OBJECT_DIR >actual &&
 
  28         test_cmp expect actual
 
  31 test_expect_success 'write midx with no packs' '
 
  32         test_when_finished rm -f pack/multi-pack-index &&
 
  33         git multi-pack-index --object-dir=. write &&
 
  34         midx_read_expect 0 0 4 .
 
  39         iii=$(printf '%03i' $i)
 
  41                 test-tool genrandom "bar" 200 &&
 
  42                 test-tool genrandom "baz $iii" 50
 
  45                 test-tool genrandom "foo"$i 100 &&
 
  46                 test-tool genrandom "foo"$(( $i + 1 )) 100 &&
 
  47                 test-tool genrandom "foo"$(( $i + 2 )) 100
 
  51                 test-tool genrandom "$iii" 8192
 
  53         git update-index --add file_$iii deep_delta_$iii wide_delta_$iii
 
  56 commit_and_list_objects () {
 
  59                 test-tool genrandom 100 8192;
 
  61         git update-index --add file_101 &&
 
  62         tree=$(git write-tree) &&
 
  63         commit=$(git commit-tree $tree -p HEAD</dev/null) &&
 
  66                 git ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\)        .*/\\1/"
 
  68         git reset --hard $commit
 
  71 test_expect_success 'create objects' '
 
  72         test_commit initial &&
 
  73         for i in $(test_seq 1 5)
 
  77         commit_and_list_objects
 
  80 test_expect_success 'write midx with one v1 pack' '
 
  81         pack=$(git pack-objects --index-version=1 $objdir/pack/test <obj-list) &&
 
  82         test_when_finished rm $objdir/pack/test-$pack.pack \
 
  83                 $objdir/pack/test-$pack.idx $objdir/pack/multi-pack-index &&
 
  84         git multi-pack-index --object-dir=$objdir write &&
 
  85         midx_read_expect 1 18 4 $objdir
 
  88 midx_git_two_modes () {
 
  89         if [ "$2" = "sorted" ]
 
  91                 git -c core.multiPackIndex=false $1 | sort >expect &&
 
  92                 git -c core.multiPackIndex=true $1 | sort >actual
 
  94                 git -c core.multiPackIndex=false $1 >expect &&
 
  95                 git -c core.multiPackIndex=true $1 >actual
 
  97         test_cmp expect actual
 
 100 compare_results_with_midx () {
 
 102         test_expect_success "check normal git operations: $MSG" '
 
 103                 midx_git_two_modes "rev-list --objects --all" &&
 
 104                 midx_git_two_modes "log --raw" &&
 
 105                 midx_git_two_modes "count-objects --verbose" &&
 
 106                 midx_git_two_modes "cat-file --batch-all-objects --buffer --batch-check" &&
 
 107                 midx_git_two_modes "cat-file --batch-all-objects --buffer --batch-check --unsorted" sorted
 
 111 test_expect_success 'write midx with one v2 pack' '
 
 112         git pack-objects --index-version=2,0x40 $objdir/pack/test <obj-list &&
 
 113         git multi-pack-index --object-dir=$objdir write &&
 
 114         midx_read_expect 1 18 4 $objdir
 
 117 compare_results_with_midx "one v2 pack"
 
 119 test_expect_success 'add more objects' '
 
 120         for i in $(test_seq 6 10)
 
 124         commit_and_list_objects
 
 127 test_expect_success 'write midx with two packs' '
 
 128         git pack-objects --index-version=1 $objdir/pack/test-2 <obj-list &&
 
 129         git multi-pack-index --object-dir=$objdir write &&
 
 130         midx_read_expect 2 34 4 $objdir
 
 133 compare_results_with_midx "two packs"
 
 135 test_expect_success 'add more packs' '
 
 136         for j in $(test_seq 11 20)
 
 138                 generate_objects $j &&
 
 139                 commit_and_list_objects &&
 
 140                 git pack-objects --index-version=2 $objdir/pack/test-pack <obj-list
 
 144 compare_results_with_midx "mixed mode (two packs + extra)"
 
 146 test_expect_success 'write midx with twelve packs' '
 
 147         git multi-pack-index --object-dir=$objdir write &&
 
 148         midx_read_expect 12 74 4 $objdir
 
 151 compare_results_with_midx "twelve packs"
 
 153 test_expect_success 'verify multi-pack-index success' '
 
 154         git multi-pack-index verify --object-dir=$objdir
 
 157 # usage: corrupt_midx_and_verify <pos> <data> <objdir> <string>
 
 158 corrupt_midx_and_verify() {
 
 164         if test -z "$COMMAND"
 
 166                 COMMAND="git multi-pack-index verify --object-dir=$OBJDIR"
 
 168         FILE=$OBJDIR/pack/multi-pack-index &&
 
 170         test_when_finished mv midx-backup $FILE &&
 
 171         cp $FILE midx-backup &&
 
 172         printf "$DATA" | dd of="$FILE" bs=1 seek="$POS" conv=notrunc &&
 
 173         test_must_fail $COMMAND 2>test_err &&
 
 174         grep -v "^+" test_err >err &&
 
 175         test_i18ngrep "$GREPSTR" err
 
 178 test_expect_success 'verify bad signature' '
 
 179         corrupt_midx_and_verify 0 "\00" $objdir \
 
 180                 "multi-pack-index signature"
 
 186 MIDX_BYTE_OID_VERSION=5
 
 187 MIDX_BYTE_CHUNK_COUNT=6
 
 189 MIDX_BYTE_CHUNK_ID=$MIDX_HEADER_SIZE
 
 190 MIDX_BYTE_CHUNK_OFFSET=$(($MIDX_HEADER_SIZE + 4))
 
 192 MIDX_CHUNK_LOOKUP_WIDTH=12
 
 193 MIDX_OFFSET_PACKNAMES=$(($MIDX_HEADER_SIZE + \
 
 194                          $MIDX_NUM_CHUNKS * $MIDX_CHUNK_LOOKUP_WIDTH))
 
 195 MIDX_BYTE_PACKNAME_ORDER=$(($MIDX_OFFSET_PACKNAMES + 2))
 
 196 MIDX_OFFSET_OID_FANOUT=$(($MIDX_OFFSET_PACKNAMES + 652))
 
 197 MIDX_OID_FANOUT_WIDTH=4
 
 198 MIDX_BYTE_OID_FANOUT_ORDER=$((MIDX_OFFSET_OID_FANOUT + 250 * $MIDX_OID_FANOUT_WIDTH + 1))
 
 199 MIDX_OFFSET_OID_LOOKUP=$(($MIDX_OFFSET_OID_FANOUT + 256 * $MIDX_OID_FANOUT_WIDTH))
 
 200 MIDX_BYTE_OID_LOOKUP=$(($MIDX_OFFSET_OID_LOOKUP + 16 * $HASH_LEN))
 
 201 MIDX_OFFSET_OBJECT_OFFSETS=$(($MIDX_OFFSET_OID_LOOKUP + $NUM_OBJECTS * $HASH_LEN))
 
 203 MIDX_BYTE_PACK_INT_ID=$(($MIDX_OFFSET_OBJECT_OFFSETS + 16 * $MIDX_OFFSET_WIDTH + 2))
 
 204 MIDX_BYTE_OFFSET=$(($MIDX_OFFSET_OBJECT_OFFSETS + 16 * $MIDX_OFFSET_WIDTH + 6))
 
 206 test_expect_success 'verify bad version' '
 
 207         corrupt_midx_and_verify $MIDX_BYTE_VERSION "\00" $objdir \
 
 208                 "multi-pack-index version"
 
 211 test_expect_success 'verify bad OID version' '
 
 212         corrupt_midx_and_verify $MIDX_BYTE_OID_VERSION "\02" $objdir \
 
 216 test_expect_success 'verify truncated chunk count' '
 
 217         corrupt_midx_and_verify $MIDX_BYTE_CHUNK_COUNT "\01" $objdir \
 
 221 test_expect_success 'verify extended chunk count' '
 
 222         corrupt_midx_and_verify $MIDX_BYTE_CHUNK_COUNT "\07" $objdir \
 
 223                 "terminating multi-pack-index chunk id appears earlier than expected"
 
 226 test_expect_success 'verify missing required chunk' '
 
 227         corrupt_midx_and_verify $MIDX_BYTE_CHUNK_ID "\01" $objdir \
 
 231 test_expect_success 'verify invalid chunk offset' '
 
 232         corrupt_midx_and_verify $MIDX_BYTE_CHUNK_OFFSET "\01" $objdir \
 
 233                 "invalid chunk offset (too large)"
 
 236 test_expect_success 'verify packnames out of order' '
 
 237         corrupt_midx_and_verify $MIDX_BYTE_PACKNAME_ORDER "z" $objdir \
 
 238                 "pack names out of order"
 
 241 test_expect_success 'verify packnames out of order' '
 
 242         corrupt_midx_and_verify $MIDX_BYTE_PACKNAME_ORDER "a" $objdir \
 
 243                 "failed to load pack"
 
 246 test_expect_success 'verify oid fanout out of order' '
 
 247         corrupt_midx_and_verify $MIDX_BYTE_OID_FANOUT_ORDER "\01" $objdir \
 
 248                 "oid fanout out of order"
 
 251 test_expect_success 'verify oid lookup out of order' '
 
 252         corrupt_midx_and_verify $MIDX_BYTE_OID_LOOKUP "\00" $objdir \
 
 253                 "oid lookup out of order"
 
 256 test_expect_success 'verify incorrect pack-int-id' '
 
 257         corrupt_midx_and_verify $MIDX_BYTE_PACK_INT_ID "\07" $objdir \
 
 261 test_expect_success 'verify incorrect offset' '
 
 262         corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\07" $objdir \
 
 263                 "incorrect object offset"
 
 266 test_expect_success 'git-fsck incorrect offset' '
 
 267         corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\07" $objdir \
 
 268                 "incorrect object offset" \
 
 269                 "git -c core.multipackindex=true fsck"
 
 272 test_expect_success 'repack removes multi-pack-index' '
 
 273         test_path_is_file $objdir/pack/multi-pack-index &&
 
 274         GIT_TEST_MULTI_PACK_INDEX=0 git repack -adf &&
 
 275         test_path_is_missing $objdir/pack/multi-pack-index
 
 278 compare_results_with_midx "after repack"
 
 280 test_expect_success 'multi-pack-index and pack-bitmap' '
 
 281         git -c repack.writeBitmaps=true repack -ad &&
 
 282         git multi-pack-index write &&
 
 283         git rev-list --test-bitmap HEAD
 
 286 test_expect_success 'multi-pack-index and alternates' '
 
 287         git init --bare alt.git &&
 
 288         echo $(pwd)/alt.git/objects >.git/objects/info/alternates &&
 
 289         echo content1 >file1 &&
 
 290         altblob=$(GIT_DIR=alt.git git hash-object -w file1) &&
 
 291         git cat-file blob $altblob &&
 
 295 compare_results_with_midx "with alternate (local midx)"
 
 297 test_expect_success 'multi-pack-index in an alternate' '
 
 298         mv .git/objects/pack/* alt.git/objects/pack &&
 
 299         test_commit add_local_objects &&
 
 300         git repack --local &&
 
 301         git multi-pack-index write &&
 
 302         midx_read_expect 1 3 4 $objdir &&
 
 303         git reset --hard HEAD~1 &&
 
 304         rm -f .git/objects/pack/*
 
 307 compare_results_with_midx "with alternate (remote midx)"
 
 309 # usage: corrupt_data <file> <pos> [<data>]
 
 314         printf "$data" | dd of="$file" bs=1 seek="$pos" conv=notrunc
 
 317 # Force 64-bit offsets by manipulating the idx file.
 
 318 # This makes the IDX file _incorrect_ so be careful to clean up after!
 
 319 test_expect_success 'force some 64-bit offsets with pack-objects' '
 
 321         mkdir objects64/pack &&
 
 322         for i in $(test_seq 1 11)
 
 326         commit_and_list_objects &&
 
 327         pack64=$(git pack-objects --index-version=2,0x40 objects64/pack/test-64 <obj-list) &&
 
 328         idx64=objects64/pack/test-64-$pack64.idx &&
 
 330         corrupt_data $idx64 2999 "\02" &&
 
 331         midx64=$(git multi-pack-index --object-dir=objects64 write) &&
 
 332         midx_read_expect 1 63 5 objects64 " large-offsets"
 
 335 test_expect_success 'verify multi-pack-index with 64-bit offsets' '
 
 336         git multi-pack-index verify --object-dir=objects64
 
 340 MIDX_OFFSET_OID_FANOUT=$((MIDX_OFFSET_PACKNAMES + 54))
 
 341 MIDX_OFFSET_OID_LOOKUP=$((MIDX_OFFSET_OID_FANOUT + 256 * $MIDX_OID_FANOUT_WIDTH))
 
 342 MIDX_OFFSET_OBJECT_OFFSETS=$(($MIDX_OFFSET_OID_LOOKUP + $NUM_OBJECTS * $HASH_LEN))
 
 343 MIDX_OFFSET_LARGE_OFFSETS=$(($MIDX_OFFSET_OBJECT_OFFSETS + $NUM_OBJECTS * $MIDX_OFFSET_WIDTH))
 
 344 MIDX_BYTE_LARGE_OFFSET=$(($MIDX_OFFSET_LARGE_OFFSETS + 3))
 
 346 test_expect_success 'verify incorrect 64-bit offset' '
 
 347         corrupt_midx_and_verify $MIDX_BYTE_LARGE_OFFSET "\07" objects64 \
 
 348                 "incorrect object offset"