summaryrefslogtreecommitdiff
path: root/t/t1092-sparse-checkout-compatibility.sh
diff options
context:
space:
mode:
Diffstat (limited to 't/t1092-sparse-checkout-compatibility.sh')
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh207
1 files changed, 188 insertions, 19 deletions
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 16fbd2c6db..f8270943aa 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -19,6 +19,8 @@ test_expect_success 'setup' '
mkdir folder1 folder2 deep x &&
mkdir deep/deeper1 deep/deeper2 deep/before deep/later &&
mkdir deep/deeper1/deepest &&
+ mkdir deep/deeper1/deepest2 &&
+ mkdir deep/deeper1/deepest3 &&
echo "after deeper1" >deep/e &&
echo "after deepest" >deep/deeper1/e &&
cp a folder1 &&
@@ -30,7 +32,9 @@ test_expect_success 'setup' '
cp a deep/deeper2 &&
cp a deep/later &&
cp a deep/deeper1/deepest &&
- cp -r deep/deeper1/deepest deep/deeper2 &&
+ cp a deep/deeper1/deepest2 &&
+ cp a deep/deeper1/deepest3 &&
+ cp -r deep/deeper1/ deep/deeper2 &&
mkdir deep/deeper1/0 &&
mkdir deep/deeper1/0/0 &&
touch deep/deeper1/0/1 &&
@@ -126,6 +130,8 @@ test_expect_success 'setup' '
git checkout -b deepest base &&
echo "updated deepest" >deep/deeper1/deepest/a &&
+ echo "updated deepest2" >deep/deeper1/deepest2/a &&
+ echo "updated deepest3" >deep/deeper1/deepest3/a &&
git commit -a -m "update deepest" &&
git checkout -f base &&
@@ -301,6 +307,14 @@ test_expect_success 'add, commit, checkout' '
test_all_match git checkout -
'
+test_expect_success 'deep changes during checkout' '
+ init_repos &&
+
+ test_sparse_match git sparse-checkout set deep/deeper1/deepest &&
+ test_all_match git checkout deepest &&
+ test_all_match git checkout base
+'
+
test_expect_success 'add outside sparse cone' '
init_repos &&
@@ -489,26 +503,118 @@ test_expect_failure 'blame with pathspec outside sparse definition' '
test_all_match git blame deep/deeper2/deepest/a
'
-# NEEDSWORK: a sparse-checkout behaves differently from a full checkout
-# in this scenario, but it shouldn't.
-test_expect_failure 'checkout and reset (mixed)' '
+test_expect_success 'checkout and reset (mixed)' '
init_repos &&
test_all_match git checkout -b reset-test update-deep &&
test_all_match git reset deepest &&
- test_all_match git reset update-folder1 &&
- test_all_match git reset update-folder2
+
+ # Because skip-worktree is preserved, resetting to update-folder1
+ # will show worktree changes for folder1/a in full-checkout, but not
+ # in sparse-checkout or sparse-index.
+ git -C full-checkout reset update-folder1 >full-checkout-out &&
+ test_sparse_match git reset update-folder1 &&
+ grep "M folder1/a" full-checkout-out &&
+ ! grep "M folder1/a" sparse-checkout-out &&
+ run_on_sparse test_path_is_missing folder1
'
-# NEEDSWORK: a sparse-checkout behaves differently from a full checkout
-# in this scenario, but it shouldn't.
-test_expect_success 'checkout and reset (mixed) [sparse]' '
+test_expect_success 'checkout and reset (merge)' '
init_repos &&
- test_sparse_match git checkout -b reset-test update-deep &&
- test_sparse_match git reset deepest &&
- test_sparse_match git reset update-folder1 &&
- test_sparse_match git reset update-folder2
+ write_script edit-contents <<-\EOF &&
+ echo text >>$1
+ EOF
+
+ test_all_match git checkout -b reset-test update-deep &&
+ run_on_all ../edit-contents a &&
+ test_all_match git reset --merge deepest &&
+ test_all_match git status --porcelain=v2 &&
+
+ test_all_match git reset --hard update-deep &&
+ run_on_all ../edit-contents deep/a &&
+ test_all_match test_must_fail git reset --merge deepest
+'
+
+test_expect_success 'checkout and reset (keep)' '
+ init_repos &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>$1
+ EOF
+
+ test_all_match git checkout -b reset-test update-deep &&
+ run_on_all ../edit-contents a &&
+ test_all_match git reset --keep deepest &&
+ test_all_match git status --porcelain=v2 &&
+
+ test_all_match git reset --hard update-deep &&
+ run_on_all ../edit-contents deep/a &&
+ test_all_match test_must_fail git reset --keep deepest
+'
+
+test_expect_success 'reset with pathspecs inside sparse definition' '
+ init_repos &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>$1
+ EOF
+
+ test_all_match git checkout -b reset-test update-deep &&
+ run_on_all ../edit-contents deep/a &&
+
+ test_all_match git reset base -- deep/a &&
+ test_all_match git status --porcelain=v2 &&
+
+ test_all_match git reset base -- nonexistent-file &&
+ test_all_match git status --porcelain=v2 &&
+
+ test_all_match git reset deepest -- deep &&
+ test_all_match git status --porcelain=v2
+'
+
+# Although the working tree differs between full and sparse checkouts after
+# reset, the state of the index is the same.
+test_expect_success 'reset with pathspecs outside sparse definition' '
+ init_repos &&
+ test_all_match git checkout -b reset-test base &&
+
+ test_sparse_match git reset update-folder1 -- folder1 &&
+ git -C full-checkout reset update-folder1 -- folder1 &&
+ test_sparse_match git status --porcelain=v2 &&
+ test_all_match git rev-parse HEAD:folder1 &&
+
+ test_sparse_match git reset update-folder2 -- folder2/a &&
+ git -C full-checkout reset update-folder2 -- folder2/a &&
+ test_sparse_match git status --porcelain=v2 &&
+ test_all_match git rev-parse HEAD:folder2/a
+'
+
+test_expect_success 'reset with wildcard pathspec' '
+ init_repos &&
+
+ test_all_match git reset update-deep -- deep\* &&
+ test_all_match git ls-files -s -- deep &&
+
+ test_all_match git reset deepest -- deep\*\*\* &&
+ test_all_match git ls-files -s -- deep &&
+
+ # The following `git reset`s result in updating the index on files with
+ # `skip-worktree` enabled. To avoid failing due to discrepencies in reported
+ # "modified" files, `test_sparse_match` reset is performed separately from
+ # "full-checkout" reset, then the index contents of all repos are verified.
+
+ test_sparse_match git reset update-folder1 -- \*/a &&
+ git -C full-checkout reset update-folder1 -- \*/a &&
+ test_all_match git ls-files -s -- deep/a folder1/a &&
+
+ test_sparse_match git reset update-folder2 -- folder\* &&
+ git -C full-checkout reset update-folder2 -- folder\* &&
+ test_all_match git ls-files -s -- folder10 folder1 folder2 &&
+
+ test_sparse_match git reset base -- folder1/\* &&
+ git -C full-checkout reset base -- folder1/\* &&
+ test_all_match git ls-files -s -- folder1
'
test_expect_success 'merge, cherry-pick, and rebase' '
@@ -685,15 +791,50 @@ test_expect_success 'submodule handling' '
grep "160000 commit $(git -C initial-repo rev-parse HEAD) modules/sub" cache
'
+# When working with a sparse index, some commands will need to expand the
+# index to operate properly. If those commands also write the index back
+# to disk, they need to convert the index to sparse before writing.
+# This test verifies that both of these events are logged in trace2 logs.
test_expect_success 'sparse-index is expanded and converted back' '
init_repos &&
- GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
- git -C sparse-index -c core.fsmonitor="" reset --hard &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C sparse-index reset -- folder1/a &&
test_region index convert_to_sparse trace2.txt &&
test_region index ensure_full_index trace2.txt
'
+test_expect_success 'index.sparse disabled inline uses full index' '
+ init_repos &&
+
+ # When index.sparse is disabled inline with `git status`, the
+ # index is expanded at the beginning of the execution then never
+ # converted back to sparse. It is then written to disk as a full index.
+ rm -f trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+ git -C sparse-index -c index.sparse=false status &&
+ ! test_region index convert_to_sparse trace2.txt &&
+ test_region index ensure_full_index trace2.txt &&
+
+ # Since index.sparse is set to true at a repo level, the index
+ # is converted from full to sparse when read, then never expanded
+ # over the course of `git status`. It is written to disk as a sparse
+ # index.
+ rm -f trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+ git -C sparse-index status &&
+ test_region index convert_to_sparse trace2.txt &&
+ ! test_region index ensure_full_index trace2.txt &&
+
+ # Now that the index has been written to disk as sparse, it is not
+ # converted to sparse (or expanded to full) when read by `git status`.
+ rm -f trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+ git -C sparse-index status &&
+ ! test_region index convert_to_sparse trace2.txt &&
+ ! test_region index ensure_full_index trace2.txt
+'
+
ensure_not_expanded () {
rm -f trace2.txt &&
echo >>sparse-index/untracked.txt &&
@@ -702,10 +843,10 @@ ensure_not_expanded () {
then
shift &&
test_must_fail env \
- GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
git -C sparse-index "$@" || return 1
else
- GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
git -C sparse-index "$@" || return 1
fi &&
test_region ! index ensure_full_index trace2.txt
@@ -726,9 +867,9 @@ test_expect_success 'sparse-index is not expanded' '
ensure_not_expanded checkout - &&
ensure_not_expanded switch rename-out-to-out &&
ensure_not_expanded switch - &&
- git -C sparse-index reset --hard &&
+ ensure_not_expanded reset --hard &&
ensure_not_expanded checkout rename-out-to-out -- deep/deeper1 &&
- git -C sparse-index reset --hard &&
+ ensure_not_expanded reset --hard &&
ensure_not_expanded restore -s rename-out-to-out -- deep/deeper1 &&
echo >>sparse-index/README.md &&
@@ -738,6 +879,34 @@ test_expect_success 'sparse-index is not expanded' '
echo >>sparse-index/untracked.txt &&
ensure_not_expanded add . &&
+ for ref in update-deep update-folder1 update-folder2 update-deep
+ do
+ echo >>sparse-index/README.md &&
+ ensure_not_expanded reset --hard $ref || return 1
+ done &&
+
+ ensure_not_expanded reset --mixed base &&
+ ensure_not_expanded reset --hard update-deep &&
+ ensure_not_expanded reset --keep base &&
+ ensure_not_expanded reset --merge update-deep &&
+ ensure_not_expanded reset --hard &&
+
+ ensure_not_expanded reset base -- deep/a &&
+ ensure_not_expanded reset base -- nonexistent-file &&
+ ensure_not_expanded reset deepest -- deep &&
+
+ # Although folder1 is outside the sparse definition, it exists as a
+ # directory entry in the index, so the pathspec will not force the
+ # index to be expanded.
+ ensure_not_expanded reset deepest -- folder1 &&
+ ensure_not_expanded reset deepest -- folder1/ &&
+
+ # Wildcard identifies only in-cone files, no index expansion
+ ensure_not_expanded reset deepest -- deep/\* &&
+
+ # Wildcard identifies only full sparse directories, no index expansion
+ ensure_not_expanded reset deepest -- folder\* &&
+
ensure_not_expanded checkout -f update-deep &&
test_config -C sparse-index pull.twohead ort &&
(