t / t1700-split-index.shon commit Merge branch 'rs/nedalloc-fixlets' (4336fdb)
   1#!/bin/sh
   2
   3test_description='split index mode tests'
   4
   5. ./test-lib.sh
   6
   7# We need total control of index splitting here
   8sane_unset GIT_TEST_SPLIT_INDEX
   9
  10# Testing a hard coded SHA against an index with an extension
  11# that can vary from run to run is problematic so we disable
  12# those extensions.
  13sane_unset GIT_TEST_FSMONITOR
  14sane_unset GIT_TEST_INDEX_THREADS
  15
  16# Create a file named as $1 with content read from stdin.
  17# Set the file's mtime to a few seconds in the past to avoid racy situations.
  18create_non_racy_file () {
  19        cat >"$1" &&
  20        test-tool chmtime =-5 "$1"
  21}
  22
  23test_expect_success 'setup' '
  24        test_oid_cache <<-EOF
  25        own_v3 sha1:8299b0bcd1ac364e5f1d7768efb62fa2da79a339
  26        own_v3 sha256:38a6d2925e3eceec33ad7b34cbff4e0086caa0daf28f31e51f5bd94b4a7af86b
  27
  28        base_v3 sha1:39d890139ee5356c7ef572216cebcd27aa41f9df
  29        base_v3 sha256:c9baeadf905112bf6c17aefbd7d02267afd70ded613c30cafed2d40cb506e1ed
  30
  31        own_v4 sha1:432ef4b63f32193984f339431fd50ca796493569
  32        own_v4 sha256:6738ac6319c25b694afa7bcc313deb182d1a59b68bf7a47b4296de83478c0420
  33
  34        base_v4 sha1:508851a7f0dfa8691e9f69c7f055865389012491
  35        base_v4 sha256:3177d4adfdd4b6904f7e921d91d715a471c0dde7cf6a4bba574927f02b699508
  36        EOF
  37'
  38
  39test_expect_success 'enable split index' '
  40        git config splitIndex.maxPercentChange 100 &&
  41        git update-index --split-index &&
  42        test-tool dump-split-index .git/index >actual &&
  43        indexversion=$(test-tool index-version <.git/index) &&
  44
  45        # NEEDSWORK: Stop hard-coding checksums.
  46        if test "$indexversion" = "4"
  47        then
  48                own=$(test_oid own_v4)
  49                base=$(test_oid base_v4)
  50        else
  51                own=$(test_oid own_v3)
  52                base=$(test_oid base_v3)
  53        fi &&
  54
  55        cat >expect <<-EOF &&
  56        own $own
  57        base $base
  58        replacements:
  59        deletions:
  60        EOF
  61        test_cmp expect actual
  62'
  63
  64test_expect_success 'add one file' '
  65        create_non_racy_file one &&
  66        git update-index --add one &&
  67        git ls-files --stage >ls-files.actual &&
  68        cat >ls-files.expect <<-EOF &&
  69        100644 $EMPTY_BLOB 0    one
  70        EOF
  71        test_cmp ls-files.expect ls-files.actual &&
  72
  73        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
  74        cat >expect <<-EOF &&
  75        base $base
  76        100644 $EMPTY_BLOB 0    one
  77        replacements:
  78        deletions:
  79        EOF
  80        test_cmp expect actual
  81'
  82
  83test_expect_success 'disable split index' '
  84        git update-index --no-split-index &&
  85        git ls-files --stage >ls-files.actual &&
  86        cat >ls-files.expect <<-EOF &&
  87        100644 $EMPTY_BLOB 0    one
  88        EOF
  89        test_cmp ls-files.expect ls-files.actual &&
  90
  91        BASE=$(test-tool dump-split-index .git/index | sed -n "s/^own/base/p") &&
  92        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
  93        cat >expect <<-EOF &&
  94        not a split index
  95        EOF
  96        test_cmp expect actual
  97'
  98
  99test_expect_success 'enable split index again, "one" now belongs to base index"' '
 100        git update-index --split-index &&
 101        git ls-files --stage >ls-files.actual &&
 102        cat >ls-files.expect <<-EOF &&
 103        100644 $EMPTY_BLOB 0    one
 104        EOF
 105        test_cmp ls-files.expect ls-files.actual &&
 106
 107        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 108        cat >expect <<-EOF &&
 109        $BASE
 110        replacements:
 111        deletions:
 112        EOF
 113        test_cmp expect actual
 114'
 115
 116test_expect_success 'modify original file, base index untouched' '
 117        echo modified | create_non_racy_file one &&
 118        file1_blob=$(git hash-object one) &&
 119        git update-index one &&
 120        git ls-files --stage >ls-files.actual &&
 121        cat >ls-files.expect <<-EOF &&
 122        100644 $file1_blob 0    one
 123        EOF
 124        test_cmp ls-files.expect ls-files.actual &&
 125
 126        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 127        q_to_tab >expect <<-EOF &&
 128        $BASE
 129        100644 $file1_blob 0Q
 130        replacements: 0
 131        deletions:
 132        EOF
 133        test_cmp expect actual
 134'
 135
 136test_expect_success 'add another file, which stays index' '
 137        create_non_racy_file two &&
 138        git update-index --add two &&
 139        git ls-files --stage >ls-files.actual &&
 140        cat >ls-files.expect <<-EOF &&
 141        100644 $file1_blob 0    one
 142        100644 $EMPTY_BLOB 0    two
 143        EOF
 144        test_cmp ls-files.expect ls-files.actual &&
 145
 146        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 147        q_to_tab >expect <<-EOF &&
 148        $BASE
 149        100644 $file1_blob 0Q
 150        100644 $EMPTY_BLOB 0    two
 151        replacements: 0
 152        deletions:
 153        EOF
 154        test_cmp expect actual
 155'
 156
 157test_expect_success 'remove file not in base index' '
 158        git update-index --force-remove two &&
 159        git ls-files --stage >ls-files.actual &&
 160        cat >ls-files.expect <<-EOF &&
 161        100644 $file1_blob 0    one
 162        EOF
 163        test_cmp ls-files.expect ls-files.actual &&
 164
 165        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 166        q_to_tab >expect <<-EOF &&
 167        $BASE
 168        100644 $file1_blob 0Q
 169        replacements: 0
 170        deletions:
 171        EOF
 172        test_cmp expect actual
 173'
 174
 175test_expect_success 'remove file in base index' '
 176        git update-index --force-remove one &&
 177        git ls-files --stage >ls-files.actual &&
 178        test_must_be_empty ls-files.actual &&
 179
 180        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 181        cat >expect <<-EOF &&
 182        $BASE
 183        replacements:
 184        deletions: 0
 185        EOF
 186        test_cmp expect actual
 187'
 188
 189test_expect_success 'add original file back' '
 190        create_non_racy_file one &&
 191        git update-index --add one &&
 192        git ls-files --stage >ls-files.actual &&
 193        cat >ls-files.expect <<-EOF &&
 194        100644 $EMPTY_BLOB 0    one
 195        EOF
 196        test_cmp ls-files.expect ls-files.actual &&
 197
 198        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 199        cat >expect <<-EOF &&
 200        $BASE
 201        100644 $EMPTY_BLOB 0    one
 202        replacements:
 203        deletions: 0
 204        EOF
 205        test_cmp expect actual
 206'
 207
 208test_expect_success 'add new file' '
 209        create_non_racy_file two &&
 210        git update-index --add two &&
 211        git ls-files --stage >actual &&
 212        cat >expect <<-EOF &&
 213        100644 $EMPTY_BLOB 0    one
 214        100644 $EMPTY_BLOB 0    two
 215        EOF
 216        test_cmp expect actual
 217'
 218
 219test_expect_success 'unify index, two files remain' '
 220        git update-index --no-split-index &&
 221        git ls-files --stage >ls-files.actual &&
 222        cat >ls-files.expect <<-EOF &&
 223        100644 $EMPTY_BLOB 0    one
 224        100644 $EMPTY_BLOB 0    two
 225        EOF
 226        test_cmp ls-files.expect ls-files.actual &&
 227
 228        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 229        cat >expect <<-EOF &&
 230        not a split index
 231        EOF
 232        test_cmp expect actual
 233'
 234
 235test_expect_success 'rev-parse --shared-index-path' '
 236        test_create_repo split-index &&
 237        (
 238                cd split-index &&
 239                git update-index --split-index &&
 240                echo .git/sharedindex* >expect &&
 241                git rev-parse --shared-index-path >actual &&
 242                test_cmp expect actual &&
 243                mkdir subdirectory &&
 244                cd subdirectory &&
 245                echo ../.git/sharedindex* >expect &&
 246                git rev-parse --shared-index-path >actual &&
 247                test_cmp expect actual
 248        )
 249'
 250
 251test_expect_success 'set core.splitIndex config variable to true' '
 252        git config core.splitIndex true &&
 253        create_non_racy_file three &&
 254        git update-index --add three &&
 255        git ls-files --stage >ls-files.actual &&
 256        cat >ls-files.expect <<-EOF &&
 257        100644 $EMPTY_BLOB 0    one
 258        100644 $EMPTY_BLOB 0    three
 259        100644 $EMPTY_BLOB 0    two
 260        EOF
 261        test_cmp ls-files.expect ls-files.actual &&
 262        BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
 263        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 264        cat >expect <<-EOF &&
 265        $BASE
 266        replacements:
 267        deletions:
 268        EOF
 269        test_cmp expect actual
 270'
 271
 272test_expect_success 'set core.splitIndex config variable to false' '
 273        git config core.splitIndex false &&
 274        git update-index --force-remove three &&
 275        git ls-files --stage >ls-files.actual &&
 276        cat >ls-files.expect <<-EOF &&
 277        100644 $EMPTY_BLOB 0    one
 278        100644 $EMPTY_BLOB 0    two
 279        EOF
 280        test_cmp ls-files.expect ls-files.actual &&
 281        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 282        cat >expect <<-EOF &&
 283        not a split index
 284        EOF
 285        test_cmp expect actual
 286'
 287
 288test_expect_success 'set core.splitIndex config variable back to true' '
 289        git config core.splitIndex true &&
 290        create_non_racy_file three &&
 291        git update-index --add three &&
 292        BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
 293        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 294        cat >expect <<-EOF &&
 295        $BASE
 296        replacements:
 297        deletions:
 298        EOF
 299        test_cmp expect actual &&
 300        create_non_racy_file four &&
 301        git update-index --add four &&
 302        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 303        cat >expect <<-EOF &&
 304        $BASE
 305        100644 $EMPTY_BLOB 0    four
 306        replacements:
 307        deletions:
 308        EOF
 309        test_cmp expect actual
 310'
 311
 312test_expect_success 'check behavior with splitIndex.maxPercentChange unset' '
 313        git config --unset splitIndex.maxPercentChange &&
 314        create_non_racy_file five &&
 315        git update-index --add five &&
 316        BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
 317        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 318        cat >expect <<-EOF &&
 319        $BASE
 320        replacements:
 321        deletions:
 322        EOF
 323        test_cmp expect actual &&
 324        create_non_racy_file six &&
 325        git update-index --add six &&
 326        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 327        cat >expect <<-EOF &&
 328        $BASE
 329        100644 $EMPTY_BLOB 0    six
 330        replacements:
 331        deletions:
 332        EOF
 333        test_cmp expect actual
 334'
 335
 336test_expect_success 'check splitIndex.maxPercentChange set to 0' '
 337        git config splitIndex.maxPercentChange 0 &&
 338        create_non_racy_file seven &&
 339        git update-index --add seven &&
 340        BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
 341        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 342        cat >expect <<-EOF &&
 343        $BASE
 344        replacements:
 345        deletions:
 346        EOF
 347        test_cmp expect actual &&
 348        create_non_racy_file eight &&
 349        git update-index --add eight &&
 350        BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
 351        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 352        cat >expect <<-EOF &&
 353        $BASE
 354        replacements:
 355        deletions:
 356        EOF
 357        test_cmp expect actual
 358'
 359
 360test_expect_success 'shared index files expire after 2 weeks by default' '
 361        create_non_racy_file ten &&
 362        git update-index --add ten &&
 363        test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
 364        just_under_2_weeks_ago=$((5-14*86400)) &&
 365        test-tool chmtime =$just_under_2_weeks_ago .git/sharedindex.* &&
 366        create_non_racy_file eleven &&
 367        git update-index --add eleven &&
 368        test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
 369        just_over_2_weeks_ago=$((-1-14*86400)) &&
 370        test-tool chmtime =$just_over_2_weeks_ago .git/sharedindex.* &&
 371        create_non_racy_file twelve &&
 372        git update-index --add twelve &&
 373        test $(ls .git/sharedindex.* | wc -l) -le 2
 374'
 375
 376test_expect_success 'check splitIndex.sharedIndexExpire set to 16 days' '
 377        git config splitIndex.sharedIndexExpire "16.days.ago" &&
 378        test-tool chmtime =$just_over_2_weeks_ago .git/sharedindex.* &&
 379        create_non_racy_file thirteen &&
 380        git update-index --add thirteen &&
 381        test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
 382        just_over_16_days_ago=$((-1-16*86400)) &&
 383        test-tool chmtime =$just_over_16_days_ago .git/sharedindex.* &&
 384        create_non_racy_file fourteen &&
 385        git update-index --add fourteen &&
 386        test $(ls .git/sharedindex.* | wc -l) -le 2
 387'
 388
 389test_expect_success 'check splitIndex.sharedIndexExpire set to "never" and "now"' '
 390        git config splitIndex.sharedIndexExpire never &&
 391        just_10_years_ago=$((-365*10*86400)) &&
 392        test-tool chmtime =$just_10_years_ago .git/sharedindex.* &&
 393        create_non_racy_file fifteen &&
 394        git update-index --add fifteen &&
 395        test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
 396        git config splitIndex.sharedIndexExpire now &&
 397        just_1_second_ago=-1 &&
 398        test-tool chmtime =$just_1_second_ago .git/sharedindex.* &&
 399        create_non_racy_file sixteen &&
 400        git update-index --add sixteen &&
 401        test $(ls .git/sharedindex.* | wc -l) -le 2
 402'
 403
 404test_expect_success POSIXPERM 'same mode for index & split index' '
 405        git init same-mode &&
 406        (
 407                cd same-mode &&
 408                test_commit A &&
 409                test_modebits .git/index >index_mode &&
 410                test_must_fail git config core.sharedRepository &&
 411                git -c core.splitIndex=true status &&
 412                shared=$(ls .git/sharedindex.*) &&
 413                case "$shared" in
 414                *" "*)
 415                        # we have more than one???
 416                        false ;;
 417                *)
 418                        test_modebits "$shared" >split_index_mode &&
 419                        test_cmp index_mode split_index_mode ;;
 420                esac
 421        )
 422'
 423
 424while read -r mode modebits
 425do
 426        test_expect_success POSIXPERM "split index respects core.sharedrepository $mode" '
 427                # Remove existing shared index files
 428                git config core.splitIndex false &&
 429                git update-index --force-remove one &&
 430                rm -f .git/sharedindex.* &&
 431                # Create one new shared index file
 432                git config core.sharedrepository "$mode" &&
 433                git config core.splitIndex true &&
 434                create_non_racy_file one &&
 435                git update-index --add one &&
 436                echo "$modebits" >expect &&
 437                test_modebits .git/index >actual &&
 438                test_cmp expect actual &&
 439                shared=$(ls .git/sharedindex.*) &&
 440                case "$shared" in
 441                *" "*)
 442                        # we have more than one???
 443                        false ;;
 444                *)
 445                        test_modebits "$shared" >actual &&
 446                        test_cmp expect actual ;;
 447                esac
 448        '
 449done <<\EOF
 4500666 -rw-rw-rw-
 4510642 -rw-r---w-
 452EOF
 453
 454test_expect_success POSIXPERM,SANITY 'graceful handling when splitting index is not allowed' '
 455        test_create_repo ro &&
 456        (
 457                cd ro &&
 458                test_commit initial &&
 459                git update-index --split-index &&
 460                test -f .git/sharedindex.*
 461        ) &&
 462        cp ro/.git/index new-index &&
 463        test_when_finished "chmod u+w ro/.git" &&
 464        chmod u-w ro/.git &&
 465        GIT_INDEX_FILE="$(pwd)/new-index" git -C ro update-index --split-index &&
 466        chmod u+w ro/.git &&
 467        rm ro/.git/sharedindex.* &&
 468        GIT_INDEX_FILE=new-index git ls-files >actual &&
 469        echo initial.t >expected &&
 470        test_cmp expected actual
 471'
 472
 473test_expect_success 'writing split index with null sha1 does not write cache tree' '
 474        git config core.splitIndex true &&
 475        git config splitIndex.maxPercentChange 0 &&
 476        git commit -m "commit" &&
 477        {
 478                git ls-tree HEAD &&
 479                printf "160000 commit $ZERO_OID\\tbroken\\n"
 480        } >broken-tree &&
 481        echo "add broken entry" >msg &&
 482
 483        tree=$(git mktree <broken-tree) &&
 484        test_tick &&
 485        commit=$(git commit-tree $tree -p HEAD <msg) &&
 486        git update-ref HEAD "$commit" &&
 487        GIT_ALLOW_NULL_SHA1=1 git reset --hard &&
 488        test_might_fail test-tool dump-cache-tree >cache-tree.out &&
 489        test_line_count = 0 cache-tree.out
 490'
 491
 492test_expect_success 'do not refresh null base index' '
 493        test_create_repo merge &&
 494        (
 495                cd merge &&
 496                test_commit initial &&
 497                git checkout -b side-branch &&
 498                test_commit extra &&
 499                git checkout master &&
 500                git update-index --split-index &&
 501                test_commit more &&
 502                # must not write a new shareindex, or we wont catch the problem
 503                git -c splitIndex.maxPercentChange=100 merge --no-edit side-branch 2>err &&
 504                # i.e. do not expect warnings like
 505                # could not freshen shared index .../shareindex.00000...
 506                test_must_be_empty err
 507        )
 508'
 509
 510test_done