]>
Commit | Line | Data |
---|---|---|
94c0956b DS |
1 | #!/bin/sh |
2 | ||
3 | test_description='sparse checkout builtin tests' | |
4 | ||
06d53148 | 5 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
334afbc7 JS |
6 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
7 | ||
ac873c2b JS |
8 | GIT_TEST_SPLIT_INDEX=false |
9 | export GIT_TEST_SPLIT_INDEX | |
10 | ||
94c0956b DS |
11 | . ./test-lib.sh |
12 | ||
761e3d26 EM |
13 | list_files() { |
14 | # Do not replace this with 'ls "$1"', as "ls" with BSD-lineage | |
15 | # enables "-A" by default for root and ends up including ".git" and | |
16 | # such in its output. (Note, though, that running the test suite as | |
17 | # root is generally not recommended.) | |
18 | (cd "$1" && printf '%s\n' *) | |
19 | } | |
20 | ||
522e6417 DS |
21 | check_files() { |
22 | list_files "$1" >actual && | |
23 | shift && | |
24 | printf "%s\n" $@ >expect && | |
25 | test_cmp expect actual | |
26 | } | |
27 | ||
94c0956b DS |
28 | test_expect_success 'setup' ' |
29 | git init repo && | |
30 | ( | |
31 | cd repo && | |
32 | echo "initial" >a && | |
33 | mkdir folder1 folder2 deep && | |
34 | mkdir deep/deeper1 deep/deeper2 && | |
35 | mkdir deep/deeper1/deepest && | |
36 | cp a folder1 && | |
37 | cp a folder2 && | |
38 | cp a deep && | |
39 | cp a deep/deeper1 && | |
40 | cp a deep/deeper2 && | |
41 | cp a deep/deeper1/deepest && | |
42 | git add . && | |
43 | git commit -m "initial commit" | |
44 | ) | |
45 | ' | |
46 | ||
45c5e470 EN |
47 | test_expect_success 'git sparse-checkout list (not sparse)' ' |
48 | test_must_fail git -C repo sparse-checkout list >list 2>err && | |
49 | test_must_be_empty list && | |
50 | test_i18ngrep "this worktree is not sparse" err | |
51 | ' | |
52 | ||
53 | test_expect_success 'git sparse-checkout list (not sparse)' ' | |
54 | git -C repo sparse-checkout set && | |
55 | rm repo/.git/info/sparse-checkout && | |
94c0956b DS |
56 | git -C repo sparse-checkout list >list 2>err && |
57 | test_must_be_empty list && | |
58 | test_i18ngrep "this worktree is not sparse (sparse-checkout file may not exist)" err | |
59 | ' | |
60 | ||
61 | test_expect_success 'git sparse-checkout list (populated)' ' | |
62 | test_when_finished rm -f repo/.git/info/sparse-checkout && | |
d622c343 DS |
63 | cat >repo/.git/info/sparse-checkout <<-\EOF && |
64 | /folder1/* | |
65 | /deep/ | |
66 | **/a | |
67 | !*bin* | |
94c0956b DS |
68 | EOF |
69 | cp repo/.git/info/sparse-checkout expect && | |
70 | git -C repo sparse-checkout list >list && | |
71 | test_cmp expect list | |
72 | ' | |
73 | ||
bab3c359 DS |
74 | test_expect_success 'git sparse-checkout init' ' |
75 | git -C repo sparse-checkout init && | |
d622c343 DS |
76 | cat >expect <<-\EOF && |
77 | /* | |
78 | !/*/ | |
bab3c359 DS |
79 | EOF |
80 | test_cmp expect repo/.git/info/sparse-checkout && | |
81 | test_cmp_config -C repo true core.sparsecheckout && | |
522e6417 | 82 | check_files repo a |
bab3c359 DS |
83 | ' |
84 | ||
7f44842a JT |
85 | test_expect_success 'git sparse-checkout init in empty repo' ' |
86 | test_when_finished rm -rf empty-repo blank-template && | |
87 | git init --template= empty-repo && | |
88 | git -C empty-repo sparse-checkout init | |
89 | ' | |
90 | ||
bab3c359 DS |
91 | test_expect_success 'git sparse-checkout list after init' ' |
92 | git -C repo sparse-checkout list >actual && | |
d622c343 DS |
93 | cat >expect <<-\EOF && |
94 | /* | |
95 | !/*/ | |
bab3c359 DS |
96 | EOF |
97 | test_cmp expect actual | |
98 | ' | |
99 | ||
100 | test_expect_success 'init with existing sparse-checkout' ' | |
101 | echo "*folder*" >> repo/.git/info/sparse-checkout && | |
102 | git -C repo sparse-checkout init && | |
d622c343 DS |
103 | cat >expect <<-\EOF && |
104 | /* | |
105 | !/*/ | |
106 | *folder* | |
bab3c359 DS |
107 | EOF |
108 | test_cmp expect repo/.git/info/sparse-checkout && | |
522e6417 | 109 | check_files repo a folder1 folder2 |
bab3c359 DS |
110 | ' |
111 | ||
d89f09c8 | 112 | test_expect_success 'clone --sparse' ' |
47dbf10d | 113 | git clone --sparse "file://$(pwd)/repo" clone && |
d89f09c8 | 114 | git -C clone sparse-checkout list >actual && |
d622c343 DS |
115 | cat >expect <<-\EOF && |
116 | /* | |
117 | !/*/ | |
d89f09c8 DS |
118 | EOF |
119 | test_cmp expect actual && | |
522e6417 | 120 | check_files clone a |
d89f09c8 DS |
121 | ' |
122 | ||
391c3a10 DS |
123 | test_expect_success 'switching to cone mode with non-cone mode patterns' ' |
124 | git init bad-patterns && | |
125 | ( | |
126 | cd bad-patterns && | |
127 | git sparse-checkout init && | |
128 | git sparse-checkout add dir && | |
129 | git config core.sparseCheckoutCone true && | |
a3eca584 DS |
130 | test_must_fail git sparse-checkout add dir 2>err && |
131 | grep "existing sparse-checkout patterns do not use cone mode" err | |
391c3a10 DS |
132 | ) |
133 | ' | |
134 | ||
b5bfc08a EN |
135 | test_expect_success 'interaction with clone --no-checkout (unborn index)' ' |
136 | git clone --no-checkout "file://$(pwd)/repo" clone_no_checkout && | |
137 | git -C clone_no_checkout sparse-checkout init --cone && | |
138 | git -C clone_no_checkout sparse-checkout set folder1 && | |
139 | ||
140 | git -C clone_no_checkout sparse-checkout list >actual && | |
141 | cat >expect <<-\EOF && | |
142 | folder1 | |
143 | EOF | |
144 | test_cmp expect actual && | |
145 | ||
146 | # nothing checked out, expect "No such file or directory" | |
147 | ! ls clone_no_checkout/* >actual && | |
148 | test_must_be_empty actual && | |
149 | test_path_is_missing clone_no_checkout/.git/index && | |
150 | ||
151 | # No branch is checked out until we manually switch to one | |
06d53148 | 152 | git -C clone_no_checkout switch main && |
b5bfc08a EN |
153 | test_path_is_file clone_no_checkout/.git/index && |
154 | check_files clone_no_checkout a folder1 | |
155 | ' | |
156 | ||
f6039a94 DS |
157 | test_expect_success 'set enables config' ' |
158 | git init empty-config && | |
159 | ( | |
160 | cd empty-config && | |
161 | test_commit test file && | |
162 | test_path_is_missing .git/config.worktree && | |
ace224ac | 163 | git sparse-checkout set nothing && |
f6039a94 | 164 | test_path_is_file .git/config.worktree && |
f6039a94 DS |
165 | test_cmp_config true core.sparseCheckout |
166 | ) | |
167 | ' | |
168 | ||
169 | test_expect_success 'set sparse-checkout using builtin' ' | |
170 | git -C repo sparse-checkout set "/*" "!/*/" "*folder*" && | |
d622c343 DS |
171 | cat >expect <<-\EOF && |
172 | /* | |
173 | !/*/ | |
174 | *folder* | |
f6039a94 DS |
175 | EOF |
176 | git -C repo sparse-checkout list >actual && | |
177 | test_cmp expect actual && | |
178 | test_cmp expect repo/.git/info/sparse-checkout && | |
522e6417 | 179 | check_files repo a folder1 folder2 |
f6039a94 DS |
180 | ' |
181 | ||
7bffca95 | 182 | test_expect_success 'set sparse-checkout using --stdin' ' |
d622c343 DS |
183 | cat >expect <<-\EOF && |
184 | /* | |
185 | !/*/ | |
186 | /folder1/ | |
187 | /folder2/ | |
7bffca95 DS |
188 | EOF |
189 | git -C repo sparse-checkout set --stdin <expect && | |
190 | git -C repo sparse-checkout list >actual && | |
191 | test_cmp expect actual && | |
192 | test_cmp expect repo/.git/info/sparse-checkout && | |
522e6417 | 193 | check_files repo "a folder1 folder2" |
7bffca95 DS |
194 | ' |
195 | ||
2631dc87 | 196 | test_expect_success 'add to sparse-checkout' ' |
a3eca584 DS |
197 | cat repo/.git/info/sparse-checkout >old && |
198 | test_when_finished cp old repo/.git/info/sparse-checkout && | |
2631dc87 DS |
199 | cat >add <<-\EOF && |
200 | pattern1 | |
201 | /folder1/ | |
202 | pattern2 | |
203 | EOF | |
a3eca584 | 204 | cat old >expect && |
2631dc87 DS |
205 | cat add >>expect && |
206 | git -C repo sparse-checkout add --stdin <add && | |
207 | git -C repo sparse-checkout list >actual && | |
208 | test_cmp expect actual && | |
209 | test_cmp expect repo/.git/info/sparse-checkout && | |
210 | check_files repo "a folder1 folder2" | |
211 | ' | |
212 | ||
879321eb DS |
213 | test_expect_success 'cone mode: match patterns' ' |
214 | git -C repo config --worktree core.sparseCheckoutCone true && | |
215 | rm -rf repo/a repo/folder1 repo/folder2 && | |
96cc8ab5 DS |
216 | git -C repo read-tree -mu HEAD 2>err && |
217 | test_i18ngrep ! "disabling cone patterns" err && | |
879321eb | 218 | git -C repo reset --hard && |
522e6417 | 219 | check_files repo a folder1 folder2 |
879321eb DS |
220 | ' |
221 | ||
96cc8ab5 DS |
222 | test_expect_success 'cone mode: warn on bad pattern' ' |
223 | test_when_finished mv sparse-checkout repo/.git/info/ && | |
224 | cp repo/.git/info/sparse-checkout . && | |
225 | echo "!/deep/deeper/*" >>repo/.git/info/sparse-checkout && | |
226 | git -C repo read-tree -mu HEAD 2>err && | |
227 | test_i18ngrep "unrecognized negative pattern" err | |
228 | ' | |
229 | ||
72918c1a | 230 | test_expect_success 'sparse-checkout disable' ' |
99dfa6f9 | 231 | test_when_finished rm -rf repo/.git/info/sparse-checkout && |
72918c1a | 232 | git -C repo sparse-checkout disable && |
99dfa6f9 | 233 | test_path_is_file repo/.git/info/sparse-checkout && |
72918c1a DS |
234 | git -C repo config --list >config && |
235 | test_must_fail git config core.sparseCheckout && | |
522e6417 | 236 | check_files repo a deep folder1 folder2 |
72918c1a DS |
237 | ' |
238 | ||
dcc5fd5f | 239 | test_expect_success 'sparse-index enabled and disabled' ' |
ac873c2b JS |
240 | git -C repo sparse-checkout init --cone --sparse-index && |
241 | test_cmp_config -C repo true index.sparse && | |
242 | git -C repo ls-files --sparse >sparse && | |
243 | git -C repo sparse-checkout disable && | |
244 | git -C repo ls-files --sparse >full && | |
c2a29405 | 245 | |
ac873c2b JS |
246 | cat >expect <<-\EOF && |
247 | @@ -1,4 +1,7 @@ | |
248 | a | |
249 | -deep/ | |
250 | -folder1/ | |
251 | -folder2/ | |
252 | +deep/a | |
253 | +deep/deeper1/a | |
254 | +deep/deeper1/deepest/a | |
255 | +deep/deeper2/a | |
256 | +folder1/a | |
257 | +folder2/a | |
258 | EOF | |
c2a29405 | 259 | |
ac873c2b JS |
260 | diff -u sparse full | tail -n +3 >actual && |
261 | test_cmp expect actual && | |
c2a29405 | 262 | |
ac873c2b JS |
263 | git -C repo config --list >config && |
264 | ! grep index.sparse config | |
dcc5fd5f DS |
265 | ' |
266 | ||
af09ce24 DS |
267 | test_expect_success 'cone mode: init and set' ' |
268 | git -C repo sparse-checkout init --cone && | |
269 | git -C repo config --list >config && | |
270 | test_i18ngrep "core.sparsecheckoutcone=true" config && | |
761e3d26 | 271 | list_files repo >dir && |
af09ce24 DS |
272 | echo a >expect && |
273 | test_cmp expect dir && | |
274 | git -C repo sparse-checkout set deep/deeper1/deepest/ 2>err && | |
275 | test_must_be_empty err && | |
522e6417 DS |
276 | check_files repo a deep && |
277 | check_files repo/deep a deeper1 && | |
278 | check_files repo/deep/deeper1 a deepest && | |
d622c343 DS |
279 | cat >expect <<-\EOF && |
280 | /* | |
281 | !/*/ | |
282 | /deep/ | |
283 | !/deep/*/ | |
284 | /deep/deeper1/ | |
285 | !/deep/deeper1/*/ | |
286 | /deep/deeper1/deepest/ | |
af09ce24 DS |
287 | EOF |
288 | test_cmp expect repo/.git/info/sparse-checkout && | |
d622c343 DS |
289 | git -C repo sparse-checkout set --stdin 2>err <<-\EOF && |
290 | folder1 | |
291 | folder2 | |
af09ce24 DS |
292 | EOF |
293 | test_must_be_empty err && | |
522e6417 | 294 | check_files repo a folder1 folder2 |
af09ce24 DS |
295 | ' |
296 | ||
de11951b | 297 | test_expect_success 'cone mode: list' ' |
d622c343 DS |
298 | cat >expect <<-\EOF && |
299 | folder1 | |
300 | folder2 | |
de11951b DS |
301 | EOF |
302 | git -C repo sparse-checkout set --stdin <expect && | |
303 | git -C repo sparse-checkout list >actual 2>err && | |
304 | test_must_be_empty err && | |
305 | test_cmp expect actual | |
306 | ' | |
307 | ||
e9de487a DS |
308 | test_expect_success 'cone mode: set with nested folders' ' |
309 | git -C repo sparse-checkout set deep deep/deeper1/deepest 2>err && | |
310 | test_line_count = 0 err && | |
d622c343 DS |
311 | cat >expect <<-\EOF && |
312 | /* | |
313 | !/*/ | |
314 | /deep/ | |
e9de487a DS |
315 | EOF |
316 | test_cmp repo/.git/info/sparse-checkout expect | |
317 | ' | |
318 | ||
2631dc87 DS |
319 | test_expect_success 'cone mode: add independent path' ' |
320 | git -C repo sparse-checkout set deep/deeper1 && | |
321 | git -C repo sparse-checkout add folder1 && | |
322 | cat >expect <<-\EOF && | |
323 | /* | |
324 | !/*/ | |
325 | /deep/ | |
326 | !/deep/*/ | |
327 | /deep/deeper1/ | |
328 | /folder1/ | |
329 | EOF | |
330 | test_cmp expect repo/.git/info/sparse-checkout && | |
331 | check_files repo a deep folder1 | |
332 | ' | |
333 | ||
334 | test_expect_success 'cone mode: add sibling path' ' | |
335 | git -C repo sparse-checkout set deep/deeper1 && | |
336 | git -C repo sparse-checkout add deep/deeper2 && | |
337 | cat >expect <<-\EOF && | |
338 | /* | |
339 | !/*/ | |
340 | /deep/ | |
341 | !/deep/*/ | |
342 | /deep/deeper1/ | |
343 | /deep/deeper2/ | |
344 | EOF | |
345 | test_cmp expect repo/.git/info/sparse-checkout && | |
346 | check_files repo a deep | |
347 | ' | |
348 | ||
349 | test_expect_success 'cone mode: add parent path' ' | |
350 | git -C repo sparse-checkout set deep/deeper1 folder1 && | |
351 | git -C repo sparse-checkout add deep && | |
352 | cat >expect <<-\EOF && | |
353 | /* | |
354 | !/*/ | |
355 | /deep/ | |
356 | /folder1/ | |
357 | EOF | |
358 | test_cmp expect repo/.git/info/sparse-checkout && | |
359 | check_files repo a deep folder1 | |
360 | ' | |
361 | ||
f56f31af | 362 | test_expect_success 'not-up-to-date does not block rest of sparsification' ' |
72064ee5 | 363 | test_when_finished git -C repo sparse-checkout disable && |
cff4e913 | 364 | test_when_finished git -C repo reset --hard && |
2631dc87 | 365 | git -C repo sparse-checkout set deep && |
f56f31af | 366 | |
e091228e DS |
367 | echo update >repo/deep/deeper2/a && |
368 | cp repo/.git/info/sparse-checkout expect && | |
f56f31af EN |
369 | test_write_lines "!/deep/*/" "/deep/deeper1/" >>expect && |
370 | ||
371 | git -C repo sparse-checkout set deep/deeper1 2>err && | |
372 | ||
22ab0b37 | 373 | test_i18ngrep "The following paths are not up to date" err && |
f56f31af EN |
374 | test_cmp expect repo/.git/info/sparse-checkout && |
375 | check_files repo/deep a deeper1 deeper2 && | |
376 | check_files repo/deep/deeper1 a deepest && | |
377 | check_files repo/deep/deeper1/deepest a && | |
378 | check_files repo/deep/deeper2 a | |
e091228e DS |
379 | ' |
380 | ||
381 | test_expect_success 'revert to old sparse-checkout on empty update' ' | |
382 | git init empty-test && | |
383 | ( | |
384 | echo >file && | |
385 | git add file && | |
386 | git commit -m "test" && | |
ace224ac DS |
387 | git sparse-checkout set nothing 2>err && |
388 | test_i18ngrep ! "Sparse checkout leaves no entry on working directory" err && | |
e091228e DS |
389 | test_i18ngrep ! ".git/index.lock" err && |
390 | git sparse-checkout set file | |
391 | ) | |
392 | ' | |
393 | ||
fb10ca5b DS |
394 | test_expect_success 'fail when lock is taken' ' |
395 | test_when_finished rm -rf repo/.git/info/sparse-checkout.lock && | |
396 | touch repo/.git/info/sparse-checkout.lock && | |
397 | test_must_fail git -C repo sparse-checkout set deep 2>err && | |
4605a730 | 398 | test_i18ngrep "Unable to create .*\.lock" err |
fb10ca5b DS |
399 | ' |
400 | ||
f75a69f8 DS |
401 | test_expect_success '.gitignore should not warn about cone mode' ' |
402 | git -C repo config --worktree core.sparseCheckoutCone true && | |
403 | echo "**/bin/*" >repo/.gitignore && | |
404 | git -C repo reset --hard 2>err && | |
405 | test_i18ngrep ! "disabling cone patterns" err | |
406 | ' | |
407 | ||
f56f31af | 408 | test_expect_success 'sparse-checkout (init|set|disable) warns with dirty status' ' |
cff4e913 DS |
409 | git clone repo dirty && |
410 | echo dirty >dirty/folder1/a && | |
f56f31af EN |
411 | |
412 | git -C dirty sparse-checkout init 2>err && | |
22ab0b37 | 413 | test_i18ngrep "warning.*The following paths are not up to date" err && |
f56f31af EN |
414 | |
415 | git -C dirty sparse-checkout set /folder2/* /deep/deeper1/* 2>err && | |
22ab0b37 | 416 | test_i18ngrep "warning.*The following paths are not up to date" err && |
f56f31af EN |
417 | test_path_is_file dirty/folder1/a && |
418 | ||
419 | git -C dirty sparse-checkout disable 2>err && | |
420 | test_must_be_empty err && | |
421 | ||
cff4e913 DS |
422 | git -C dirty reset --hard && |
423 | git -C dirty sparse-checkout init && | |
424 | git -C dirty sparse-checkout set /folder2/* /deep/deeper1/* && | |
f56f31af EN |
425 | test_path_is_missing dirty/folder1/a && |
426 | git -C dirty sparse-checkout disable && | |
427 | test_path_is_file dirty/folder1/a | |
cff4e913 DS |
428 | ' |
429 | ||
ebb568b9 EN |
430 | test_expect_success 'sparse-checkout (init|set|disable) warns with unmerged status' ' |
431 | git clone repo unmerged && | |
432 | ||
433 | cat >input <<-EOF && | |
d827bce5 | 434 | 0 $ZERO_OID folder1/a |
ebb568b9 EN |
435 | 100644 $(git -C unmerged rev-parse HEAD:folder1/a) 1 folder1/a |
436 | EOF | |
437 | git -C unmerged update-index --index-info <input && | |
438 | ||
439 | git -C unmerged sparse-checkout init 2>err && | |
440 | test_i18ngrep "warning.*The following paths are unmerged" err && | |
441 | ||
442 | git -C unmerged sparse-checkout set /folder2/* /deep/deeper1/* 2>err && | |
443 | test_i18ngrep "warning.*The following paths are unmerged" err && | |
444 | test_path_is_file dirty/folder1/a && | |
445 | ||
446 | git -C unmerged sparse-checkout disable 2>err && | |
447 | test_i18ngrep "warning.*The following paths are unmerged" err && | |
448 | ||
449 | git -C unmerged reset --hard && | |
450 | git -C unmerged sparse-checkout init && | |
451 | git -C unmerged sparse-checkout set /folder2/* /deep/deeper1/* && | |
452 | git -C unmerged sparse-checkout disable | |
453 | ' | |
454 | ||
49fdd51a | 455 | test_expect_failure 'sparse-checkout reapply' ' |
5644ca28 EN |
456 | git clone repo tweak && |
457 | ||
458 | echo dirty >tweak/deep/deeper2/a && | |
459 | ||
460 | cat >input <<-EOF && | |
d827bce5 | 461 | 0 $ZERO_OID folder1/a |
5644ca28 EN |
462 | 100644 $(git -C tweak rev-parse HEAD:folder1/a) 1 folder1/a |
463 | EOF | |
464 | git -C tweak update-index --index-info <input && | |
465 | ||
466 | git -C tweak sparse-checkout init --cone 2>err && | |
467 | test_i18ngrep "warning.*The following paths are not up to date" err && | |
468 | test_i18ngrep "warning.*The following paths are unmerged" err && | |
469 | ||
470 | git -C tweak sparse-checkout set folder2 deep/deeper1 2>err && | |
471 | test_i18ngrep "warning.*The following paths are not up to date" err && | |
472 | test_i18ngrep "warning.*The following paths are unmerged" err && | |
473 | ||
474 | git -C tweak sparse-checkout reapply 2>err && | |
475 | test_i18ngrep "warning.*The following paths are not up to date" err && | |
476 | test_path_is_file tweak/deep/deeper2/a && | |
477 | test_i18ngrep "warning.*The following paths are unmerged" err && | |
478 | test_path_is_file tweak/folder1/a && | |
479 | ||
480 | git -C tweak checkout HEAD deep/deeper2/a && | |
481 | git -C tweak sparse-checkout reapply 2>err && | |
482 | test_i18ngrep ! "warning.*The following paths are not up to date" err && | |
483 | test_path_is_missing tweak/deep/deeper2/a && | |
484 | test_i18ngrep "warning.*The following paths are unmerged" err && | |
485 | test_path_is_file tweak/folder1/a && | |
486 | ||
49fdd51a DS |
487 | # NEEDSWORK: We are asking to update a file outside of the |
488 | # sparse-checkout cone, but this is no longer allowed. | |
5644ca28 EN |
489 | git -C tweak add folder1/a && |
490 | git -C tweak sparse-checkout reapply 2>err && | |
491 | test_must_be_empty err && | |
492 | test_path_is_missing tweak/deep/deeper2/a && | |
493 | test_path_is_missing tweak/folder1/a && | |
494 | ||
495 | git -C tweak sparse-checkout disable | |
496 | ' | |
497 | ||
190a65f9 | 498 | test_expect_success 'cone mode: set with core.ignoreCase=true' ' |
72064ee5 | 499 | rm repo/.git/info/sparse-checkout && |
190a65f9 DS |
500 | git -C repo sparse-checkout init --cone && |
501 | git -C repo -c core.ignoreCase=true sparse-checkout set folder1 && | |
d622c343 DS |
502 | cat >expect <<-\EOF && |
503 | /* | |
504 | !/*/ | |
505 | /folder1/ | |
190a65f9 DS |
506 | EOF |
507 | test_cmp expect repo/.git/info/sparse-checkout && | |
522e6417 | 508 | check_files repo a folder1 |
190a65f9 DS |
509 | ' |
510 | ||
4fd683b6 DS |
511 | test_expect_success 'interaction with submodules' ' |
512 | git clone repo super && | |
513 | ( | |
514 | cd super && | |
515 | mkdir modules && | |
516 | git submodule add ../repo modules/child && | |
517 | git add . && | |
518 | git commit -m "add submodule" && | |
519 | git sparse-checkout init --cone && | |
520 | git sparse-checkout set folder1 | |
521 | ) && | |
522e6417 DS |
522 | check_files super a folder1 modules && |
523 | check_files super/modules/child a deep folder1 folder2 | |
4fd683b6 DS |
524 | ' |
525 | ||
3c754067 DS |
526 | test_expect_success 'different sparse-checkouts with worktrees' ' |
527 | git -C repo worktree add --detach ../worktree && | |
528 | check_files worktree "a deep folder1 folder2" && | |
529 | git -C worktree sparse-checkout init --cone && | |
530 | git -C repo sparse-checkout set folder1 && | |
531 | git -C worktree sparse-checkout set deep/deeper1 && | |
532 | check_files repo a folder1 && | |
533 | check_files worktree a deep | |
534 | ' | |
535 | ||
f998a3f1 DS |
536 | test_expect_success 'set using filename keeps file on-disk' ' |
537 | git -C repo sparse-checkout set a deep && | |
538 | cat >expect <<-\EOF && | |
539 | /* | |
540 | !/*/ | |
541 | /a/ | |
542 | /deep/ | |
543 | EOF | |
544 | test_cmp expect repo/.git/info/sparse-checkout && | |
545 | check_files repo a deep | |
546 | ' | |
547 | ||
41de0c6f DS |
548 | check_read_tree_errors () { |
549 | REPO=$1 | |
550 | FILES=$2 | |
551 | ERRORS=$3 | |
d585f0e7 DS |
552 | git -C $REPO -c core.sparseCheckoutCone=false read-tree -mu HEAD 2>err && |
553 | test_must_be_empty err && | |
554 | check_files $REPO "$FILES" && | |
41de0c6f DS |
555 | git -C $REPO read-tree -mu HEAD 2>err && |
556 | if test -z "$ERRORS" | |
557 | then | |
558 | test_must_be_empty err | |
559 | else | |
560 | test_i18ngrep "$ERRORS" err | |
561 | fi && | |
562 | check_files $REPO $FILES | |
563 | } | |
564 | ||
565 | test_expect_success 'pattern-checks: /A/**' ' | |
566 | cat >repo/.git/info/sparse-checkout <<-\EOF && | |
567 | /* | |
568 | !/*/ | |
569 | /folder1/** | |
570 | EOF | |
571 | check_read_tree_errors repo "a folder1" "disabling cone pattern matching" | |
572 | ' | |
573 | ||
574 | test_expect_success 'pattern-checks: /A/**/B/' ' | |
575 | cat >repo/.git/info/sparse-checkout <<-\EOF && | |
576 | /* | |
577 | !/*/ | |
578 | /deep/**/deepest | |
579 | EOF | |
580 | check_read_tree_errors repo "a deep" "disabling cone pattern matching" && | |
581 | check_files repo/deep "deeper1" && | |
582 | check_files repo/deep/deeper1 "deepest" | |
583 | ' | |
584 | ||
9e6d3e64 DS |
585 | test_expect_success 'pattern-checks: too short' ' |
586 | cat >repo/.git/info/sparse-checkout <<-\EOF && | |
587 | /* | |
588 | !/*/ | |
6c11c6a1 | 589 | / |
9e6d3e64 DS |
590 | EOF |
591 | check_read_tree_errors repo "a" "disabling cone pattern matching" | |
592 | ' | |
6c11c6a1 DS |
593 | test_expect_success 'pattern-checks: not too short' ' |
594 | cat >repo/.git/info/sparse-checkout <<-\EOF && | |
595 | /* | |
596 | !/*/ | |
597 | /b/ | |
598 | EOF | |
599 | git -C repo read-tree -mu HEAD 2>err && | |
600 | test_must_be_empty err && | |
601 | check_files repo a | |
602 | ' | |
9e6d3e64 | 603 | |
9abc60f8 DS |
604 | test_expect_success 'pattern-checks: trailing "*"' ' |
605 | cat >repo/.git/info/sparse-checkout <<-\EOF && | |
606 | /* | |
607 | !/*/ | |
608 | /a* | |
609 | EOF | |
610 | check_read_tree_errors repo "a" "disabling cone pattern matching" | |
611 | ' | |
612 | ||
613 | test_expect_success 'pattern-checks: starting "*"' ' | |
614 | cat >repo/.git/info/sparse-checkout <<-\EOF && | |
615 | /* | |
616 | !/*/ | |
617 | *eep/ | |
618 | EOF | |
619 | check_read_tree_errors repo "a deep" "disabling cone pattern matching" | |
620 | ' | |
621 | ||
622 | test_expect_success 'pattern-checks: contained glob characters' ' | |
623 | for c in "[a]" "\\" "?" "*" | |
624 | do | |
625 | cat >repo/.git/info/sparse-checkout <<-EOF && | |
626 | /* | |
627 | !/*/ | |
628 | something$c-else/ | |
629 | EOF | |
db5875aa | 630 | check_read_tree_errors repo "a" "disabling cone pattern matching" || return 1 |
9abc60f8 DS |
631 | done |
632 | ' | |
633 | ||
e53ffe27 | 634 | test_expect_success BSLASHPSPEC 'pattern-checks: escaped characters' ' |
4f52c2ce DS |
635 | git clone repo escaped && |
636 | TREEOID=$(git -C escaped rev-parse HEAD:folder1) && | |
637 | NEWTREE=$(git -C escaped mktree <<-EOF | |
638 | $(git -C escaped ls-tree HEAD) | |
639 | 040000 tree $TREEOID zbad\\dir | |
640 | 040000 tree $TREEOID zdoes*exist | |
e53ffe27 | 641 | 040000 tree $TREEOID zglob[!a]? |
4f52c2ce DS |
642 | EOF |
643 | ) && | |
644 | COMMIT=$(git -C escaped commit-tree $NEWTREE -p HEAD) && | |
645 | git -C escaped reset --hard $COMMIT && | |
e53ffe27 | 646 | check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist" zglob[!a]? && |
4f52c2ce | 647 | git -C escaped sparse-checkout init --cone && |
e53ffe27 | 648 | git -C escaped sparse-checkout set zbad\\dir/bogus "zdoes*not*exist" "zdoes*exist" "zglob[!a]?" && |
d585f0e7 | 649 | cat >expect <<-\EOF && |
9abc60f8 DS |
650 | /* |
651 | !/*/ | |
4f52c2ce DS |
652 | /zbad\\dir/ |
653 | !/zbad\\dir/*/ | |
d585f0e7 | 654 | /zbad\\dir/bogus/ |
4f52c2ce | 655 | /zdoes\*exist/ |
d585f0e7 | 656 | /zdoes\*not\*exist/ |
e53ffe27 | 657 | /zglob\[!a]\?/ |
9abc60f8 | 658 | EOF |
d585f0e7 | 659 | test_cmp expect escaped/.git/info/sparse-checkout && |
e53ffe27 | 660 | check_read_tree_errors escaped "a zbad\\dir zdoes*exist zglob[!a]?" && |
e55682ea DS |
661 | git -C escaped ls-tree -d --name-only HEAD >list-expect && |
662 | git -C escaped sparse-checkout set --stdin <list-expect && | |
bd64de42 DS |
663 | cat >expect <<-\EOF && |
664 | /* | |
665 | !/*/ | |
666 | /deep/ | |
667 | /folder1/ | |
668 | /folder2/ | |
669 | /zbad\\dir/ | |
670 | /zdoes\*exist/ | |
e53ffe27 | 671 | /zglob\[!a]\?/ |
bd64de42 DS |
672 | EOF |
673 | test_cmp expect escaped/.git/info/sparse-checkout && | |
e53ffe27 | 674 | check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist" zglob[!a]? && |
e55682ea DS |
675 | git -C escaped sparse-checkout list >list-actual && |
676 | test_cmp list-expect list-actual | |
9abc60f8 DS |
677 | ' |
678 | ||
ef076599 DS |
679 | test_expect_success MINGW 'cone mode replaces backslashes with slashes' ' |
680 | git -C repo sparse-checkout set deep\\deeper1 && | |
681 | cat >expect <<-\EOF && | |
682 | /* | |
683 | !/*/ | |
684 | /deep/ | |
685 | !/deep/*/ | |
686 | /deep/deeper1/ | |
687 | EOF | |
688 | test_cmp expect repo/.git/info/sparse-checkout && | |
689 | check_files repo a deep && | |
690 | check_files repo/deep a deeper1 | |
691 | ' | |
692 | ||
55dfcf95 DS |
693 | test_expect_success 'cone mode clears ignored subdirectories' ' |
694 | rm repo/.git/info/sparse-checkout && | |
695 | ||
696 | git -C repo sparse-checkout init --cone && | |
697 | git -C repo sparse-checkout set deep/deeper1 && | |
698 | ||
699 | cat >repo/.gitignore <<-\EOF && | |
700 | obj/ | |
701 | *.o | |
702 | EOF | |
703 | ||
704 | git -C repo add .gitignore && | |
705 | git -C repo commit -m ".gitignore" && | |
706 | ||
707 | mkdir -p repo/obj repo/folder1/obj repo/deep/deeper2/obj && | |
708 | for file in folder1/obj/a obj/a folder1/file.o folder1.o \ | |
709 | deep/deeper2/obj/a deep/deeper2/file.o file.o | |
710 | do | |
711 | echo ignored >repo/$file || return 1 | |
712 | done && | |
713 | ||
714 | git -C repo status --porcelain=v2 >out && | |
715 | test_must_be_empty out && | |
716 | ||
717 | git -C repo sparse-checkout reapply && | |
718 | test_path_is_missing repo/folder1 && | |
719 | test_path_is_missing repo/deep/deeper2 && | |
720 | test_path_is_dir repo/obj && | |
721 | test_path_is_file repo/file.o && | |
722 | ||
723 | git -C repo status --porcelain=v2 >out && | |
724 | test_must_be_empty out && | |
725 | ||
726 | git -C repo sparse-checkout set deep/deeper2 && | |
727 | test_path_is_missing repo/deep/deeper1 && | |
728 | test_path_is_dir repo/deep/deeper2 && | |
729 | test_path_is_dir repo/obj && | |
730 | test_path_is_file repo/file.o && | |
731 | ||
732 | >repo/deep/deeper2/ignored.o && | |
733 | >repo/deep/deeper2/untracked && | |
734 | ||
735 | # When an untracked file is in the way, all untracked files | |
736 | # (even ignored files) are preserved. | |
737 | git -C repo sparse-checkout set folder1 2>err && | |
738 | grep "contains untracked files" err && | |
739 | test_path_is_file repo/deep/deeper2/ignored.o && | |
740 | test_path_is_file repo/deep/deeper2/untracked && | |
741 | ||
742 | # The rest of the cone matches expectation | |
743 | test_path_is_missing repo/deep/deeper1 && | |
744 | test_path_is_dir repo/obj && | |
745 | test_path_is_file repo/file.o && | |
746 | ||
747 | git -C repo status --porcelain=v2 >out && | |
748 | echo "? deep/deeper2/untracked" >expect && | |
749 | test_cmp expect out | |
750 | ' | |
751 | ||
a481d437 DS |
752 | test_expect_success 'malformed cone-mode patterns' ' |
753 | git -C repo sparse-checkout init --cone && | |
754 | mkdir -p repo/foo/bar && | |
755 | touch repo/foo/bar/x repo/foo/y && | |
756 | cat >repo/.git/info/sparse-checkout <<-\EOF && | |
757 | /* | |
758 | !/*/ | |
759 | /foo/ | |
760 | !/foo/*/ | |
761 | /foo/\*/ | |
762 | EOF | |
763 | ||
764 | # Listing the patterns will notice the duplicate pattern and | |
765 | # emit a warning. It will list the patterns directly instead | |
766 | # of using the cone-mode translation to a set of directories. | |
767 | git -C repo sparse-checkout list >actual 2>err && | |
768 | test_cmp repo/.git/info/sparse-checkout actual && | |
769 | grep "warning: your sparse-checkout file may have issues: pattern .* is repeated" err && | |
770 | grep "warning: disabling cone pattern matching" err | |
771 | ' | |
772 | ||
94c0956b | 773 | test_done |