2ac47aa0e4a7164cd06037496832a1744990a774
   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 'enable split index' '
  24        git config splitIndex.maxPercentChange 100 &&
  25        git update-index --split-index &&
  26        test-tool dump-split-index .git/index >actual &&
  27        indexversion=$(test-tool index-version <.git/index) &&
  28        if test "$indexversion" = "4"
  29        then
  30                own=3527df833c6c100d3d1d921a9a782d62a8be4b58
  31                base=746f7ab2ed44fb839efdfbffcf399d0b113fb4cb
  32        else
  33                own=5e9b60117ece18da410ddecc8b8d43766a0e4204
  34                base=4370042739b31cd17a5c5cd6043a77c9a00df113
  35        fi &&
  36        cat >expect <<-EOF &&
  37        own $own
  38        base $base
  39        replacements:
  40        deletions:
  41        EOF
  42        test_cmp expect actual
  43'
  44
  45test_expect_success 'add one file' '
  46        create_non_racy_file one &&
  47        git update-index --add one &&
  48        git ls-files --stage >ls-files.actual &&
  49        cat >ls-files.expect <<-EOF &&
  50        100644 $EMPTY_BLOB 0    one
  51        EOF
  52        test_cmp ls-files.expect ls-files.actual &&
  53
  54        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
  55        cat >expect <<-EOF &&
  56        base $base
  57        100644 $EMPTY_BLOB 0    one
  58        replacements:
  59        deletions:
  60        EOF
  61        test_cmp expect actual
  62'
  63
  64test_expect_success 'disable split index' '
  65        git update-index --no-split-index &&
  66        git ls-files --stage >ls-files.actual &&
  67        cat >ls-files.expect <<-EOF &&
  68        100644 $EMPTY_BLOB 0    one
  69        EOF
  70        test_cmp ls-files.expect ls-files.actual &&
  71
  72        BASE=$(test-tool dump-split-index .git/index | sed -n "s/^own/base/p") &&
  73        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
  74        cat >expect <<-EOF &&
  75        not a split index
  76        EOF
  77        test_cmp expect actual
  78'
  79
  80test_expect_success 'enable split index again, "one" now belongs to base index"' '
  81        git update-index --split-index &&
  82        git ls-files --stage >ls-files.actual &&
  83        cat >ls-files.expect <<-EOF &&
  84        100644 $EMPTY_BLOB 0    one
  85        EOF
  86        test_cmp ls-files.expect ls-files.actual &&
  87
  88        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
  89        cat >expect <<-EOF &&
  90        $BASE
  91        replacements:
  92        deletions:
  93        EOF
  94        test_cmp expect actual
  95'
  96
  97test_expect_success 'modify original file, base index untouched' '
  98        echo modified | create_non_racy_file one &&
  99        git update-index one &&
 100        git ls-files --stage >ls-files.actual &&
 101        cat >ls-files.expect <<-EOF &&
 102        100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0       one
 103        EOF
 104        test_cmp ls-files.expect ls-files.actual &&
 105
 106        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 107        q_to_tab >expect <<-EOF &&
 108        $BASE
 109        100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
 110        replacements: 0
 111        deletions:
 112        EOF
 113        test_cmp expect actual
 114'
 115
 116test_expect_success 'add another file, which stays index' '
 117        create_non_racy_file two &&
 118        git update-index --add two &&
 119        git ls-files --stage >ls-files.actual &&
 120        cat >ls-files.expect <<-EOF &&
 121        100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0       one
 122        100644 $EMPTY_BLOB 0    two
 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 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
 130        100644 $EMPTY_BLOB 0    two
 131        replacements: 0
 132        deletions:
 133        EOF
 134        test_cmp expect actual
 135'
 136
 137test_expect_success 'remove file not in base index' '
 138        git update-index --force-remove two &&
 139        git ls-files --stage >ls-files.actual &&
 140        cat >ls-files.expect <<-EOF &&
 141        100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0       one
 142        EOF
 143        test_cmp ls-files.expect ls-files.actual &&
 144
 145        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 146        q_to_tab >expect <<-EOF &&
 147        $BASE
 148        100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
 149        replacements: 0
 150        deletions:
 151        EOF
 152        test_cmp expect actual
 153'
 154
 155test_expect_success 'remove file in base index' '
 156        git update-index --force-remove one &&
 157        git ls-files --stage >ls-files.actual &&
 158        test_must_be_empty ls-files.actual &&
 159
 160        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 161        cat >expect <<-EOF &&
 162        $BASE
 163        replacements:
 164        deletions: 0
 165        EOF
 166        test_cmp expect actual
 167'
 168
 169test_expect_success 'add original file back' '
 170        create_non_racy_file one &&
 171        git update-index --add one &&
 172        git ls-files --stage >ls-files.actual &&
 173        cat >ls-files.expect <<-EOF &&
 174        100644 $EMPTY_BLOB 0    one
 175        EOF
 176        test_cmp ls-files.expect ls-files.actual &&
 177
 178        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 179        cat >expect <<-EOF &&
 180        $BASE
 181        100644 $EMPTY_BLOB 0    one
 182        replacements:
 183        deletions: 0
 184        EOF
 185        test_cmp expect actual
 186'
 187
 188test_expect_success 'add new file' '
 189        create_non_racy_file two &&
 190        git update-index --add two &&
 191        git ls-files --stage >actual &&
 192        cat >expect <<-EOF &&
 193        100644 $EMPTY_BLOB 0    one
 194        100644 $EMPTY_BLOB 0    two
 195        EOF
 196        test_cmp expect actual
 197'
 198
 199test_expect_success 'unify index, two files remain' '
 200        git update-index --no-split-index &&
 201        git ls-files --stage >ls-files.actual &&
 202        cat >ls-files.expect <<-EOF &&
 203        100644 $EMPTY_BLOB 0    one
 204        100644 $EMPTY_BLOB 0    two
 205        EOF
 206        test_cmp ls-files.expect ls-files.actual &&
 207
 208        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 209        cat >expect <<-EOF &&
 210        not a split index
 211        EOF
 212        test_cmp expect actual
 213'
 214
 215test_expect_success 'rev-parse --shared-index-path' '
 216        test_create_repo split-index &&
 217        (
 218                cd split-index &&
 219                git update-index --split-index &&
 220                echo .git/sharedindex* >expect &&
 221                git rev-parse --shared-index-path >actual &&
 222                test_cmp expect actual &&
 223                mkdir subdirectory &&
 224                cd subdirectory &&
 225                echo ../.git/sharedindex* >expect &&
 226                git rev-parse --shared-index-path >actual &&
 227                test_cmp expect actual
 228        )
 229'
 230
 231test_expect_success 'set core.splitIndex config variable to true' '
 232        git config core.splitIndex true &&
 233        create_non_racy_file three &&
 234        git update-index --add three &&
 235        git ls-files --stage >ls-files.actual &&
 236        cat >ls-files.expect <<-EOF &&
 237        100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       one
 238        100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       three
 239        100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       two
 240        EOF
 241        test_cmp ls-files.expect ls-files.actual &&
 242        BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
 243        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 244        cat >expect <<-EOF &&
 245        $BASE
 246        replacements:
 247        deletions:
 248        EOF
 249        test_cmp expect actual
 250'
 251
 252test_expect_success 'set core.splitIndex config variable to false' '
 253        git config core.splitIndex false &&
 254        git update-index --force-remove three &&
 255        git ls-files --stage >ls-files.actual &&
 256        cat >ls-files.expect <<-EOF &&
 257        100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       one
 258        100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       two
 259        EOF
 260        test_cmp ls-files.expect ls-files.actual &&
 261        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 262        cat >expect <<-EOF &&
 263        not a split index
 264        EOF
 265        test_cmp expect actual
 266'
 267
 268test_expect_success 'set core.splitIndex config variable back to true' '
 269        git config core.splitIndex true &&
 270        create_non_racy_file three &&
 271        git update-index --add three &&
 272        BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
 273        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 274        cat >expect <<-EOF &&
 275        $BASE
 276        replacements:
 277        deletions:
 278        EOF
 279        test_cmp expect actual &&
 280        create_non_racy_file four &&
 281        git update-index --add four &&
 282        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 283        cat >expect <<-EOF &&
 284        $BASE
 285        100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       four
 286        replacements:
 287        deletions:
 288        EOF
 289        test_cmp expect actual
 290'
 291
 292test_expect_success 'check behavior with splitIndex.maxPercentChange unset' '
 293        git config --unset splitIndex.maxPercentChange &&
 294        create_non_racy_file five &&
 295        git update-index --add five &&
 296        BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
 297        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 298        cat >expect <<-EOF &&
 299        $BASE
 300        replacements:
 301        deletions:
 302        EOF
 303        test_cmp expect actual &&
 304        create_non_racy_file six &&
 305        git update-index --add six &&
 306        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 307        cat >expect <<-EOF &&
 308        $BASE
 309        100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       six
 310        replacements:
 311        deletions:
 312        EOF
 313        test_cmp expect actual
 314'
 315
 316test_expect_success 'check splitIndex.maxPercentChange set to 0' '
 317        git config splitIndex.maxPercentChange 0 &&
 318        create_non_racy_file seven &&
 319        git update-index --add seven &&
 320        BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
 321        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 322        cat >expect <<-EOF &&
 323        $BASE
 324        replacements:
 325        deletions:
 326        EOF
 327        test_cmp expect actual &&
 328        create_non_racy_file eight &&
 329        git update-index --add eight &&
 330        BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
 331        test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
 332        cat >expect <<-EOF &&
 333        $BASE
 334        replacements:
 335        deletions:
 336        EOF
 337        test_cmp expect actual
 338'
 339
 340test_expect_success 'shared index files expire after 2 weeks by default' '
 341        create_non_racy_file ten &&
 342        git update-index --add ten &&
 343        test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
 344        just_under_2_weeks_ago=$((5-14*86400)) &&
 345        test-tool chmtime =$just_under_2_weeks_ago .git/sharedindex.* &&
 346        create_non_racy_file eleven &&
 347        git update-index --add eleven &&
 348        test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
 349        just_over_2_weeks_ago=$((-1-14*86400)) &&
 350        test-tool chmtime =$just_over_2_weeks_ago .git/sharedindex.* &&
 351        create_non_racy_file twelve &&
 352        git update-index --add twelve &&
 353        test $(ls .git/sharedindex.* | wc -l) -le 2
 354'
 355
 356test_expect_success 'check splitIndex.sharedIndexExpire set to 16 days' '
 357        git config splitIndex.sharedIndexExpire "16.days.ago" &&
 358        test-tool chmtime =$just_over_2_weeks_ago .git/sharedindex.* &&
 359        create_non_racy_file thirteen &&
 360        git update-index --add thirteen &&
 361        test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
 362        just_over_16_days_ago=$((-1-16*86400)) &&
 363        test-tool chmtime =$just_over_16_days_ago .git/sharedindex.* &&
 364        create_non_racy_file fourteen &&
 365        git update-index --add fourteen &&
 366        test $(ls .git/sharedindex.* | wc -l) -le 2
 367'
 368
 369test_expect_success 'check splitIndex.sharedIndexExpire set to "never" and "now"' '
 370        git config splitIndex.sharedIndexExpire never &&
 371        just_10_years_ago=$((-365*10*86400)) &&
 372        test-tool chmtime =$just_10_years_ago .git/sharedindex.* &&
 373        create_non_racy_file fifteen &&
 374        git update-index --add fifteen &&
 375        test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
 376        git config splitIndex.sharedIndexExpire now &&
 377        just_1_second_ago=-1 &&
 378        test-tool chmtime =$just_1_second_ago .git/sharedindex.* &&
 379        create_non_racy_file sixteen &&
 380        git update-index --add sixteen &&
 381        test $(ls .git/sharedindex.* | wc -l) -le 2
 382'
 383
 384while read -r mode modebits
 385do
 386        test_expect_success POSIXPERM "split index respects core.sharedrepository $mode" '
 387                # Remove existing shared index files
 388                git config core.splitIndex false &&
 389                git update-index --force-remove one &&
 390                rm -f .git/sharedindex.* &&
 391                # Create one new shared index file
 392                git config core.sharedrepository "$mode" &&
 393                git config core.splitIndex true &&
 394                create_non_racy_file one &&
 395                git update-index --add one &&
 396                echo "$modebits" >expect &&
 397                test_modebits .git/index >actual &&
 398                test_cmp expect actual &&
 399                shared=$(ls .git/sharedindex.*) &&
 400                case "$shared" in
 401                *" "*)
 402                        # we have more than one???
 403                        false ;;
 404                *)
 405                        test_modebits "$shared" >actual &&
 406                        test_cmp expect actual ;;
 407                esac
 408        '
 409done <<\EOF
 4100666 -rw-rw-rw-
 4110642 -rw-r---w-
 412EOF
 413
 414test_expect_success POSIXPERM,SANITY 'graceful handling when splitting index is not allowed' '
 415        test_create_repo ro &&
 416        (
 417                cd ro &&
 418                test_commit initial &&
 419                git update-index --split-index &&
 420                test -f .git/sharedindex.*
 421        ) &&
 422        cp ro/.git/index new-index &&
 423        test_when_finished "chmod u+w ro/.git" &&
 424        chmod u-w ro/.git &&
 425        GIT_INDEX_FILE="$(pwd)/new-index" git -C ro update-index --split-index &&
 426        chmod u+w ro/.git &&
 427        rm ro/.git/sharedindex.* &&
 428        GIT_INDEX_FILE=new-index git ls-files >actual &&
 429        echo initial.t >expected &&
 430        test_cmp expected actual
 431'
 432
 433test_expect_success 'writing split index with null sha1 does not write cache tree' '
 434        git config core.splitIndex true &&
 435        git config splitIndex.maxPercentChange 0 &&
 436        git commit -m "commit" &&
 437        {
 438                git ls-tree HEAD &&
 439                printf "160000 commit $ZERO_OID\\tbroken\\n"
 440        } >broken-tree &&
 441        echo "add broken entry" >msg &&
 442
 443        tree=$(git mktree <broken-tree) &&
 444        test_tick &&
 445        commit=$(git commit-tree $tree -p HEAD <msg) &&
 446        git update-ref HEAD "$commit" &&
 447        GIT_ALLOW_NULL_SHA1=1 git reset --hard &&
 448        test_might_fail test-tool dump-cache-tree >cache-tree.out &&
 449        test_line_count = 0 cache-tree.out
 450'
 451
 452test_done