Merge branch 'es/worktree-repair-copied' into cw/worktrees-relative
[git/gitster.git] / t / t1501-work-tree.sh
blobae6528aecea7d3b36cfe51c5f19c7098f05429e3
1 #!/bin/sh
3 test_description='test separate work tree'
5 TEST_PASSES_SANITIZE_LEAK=true
6 . ./test-lib.sh
8 test_expect_success 'setup' '
9 EMPTY_TREE=$(git write-tree) &&
10 EMPTY_BLOB=$(git hash-object -t blob --stdin </dev/null) &&
11 CHANGED_BLOB=$(echo changed | git hash-object -t blob --stdin) &&
12 EMPTY_BLOB7=$(echo $EMPTY_BLOB | sed "s/\(.......\).*/\1/") &&
13 CHANGED_BLOB7=$(echo $CHANGED_BLOB | sed "s/\(.......\).*/\1/") &&
15 mkdir -p work/sub/dir &&
16 mkdir -p work2 &&
17 mv .git repo.git
20 test_expect_success 'setup: helper for testing rev-parse' '
21 test_rev_parse() {
22 echo $1 >expected.bare &&
23 echo $2 >expected.inside-git &&
24 echo $3 >expected.inside-worktree &&
25 if test $# -ge 4
26 then
27 echo $4 >expected.prefix
28 fi &&
30 git rev-parse --is-bare-repository >actual.bare &&
31 git rev-parse --is-inside-git-dir >actual.inside-git &&
32 git rev-parse --is-inside-work-tree >actual.inside-worktree &&
33 if test $# -ge 4
34 then
35 git rev-parse --show-prefix >actual.prefix
36 fi &&
38 test_cmp expected.bare actual.bare &&
39 test_cmp expected.inside-git actual.inside-git &&
40 test_cmp expected.inside-worktree actual.inside-worktree &&
41 if test $# -ge 4
42 then
43 # rev-parse --show-prefix should output
44 # a single newline when at the top of the work tree,
45 # but we test for that separately.
46 test -z "$4" && test_must_be_empty actual.prefix ||
47 test_cmp expected.prefix actual.prefix
52 test_expect_success 'setup: core.worktree = relative path' '
53 sane_unset GIT_WORK_TREE &&
54 GIT_DIR=repo.git &&
55 GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
56 export GIT_DIR GIT_CONFIG &&
57 git config core.worktree ../work
60 test_expect_success 'outside' '
61 test_rev_parse false false false
64 test_expect_success 'inside work tree' '
66 cd work &&
67 GIT_DIR=../repo.git &&
68 GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
69 test_rev_parse false false true ""
73 test_expect_success 'empty prefix is actually written out' '
74 echo >expected &&
76 cd work &&
77 GIT_DIR=../repo.git &&
78 GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
79 git rev-parse --show-prefix >../actual
80 ) &&
81 test_cmp expected actual
84 test_expect_success 'subdir of work tree' '
86 cd work/sub/dir &&
87 GIT_DIR=../../../repo.git &&
88 GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
89 test_rev_parse false false true sub/dir/
93 test_expect_success 'setup: core.worktree = absolute path' '
94 sane_unset GIT_WORK_TREE &&
95 GIT_DIR=$(pwd)/repo.git &&
96 GIT_CONFIG=$GIT_DIR/config &&
97 export GIT_DIR GIT_CONFIG &&
98 git config core.worktree "$(pwd)/work"
101 test_expect_success 'outside' '
102 test_rev_parse false false false &&
104 cd work2 &&
105 test_rev_parse false false false
109 test_expect_success 'inside work tree' '
111 cd work &&
112 test_rev_parse false false true ""
116 test_expect_success 'subdir of work tree' '
118 cd work/sub/dir &&
119 test_rev_parse false false true sub/dir/
123 test_expect_success 'setup: GIT_WORK_TREE=relative (override core.worktree)' '
124 GIT_DIR=$(pwd)/repo.git &&
125 GIT_CONFIG=$GIT_DIR/config &&
126 git config core.worktree non-existent &&
127 GIT_WORK_TREE=work &&
128 export GIT_DIR GIT_CONFIG GIT_WORK_TREE
131 test_expect_success 'outside' '
132 test_rev_parse false false false &&
134 cd work2 &&
135 test_rev_parse false false false
139 test_expect_success 'inside work tree' '
141 cd work &&
142 GIT_WORK_TREE=. &&
143 test_rev_parse false false true ""
147 test_expect_success 'subdir of work tree' '
149 cd work/sub/dir &&
150 GIT_WORK_TREE=../.. &&
151 test_rev_parse false false true sub/dir/
155 test_expect_success 'setup: GIT_WORK_TREE=absolute, below git dir' '
156 mv work repo.git/work &&
157 mv work2 repo.git/work2 &&
158 GIT_DIR=$(pwd)/repo.git &&
159 GIT_CONFIG=$GIT_DIR/config &&
160 GIT_WORK_TREE=$(pwd)/repo.git/work &&
161 export GIT_DIR GIT_CONFIG GIT_WORK_TREE
164 test_expect_success 'outside' '
165 echo outside &&
166 test_rev_parse false false false
169 test_expect_success 'in repo.git' '
171 cd repo.git &&
172 test_rev_parse false true false
173 ) &&
175 cd repo.git/objects &&
176 test_rev_parse false true false
177 ) &&
179 cd repo.git/work2 &&
180 test_rev_parse false true false
184 test_expect_success 'inside work tree' '
186 cd repo.git/work &&
187 test_rev_parse false true true ""
191 test_expect_success 'subdir of work tree' '
193 cd repo.git/work/sub/dir &&
194 test_rev_parse false true true sub/dir/
198 test_expect_success 'find work tree from repo' '
199 echo sub/dir/untracked >expected &&
200 cat <<-\EOF >repo.git/work/.gitignore &&
201 expected.*
202 actual.*
203 .gitignore
205 >repo.git/work/sub/dir/untracked &&
207 cd repo.git &&
208 git ls-files --others --exclude-standard >../actual
209 ) &&
210 test_cmp expected actual
213 test_expect_success 'find work tree from work tree' '
214 echo sub/dir/tracked >expected &&
215 >repo.git/work/sub/dir/tracked &&
217 cd repo.git/work/sub/dir &&
218 git --git-dir=../../.. add tracked
219 ) &&
221 cd repo.git &&
222 git ls-files >../actual
223 ) &&
224 test_cmp expected actual
227 test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' '
229 cd repo.git/work/sub/dir &&
230 GIT_DIR=../../.. &&
231 GIT_WORK_TREE=../.. &&
232 GIT_PAGER= &&
233 export GIT_DIR GIT_WORK_TREE GIT_PAGER &&
235 git diff --exit-code tracked &&
236 echo changed >tracked &&
237 test_must_fail git diff --exit-code tracked
241 test_expect_success 'diff-index respects work tree under .git dir' '
242 cat >diff-index-cached.expected <<-EOF &&
243 :000000 100644 $ZERO_OID $EMPTY_BLOB A sub/dir/tracked
245 cat >diff-index.expected <<-EOF &&
246 :000000 100644 $ZERO_OID $ZERO_OID A sub/dir/tracked
250 GIT_DIR=repo.git &&
251 GIT_WORK_TREE=repo.git/work &&
252 export GIT_DIR GIT_WORK_TREE &&
253 git diff-index $EMPTY_TREE >diff-index.actual &&
254 git diff-index --cached $EMPTY_TREE >diff-index-cached.actual
255 ) &&
256 test_cmp diff-index.expected diff-index.actual &&
257 test_cmp diff-index-cached.expected diff-index-cached.actual
260 test_expect_success 'diff-files respects work tree under .git dir' '
261 cat >diff-files.expected <<-EOF &&
262 :100644 100644 $EMPTY_BLOB $ZERO_OID M sub/dir/tracked
266 GIT_DIR=repo.git &&
267 GIT_WORK_TREE=repo.git/work &&
268 export GIT_DIR GIT_WORK_TREE &&
269 git diff-files >diff-files.actual
270 ) &&
271 test_cmp diff-files.expected diff-files.actual
274 test_expect_success 'git diff respects work tree under .git dir' '
275 cat >diff-TREE.expected <<-EOF &&
276 diff --git a/sub/dir/tracked b/sub/dir/tracked
277 new file mode 100644
278 index 0000000..$CHANGED_BLOB7
279 --- /dev/null
280 +++ b/sub/dir/tracked
281 @@ -0,0 +1 @@
282 +changed
284 cat >diff-TREE-cached.expected <<-EOF &&
285 diff --git a/sub/dir/tracked b/sub/dir/tracked
286 new file mode 100644
287 index 0000000..$EMPTY_BLOB7
289 cat >diff-FILES.expected <<-EOF &&
290 diff --git a/sub/dir/tracked b/sub/dir/tracked
291 index $EMPTY_BLOB7..$CHANGED_BLOB7 100644
292 --- a/sub/dir/tracked
293 +++ b/sub/dir/tracked
294 @@ -0,0 +1 @@
295 +changed
299 GIT_DIR=repo.git &&
300 GIT_WORK_TREE=repo.git/work &&
301 export GIT_DIR GIT_WORK_TREE &&
302 git diff $EMPTY_TREE >diff-TREE.actual &&
303 git diff --cached $EMPTY_TREE >diff-TREE-cached.actual &&
304 git diff >diff-FILES.actual
305 ) &&
306 test_cmp diff-TREE.expected diff-TREE.actual &&
307 test_cmp diff-TREE-cached.expected diff-TREE-cached.actual &&
308 test_cmp diff-FILES.expected diff-FILES.actual
311 test_expect_success 'git grep' '
312 echo dir/tracked >expected.grep &&
314 cd repo.git/work/sub &&
315 GIT_DIR=../.. &&
316 GIT_WORK_TREE=.. &&
317 export GIT_DIR GIT_WORK_TREE &&
318 git grep -l changed >../../../actual.grep
319 ) &&
320 test_cmp expected.grep actual.grep
323 test_expect_success 'git commit' '
325 cd repo.git &&
326 GIT_DIR=. GIT_WORK_TREE=work git commit -a -m done
330 test_expect_success 'absolute pathspec should fail gracefully' '
332 cd repo.git &&
333 test_might_fail git config --unset core.worktree &&
334 test_must_fail git log HEAD -- /home
338 test_expect_success 'make_relative_path handles double slashes in GIT_DIR' '
339 >dummy_file &&
340 echo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file &&
341 git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file
344 test_expect_success 'relative $GIT_WORK_TREE and git subprocesses' '
345 GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work \
346 test-tool subprocess --setup-work-tree rev-parse --show-toplevel >actual &&
347 echo "$(pwd)/repo.git/work" >expected &&
348 test_cmp expected actual
351 test_expect_success 'Multi-worktree setup' '
352 mkdir work &&
353 mkdir -p repo.git/repos/foo &&
354 cp repo.git/HEAD repo.git/index repo.git/repos/foo &&
355 { cp repo.git/sharedindex.* repo.git/repos/foo || :; } &&
356 sane_unset GIT_DIR GIT_CONFIG GIT_WORK_TREE
359 test_expect_success 'GIT_DIR set (1)' '
360 echo "gitdir: repo.git/repos/foo" >gitfile &&
361 echo ../.. >repo.git/repos/foo/commondir &&
363 cd work &&
364 GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
365 test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
366 test_cmp expect actual
370 test_expect_success 'GIT_DIR set (2)' '
371 echo "gitdir: repo.git/repos/foo" >gitfile &&
372 echo "$(pwd)/repo.git" >repo.git/repos/foo/commondir &&
374 cd work &&
375 GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
376 test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
377 test_cmp expect actual
381 test_expect_success 'Auto discovery' '
382 echo "gitdir: repo.git/repos/foo" >.git &&
383 echo ../.. >repo.git/repos/foo/commondir &&
385 cd work &&
386 git rev-parse --git-common-dir >actual &&
387 test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
388 test_cmp expect actual &&
389 echo haha >data1 &&
390 git add data1 &&
391 git ls-files --full-name :/ | grep data1 >actual &&
392 echo work/data1 >expect &&
393 test_cmp expect actual
397 test_expect_success '$GIT_DIR/common overrides core.worktree' '
398 mkdir elsewhere &&
399 git --git-dir=repo.git config core.worktree "$TRASH_DIRECTORY/elsewhere" &&
400 echo "gitdir: repo.git/repos/foo" >.git &&
401 echo ../.. >repo.git/repos/foo/commondir &&
403 cd work &&
404 git rev-parse --git-common-dir >actual &&
405 test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
406 test_cmp expect actual &&
407 echo haha >data2 &&
408 git add data2 &&
409 git ls-files --full-name :/ | grep data2 >actual &&
410 echo work/data2 >expect &&
411 test_cmp expect actual
415 test_expect_success '$GIT_WORK_TREE overrides $GIT_DIR/common' '
416 echo "gitdir: repo.git/repos/foo" >.git &&
417 echo ../.. >repo.git/repos/foo/commondir &&
419 cd work &&
420 echo haha >data3 &&
421 git --git-dir=../.git --work-tree=. add data3 &&
422 git ls-files --full-name -- :/ | grep data3 >actual &&
423 echo data3 >expect &&
424 test_cmp expect actual
428 test_expect_success 'error out gracefully on invalid $GIT_WORK_TREE' '
430 GIT_WORK_TREE=/.invalid/work/tree &&
431 export GIT_WORK_TREE &&
432 test_expect_code 128 git rev-parse
436 test_expect_success 'refs work with relative gitdir and work tree' '
437 git init relative &&
438 git -C relative commit --allow-empty -m one &&
439 git -C relative commit --allow-empty -m two &&
441 GIT_DIR=relative/.git GIT_WORK_TREE=relative git reset HEAD^ &&
443 git -C relative log -1 --format=%s >actual &&
444 echo one >expect &&
445 test_cmp expect actual
448 test_done