Merge branch 'master' into next
[git] / t / t1501-worktree.sh
1 #!/bin/sh
2
3 test_description='test separate work tree'
4 . ./test-lib.sh
5
6 test_expect_success 'setup' '
7         EMPTY_TREE=$(git write-tree) &&
8         EMPTY_BLOB=$(git hash-object -t blob --stdin </dev/null) &&
9         CHANGED_BLOB=$(echo changed | git hash-object -t blob --stdin) &&
10         ZEROES=0000000000000000000000000000000000000000 &&
11         EMPTY_BLOB7=$(echo $EMPTY_BLOB | sed "s/\(.......\).*/\1/") &&
12         CHANGED_BLOB7=$(echo $CHANGED_BLOB | sed "s/\(.......\).*/\1/") &&
13
14         mkdir -p work/sub/dir &&
15         mkdir -p work2 &&
16         mv .git repo.git
17 '
18
19 test_expect_success 'setup: helper for testing rev-parse' '
20         test_rev_parse() {
21                 echo $1 >expected.bare &&
22                 echo $2 >expected.inside-git &&
23                 echo $3 >expected.inside-worktree &&
24                 if test $# -ge 4
25                 then
26                         echo $4 >expected.prefix
27                 fi &&
28
29                 git rev-parse --is-bare-repository >actual.bare &&
30                 git rev-parse --is-inside-git-dir >actual.inside-git &&
31                 git rev-parse --is-inside-work-tree >actual.inside-worktree &&
32                 if test $# -ge 4
33                 then
34                         git rev-parse --show-prefix >actual.prefix
35                 fi &&
36
37                 test_cmp expected.bare actual.bare &&
38                 test_cmp expected.inside-git actual.inside-git &&
39                 test_cmp expected.inside-worktree actual.inside-worktree &&
40                 if test $# -ge 4
41                 then
42                         # rev-parse --show-prefix should output
43                         # a single newline when at the top of the work tree,
44                         # but we test for that separately.
45                         test -z "$4" && ! test -s actual.prefix ||
46                         test_cmp expected.prefix actual.prefix
47                 fi
48         }
49 '
50
51 test_expect_success 'setup: core.worktree = relative path' '
52         unset GIT_WORK_TREE;
53         GIT_DIR=repo.git &&
54         GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
55         export GIT_DIR GIT_CONFIG &&
56         git config core.worktree ../work
57 '
58
59 test_expect_success 'outside' '
60         test_rev_parse false false false
61 '
62
63 test_expect_success 'inside work tree' '
64         (
65                 cd work &&
66                 GIT_DIR=../repo.git &&
67                 GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
68                 test_rev_parse false false true ""
69         )
70 '
71
72 test_expect_failure 'empty prefix is actually written out' '
73         echo >expected &&
74         (
75                 cd work &&
76                 GIT_DIR=../repo.git &&
77                 GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
78                 git rev-parse --show-prefix >../actual
79         ) &&
80         test_cmp expected actual
81 '
82
83 test_expect_success 'subdir of work tree' '
84         (
85                 cd work/sub/dir &&
86                 GIT_DIR=../../../repo.git &&
87                 GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
88                 test_rev_parse false false true sub/dir/
89         )
90 '
91
92 test_expect_success 'setup: core.worktree = absolute path' '
93         unset GIT_WORK_TREE;
94         GIT_DIR=$(pwd)/repo.git &&
95         GIT_CONFIG=$GIT_DIR/config &&
96         export GIT_DIR GIT_CONFIG &&
97         git config core.worktree "$(pwd)/work"
98 '
99
100 test_expect_success 'outside' '
101         test_rev_parse false false false &&
102         (
103                 cd work2 &&
104                 test_rev_parse false false false
105         )
106 '
107
108 test_expect_success 'inside work tree' '
109         (
110                 cd work &&
111                 test_rev_parse false false true ""
112         )
113 '
114
115 test_expect_success 'subdir of work tree' '
116         (
117                 cd work/sub/dir &&
118                 test_rev_parse false false true sub/dir/
119         )
120 '
121
122 test_expect_success 'setup: GIT_WORK_TREE=relative (override core.worktree)' '
123         GIT_DIR=$(pwd)/repo.git &&
124         GIT_CONFIG=$GIT_DIR/config &&
125         git config core.worktree non-existent &&
126         GIT_WORK_TREE=work &&
127         export GIT_DIR GIT_CONFIG GIT_WORK_TREE
128 '
129
130 test_expect_success 'outside' '
131         test_rev_parse false false false &&
132         (
133                 cd work2 &&
134                 test_rev_parse false false false
135         )
136 '
137
138 test_expect_success 'inside work tree' '
139         (
140                 cd work &&
141                 GIT_WORK_TREE=. &&
142                 test_rev_parse false false true ""
143         )
144 '
145
146 test_expect_success 'subdir of work tree' '
147         (
148                 cd work/sub/dir &&
149                 GIT_WORK_TREE=../.. &&
150                 test_rev_parse false false true sub/dir/
151         )
152 '
153
154 test_expect_success 'setup: GIT_WORK_TREE=absolute, below git dir' '
155         mv work repo.git/work &&
156         mv work2 repo.git/work2 &&
157         GIT_DIR=$(pwd)/repo.git &&
158         GIT_CONFIG=$GIT_DIR/config &&
159         GIT_WORK_TREE=$(pwd)/repo.git/work &&
160         export GIT_DIR GIT_CONFIG GIT_WORK_TREE
161 '
162
163 test_expect_success 'outside' '
164         echo outside &&
165         test_rev_parse false false false
166 '
167
168 test_expect_success 'in repo.git' '
169         (
170                 cd repo.git &&
171                 test_rev_parse false true false
172         ) &&
173         (
174                 cd repo.git/objects &&
175                 test_rev_parse false true false
176         ) &&
177         (
178                 cd repo.git/work2 &&
179                 test_rev_parse false true false
180         )
181 '
182
183 test_expect_success 'inside work tree' '
184         (
185                 cd repo.git/work &&
186                 test_rev_parse false true true ""
187         )
188 '
189
190 test_expect_success 'subdir of work tree' '
191         (
192                 cd repo.git/work/sub/dir &&
193                 test_rev_parse false true true sub/dir/
194         )
195 '
196
197 test_expect_success 'find work tree from repo' '
198         echo sub/dir/untracked >expected &&
199         cat <<-\EOF >repo.git/work/.gitignore &&
200         expected.*
201         actual.*
202         .gitignore
203         EOF
204         >repo.git/work/sub/dir/untracked &&
205         (
206                 cd repo.git &&
207                 git ls-files --others --exclude-standard >../actual
208         ) &&
209         test_cmp expected actual
210 '
211
212 test_expect_success 'find work tree from work tree' '
213         echo sub/dir/tracked >expected &&
214         >repo.git/work/sub/dir/tracked &&
215         (
216                 cd repo.git/work/sub/dir &&
217                 git --git-dir=../../.. add tracked
218         ) &&
219         (
220                 cd repo.git &&
221                 git ls-files >../actual
222         ) &&
223         test_cmp expected actual
224 '
225
226 test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' '
227         (
228                 cd repo.git/work/sub/dir &&
229                 GIT_DIR=../../.. &&
230                 GIT_WORK_TREE=../.. &&
231                 GIT_PAGER= &&
232                 export GIT_DIR GIT_WORK_TREE GIT_PAGER &&
233
234                 git diff --exit-code tracked &&
235                 echo changed >tracked &&
236                 test_must_fail git diff --exit-code tracked
237         )
238 '
239
240 test_expect_success 'diff-index respects work tree under .git dir' '
241         cat >diff-index-cached.expected <<-EOF &&
242         :000000 100644 $ZEROES $EMPTY_BLOB A    sub/dir/tracked
243         EOF
244         cat >diff-index.expected <<-EOF &&
245         :000000 100644 $ZEROES $ZEROES A        sub/dir/tracked
246         EOF
247
248         (
249                 GIT_DIR=repo.git &&
250                 GIT_WORK_TREE=repo.git/work &&
251                 export GIT_DIR GIT_WORK_TREE &&
252                 git diff-index $EMPTY_TREE >diff-index.actual &&
253                 git diff-index --cached $EMPTY_TREE >diff-index-cached.actual
254         ) &&
255         test_cmp diff-index.expected diff-index.actual &&
256         test_cmp diff-index-cached.expected diff-index-cached.actual
257 '
258
259 test_expect_success 'diff-files respects work tree under .git dir' '
260         cat >diff-files.expected <<-EOF &&
261         :100644 100644 $EMPTY_BLOB $ZEROES M    sub/dir/tracked
262         EOF
263
264         (
265                 GIT_DIR=repo.git &&
266                 GIT_WORK_TREE=repo.git/work &&
267                 export GIT_DIR GIT_WORK_TREE &&
268                 git diff-files >diff-files.actual
269         ) &&
270         test_cmp diff-files.expected diff-files.actual
271 '
272
273 test_expect_success 'git diff respects work tree under .git dir' '
274         cat >diff-TREE.expected <<-EOF &&
275         diff --git a/sub/dir/tracked b/sub/dir/tracked
276         new file mode 100644
277         index 0000000..$CHANGED_BLOB7
278         --- /dev/null
279         +++ b/sub/dir/tracked
280         @@ -0,0 +1 @@
281         +changed
282         EOF
283         cat >diff-TREE-cached.expected <<-EOF &&
284         diff --git a/sub/dir/tracked b/sub/dir/tracked
285         new file mode 100644
286         index 0000000..$EMPTY_BLOB7
287         EOF
288         cat >diff-FILES.expected <<-EOF &&
289         diff --git a/sub/dir/tracked b/sub/dir/tracked
290         index $EMPTY_BLOB7..$CHANGED_BLOB7 100644
291         --- a/sub/dir/tracked
292         +++ b/sub/dir/tracked
293         @@ -0,0 +1 @@
294         +changed
295         EOF
296
297         (
298                 GIT_DIR=repo.git &&
299                 GIT_WORK_TREE=repo.git/work &&
300                 export GIT_DIR GIT_WORK_TREE &&
301                 git diff $EMPTY_TREE >diff-TREE.actual &&
302                 git diff --cached $EMPTY_TREE >diff-TREE-cached.actual &&
303                 git diff >diff-FILES.actual
304         ) &&
305         test_cmp diff-TREE.expected diff-TREE.actual &&
306         test_cmp diff-TREE-cached.expected diff-TREE-cached.actual &&
307         test_cmp diff-FILES.expected diff-FILES.actual
308 '
309
310 test_expect_success 'git grep' '
311         echo dir/tracked >expected.grep &&
312         (
313                 cd repo.git/work/sub &&
314                 GIT_DIR=../.. &&
315                 GIT_WORK_TREE=.. &&
316                 export GIT_DIR GIT_WORK_TREE &&
317                 git grep -l changed >../../../actual.grep
318         ) &&
319         test_cmp expected.grep actual.grep
320 '
321
322 test_expect_success 'git commit' '
323         (
324                 cd repo.git &&
325                 GIT_DIR=. GIT_WORK_TREE=work git commit -a -m done
326         )
327 '
328
329 test_expect_success 'absolute pathspec should fail gracefully' '
330         (
331                 cd repo.git &&
332                 test_might_fail git config --unset core.worktree &&
333                 test_must_fail git log HEAD -- /home
334         )
335 '
336
337 test_expect_success 'make_relative_path handles double slashes in GIT_DIR' '
338         >dummy_file
339         echo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file &&
340         git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file
341 '
342
343 test_done