(command.CommandList children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'test_description='> name:test_description) op: assign_op.Equal rhs: {(SQ <'test separate work tree'>)} spids: [4] ) ] redirects: [] ) (C {<.>} {<'./test-lib.sh'>}) (C {<test_expect_success>} {(SQ <setup>)} { (SQ <'\n'> <'\tEMPTY_TREE=$(git write-tree) &&\n'> <'\tEMPTY_BLOB=$(git hash-object -t blob --stdin </dev/null) &&\n'> <'\tCHANGED_BLOB=$(echo changed | git hash-object -t blob --stdin) &&\n'> <'\tEMPTY_BLOB7=$(echo $EMPTY_BLOB | sed "s/\\(.......\\).*/\\1/") &&\n'> <'\tCHANGED_BLOB7=$(echo $CHANGED_BLOB | sed "s/\\(.......\\).*/\\1/") &&\n'> <'\n'> <'\tmkdir -p work/sub/dir &&\n'> <'\tmkdir -p work2 &&\n'> <'\tmv .git repo.git\n'> ) } ) (C {<test_expect_success>} {(SQ <'setup: helper for testing rev-parse'>)} { (SQ <'\n'> <'\ttest_rev_parse() {\n'> <'\t\techo $1 >expected.bare &&\n'> <'\t\techo $2 >expected.inside-git &&\n'> <'\t\techo $3 >expected.inside-worktree &&\n'> <'\t\tif test $# -ge 4\n'> <'\t\tthen\n'> <'\t\t\techo $4 >expected.prefix\n'> <'\t\tfi &&\n'> <'\n'> <'\t\tgit rev-parse --is-bare-repository >actual.bare &&\n'> <'\t\tgit rev-parse --is-inside-git-dir >actual.inside-git &&\n'> <'\t\tgit rev-parse --is-inside-work-tree >actual.inside-worktree &&\n'> <'\t\tif test $# -ge 4\n'> <'\t\tthen\n'> <'\t\t\tgit rev-parse --show-prefix >actual.prefix\n'> <'\t\tfi &&\n'> <'\n'> <'\t\ttest_cmp expected.bare actual.bare &&\n'> <'\t\ttest_cmp expected.inside-git actual.inside-git &&\n'> <'\t\ttest_cmp expected.inside-worktree actual.inside-worktree &&\n'> <'\t\tif test $# -ge 4\n'> <'\t\tthen\n'> <'\t\t\t# rev-parse --show-prefix should output\n'> <'\t\t\t# a single newline when at the top of the work tree,\n'> <'\t\t\t# but we test for that separately.\n'> <'\t\t\ttest -z "$4" && ! test -s actual.prefix ||\n'> <'\t\t\ttest_cmp expected.prefix actual.prefix\n'> <'\t\tfi\n'> <'\t}\n'> ) } ) (C {<test_expect_success>} {(SQ <'setup: core.worktree = relative path'>)} { (SQ <'\n'> <'\tsane_unset GIT_WORK_TREE &&\n'> <'\tGIT_DIR=repo.git &&\n'> <'\tGIT_CONFIG="$(pwd)"/$GIT_DIR/config &&\n'> <'\texport GIT_DIR GIT_CONFIG &&\n'> <'\tgit config core.worktree ../work\n'> ) } ) (C {<test_expect_success>} {(SQ <outside>)} {(SQ <'\n'> <'\ttest_rev_parse false false false\n'>)}) (C {<test_expect_success>} {(SQ <'inside work tree'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd work &&\n'> <'\t\tGIT_DIR=../repo.git &&\n'> <'\t\tGIT_CONFIG="$(pwd)"/$GIT_DIR/config &&\n'> <'\t\ttest_rev_parse false false true ""\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'empty prefix is actually written out'>)} { (SQ <'\n'> <'\techo >expected &&\n'> <'\t(\n'> <'\t\tcd work &&\n'> <'\t\tGIT_DIR=../repo.git &&\n'> <'\t\tGIT_CONFIG="$(pwd)"/$GIT_DIR/config &&\n'> <'\t\tgit rev-parse --show-prefix >../actual\n'> <'\t) &&\n'> <'\ttest_cmp expected actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'subdir of work tree'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd work/sub/dir &&\n'> <'\t\tGIT_DIR=../../../repo.git &&\n'> <'\t\tGIT_CONFIG="$(pwd)"/$GIT_DIR/config &&\n'> <'\t\ttest_rev_parse false false true sub/dir/\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'setup: core.worktree = absolute path'>)} { (SQ <'\n'> <'\tsane_unset GIT_WORK_TREE &&\n'> <'\tGIT_DIR=$(pwd)/repo.git &&\n'> <'\tGIT_CONFIG=$GIT_DIR/config &&\n'> <'\texport GIT_DIR GIT_CONFIG &&\n'> <'\tgit config core.worktree "$(pwd)/work"\n'> ) } ) (C {<test_expect_success>} {(SQ <outside>)} { (SQ <'\n'> <'\ttest_rev_parse false false false &&\n'> <'\t(\n'> <'\t\tcd work2 &&\n'> <'\t\ttest_rev_parse false false false\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'inside work tree'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd work &&\n'> <'\t\ttest_rev_parse false false true ""\n'> <'\t)\n'>) } ) (C {<test_expect_success>} {(SQ <'subdir of work tree'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd work/sub/dir &&\n'> <'\t\ttest_rev_parse false false true sub/dir/\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'setup: GIT_WORK_TREE=relative (override core.worktree)'>)} { (SQ <'\n'> <'\tGIT_DIR=$(pwd)/repo.git &&\n'> <'\tGIT_CONFIG=$GIT_DIR/config &&\n'> <'\tgit config core.worktree non-existent &&\n'> <'\tGIT_WORK_TREE=work &&\n'> <'\texport GIT_DIR GIT_CONFIG GIT_WORK_TREE\n'> ) } ) (C {<test_expect_success>} {(SQ <outside>)} { (SQ <'\n'> <'\ttest_rev_parse false false false &&\n'> <'\t(\n'> <'\t\tcd work2 &&\n'> <'\t\ttest_rev_parse false false false\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'inside work tree'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd work &&\n'> <'\t\tGIT_WORK_TREE=. &&\n'> <'\t\ttest_rev_parse false false true ""\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'subdir of work tree'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd work/sub/dir &&\n'> <'\t\tGIT_WORK_TREE=../.. &&\n'> <'\t\ttest_rev_parse false false true sub/dir/\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'setup: GIT_WORK_TREE=absolute, below git dir'>)} { (SQ <'\n'> <'\tmv work repo.git/work &&\n'> <'\tmv work2 repo.git/work2 &&\n'> <'\tGIT_DIR=$(pwd)/repo.git &&\n'> <'\tGIT_CONFIG=$GIT_DIR/config &&\n'> <'\tGIT_WORK_TREE=$(pwd)/repo.git/work &&\n'> <'\texport GIT_DIR GIT_CONFIG GIT_WORK_TREE\n'> ) } ) (C {<test_expect_success>} {(SQ <outside>)} {(SQ <'\n'> <'\techo outside &&\n'> <'\ttest_rev_parse false false false\n'>)} ) (C {<test_expect_success>} {(SQ <'in repo.git'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd repo.git &&\n'> <'\t\ttest_rev_parse false true false\n'> <'\t) &&\n'> <'\t(\n'> <'\t\tcd repo.git/objects &&\n'> <'\t\ttest_rev_parse false true false\n'> <'\t) &&\n'> <'\t(\n'> <'\t\tcd repo.git/work2 &&\n'> <'\t\ttest_rev_parse false true false\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'inside work tree'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd repo.git/work &&\n'> <'\t\ttest_rev_parse false true true ""\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'subdir of work tree'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd repo.git/work/sub/dir &&\n'> <'\t\ttest_rev_parse false true true sub/dir/\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'find work tree from repo'>)} { (SQ <'\n'> <'\techo sub/dir/untracked >expected &&\n'> <'\tcat <<-\\EOF >repo.git/work/.gitignore &&\n'> <'\texpected.*\n'> <'\tactual.*\n'> <'\t.gitignore\n'> <'\tEOF\n'> <'\t>repo.git/work/sub/dir/untracked &&\n'> <'\t(\n'> <'\t\tcd repo.git &&\n'> <'\t\tgit ls-files --others --exclude-standard >../actual\n'> <'\t) &&\n'> <'\ttest_cmp expected actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'find work tree from work tree'>)} { (SQ <'\n'> <'\techo sub/dir/tracked >expected &&\n'> <'\t>repo.git/work/sub/dir/tracked &&\n'> <'\t(\n'> <'\t\tcd repo.git/work/sub/dir &&\n'> <'\t\tgit --git-dir=../../.. add tracked\n'> <'\t) &&\n'> <'\t(\n'> <'\t\tcd repo.git &&\n'> <'\t\tgit ls-files >../actual\n'> <'\t) &&\n'> <'\ttest_cmp expected actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'_gently() groks relative GIT_DIR & GIT_WORK_TREE'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd repo.git/work/sub/dir &&\n'> <'\t\tGIT_DIR=../../.. &&\n'> <'\t\tGIT_WORK_TREE=../.. &&\n'> <'\t\tGIT_PAGER= &&\n'> <'\t\texport GIT_DIR GIT_WORK_TREE GIT_PAGER &&\n'> <'\n'> <'\t\tgit diff --exit-code tracked &&\n'> <'\t\techo changed >tracked &&\n'> <'\t\ttest_must_fail git diff --exit-code tracked\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'diff-index respects work tree under .git dir'>)} { (SQ <'\n'> <'\tcat >diff-index-cached.expected <<-EOF &&\n'> <'\t:000000 100644 $_z40 $EMPTY_BLOB A\tsub/dir/tracked\n'> <'\tEOF\n'> <'\tcat >diff-index.expected <<-EOF &&\n'> <'\t:000000 100644 $_z40 $_z40 A\tsub/dir/tracked\n'> <'\tEOF\n'> <'\n'> <'\t(\n'> <'\t\tGIT_DIR=repo.git &&\n'> <'\t\tGIT_WORK_TREE=repo.git/work &&\n'> <'\t\texport GIT_DIR GIT_WORK_TREE &&\n'> <'\t\tgit diff-index $EMPTY_TREE >diff-index.actual &&\n'> <'\t\tgit diff-index --cached $EMPTY_TREE >diff-index-cached.actual\n'> <'\t) &&\n'> <'\ttest_cmp diff-index.expected diff-index.actual &&\n'> <'\ttest_cmp diff-index-cached.expected diff-index-cached.actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'diff-files respects work tree under .git dir'>)} { (SQ <'\n'> <'\tcat >diff-files.expected <<-EOF &&\n'> <'\t:100644 100644 $EMPTY_BLOB $_z40 M\tsub/dir/tracked\n'> <'\tEOF\n'> <'\n'> <'\t(\n'> <'\t\tGIT_DIR=repo.git &&\n'> <'\t\tGIT_WORK_TREE=repo.git/work &&\n'> <'\t\texport GIT_DIR GIT_WORK_TREE &&\n'> <'\t\tgit diff-files >diff-files.actual\n'> <'\t) &&\n'> <'\ttest_cmp diff-files.expected diff-files.actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'git diff respects work tree under .git dir'>)} { (SQ <'\n'> <'\tcat >diff-TREE.expected <<-EOF &&\n'> <'\tdiff --git a/sub/dir/tracked b/sub/dir/tracked\n'> <'\tnew file mode 100644\n'> <'\tindex 0000000..$CHANGED_BLOB7\n'> <'\t--- /dev/null\n'> <'\t+++ b/sub/dir/tracked\n'> <'\t@@ -0,0 +1 @@\n'> <'\t+changed\n'> <'\tEOF\n'> <'\tcat >diff-TREE-cached.expected <<-EOF &&\n'> <'\tdiff --git a/sub/dir/tracked b/sub/dir/tracked\n'> <'\tnew file mode 100644\n'> <'\tindex 0000000..$EMPTY_BLOB7\n'> <'\tEOF\n'> <'\tcat >diff-FILES.expected <<-EOF &&\n'> <'\tdiff --git a/sub/dir/tracked b/sub/dir/tracked\n'> <'\tindex $EMPTY_BLOB7..$CHANGED_BLOB7 100644\n'> <'\t--- a/sub/dir/tracked\n'> <'\t+++ b/sub/dir/tracked\n'> <'\t@@ -0,0 +1 @@\n'> <'\t+changed\n'> <'\tEOF\n'> <'\n'> <'\t(\n'> <'\t\tGIT_DIR=repo.git &&\n'> <'\t\tGIT_WORK_TREE=repo.git/work &&\n'> <'\t\texport GIT_DIR GIT_WORK_TREE &&\n'> <'\t\tgit diff $EMPTY_TREE >diff-TREE.actual &&\n'> <'\t\tgit diff --cached $EMPTY_TREE >diff-TREE-cached.actual &&\n'> <'\t\tgit diff >diff-FILES.actual\n'> <'\t) &&\n'> <'\ttest_cmp diff-TREE.expected diff-TREE.actual &&\n'> <'\ttest_cmp diff-TREE-cached.expected diff-TREE-cached.actual &&\n'> <'\ttest_cmp diff-FILES.expected diff-FILES.actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'git grep'>)} { (SQ <'\n'> <'\techo dir/tracked >expected.grep &&\n'> <'\t(\n'> <'\t\tcd repo.git/work/sub &&\n'> <'\t\tGIT_DIR=../.. &&\n'> <'\t\tGIT_WORK_TREE=.. &&\n'> <'\t\texport GIT_DIR GIT_WORK_TREE &&\n'> <'\t\tgit grep -l changed >../../../actual.grep\n'> <'\t) &&\n'> <'\ttest_cmp expected.grep actual.grep\n'> ) } ) (C {<test_expect_success>} {(SQ <'git commit'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd repo.git &&\n'> <'\t\tGIT_DIR=. GIT_WORK_TREE=work git commit -a -m done\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'absolute pathspec should fail gracefully'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd repo.git &&\n'> <'\t\ttest_might_fail git config --unset core.worktree &&\n'> <'\t\ttest_must_fail git log HEAD -- /home\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'make_relative_path handles double slashes in GIT_DIR'>)} { (SQ <'\n'> <'\t>dummy_file &&\n'> <'\techo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file &&\n'> <'\tgit --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file\n'> ) } ) (C {<test_expect_success>} {(SQ <'relative $GIT_WORK_TREE and git subprocesses'>)} { (SQ <'\n'> <'\tGIT_DIR=repo.git GIT_WORK_TREE=repo.git/work \\\n'> <'\ttest-subprocess --setup-work-tree rev-parse --show-toplevel >actual &&\n'> <'\techo "$(pwd)/repo.git/work" >expected &&\n'> <'\ttest_cmp expected actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'Multi-worktree setup'>)} { (SQ <'\n'> <'\tmkdir work &&\n'> <'\tmkdir -p repo.git/repos/foo &&\n'> <'\tcp repo.git/HEAD repo.git/index repo.git/repos/foo &&\n'> <'\ttest_might_fail cp repo.git/sharedindex.* repo.git/repos/foo &&\n'> <'\tsane_unset GIT_DIR GIT_CONFIG GIT_WORK_TREE\n'> ) } ) (C {<test_expect_success>} {(SQ <'GIT_DIR set (1)'>)} { (SQ <'\n'> <'\techo "gitdir: repo.git/repos/foo" >gitfile &&\n'> <'\techo ../.. >repo.git/repos/foo/commondir &&\n'> <'\t(\n'> <'\t\tcd work &&\n'> <'\t\tGIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&\n'> <'\t\ttest-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'GIT_DIR set (2)'>)} { (SQ <'\n'> <'\techo "gitdir: repo.git/repos/foo" >gitfile &&\n'> <'\techo "$(pwd)/repo.git" >repo.git/repos/foo/commondir &&\n'> <'\t(\n'> <'\t\tcd work &&\n'> <'\t\tGIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&\n'> <'\t\ttest-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'Auto discovery'>)} { (SQ <'\n'> <'\techo "gitdir: repo.git/repos/foo" >.git &&\n'> <'\techo ../.. >repo.git/repos/foo/commondir &&\n'> <'\t(\n'> <'\t\tcd work &&\n'> <'\t\tgit rev-parse --git-common-dir >actual &&\n'> <'\t\ttest-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&\n'> <'\t\ttest_cmp expect actual &&\n'> <'\t\techo haha >data1 &&\n'> <'\t\tgit add data1 &&\n'> <'\t\tgit ls-files --full-name :/ | grep data1 >actual &&\n'> <'\t\techo work/data1 >expect &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'$GIT_DIR/common overrides core.worktree'>)} { (SQ <'\n'> <'\tmkdir elsewhere &&\n'> <'\tgit --git-dir=repo.git config core.worktree "$TRASH_DIRECTORY/elsewhere" &&\n'> <'\techo "gitdir: repo.git/repos/foo" >.git &&\n'> <'\techo ../.. >repo.git/repos/foo/commondir &&\n'> <'\t(\n'> <'\t\tcd work &&\n'> <'\t\tgit rev-parse --git-common-dir >actual &&\n'> <'\t\ttest-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&\n'> <'\t\ttest_cmp expect actual &&\n'> <'\t\techo haha >data2 &&\n'> <'\t\tgit add data2 &&\n'> <'\t\tgit ls-files --full-name :/ | grep data2 >actual &&\n'> <'\t\techo work/data2 >expect &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'$GIT_WORK_TREE overrides $GIT_DIR/common'>)} { (SQ <'\n'> <'\techo "gitdir: repo.git/repos/foo" >.git &&\n'> <'\techo ../.. >repo.git/repos/foo/commondir &&\n'> <'\t(\n'> <'\t\tcd work &&\n'> <'\t\techo haha >data3 &&\n'> <'\t\tgit --git-dir=../.git --work-tree=. add data3 &&\n'> <'\t\tgit ls-files --full-name -- :/ | grep data3 >actual &&\n'> <'\t\techo data3 >expect &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'> ) } ) (C {<test_done>}) ] )