#!/bin/sh
# This test can give false success if your machine is sufficiently
# slow or all trials happened to happen on second boundaries.
test_description='racy split index'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
# Only split the index when the test explicitly says so.
sane_unset GIT_TEST_SPLIT_INDEX &&
git config splitIndex.maxPercentChange 100 &&
echo "cached content" >racy-file &&
git add racy-file &&
git commit -m initial &&
echo something >other-file &&
# No raciness with this file.
test-tool chmtime =-20 other-file &&
echo "+cached content" >expect
'
check_cached_diff () {
git diff-index --patch --cached $EMPTY_TREE racy-file >diff &&
tail -1 diff >actual &&
test_cmp expect actual
}
trials="0 1 2 3 4"
for trial in $trials
do
test_expect_success "split the index while adding a racily clean file #$trial" '
rm -f .git/index .git/sharedindex.* &&
# The next three commands must be run within the same
# second (so both writes to racy-file result in the same
# mtime) to create the interesting racy situation.
echo "cached content" >racy-file &&
# Update and split the index. The cache entry of
# racy-file will be stored only in the shared index.
git update-index --split-index --add racy-file &&
# File size must stay the same.
echo "dirty worktree" >racy-file &&
# Subsequent git commands should notice that racy-file
# and the split index have the same mtime, and check
# the content of the file to see if it is actually
# clean.
check_cached_diff
'
done
for trial in $trials
do
test_expect_success "add a racily clean file to an already split index #$trial" '
rm -f .git/index .git/sharedindex.* &&
git update-index --split-index &&
# The next three commands must be run within the same
# second.
echo "cached content" >racy-file &&
# Update the split index. The cache entry of racy-file
# will be stored only in the split index.
git update-index --add racy-file &&
# File size must stay the same.
echo "dirty worktree" >racy-file &&
# Subsequent git commands should notice that racy-file
# and the split index have the same mtime, and check
# the content of the file to see if it is actually
# clean.
check_cached_diff
'
done
for trial in $trials
do
test_expect_success "split the index when the index contains a racily clean cache entry #$trial" '
rm -f .git/index .git/sharedindex.* &&
# The next three commands must be run within the same
# second.
echo "cached content" >racy-file &&
git update-index --add racy-file &&
# File size must stay the same.
echo "dirty worktree" >racy-file &&
# Now wait a bit to ensure that the split index written
# below will get a more recent mtime than racy-file.
sleep 1 &&
# Update and split the index when the index contains
# the racily clean cache entry of racy-file.
# A corresponding replacement cache entry with smudged
# stat data should be added to the new split index.
git update-index --split-index --add other-file &&
# Subsequent git commands should notice the smudged
# stat data in the replacement cache entry and that it
# doesnt match with the file the worktree.
check_cached_diff
'
done
for trial in $trials
do
test_expect_success "update the split index when it contains a new racily clean cache entry #$trial" '
rm -f .git/index .git/sharedindex.* &&
git update-index --split-index &&
# The next three commands must be run within the same
# second.
echo "cached content" >racy-file &&
# Update the split index. The cache entry of racy-file
# will be stored only in the split index.
git update-index --add racy-file &&
# File size must stay the same.
echo "dirty worktree" >racy-file &&
# Now wait a bit to ensure that the split index written
# below will get a more recent mtime than racy-file.
sleep 1 &&
# Update the split index when the racily clean cache
# entry of racy-file is only stored in the split index.
# An updated cache entry with smudged stat data should
# be added to the new split index.
git update-index --add other-file &&
# Subsequent git commands should notice the smudged
# stat data.
check_cached_diff
'
done
for trial in $trials
do
test_expect_success "update the split index when a racily clean cache entry is stored only in the shared index #$trial" '
rm -f .git/index .git/sharedindex.* &&
# The next three commands must be run within the same
# second.
echo "cached content" >racy-file &&
# Update and split the index. The cache entry of
# racy-file will be stored only in the shared index.
git update-index --split-index --add racy-file &&
# File size must stay the same.
echo "dirty worktree" >racy-file &&
# Now wait a bit to ensure that the split index written
# below will get a more recent mtime than racy-file.
sleep 1 &&
# Update the split index when the racily clean cache
# entry of racy-file is only stored in the shared index.
# A corresponding replacement cache entry with smudged
# stat data should be added to the new split index.
git update-index --add other-file &&
# Subsequent git commands should notice the smudged
# stat data.
check_cached_diff
'
done
for trial in $trials
do
test_expect_success "update the split index after unpack trees() copied a racily clean cache entry from the shared index #$trial" '
rm -f .git/index .git/sharedindex.* &&
# The next three commands must be run within the same
# second.
echo "cached content" >racy-file &&
# Update and split the index. The cache entry of
# racy-file will be stored only in the shared index.
git update-index --split-index --add racy-file &&
# File size must stay the same.
echo "dirty worktree" >racy-file &&
# Now wait a bit to ensure that the split index written
# below will get a more recent mtime than racy-file.
sleep 1 &&
# Update the split index after unpack_trees() copied the
# racily clean cache entry of racy-file from the shared
# index. A corresponding replacement cache entry
# with smudged stat data should be added to the new
# split index.
git read-tree -m HEAD &&
# Subsequent git commands should notice the smudged
# stat data.
check_cached_diff
'
done
test_done