]> git.ipfire.org Git - thirdparty/git.git/blobdiff - t/t1091-sparse-checkout-builtin.sh
Sync with 2.35.5
[thirdparty/git.git] / t / t1091-sparse-checkout-builtin.sh
index 38fc8340f5c9b7bfd2ede379545af809c2e9e636..7931d51ea90761fbd591f16e353918e13dd1eb2f 100755 (executable)
@@ -5,6 +5,9 @@ test_description='sparse checkout builtin tests'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+GIT_TEST_SPLIT_INDEX=false
+export GIT_TEST_SPLIT_INDEX
+
 . ./test-lib.sh
 
 list_files() {
@@ -41,7 +44,15 @@ test_expect_success 'setup' '
        )
 '
 
-test_expect_success 'git sparse-checkout list (empty)' '
+test_expect_success 'git sparse-checkout list (not sparse)' '
+       test_must_fail git -C repo sparse-checkout list >list 2>err &&
+       test_must_be_empty list &&
+       test_i18ngrep "this worktree is not sparse" err
+'
+
+test_expect_success 'git sparse-checkout list (not sparse)' '
+       git -C repo sparse-checkout set &&
+       rm repo/.git/info/sparse-checkout &&
        git -C repo sparse-checkout list >list 2>err &&
        test_must_be_empty list &&
        test_i18ngrep "this worktree is not sparse (sparse-checkout file may not exist)" err
@@ -71,6 +82,12 @@ test_expect_success 'git sparse-checkout init' '
        check_files repo a
 '
 
+test_expect_success 'git sparse-checkout init in empty repo' '
+       test_when_finished rm -rf empty-repo blank-template &&
+       git init --template= empty-repo &&
+       git -C empty-repo sparse-checkout init
+'
+
 test_expect_success 'git sparse-checkout list after init' '
        git -C repo sparse-checkout list >actual &&
        cat >expect <<-\EOF &&
@@ -103,6 +120,18 @@ test_expect_success 'clone --sparse' '
        check_files clone a
 '
 
+test_expect_success 'switching to cone mode with non-cone mode patterns' '
+       git init bad-patterns &&
+       (
+               cd bad-patterns &&
+               git sparse-checkout init &&
+               git sparse-checkout add dir &&
+               git config --worktree core.sparseCheckoutCone true &&
+               test_must_fail git sparse-checkout add dir 2>err &&
+               grep "existing sparse-checkout patterns do not use cone mode" err
+       )
+'
+
 test_expect_success 'interaction with clone --no-checkout (unborn index)' '
        git clone --no-checkout "file://$(pwd)/repo" clone_no_checkout &&
        git -C clone_no_checkout sparse-checkout init --cone &&
@@ -126,9 +155,9 @@ test_expect_success 'interaction with clone --no-checkout (unborn index)' '
 '
 
 test_expect_success 'set enables config' '
-       git init empty-config &&
+       git init worktree-config &&
        (
-               cd empty-config &&
+               cd worktree-config &&
                test_commit test file &&
                test_path_is_missing .git/config.worktree &&
                git sparse-checkout set nothing &&
@@ -165,12 +194,14 @@ test_expect_success 'set sparse-checkout using --stdin' '
 '
 
 test_expect_success 'add to sparse-checkout' '
-       cat repo/.git/info/sparse-checkout >expect &&
+       cat repo/.git/info/sparse-checkout >old &&
+       test_when_finished cp old repo/.git/info/sparse-checkout &&
        cat >add <<-\EOF &&
        pattern1
        /folder1/
        pattern2
        EOF
+       cat old >expect &&
        cat add >>expect &&
        git -C repo sparse-checkout add --stdin <add &&
        git -C repo sparse-checkout list >actual &&
@@ -179,6 +210,21 @@ test_expect_success 'add to sparse-checkout' '
        check_files repo "a folder1 folder2"
 '
 
+test_expect_success 'worktree: add copies sparse-checkout patterns' '
+       cat repo/.git/info/sparse-checkout >old &&
+       test_when_finished cp old repo/.git/info/sparse-checkout &&
+       test_when_finished git -C repo worktree remove ../worktree &&
+       git -C repo sparse-checkout set --no-cone "/*" &&
+       git -C repo worktree add --quiet ../worktree 2>err &&
+       test_must_be_empty err &&
+       new="$(git -C worktree rev-parse --git-path info/sparse-checkout)" &&
+       test_path_is_file "$new" &&
+       test_cmp repo/.git/info/sparse-checkout "$new" &&
+       git -C worktree sparse-checkout set --cone &&
+       test_cmp_config -C worktree true core.sparseCheckoutCone &&
+       test_must_fail git -C repo core.sparseCheckoutCone
+'
+
 test_expect_success 'cone mode: match patterns' '
        git -C repo config --worktree core.sparseCheckoutCone true &&
        rm -rf repo/a repo/folder1 repo/folder2 &&
@@ -208,14 +254,29 @@ test_expect_success 'sparse-checkout disable' '
 test_expect_success 'sparse-index enabled and disabled' '
        git -C repo sparse-checkout init --cone --sparse-index &&
        test_cmp_config -C repo true index.sparse &&
-       test-tool -C repo read-cache --table >cache &&
-       grep " tree " cache &&
-
+       git -C repo ls-files --sparse >sparse &&
        git -C repo sparse-checkout disable &&
-       test-tool -C repo read-cache --table >cache &&
-       ! grep " tree " cache &&
+       git -C repo ls-files --sparse >full &&
+
+       cat >expect <<-\EOF &&
+       @@ -1,4 +1,7 @@
+        a
+       -deep/
+       -folder1/
+       -folder2/
+       +deep/a
+       +deep/deeper1/a
+       +deep/deeper1/deepest/a
+       +deep/deeper2/a
+       +folder1/a
+       +folder2/a
+       EOF
+
+       diff -u sparse full | tail -n +3 >actual &&
+       test_cmp expect actual &&
+
        git -C repo config --list >config &&
-       ! grep index.sparse config
+       test_cmp_config -C repo false index.sparse
 '
 
 test_expect_success 'cone mode: init and set' '
@@ -406,7 +467,7 @@ test_expect_success 'sparse-checkout (init|set|disable) warns with unmerged stat
        git -C unmerged sparse-checkout disable
 '
 
-test_expect_success 'sparse-checkout reapply' '
+test_expect_failure 'sparse-checkout reapply' '
        git clone repo tweak &&
 
        echo dirty >tweak/deep/deeper2/a &&
@@ -438,6 +499,8 @@ test_expect_success 'sparse-checkout reapply' '
        test_i18ngrep "warning.*The following paths are unmerged" err &&
        test_path_is_file tweak/folder1/a &&
 
+       # NEEDSWORK: We are asking to update a file outside of the
+       # sparse-checkout cone, but this is no longer allowed.
        git -C tweak add folder1/a &&
        git -C tweak sparse-checkout reapply 2>err &&
        test_must_be_empty err &&
@@ -447,6 +510,37 @@ test_expect_success 'sparse-checkout reapply' '
        git -C tweak sparse-checkout disable
 '
 
+test_expect_success 'reapply can handle config options' '
+       git -C repo sparse-checkout init --cone --no-sparse-index &&
+       git -C repo config --worktree --list >actual &&
+       cat >expect <<-\EOF &&
+       core.sparsecheckout=true
+       core.sparsecheckoutcone=true
+       index.sparse=false
+       EOF
+       test_cmp expect actual &&
+
+       git -C repo sparse-checkout reapply --no-cone --no-sparse-index &&
+       git -C repo config --worktree --list >actual &&
+       cat >expect <<-\EOF &&
+       core.sparsecheckout=true
+       core.sparsecheckoutcone=false
+       index.sparse=false
+       EOF
+       test_cmp expect actual &&
+
+       git -C repo sparse-checkout reapply --cone --sparse-index &&
+       git -C repo config --worktree --list >actual &&
+       cat >expect <<-\EOF &&
+       core.sparsecheckout=true
+       core.sparsecheckoutcone=true
+       index.sparse=true
+       EOF
+       test_cmp expect actual &&
+
+       git -C repo sparse-checkout disable
+'
+
 test_expect_success 'cone mode: set with core.ignoreCase=true' '
        rm repo/.git/info/sparse-checkout &&
        git -C repo sparse-checkout init --cone &&
@@ -465,7 +559,8 @@ test_expect_success 'interaction with submodules' '
        (
                cd super &&
                mkdir modules &&
-               git submodule add ../repo modules/child &&
+               git -c protocol.file.allow=always \
+                       submodule add ../repo modules/child &&
                git add . &&
                git commit -m "add submodule" &&
                git sparse-checkout init --cone &&
@@ -476,17 +571,17 @@ test_expect_success 'interaction with submodules' '
 '
 
 test_expect_success 'different sparse-checkouts with worktrees' '
+       git -C repo sparse-checkout set --cone deep folder1 &&
        git -C repo worktree add --detach ../worktree &&
-       check_files worktree "a deep folder1 folder2" &&
-       git -C worktree sparse-checkout init --cone &&
-       git -C repo sparse-checkout set folder1 &&
-       git -C worktree sparse-checkout set deep/deeper1 &&
-       check_files repo a folder1 &&
-       check_files worktree a deep
+       check_files worktree "a deep folder1" &&
+       git -C repo sparse-checkout set --cone folder1 &&
+       git -C worktree sparse-checkout set --cone deep/deeper1 &&
+       check_files repo "a folder1" &&
+       check_files worktree "a deep"
 '
 
 test_expect_success 'set using filename keeps file on-disk' '
-       git -C repo sparse-checkout set a deep &&
+       git -C repo sparse-checkout set --skip-checks a deep &&
        cat >expect <<-\EOF &&
        /*
        !/*/
@@ -579,7 +674,7 @@ test_expect_success 'pattern-checks: contained glob characters' '
                !/*/
                something$c-else/
                EOF
-               check_read_tree_errors repo "a" "disabling cone pattern matching"
+               check_read_tree_errors repo "a" "disabling cone pattern matching" || return 1
        done
 '
 
@@ -597,7 +692,7 @@ test_expect_success BSLASHPSPEC 'pattern-checks: escaped characters' '
        git -C escaped reset --hard $COMMIT &&
        check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist" zglob[!a]? &&
        git -C escaped sparse-checkout init --cone &&
-       git -C escaped sparse-checkout set zbad\\dir/bogus "zdoes*not*exist" "zdoes*exist" "zglob[!a]?" &&
+       git -C escaped sparse-checkout set --skip-checks zbad\\dir/bogus "zdoes*not*exist" "zdoes*exist" "zglob[!a]?" &&
        cat >expect <<-\EOF &&
        /*
        !/*/
@@ -642,4 +737,139 @@ test_expect_success MINGW 'cone mode replaces backslashes with slashes' '
        check_files repo/deep a deeper1
 '
 
+test_expect_success 'cone mode clears ignored subdirectories' '
+       rm repo/.git/info/sparse-checkout &&
+
+       git -C repo sparse-checkout init --cone &&
+       git -C repo sparse-checkout set deep/deeper1 &&
+
+       cat >repo/.gitignore <<-\EOF &&
+       obj/
+       *.o
+       EOF
+
+       git -C repo add .gitignore &&
+       git -C repo commit -m ".gitignore" &&
+
+       mkdir -p repo/obj repo/folder1/obj repo/deep/deeper2/obj &&
+       for file in folder1/obj/a obj/a folder1/file.o folder1.o \
+                   deep/deeper2/obj/a deep/deeper2/file.o file.o
+       do
+               echo ignored >repo/$file || return 1
+       done &&
+
+       git -C repo status --porcelain=v2 >out &&
+       test_must_be_empty out &&
+
+       git -C repo sparse-checkout reapply &&
+       test_path_is_missing repo/folder1 &&
+       test_path_is_missing repo/deep/deeper2 &&
+       test_path_is_dir repo/obj &&
+       test_path_is_file repo/file.o &&
+
+       git -C repo status --porcelain=v2 >out &&
+       test_must_be_empty out &&
+
+       git -C repo sparse-checkout set deep/deeper2 &&
+       test_path_is_missing repo/deep/deeper1 &&
+       test_path_is_dir repo/deep/deeper2 &&
+       test_path_is_dir repo/obj &&
+       test_path_is_file repo/file.o &&
+
+       >repo/deep/deeper2/ignored.o &&
+       >repo/deep/deeper2/untracked &&
+
+       # When an untracked file is in the way, all untracked files
+       # (even ignored files) are preserved.
+       git -C repo sparse-checkout set folder1 2>err &&
+       grep "contains untracked files" err &&
+       test_path_is_file repo/deep/deeper2/ignored.o &&
+       test_path_is_file repo/deep/deeper2/untracked &&
+
+       # The rest of the cone matches expectation
+       test_path_is_missing repo/deep/deeper1 &&
+       test_path_is_dir repo/obj &&
+       test_path_is_file repo/file.o &&
+
+       git -C repo status --porcelain=v2 >out &&
+       echo "? deep/deeper2/untracked" >expect &&
+       test_cmp expect out
+'
+
+test_expect_success 'malformed cone-mode patterns' '
+       git -C repo sparse-checkout init --cone &&
+       mkdir -p repo/foo/bar &&
+       touch repo/foo/bar/x repo/foo/y &&
+       cat >repo/.git/info/sparse-checkout <<-\EOF &&
+       /*
+       !/*/
+       /foo/
+       !/foo/*/
+       /foo/\*/
+       EOF
+
+       # Listing the patterns will notice the duplicate pattern and
+       # emit a warning. It will list the patterns directly instead
+       # of using the cone-mode translation to a set of directories.
+       git -C repo sparse-checkout list >actual 2>err &&
+       test_cmp repo/.git/info/sparse-checkout actual &&
+       grep "warning: your sparse-checkout file may have issues: pattern .* is repeated" err &&
+       grep "warning: disabling cone pattern matching" err
+'
+
+test_expect_success 'set from subdir pays attention to prefix' '
+       git -C repo sparse-checkout disable &&
+       git -C repo/deep sparse-checkout set --cone deeper2 ../folder1 &&
+
+       git -C repo sparse-checkout list >actual &&
+
+       cat >expect <<-\EOF &&
+       deep/deeper2
+       folder1
+       EOF
+       test_cmp expect actual
+'
+
+test_expect_success 'add from subdir pays attention to prefix' '
+       git -C repo sparse-checkout set --cone deep/deeper2 &&
+       git -C repo/deep sparse-checkout add deeper1/deepest ../folder1 &&
+
+       git -C repo sparse-checkout list >actual &&
+
+       cat >expect <<-\EOF &&
+       deep/deeper1/deepest
+       deep/deeper2
+       folder1
+       EOF
+       test_cmp expect actual
+'
+
+test_expect_success 'set from subdir in non-cone mode throws an error' '
+       git -C repo sparse-checkout disable &&
+       test_must_fail git -C repo/deep sparse-checkout set --no-cone deeper2 ../folder1 2>error &&
+
+       grep "run from the toplevel directory in non-cone mode" error
+'
+
+test_expect_success 'set from subdir in non-cone mode throws an error' '
+       git -C repo sparse-checkout set --no-cone deep/deeper2 &&
+       test_must_fail git -C repo/deep sparse-checkout add deeper1/deepest ../folder1 2>error &&
+
+       grep "run from the toplevel directory in non-cone mode" error
+'
+
+test_expect_success 'by default, cone mode will error out when passed files' '
+       git -C repo sparse-checkout reapply --cone &&
+       test_must_fail git -C repo sparse-checkout add .gitignore 2>error &&
+
+       grep ".gitignore.*is not a directory" error
+'
+
+test_expect_success 'by default, non-cone mode will warn on individual files' '
+       git -C repo sparse-checkout reapply --no-cone &&
+       git -C repo sparse-checkout add .gitignore 2>warning &&
+
+       grep "pass a leading slash before paths.*if you want a single file" warning
+'
+
 test_done