#!/bin/sh global test_description := ''sparse checkout tests * (tag: removed, master) removed | D sub/added * (HEAD, tag: top) modified and added | M init.t | A sub/added * (tag: init) init A init.t '' source ./test-lib.sh source "$TEST_DIRECTORY"/lib-read-tree.sh test_expect_success 'setup' ' cat >expected <<-EOF && 100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0 init.t 100644 $EMPTY_BLOB 0 sub/added 100644 $EMPTY_BLOB 0 sub/addedtoo 100644 $EMPTY_BLOB 0 subsub/added EOF cat >expected.swt <<-\EOF && H init.t H sub/added H sub/addedtoo H subsub/added EOF test_commit init && echo modified >>init.t && mkdir sub subsub && touch sub/added sub/addedtoo subsub/added && git add init.t sub/added sub/addedtoo subsub/added && git commit -m "modified and added" && git tag top && git rm sub/added && git commit -m removed && git tag removed && git checkout top && git ls-files --stage >result && test_cmp expected result ' test_expect_success 'read-tree without .git/info/sparse-checkout' ' read_tree_u_must_succeed -m -u HEAD && git ls-files --stage >result && test_cmp expected result && git ls-files -t >result && test_cmp expected.swt result ' test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' ' echo >.git/info/sparse-checkout && read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && test_cmp expected.swt result && test -f init.t && test -f sub/added ' test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse-checkout and enabled' ' git config core.sparsecheckout true && echo >.git/info/sparse-checkout && read_tree_u_must_succeed --no-sparse-checkout -m -u HEAD && git ls-files -t >result && test_cmp expected.swt result && test -f init.t && test -f sub/added ' test_expect_success 'read-tree with empty .git/info/sparse-checkout' ' git config core.sparsecheckout true && echo >.git/info/sparse-checkout && read_tree_u_must_fail -m -u HEAD && git ls-files --stage >result && test_cmp expected result && git ls-files -t >result && test_cmp expected.swt result && test -f init.t && test -f sub/added ' test_expect_success 'match directories with trailing slash' ' cat >expected.swt-noinit <<-\EOF && S init.t H sub/added H sub/addedtoo S subsub/added EOF echo sub/ > .git/info/sparse-checkout && read_tree_u_must_succeed -m -u HEAD && git ls-files -t > result && test_cmp expected.swt-noinit result && test ! -f init.t && test -f sub/added ' test_expect_success 'match directories without trailing slash' ' echo sub >.git/info/sparse-checkout && read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-noinit result && test ! -f init.t && test -f sub/added ' test_expect_success 'match directories with negated patterns' ' cat >expected.swt-negation <<\EOF && S init.t S sub/added H sub/addedtoo S subsub/added EOF cat >.git/info/sparse-checkout <<\EOF && sub !sub/added EOF git read-tree -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-negation result && test ! -f init.t && test ! -f sub/added && test -f sub/addedtoo ' test_expect_success 'match directories with negated patterns (2)' ' cat >expected.swt-negation2 <<\EOF && H init.t H sub/added S sub/addedtoo H subsub/added EOF cat >.git/info/sparse-checkout <<\EOF && /* !sub sub/added EOF git read-tree -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-negation2 result && test -f init.t && test -f sub/added && test ! -f sub/addedtoo ' test_expect_success 'match directory pattern' ' echo "s?b" >.git/info/sparse-checkout && read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-noinit result && test ! -f init.t && test -f sub/added ' test_expect_success 'checkout area changes' ' cat >expected.swt-nosub <<-\EOF && H init.t S sub/added S sub/addedtoo S subsub/added EOF echo init.t >.git/info/sparse-checkout && read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-nosub result && test -f init.t && test ! -f sub/added ' test_expect_success 'read-tree updates worktree, absent case' ' echo sub/added >.git/info/sparse-checkout && git checkout -f top && read_tree_u_must_succeed -m -u HEAD^ && test ! -f init.t ' test_expect_success 'read-tree updates worktree, dirty case' ' echo sub/added >.git/info/sparse-checkout && git checkout -f top && echo dirty >init.t && read_tree_u_must_succeed -m -u HEAD^ && grep -q dirty init.t && rm init.t ' test_expect_success 'read-tree removes worktree, dirty case' ' echo init.t >.git/info/sparse-checkout && git checkout -f top && echo dirty >added && read_tree_u_must_succeed -m -u HEAD^ && grep -q dirty added ' test_expect_success 'read-tree adds to worktree, absent case' ' echo init.t >.git/info/sparse-checkout && git checkout -f removed && read_tree_u_must_succeed -u -m HEAD^ && test ! -f sub/added ' test_expect_success 'read-tree adds to worktree, dirty case' ' echo init.t >.git/info/sparse-checkout && git checkout -f removed && mkdir sub && echo dirty >sub/added && read_tree_u_must_succeed -u -m HEAD^ && grep -q dirty sub/added ' test_expect_success 'index removal and worktree narrowing at the same time' ' >empty && echo init.t >.git/info/sparse-checkout && echo sub/added >>.git/info/sparse-checkout && git checkout -f top && echo init.t >.git/info/sparse-checkout && git checkout removed && git ls-files sub/added >result && test ! -f sub/added && test_cmp empty result ' test_expect_success 'read-tree --reset removes outside worktree' ' >empty && echo init.t >.git/info/sparse-checkout && git checkout -f top && git reset --hard removed && git ls-files sub/added >result && test_cmp empty result ' test_expect_success 'print errors when failed to update worktree' ' echo sub >.git/info/sparse-checkout && git checkout -f init && mkdir sub && touch sub/added sub/addedtoo && test_must_fail git checkout top 2>actual && cat >expected <<\EOF && error: The following untracked working tree files would be overwritten by checkout: sub/added sub/addedtoo Please move or remove them before you switch branches. Aborting EOF test_i18ncmp expected actual ' test_expect_success 'checkout without --ignore-skip-worktree-bits' ' echo "*" >.git/info/sparse-checkout && git checkout -f top && test_path_is_file init.t && echo sub >.git/info/sparse-checkout && git checkout && echo modified >> sub/added && git checkout . && test_path_is_missing init.t && git diff --exit-code HEAD ' test_expect_success 'checkout with --ignore-skip-worktree-bits' ' echo "*" >.git/info/sparse-checkout && git checkout -f top && test_path_is_file init.t && echo sub >.git/info/sparse-checkout && git checkout && echo modified >> sub/added && git checkout --ignore-skip-worktree-bits . && test_path_is_file init.t && git diff --exit-code HEAD ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: { (SQ <"sparse checkout tests\n"> <"\n"> <"* (tag: removed, master) removed\n"> <"| D\tsub/added\n"> <"* (HEAD, tag: top) modified and added\n"> <"| M\tinit.t\n"> <"| A\tsub/added\n"> <"* (tag: init) init\n"> <" A\tinit.t\n"> ) } spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (C {(.)} {(DQ ($ VSub_Name "$TEST_DIRECTORY")) (/lib-read-tree.sh)}) (C {(test_expect_success)} {(SQ )} { (SQ <"\n"> <"\tcat >expected <<-EOF &&\n"> <"\t100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0\tinit.t\n"> <"\t100644 $EMPTY_BLOB 0\tsub/added\n"> <"\t100644 $EMPTY_BLOB 0\tsub/addedtoo\n"> <"\t100644 $EMPTY_BLOB 0\tsubsub/added\n"> <"\tEOF\n"> <"\tcat >expected.swt <<-\\EOF &&\n"> <"\tH init.t\n"> <"\tH sub/added\n"> <"\tH sub/addedtoo\n"> <"\tH subsub/added\n"> <"\tEOF\n"> <"\n"> <"\ttest_commit init &&\n"> <"\techo modified >>init.t &&\n"> <"\tmkdir sub subsub &&\n"> <"\ttouch sub/added sub/addedtoo subsub/added &&\n"> <"\tgit add init.t sub/added sub/addedtoo subsub/added &&\n"> <"\tgit commit -m \"modified and added\" &&\n"> <"\tgit tag top &&\n"> <"\tgit rm sub/added &&\n"> <"\tgit commit -m removed &&\n"> <"\tgit tag removed &&\n"> <"\tgit checkout top &&\n"> <"\tgit ls-files --stage >result &&\n"> <"\ttest_cmp expected result\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree without .git/info/sparse-checkout">)} { (SQ <"\n"> <"\tread_tree_u_must_succeed -m -u HEAD &&\n"> <"\tgit ls-files --stage >result &&\n"> <"\ttest_cmp expected result &&\n"> <"\tgit ls-files -t >result &&\n"> <"\ttest_cmp expected.swt result\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree with .git/info/sparse-checkout but disabled">)} { (SQ <"\n"> <"\techo >.git/info/sparse-checkout &&\n"> <"\tread_tree_u_must_succeed -m -u HEAD &&\n"> <"\tgit ls-files -t >result &&\n"> <"\ttest_cmp expected.swt result &&\n"> <"\ttest -f init.t &&\n"> <"\ttest -f sub/added\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree --no-sparse-checkout with empty .git/info/sparse-checkout and enabled">)} { (SQ <"\n"> <"\tgit config core.sparsecheckout true &&\n"> <"\techo >.git/info/sparse-checkout &&\n"> <"\tread_tree_u_must_succeed --no-sparse-checkout -m -u HEAD &&\n"> <"\tgit ls-files -t >result &&\n"> <"\ttest_cmp expected.swt result &&\n"> <"\ttest -f init.t &&\n"> <"\ttest -f sub/added\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree with empty .git/info/sparse-checkout">)} { (SQ <"\n"> <"\tgit config core.sparsecheckout true &&\n"> <"\techo >.git/info/sparse-checkout &&\n"> <"\tread_tree_u_must_fail -m -u HEAD &&\n"> <"\tgit ls-files --stage >result &&\n"> <"\ttest_cmp expected result &&\n"> <"\tgit ls-files -t >result &&\n"> <"\ttest_cmp expected.swt result &&\n"> <"\ttest -f init.t &&\n"> <"\ttest -f sub/added\n"> ) } ) (C {(test_expect_success)} {(SQ <"match directories with trailing slash">)} { (SQ <"\n"> <"\tcat >expected.swt-noinit <<-\\EOF &&\n"> <"\tS init.t\n"> <"\tH sub/added\n"> <"\tH sub/addedtoo\n"> <"\tS subsub/added\n"> <"\tEOF\n"> <"\n"> <"\techo sub/ > .git/info/sparse-checkout &&\n"> <"\tread_tree_u_must_succeed -m -u HEAD &&\n"> <"\tgit ls-files -t > result &&\n"> <"\ttest_cmp expected.swt-noinit result &&\n"> <"\ttest ! -f init.t &&\n"> <"\ttest -f sub/added\n"> ) } ) (C {(test_expect_success)} {(SQ <"match directories without trailing slash">)} { (SQ <"\n"> <"\techo sub >.git/info/sparse-checkout &&\n"> <"\tread_tree_u_must_succeed -m -u HEAD &&\n"> <"\tgit ls-files -t >result &&\n"> <"\ttest_cmp expected.swt-noinit result &&\n"> <"\ttest ! -f init.t &&\n"> <"\ttest -f sub/added\n"> ) } ) (C {(test_expect_success)} {(SQ <"match directories with negated patterns">)} { (SQ <"\n"> <"\tcat >expected.swt-negation <<\\EOF &&\n"> <"S init.t\n"> <"S sub/added\n"> <"H sub/addedtoo\n"> <"S subsub/added\n"> <"EOF\n"> <"\n"> <"\tcat >.git/info/sparse-checkout <<\\EOF &&\n"> <"sub\n"> <"!sub/added\n"> <"EOF\n"> <"\tgit read-tree -m -u HEAD &&\n"> <"\tgit ls-files -t >result &&\n"> <"\ttest_cmp expected.swt-negation result &&\n"> <"\ttest ! -f init.t &&\n"> <"\ttest ! -f sub/added &&\n"> <"\ttest -f sub/addedtoo\n"> ) } ) (C {(test_expect_success)} {(SQ <"match directories with negated patterns (2)">)} { (SQ <"\n"> <"\tcat >expected.swt-negation2 <<\\EOF &&\n"> <"H init.t\n"> <"H sub/added\n"> <"S sub/addedtoo\n"> <"H subsub/added\n"> <"EOF\n"> <"\n"> <"\tcat >.git/info/sparse-checkout <<\\EOF &&\n"> <"/*\n"> <"!sub\n"> <"sub/added\n"> <"EOF\n"> <"\tgit read-tree -m -u HEAD &&\n"> <"\tgit ls-files -t >result &&\n"> <"\ttest_cmp expected.swt-negation2 result &&\n"> <"\ttest -f init.t &&\n"> <"\ttest -f sub/added &&\n"> <"\ttest ! -f sub/addedtoo\n"> ) } ) (C {(test_expect_success)} {(SQ <"match directory pattern">)} { (SQ <"\n"> <"\techo \"s?b\" >.git/info/sparse-checkout &&\n"> <"\tread_tree_u_must_succeed -m -u HEAD &&\n"> <"\tgit ls-files -t >result &&\n"> <"\ttest_cmp expected.swt-noinit result &&\n"> <"\ttest ! -f init.t &&\n"> <"\ttest -f sub/added\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout area changes">)} { (SQ <"\n"> <"\tcat >expected.swt-nosub <<-\\EOF &&\n"> <"\tH init.t\n"> <"\tS sub/added\n"> <"\tS sub/addedtoo\n"> <"\tS subsub/added\n"> <"\tEOF\n"> <"\n"> <"\techo init.t >.git/info/sparse-checkout &&\n"> <"\tread_tree_u_must_succeed -m -u HEAD &&\n"> <"\tgit ls-files -t >result &&\n"> <"\ttest_cmp expected.swt-nosub result &&\n"> <"\ttest -f init.t &&\n"> <"\ttest ! -f sub/added\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree updates worktree, absent case">)} { (SQ <"\n"> <"\techo sub/added >.git/info/sparse-checkout &&\n"> <"\tgit checkout -f top &&\n"> <"\tread_tree_u_must_succeed -m -u HEAD^ &&\n"> <"\ttest ! -f init.t\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree updates worktree, dirty case">)} { (SQ <"\n"> <"\techo sub/added >.git/info/sparse-checkout &&\n"> <"\tgit checkout -f top &&\n"> <"\techo dirty >init.t &&\n"> <"\tread_tree_u_must_succeed -m -u HEAD^ &&\n"> <"\tgrep -q dirty init.t &&\n"> <"\trm init.t\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree removes worktree, dirty case">)} { (SQ <"\n"> <"\techo init.t >.git/info/sparse-checkout &&\n"> <"\tgit checkout -f top &&\n"> <"\techo dirty >added &&\n"> <"\tread_tree_u_must_succeed -m -u HEAD^ &&\n"> <"\tgrep -q dirty added\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree adds to worktree, absent case">)} { (SQ <"\n"> <"\techo init.t >.git/info/sparse-checkout &&\n"> <"\tgit checkout -f removed &&\n"> <"\tread_tree_u_must_succeed -u -m HEAD^ &&\n"> <"\ttest ! -f sub/added\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree adds to worktree, dirty case">)} { (SQ <"\n"> <"\techo init.t >.git/info/sparse-checkout &&\n"> <"\tgit checkout -f removed &&\n"> <"\tmkdir sub &&\n"> <"\techo dirty >sub/added &&\n"> <"\tread_tree_u_must_succeed -u -m HEAD^ &&\n"> <"\tgrep -q dirty sub/added\n"> ) } ) (C {(test_expect_success)} {(SQ <"index removal and worktree narrowing at the same time">)} { (SQ <"\n"> <"\t>empty &&\n"> <"\techo init.t >.git/info/sparse-checkout &&\n"> <"\techo sub/added >>.git/info/sparse-checkout &&\n"> <"\tgit checkout -f top &&\n"> <"\techo init.t >.git/info/sparse-checkout &&\n"> <"\tgit checkout removed &&\n"> <"\tgit ls-files sub/added >result &&\n"> <"\ttest ! -f sub/added &&\n"> <"\ttest_cmp empty result\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree --reset removes outside worktree">)} { (SQ <"\n"> <"\t>empty &&\n"> <"\techo init.t >.git/info/sparse-checkout &&\n"> <"\tgit checkout -f top &&\n"> <"\tgit reset --hard removed &&\n"> <"\tgit ls-files sub/added >result &&\n"> <"\ttest_cmp empty result\n"> ) } ) (C {(test_expect_success)} {(SQ <"print errors when failed to update worktree">)} { (SQ <"\n"> <"\techo sub >.git/info/sparse-checkout &&\n"> <"\tgit checkout -f init &&\n"> <"\tmkdir sub &&\n"> <"\ttouch sub/added sub/addedtoo &&\n"> <"\ttest_must_fail git checkout top 2>actual &&\n"> <"\tcat >expected <<\\EOF &&\n"> <"error: The following untracked working tree files would be overwritten by checkout:\n"> <"\tsub/added\n"> <"\tsub/addedtoo\n"> <"Please move or remove them before you switch branches.\n"> <"Aborting\n"> <"EOF\n"> <"\ttest_i18ncmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout without --ignore-skip-worktree-bits">)} { (SQ <"\n"> <"\techo \"*\" >.git/info/sparse-checkout &&\n"> <"\tgit checkout -f top &&\n"> <"\ttest_path_is_file init.t &&\n"> <"\techo sub >.git/info/sparse-checkout &&\n"> <"\tgit checkout &&\n"> <"\techo modified >> sub/added &&\n"> <"\tgit checkout . &&\n"> <"\ttest_path_is_missing init.t &&\n"> <"\tgit diff --exit-code HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout with --ignore-skip-worktree-bits">)} { (SQ <"\n"> <"\techo \"*\" >.git/info/sparse-checkout &&\n"> <"\tgit checkout -f top &&\n"> <"\ttest_path_is_file init.t &&\n"> <"\techo sub >.git/info/sparse-checkout &&\n"> <"\tgit checkout &&\n"> <"\techo modified >> sub/added &&\n"> <"\tgit checkout --ignore-skip-worktree-bits . &&\n"> <"\ttest_path_is_file init.t &&\n"> <"\tgit diff --exit-code HEAD\n"> ) } ) (C {(test_done)}) ] )