]> git.ipfire.org Git - thirdparty/git.git/blobdiff - t/t1092-sparse-checkout-compatibility.sh
Sync with 2.33.5
[thirdparty/git.git] / t / t1092-sparse-checkout-compatibility.sh
index 51fd377a8e475539202aecca51cc66d9a1d26779..c37e0f59bca02ef61c9da19adbb25141a3076483 100755 (executable)
@@ -47,7 +47,7 @@ test_expect_success 'setup' '
                git checkout -b base &&
                for dir in folder1 folder2 deep
                do
-                       git checkout -b update-$dir &&
+                       git checkout -b update-$dir base &&
                        echo "updated $dir" >$dir/a &&
                        git commit -a -m "update $dir" || return 1
                done &&
@@ -114,6 +114,16 @@ test_expect_success 'setup' '
                git add . &&
                git commit -m "file to dir" &&
 
+               for side in left right
+               do
+                       git checkout -b merge-$side base &&
+                       echo $side >>deep/deeper2/a &&
+                       echo $side >>folder1/a &&
+                       echo $side >>folder2/a &&
+                       git add . &&
+                       git commit -m "$side" || return 1
+               done &&
+
                git checkout -b deepest base &&
                echo "updated deepest" >deep/deeper1/deepest/a &&
                git commit -a -m "update deepest" &&
@@ -177,6 +187,16 @@ test_sparse_match () {
        test_cmp sparse-checkout-err sparse-index-err
 }
 
+test_sparse_unstaged () {
+       file=$1 &&
+       for repo in sparse-checkout sparse-index
+       do
+               # Skip "unmerged" paths
+               git -C $repo diff --staged --diff-filter=u -- "$file" >diff &&
+               test_must_be_empty diff || return 1
+       done
+}
+
 test_expect_success 'sparse-index contents' '
        init_repos &&
 
@@ -281,6 +301,20 @@ test_expect_success 'add, commit, checkout' '
        test_all_match git checkout -
 '
 
+test_expect_success 'add outside sparse cone' '
+       init_repos &&
+
+       run_on_sparse mkdir folder1 &&
+       run_on_sparse ../edit-contents folder1/a &&
+       run_on_sparse ../edit-contents folder1/newfile &&
+       test_sparse_match test_must_fail git add folder1/a &&
+       grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+       test_sparse_unstaged folder1/a &&
+       test_sparse_match test_must_fail git add folder1/newfile &&
+       grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+       test_sparse_unstaged folder1/newfile
+'
+
 test_expect_success 'commit including unstaged changes' '
        init_repos &&
 
@@ -312,9 +346,6 @@ test_expect_success 'commit including unstaged changes' '
 test_expect_success 'status/add: outside sparse cone' '
        init_repos &&
 
-       # adding a "missing" file outside the cone should fail
-       test_sparse_match test_must_fail git add folder1/a &&
-
        # folder1 is at HEAD, but outside the sparse cone
        run_on_sparse mkdir folder1 &&
        cp initial-repo/folder1/a sparse-checkout/folder1/a &&
@@ -330,21 +361,29 @@ test_expect_success 'status/add: outside sparse cone' '
 
        test_sparse_match git status --porcelain=v2 &&
 
-       # This "git add folder1/a" fails with a warning
-       # in the sparse repos, differing from the full
-       # repo. This is intentional.
+       # Adding the path outside of the sparse-checkout cone should fail.
        test_sparse_match test_must_fail git add folder1/a &&
+       grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+       test_sparse_unstaged folder1/a &&
        test_sparse_match test_must_fail git add --refresh folder1/a &&
-       test_all_match git status --porcelain=v2 &&
-
-       test_all_match git add . &&
+       grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+       test_sparse_unstaged folder1/a &&
+       test_sparse_match test_must_fail git add folder1/new &&
+       grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+       test_sparse_unstaged folder1/new &&
+       test_sparse_match git add --sparse folder1/a &&
+       test_sparse_match git add --sparse folder1/new &&
+
+       test_all_match git add --sparse . &&
        test_all_match git status --porcelain=v2 &&
        test_all_match git commit -m folder1/new &&
+       test_all_match git rev-parse HEAD^{tree} &&
 
        run_on_all ../edit-contents folder1/newer &&
-       test_all_match git add folder1/ &&
+       test_all_match git add --sparse folder1/ &&
        test_all_match git status --porcelain=v2 &&
-       test_all_match git commit -m folder1/newer
+       test_all_match git commit -m folder1/newer &&
+       test_all_match git rev-parse HEAD^{tree}
 '
 
 test_expect_success 'checkout and reset --hard' '
@@ -472,16 +511,97 @@ test_expect_success 'checkout and reset (mixed) [sparse]' '
        test_sparse_match git reset update-folder2
 '
 
-test_expect_success 'merge' '
+test_expect_success 'merge, cherry-pick, and rebase' '
        init_repos &&
 
-       test_all_match git checkout -b merge update-deep &&
-       test_all_match git merge -m "folder1" update-folder1 &&
-       test_all_match git rev-parse HEAD^{tree} &&
-       test_all_match git merge -m "folder2" update-folder2 &&
+       for OPERATION in "merge -m merge" cherry-pick "rebase --apply" "rebase --merge"
+       do
+               test_all_match git checkout -B temp update-deep &&
+               test_all_match git $OPERATION update-folder1 &&
+               test_all_match git rev-parse HEAD^{tree} &&
+               test_all_match git $OPERATION update-folder2 &&
+               test_all_match git rev-parse HEAD^{tree} || return 1
+       done
+'
+
+test_expect_success 'merge with conflict outside cone' '
+       init_repos &&
+
+       test_all_match git checkout -b merge-tip merge-left &&
+       test_all_match git status --porcelain=v2 &&
+       test_all_match test_must_fail git merge -m merge merge-right &&
+       test_all_match git status --porcelain=v2 &&
+
+       # Resolve the conflict in different ways:
+       # 1. Revert to the base
+       test_all_match git checkout base -- deep/deeper2/a &&
+       test_all_match git status --porcelain=v2 &&
+
+       # 2. Add the file with conflict markers
+       test_sparse_match test_must_fail git add folder1/a &&
+       grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+       test_sparse_unstaged folder1/a &&
+       test_all_match git add --sparse folder1/a &&
+       test_all_match git status --porcelain=v2 &&
+
+       # 3. Rename the file to another sparse filename and
+       #    accept conflict markers as resolved content.
+       run_on_all mv folder2/a folder2/z &&
+       test_sparse_match test_must_fail git add folder2 &&
+       grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+       test_sparse_unstaged folder2/z &&
+       test_all_match git add --sparse folder2 &&
+       test_all_match git status --porcelain=v2 &&
+
+       test_all_match git merge --continue &&
+       test_all_match git status --porcelain=v2 &&
        test_all_match git rev-parse HEAD^{tree}
 '
 
+test_expect_success 'cherry-pick/rebase with conflict outside cone' '
+       init_repos &&
+
+       for OPERATION in cherry-pick rebase
+       do
+               test_all_match git checkout -B tip &&
+               test_all_match git reset --hard merge-left &&
+               test_all_match git status --porcelain=v2 &&
+               test_all_match test_must_fail git $OPERATION merge-right &&
+               test_all_match git status --porcelain=v2 &&
+
+               # Resolve the conflict in different ways:
+               # 1. Revert to the base
+               test_all_match git checkout base -- deep/deeper2/a &&
+               test_all_match git status --porcelain=v2 &&
+
+               # 2. Add the file with conflict markers
+               # NEEDSWORK: Even though the merge conflict removed the
+               # SKIP_WORKTREE bit from the index entry for folder1/a, we should
+               # warn that this is a problematic add.
+               test_sparse_match test_must_fail git add folder1/a &&
+               grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+               test_sparse_unstaged folder1/a &&
+               test_all_match git add --sparse folder1/a &&
+               test_all_match git status --porcelain=v2 &&
+
+               # 3. Rename the file to another sparse filename and
+               #    accept conflict markers as resolved content.
+               # NEEDSWORK: This mode now fails, because folder2/z is
+               # outside of the sparse-checkout cone and does not match an
+               # existing index entry with the SKIP_WORKTREE bit cleared.
+               run_on_all mv folder2/a folder2/z &&
+               test_sparse_match test_must_fail git add folder2 &&
+               grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+               test_sparse_unstaged folder2/z &&
+               test_all_match git add --sparse folder2 &&
+               test_all_match git status --porcelain=v2 &&
+
+               test_all_match git $OPERATION --continue &&
+               test_all_match git status --porcelain=v2 &&
+               test_all_match git rev-parse HEAD^{tree} || return 1
+       done
+'
+
 test_expect_success 'merge with outside renames' '
        init_repos &&
 
@@ -549,6 +669,7 @@ test_expect_success 'clean' '
 test_expect_success 'submodule handling' '
        init_repos &&
 
+       test_sparse_match git sparse-checkout add modules &&
        test_all_match mkdir modules &&
        test_all_match touch modules/a &&
        test_all_match git add modules &&
@@ -560,6 +681,7 @@ test_expect_success 'submodule handling' '
        test_all_match git commit -m "add submodule" &&
 
        # having a submodule prevents "modules" from collapse
+       test_sparse_match git sparse-checkout set deep/deeper1 &&
        test-tool -C sparse-index read-cache --table >cache &&
        grep "100644 blob .*    modules/a" cache &&
        grep "160000 commit $(git -C initial-repo rev-parse HEAD)       modules/sub" cache
@@ -577,8 +699,17 @@ test_expect_success 'sparse-index is expanded and converted back' '
 ensure_not_expanded () {
        rm -f trace2.txt &&
        echo >>sparse-index/untracked.txt &&
-       GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
-               git -C sparse-index "$@" &&
+
+       if test "$1" = "!"
+       then
+               shift &&
+               test_must_fail env \
+                       GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+                       git -C sparse-index "$@" || return 1
+       else
+               GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+                       git -C sparse-index "$@" || return 1
+       fi &&
        test_region ! index ensure_full_index trace2.txt
 }
 
@@ -600,7 +731,42 @@ test_expect_success 'sparse-index is not expanded' '
        git -C sparse-index reset --hard &&
        ensure_not_expanded checkout rename-out-to-out -- deep/deeper1 &&
        git -C sparse-index reset --hard &&
-       ensure_not_expanded restore -s rename-out-to-out -- deep/deeper1
+       ensure_not_expanded restore -s rename-out-to-out -- deep/deeper1 &&
+
+       echo >>sparse-index/README.md &&
+       ensure_not_expanded add -A &&
+       echo >>sparse-index/extra.txt &&
+       ensure_not_expanded add extra.txt &&
+       echo >>sparse-index/untracked.txt &&
+       ensure_not_expanded add . &&
+
+       ensure_not_expanded checkout -f update-deep &&
+       test_config -C sparse-index pull.twohead ort &&
+       (
+               sane_unset GIT_TEST_MERGE_ALGORITHM &&
+               for OPERATION in "merge -m merge" cherry-pick rebase
+               do
+                       ensure_not_expanded merge -m merge update-folder1 &&
+                       ensure_not_expanded merge -m merge update-folder2 || return 1
+               done
+       )
+'
+
+test_expect_success 'sparse-index is not expanded: merge conflict in cone' '
+       init_repos &&
+
+       for side in right left
+       do
+               git -C sparse-index checkout -b expand-$side base &&
+               echo $side >sparse-index/deep/a &&
+               git -C sparse-index commit -a -m "$side" || return 1
+       done &&
+
+       (
+               sane_unset GIT_TEST_MERGE_ALGORITHM &&
+               git -C sparse-index config pull.twohead ort &&
+               ensure_not_expanded ! merge -m merged expand-right
+       )
 '
 
 # NEEDSWORK: a sparse-checkout behaves differently from a full checkout