3
test_description='test separate work tree'
4
. ./test-lib.sh
5
6
-test_rev_parse() {
7
- name=$1
8
- shift
9
-
10
- test_expect_success "$name: is-bare-repository" \
11
- "test '$1' = \"\$(git rev-parse --is-bare-repository)\""
12
- shift
13
- [ $# -eq 0 ] && return
14
-
15
- test_expect_success "$name: is-inside-git-dir" \
16
- "test '$1' = \"\$(git rev-parse --is-inside-git-dir)\""
17
- shift
18
- [ $# -eq 0 ] && return
19
-
20
- test_expect_success "$name: is-inside-work-tree" \
21
- "test '$1' = \"\$(git rev-parse --is-inside-work-tree)\""
22
- shift
23
- [ $# -eq 0 ] && return
24
-
25
- test_expect_success "$name: prefix" \
26
- "test '$1' = \"\$(git rev-parse --show-prefix)\""
27
- shift
28
- [ $# -eq 0 ] && return
29
-}
30
-
31
-EMPTY_TREE=$(git write-tree)
32
-mkdir -p work/sub/dir || exit 1
33
-mkdir -p work2 || exit 1
34
-mv .git repo.git || exit 1
35
-
36
-say "core.worktree = relative path"
37
-GIT_DIR=repo.git
38
-GIT_CONFIG="$(pwd)"/$GIT_DIR/config
39
-export GIT_DIR GIT_CONFIG
40
-unset GIT_WORK_TREE
41
-git config core.worktree ../work
42
-test_rev_parse 'outside' false false false
43
-cd work || exit 1
44
-GIT_DIR=../repo.git
45
-GIT_CONFIG="$(pwd)"/$GIT_DIR/config
46
-test_rev_parse 'inside' false false true ''
47
-cd sub/dir || exit 1
48
-GIT_DIR=../../../repo.git
49
-GIT_CONFIG="$(pwd)"/$GIT_DIR/config
50
-test_rev_parse 'subdirectory' false false true sub/dir/
51
-cd ../../.. || exit 1
52
-
53
-say "core.worktree = absolute path"
54
-GIT_DIR=$(pwd)/repo.git
55
-GIT_CONFIG=$GIT_DIR/config
56
-git config core.worktree "$(pwd)/work"
57
-test_rev_parse 'outside' false false false
58
-cd work2
59
-test_rev_parse 'outside2' false false false
60
-cd ../work || exit 1
61
-test_rev_parse 'inside' false false true ''
62
-cd sub/dir || exit 1
63
-test_rev_parse 'subdirectory' false false true sub/dir/
64
-cd ../../.. || exit 1
65
-
66
-say "GIT_WORK_TREE=relative path (override core.worktree)"
67
-GIT_DIR=$(pwd)/repo.git
68
-GIT_CONFIG=$GIT_DIR/config
69
-git config core.worktree non-existent
70
-GIT_WORK_TREE=work
71
-export GIT_WORK_TREE
72
-test_rev_parse 'outside' false false false
73
-cd work2
74
-test_rev_parse 'outside' false false false
75
-cd ../work || exit 1
76
-GIT_WORK_TREE=.
77
-test_rev_parse 'inside' false false true ''
78
-cd sub/dir || exit 1
79
-GIT_WORK_TREE=../..
80
-test_rev_parse 'subdirectory' false false true sub/dir/
81
-cd ../../.. || exit 1
82
-
83
-mv work repo.git/work
84
-mv work2 repo.git/work2
85
-
86
-say "GIT_WORK_TREE=absolute path, work tree below git dir"
87
-GIT_DIR=$(pwd)/repo.git
88
-GIT_CONFIG=$GIT_DIR/config
89
-GIT_WORK_TREE=$(pwd)/repo.git/work
90
-test_rev_parse 'outside' false false false
91
-cd repo.git || exit 1
92
-test_rev_parse 'in repo.git' false true false
93
-cd objects || exit 1
94
-test_rev_parse 'in repo.git/objects' false true false
95
-cd ../work2 || exit 1
96
-test_rev_parse 'in repo.git/work2' false true false
97
-cd ../work || exit 1
98
-test_rev_parse 'in repo.git/work' false true true ''
99
-cd sub/dir || exit 1
100
-test_rev_parse 'in repo.git/sub/dir' false true true sub/dir/
101
-cd ../../../.. || exit 1
102
-
103
-test_expect_success 'repo finds its work tree' '
104
- (cd repo.git &&
105
- : > work/sub/dir/untracked &&
106
- test sub/dir/untracked = "$(git ls-files --others)")
107
-'
108
-
109
-test_expect_success 'repo finds its work tree from work tree, too' '
110
- (cd repo.git/work/sub/dir &&
111
- : > tracked &&
112
- git --git-dir=../../.. add tracked &&
113
- cd ../../.. &&
114
- test sub/dir/tracked = "$(git ls-files)")
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' '
118
- (cd repo.git/work/sub/dir &&
119
- GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \
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 &&
121
- echo changed > tracked &&
122
- ! GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \
123
- git diff --exit-code tracked)
124
-'
125
-cat > diff-index-cached.expected <<\EOF
126
-:000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A sub/dir/tracked
127
-EOF
128
-cat > diff-index.expected <<\EOF
129
-:000000 100644 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 A sub/dir/tracked
130
-EOF
131
-
132
-
133
-test_expect_success 'git diff-index' '
134
- GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-index $EMPTY_TREE > result &&
135
- test_cmp diff-index.expected result &&
136
- GIT_DIR=repo.git git diff-index --cached $EMPTY_TREE > result &&
137
- test_cmp diff-index-cached.expected result
138
-'
139
-cat >diff-files.expected <<\EOF
140
-:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M sub/dir/tracked
141
-EOF
142
-
143
-test_expect_success 'git diff-files' '
144
- GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-files > result &&
145
- test_cmp diff-files.expected result
146
-'
147
-
148
-cat >diff-TREE.expected <<\EOF
149
-diff --git a/sub/dir/tracked b/sub/dir/tracked
150
-new file mode 100644
151
-index 0000000..5ea2ed4
152
---- /dev/null
153
-+++ b/sub/dir/tracked
154
-@@ -0,0 +1 @@
155
-+changed
156
-EOF
157
-cat >diff-TREE-cached.expected <<\EOF
158
-diff --git a/sub/dir/tracked b/sub/dir/tracked
159
-new file mode 100644
160
-index 0000000..e69de29
161
-EOF
162
-cat >diff-FILES.expected <<\EOF
163
-diff --git a/sub/dir/tracked b/sub/dir/tracked
164
-index e69de29..5ea2ed4 100644
165
---- a/sub/dir/tracked
166
-+++ b/sub/dir/tracked
167
-@@ -0,0 +1 @@
168
-+changed
169
-EOF
170
-
171
-test_expect_success 'git diff' '
172
- GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff $EMPTY_TREE > result &&
173
- test_cmp diff-TREE.expected result &&
174
- GIT_DIR=repo.git git diff --cached $EMPTY_TREE > result &&
175
- test_cmp diff-TREE-cached.expected result &&
176
- GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff > result &&
177
- test_cmp diff-FILES.expected result
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' '
181
- (cd repo.git/work/sub &&
182
- GIT_DIR=../.. GIT_WORK_TREE=.. git grep -l changed | grep dir/tracked)
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' '
328
329
test_expect_success 'absolute pathspec should fail gracefully' '
330
(
194
- cd repo.git || exit 1
195
- git config --unset core.worktree
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' '
201
- : > dummy_file
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
'