#!/bin/sh test_description='split index mode tests' . ./test-lib.sh # We need total control of index splitting here sane_unset GIT_TEST_SPLIT_INDEX # A couple of tests expect the index to have a specific checksum, # but the presence of the optional FSMN extension would interfere # with those checks, so disable it in this test script. sane_unset GIT_FSMONITOR_TEST # Create a file named as $1 with content read from stdin. # Set the file's mtime to a few seconds in the past to avoid racy situations. create_non_racy_file () { cat >"$1" && test-tool chmtime =-5 "$1" } test_expect_success 'enable split index' ' git config splitIndex.maxPercentChange 100 && git update-index --split-index && test-tool dump-split-index .git/index >actual && indexversion=$(test-tool index-version <.git/index) && if test "$indexversion" = "4" then own=432ef4b63f32193984f339431fd50ca796493569 base=508851a7f0dfa8691e9f69c7f055865389012491 else own=8299b0bcd1ac364e5f1d7768efb62fa2da79a339 base=39d890139ee5356c7ef572216cebcd27aa41f9df fi && cat >expect <<-EOF && own $own base $base replacements: deletions: EOF test_cmp expect actual ' test_expect_success 'add one file' ' create_non_racy_file one && git update-index --add one && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && 100644 $EMPTY_BLOB 0 one EOF test_cmp ls-files.expect ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && base $base 100644 $EMPTY_BLOB 0 one replacements: deletions: EOF test_cmp expect actual ' test_expect_success 'disable split index' ' git update-index --no-split-index && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && 100644 $EMPTY_BLOB 0 one EOF test_cmp ls-files.expect ls-files.actual && BASE=$(test-tool dump-split-index .git/index | grep "^own" | sed "s/own/base/") && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && not a split index EOF test_cmp expect actual ' test_expect_success 'enable split index again, "one" now belongs to base index"' ' git update-index --split-index && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && 100644 $EMPTY_BLOB 0 one EOF test_cmp ls-files.expect ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE replacements: deletions: EOF test_cmp expect actual ' test_expect_success 'modify original file, base index untouched' ' echo modified | create_non_racy_file one && git update-index one && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one EOF test_cmp ls-files.expect ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && q_to_tab >expect <<-EOF && $BASE 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q replacements: 0 deletions: EOF test_cmp expect actual ' test_expect_success 'add another file, which stays index' ' create_non_racy_file two && git update-index --add two && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one 100644 $EMPTY_BLOB 0 two EOF test_cmp ls-files.expect ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && q_to_tab >expect <<-EOF && $BASE 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q 100644 $EMPTY_BLOB 0 two replacements: 0 deletions: EOF test_cmp expect actual ' test_expect_success 'remove file not in base index' ' git update-index --force-remove two && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one EOF test_cmp ls-files.expect ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && q_to_tab >expect <<-EOF && $BASE 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q replacements: 0 deletions: EOF test_cmp expect actual ' test_expect_success 'remove file in base index' ' git update-index --force-remove one && git ls-files --stage >ls-files.actual && test_must_be_empty ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE replacements: deletions: 0 EOF test_cmp expect actual ' test_expect_success 'add original file back' ' create_non_racy_file one && git update-index --add one && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && 100644 $EMPTY_BLOB 0 one EOF test_cmp ls-files.expect ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE 100644 $EMPTY_BLOB 0 one replacements: deletions: 0 EOF test_cmp expect actual ' test_expect_success 'add new file' ' create_non_racy_file two && git update-index --add two && git ls-files --stage >actual && cat >expect <<-EOF && 100644 $EMPTY_BLOB 0 one 100644 $EMPTY_BLOB 0 two EOF test_cmp expect actual ' test_expect_success 'unify index, two files remain' ' git update-index --no-split-index && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && 100644 $EMPTY_BLOB 0 one 100644 $EMPTY_BLOB 0 two EOF test_cmp ls-files.expect ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && not a split index EOF test_cmp expect actual ' test_expect_success 'rev-parse --shared-index-path' ' test_create_repo split-index && ( cd split-index && git update-index --split-index && echo .git/sharedindex* >expect && git rev-parse --shared-index-path >actual && test_cmp expect actual && mkdir subdirectory && cd subdirectory && echo ../.git/sharedindex* >expect && git rev-parse --shared-index-path >actual && test_cmp expect actual ) ' test_expect_success 'set core.splitIndex config variable to true' ' git config core.splitIndex true && create_non_racy_file three && git update-index --add three && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 three 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two EOF test_cmp ls-files.expect ls-files.actual && BASE=$(test-tool dump-split-index .git/index | grep "^base") && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE replacements: deletions: EOF test_cmp expect actual ' test_expect_success 'set core.splitIndex config variable to false' ' git config core.splitIndex false && git update-index --force-remove three && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two EOF test_cmp ls-files.expect ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && not a split index EOF test_cmp expect actual ' test_expect_success 'set core.splitIndex config variable back to true' ' git config core.splitIndex true && create_non_racy_file three && git update-index --add three && BASE=$(test-tool dump-split-index .git/index | grep "^base") && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE replacements: deletions: EOF test_cmp expect actual && create_non_racy_file four && git update-index --add four && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 four replacements: deletions: EOF test_cmp expect actual ' test_expect_success 'check behavior with splitIndex.maxPercentChange unset' ' git config --unset splitIndex.maxPercentChange && create_non_racy_file five && git update-index --add five && BASE=$(test-tool dump-split-index .git/index | grep "^base") && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE replacements: deletions: EOF test_cmp expect actual && create_non_racy_file six && git update-index --add six && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 six replacements: deletions: EOF test_cmp expect actual ' test_expect_success 'check splitIndex.maxPercentChange set to 0' ' git config splitIndex.maxPercentChange 0 && create_non_racy_file seven && git update-index --add seven && BASE=$(test-tool dump-split-index .git/index | grep "^base") && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE replacements: deletions: EOF test_cmp expect actual && create_non_racy_file eight && git update-index --add eight && BASE=$(test-tool dump-split-index .git/index | grep "^base") && test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE replacements: deletions: EOF test_cmp expect actual ' test_expect_success 'shared index files expire after 2 weeks by default' ' create_non_racy_file ten && git update-index --add ten && test $(ls .git/sharedindex.* | wc -l) -gt 2 && just_under_2_weeks_ago=$((5-14*86400)) && test-tool chmtime =$just_under_2_weeks_ago .git/sharedindex.* && create_non_racy_file eleven && git update-index --add eleven && test $(ls .git/sharedindex.* | wc -l) -gt 2 && just_over_2_weeks_ago=$((-1-14*86400)) && test-tool chmtime =$just_over_2_weeks_ago .git/sharedindex.* && create_non_racy_file twelve && git update-index --add twelve && test $(ls .git/sharedindex.* | wc -l) -le 2 ' test_expect_success 'check splitIndex.sharedIndexExpire set to 16 days' ' git config splitIndex.sharedIndexExpire "16.days.ago" && test-tool chmtime =$just_over_2_weeks_ago .git/sharedindex.* && create_non_racy_file thirteen && git update-index --add thirteen && test $(ls .git/sharedindex.* | wc -l) -gt 2 && just_over_16_days_ago=$((-1-16*86400)) && test-tool chmtime =$just_over_16_days_ago .git/sharedindex.* && create_non_racy_file fourteen && git update-index --add fourteen && test $(ls .git/sharedindex.* | wc -l) -le 2 ' test_expect_success 'check splitIndex.sharedIndexExpire set to "never" and "now"' ' git config splitIndex.sharedIndexExpire never && just_10_years_ago=$((-365*10*86400)) && test-tool chmtime =$just_10_years_ago .git/sharedindex.* && create_non_racy_file fifteen && git update-index --add fifteen && test $(ls .git/sharedindex.* | wc -l) -gt 2 && git config splitIndex.sharedIndexExpire now && just_1_second_ago=-1 && test-tool chmtime =$just_1_second_ago .git/sharedindex.* && create_non_racy_file sixteen && git update-index --add sixteen && test $(ls .git/sharedindex.* | wc -l) -le 2 ' while read -r mode modebits do test_expect_success POSIXPERM "split index respects core.sharedrepository $mode" ' # Remove existing shared index files git config core.splitIndex false && git update-index --force-remove one && rm -f .git/sharedindex.* && # Create one new shared index file git config core.sharedrepository "$mode" && git config core.splitIndex true && create_non_racy_file one && git update-index --add one && echo "$modebits" >expect && test_modebits .git/index >actual && test_cmp expect actual && shared=$(ls .git/sharedindex.*) && case "$shared" in *" "*) # we have more than one??? false ;; *) test_modebits "$shared" >actual && test_cmp expect actual ;; esac ' done <<\EOF 0666 -rw-rw-rw- 0642 -rw-r---w- EOF test_expect_success POSIXPERM,SANITY 'graceful handling when splitting index is not allowed' ' test_create_repo ro && ( cd ro && test_commit initial && git update-index --split-index && test -f .git/sharedindex.* ) && cp ro/.git/index new-index && test_when_finished "chmod u+w ro/.git" && chmod u-w ro/.git && GIT_INDEX_FILE="$(pwd)/new-index" git -C ro update-index --split-index && chmod u+w ro/.git && rm ro/.git/sharedindex.* && GIT_INDEX_FILE=new-index git ls-files >actual && echo initial.t >expected && test_cmp expected actual ' test_expect_success 'writing split index with null sha1 does not write cache tree' ' git config core.splitIndex true && git config splitIndex.maxPercentChange 0 && git commit -m "commit" && { git ls-tree HEAD && printf "160000 commit $ZERO_OID\\tbroken\\n" } >broken-tree && echo "add broken entry" >msg && tree=$(git mktree cache-tree.out && test_line_count = 0 cache-tree.out ' test_done