3 test_description='sparse checkout builtin tests'
8 # Do not replace this with 'ls "$1"', as "ls" with BSD-lineage
9 # enables "-A" by default for root and ends up including ".git" and
10 # such in its output. (Note, though, that running the test suite as
11 # root is generally not recommended.)
12 (cd "$1" && printf '%s\n' *)
16 list_files "$1" >actual &&
18 printf "%s\n" $@ >expect &&
19 test_cmp expect actual
22 test_expect_success 'setup' '
27 mkdir folder1 folder2 deep &&
28 mkdir deep/deeper1 deep/deeper2 &&
29 mkdir deep/deeper1/deepest &&
35 cp a deep/deeper1/deepest &&
37 git commit -m "initial commit"
41 test_expect_success 'git sparse-checkout list (empty)' '
42 git -C repo sparse-checkout list >list 2>err &&
43 test_must_be_empty list &&
44 test_i18ngrep "this worktree is not sparse (sparse-checkout file may not exist)" err
47 test_expect_success 'git sparse-checkout list (populated)' '
48 test_when_finished rm -f repo/.git/info/sparse-checkout &&
49 cat >repo/.git/info/sparse-checkout <<-\EOF &&
55 cp repo/.git/info/sparse-checkout expect &&
56 git -C repo sparse-checkout list >list &&
60 test_expect_success 'git sparse-checkout init' '
61 git -C repo sparse-checkout init &&
62 cat >expect <<-\EOF &&
66 test_cmp expect repo/.git/info/sparse-checkout &&
67 test_cmp_config -C repo true core.sparsecheckout &&
71 test_expect_success 'git sparse-checkout list after init' '
72 git -C repo sparse-checkout list >actual &&
73 cat >expect <<-\EOF &&
77 test_cmp expect actual
80 test_expect_success 'init with existing sparse-checkout' '
81 echo "*folder*" >> repo/.git/info/sparse-checkout &&
82 git -C repo sparse-checkout init &&
83 cat >expect <<-\EOF &&
88 test_cmp expect repo/.git/info/sparse-checkout &&
89 check_files repo a folder1 folder2
92 test_expect_success 'clone --sparse' '
93 git clone --sparse "file://$(pwd)/repo" clone &&
94 git -C clone sparse-checkout list >actual &&
95 cat >expect <<-\EOF &&
99 test_cmp expect actual &&
103 test_expect_success 'set enables config' '
104 git init empty-config &&
107 test_commit test file &&
108 test_path_is_missing .git/config.worktree &&
109 test_must_fail git sparse-checkout set nothing &&
110 test_path_is_file .git/config.worktree &&
111 test_must_fail git config core.sparseCheckout &&
112 git sparse-checkout set "/*" &&
113 test_cmp_config true core.sparseCheckout
117 test_expect_success 'set sparse-checkout using builtin' '
118 git -C repo sparse-checkout set "/*" "!/*/" "*folder*" &&
119 cat >expect <<-\EOF &&
124 git -C repo sparse-checkout list >actual &&
125 test_cmp expect actual &&
126 test_cmp expect repo/.git/info/sparse-checkout &&
127 check_files repo a folder1 folder2
130 test_expect_success 'set sparse-checkout using --stdin' '
131 cat >expect <<-\EOF &&
137 git -C repo sparse-checkout set --stdin <expect &&
138 git -C repo sparse-checkout list >actual &&
139 test_cmp expect actual &&
140 test_cmp expect repo/.git/info/sparse-checkout &&
141 check_files repo "a folder1 folder2"
144 test_expect_success 'cone mode: match patterns' '
145 git -C repo config --worktree core.sparseCheckoutCone true &&
146 rm -rf repo/a repo/folder1 repo/folder2 &&
147 git -C repo read-tree -mu HEAD 2>err &&
148 test_i18ngrep ! "disabling cone patterns" err &&
149 git -C repo reset --hard &&
150 check_files repo a folder1 folder2
153 test_expect_success 'cone mode: warn on bad pattern' '
154 test_when_finished mv sparse-checkout repo/.git/info/ &&
155 cp repo/.git/info/sparse-checkout . &&
156 echo "!/deep/deeper/*" >>repo/.git/info/sparse-checkout &&
157 git -C repo read-tree -mu HEAD 2>err &&
158 test_i18ngrep "unrecognized negative pattern" err
161 test_expect_success 'sparse-checkout disable' '
162 test_when_finished rm -rf repo/.git/info/sparse-checkout &&
163 git -C repo sparse-checkout disable &&
164 test_path_is_file repo/.git/info/sparse-checkout &&
165 git -C repo config --list >config &&
166 test_must_fail git config core.sparseCheckout &&
167 check_files repo a deep folder1 folder2
170 test_expect_success 'cone mode: init and set' '
171 git -C repo sparse-checkout init --cone &&
172 git -C repo config --list >config &&
173 test_i18ngrep "core.sparsecheckoutcone=true" config &&
174 list_files repo >dir &&
176 test_cmp expect dir &&
177 git -C repo sparse-checkout set deep/deeper1/deepest/ 2>err &&
178 test_must_be_empty err &&
179 check_files repo a deep &&
180 check_files repo/deep a deeper1 &&
181 check_files repo/deep/deeper1 a deepest &&
182 cat >expect <<-\EOF &&
189 /deep/deeper1/deepest/
191 test_cmp expect repo/.git/info/sparse-checkout &&
192 git -C repo sparse-checkout set --stdin 2>err <<-\EOF &&
196 test_must_be_empty err &&
197 check_files repo a folder1 folder2
200 test_expect_success 'cone mode: list' '
201 cat >expect <<-\EOF &&
205 git -C repo sparse-checkout set --stdin <expect &&
206 git -C repo sparse-checkout list >actual 2>err &&
207 test_must_be_empty err &&
208 test_cmp expect actual
211 test_expect_success 'cone mode: set with nested folders' '
212 git -C repo sparse-checkout set deep deep/deeper1/deepest 2>err &&
213 test_line_count = 0 err &&
214 cat >expect <<-\EOF &&
219 test_cmp repo/.git/info/sparse-checkout expect
222 test_expect_success 'revert to old sparse-checkout on bad update' '
223 test_when_finished git -C repo reset --hard &&
224 echo update >repo/deep/deeper2/a &&
225 cp repo/.git/info/sparse-checkout expect &&
226 test_must_fail git -C repo sparse-checkout set deep/deeper1 2>err &&
227 test_i18ngrep "cannot set sparse-checkout patterns" err &&
228 test_cmp repo/.git/info/sparse-checkout expect &&
229 check_files repo/deep a deeper1 deeper2
232 test_expect_success 'revert to old sparse-checkout on empty update' '
233 git init empty-test &&
237 git commit -m "test" &&
238 test_must_fail git sparse-checkout set nothing 2>err &&
239 test_i18ngrep "Sparse checkout leaves no entry on working directory" err &&
240 test_i18ngrep ! ".git/index.lock" err &&
241 git sparse-checkout set file
245 test_expect_success 'fail when lock is taken' '
246 test_when_finished rm -rf repo/.git/info/sparse-checkout.lock &&
247 touch repo/.git/info/sparse-checkout.lock &&
248 test_must_fail git -C repo sparse-checkout set deep 2>err &&
249 test_i18ngrep "File exists" err
252 test_expect_success '.gitignore should not warn about cone mode' '
253 git -C repo config --worktree core.sparseCheckoutCone true &&
254 echo "**/bin/*" >repo/.gitignore &&
255 git -C repo reset --hard 2>err &&
256 test_i18ngrep ! "disabling cone patterns" err
259 test_expect_success 'sparse-checkout (init|set|disable) fails with dirty status' '
260 git clone repo dirty &&
261 echo dirty >dirty/folder1/a &&
262 test_must_fail git -C dirty sparse-checkout init &&
263 test_must_fail git -C dirty sparse-checkout set /folder2/* /deep/deeper1/* &&
264 test_must_fail git -C dirty sparse-checkout disable &&
265 git -C dirty reset --hard &&
266 git -C dirty sparse-checkout init &&
267 git -C dirty sparse-checkout set /folder2/* /deep/deeper1/* &&
268 git -C dirty sparse-checkout disable
271 test_expect_success 'cone mode: set with core.ignoreCase=true' '
272 git -C repo sparse-checkout init --cone &&
273 git -C repo -c core.ignoreCase=true sparse-checkout set folder1 &&
274 cat >expect <<-\EOF &&
279 test_cmp expect repo/.git/info/sparse-checkout &&
280 check_files repo a folder1
283 test_expect_success 'interaction with submodules' '
284 git clone repo super &&
288 git submodule add ../repo modules/child &&
290 git commit -m "add submodule" &&
291 git sparse-checkout init --cone &&
292 git sparse-checkout set folder1
294 check_files super a folder1 modules &&
295 check_files super/modules/child a deep folder1 folder2
298 test_expect_success 'different sparse-checkouts with worktrees' '
299 git -C repo worktree add --detach ../worktree &&
300 check_files worktree "a deep folder1 folder2" &&
301 git -C worktree sparse-checkout init --cone &&
302 git -C repo sparse-checkout set folder1 &&
303 git -C worktree sparse-checkout set deep/deeper1 &&
304 check_files repo a folder1 &&
305 check_files worktree a deep
308 test_expect_success 'set using filename keeps file on-disk' '
309 git -C repo sparse-checkout set a deep &&
310 cat >expect <<-\EOF &&
316 test_cmp expect repo/.git/info/sparse-checkout &&
317 check_files repo a deep
320 check_read_tree_errors () {
324 git -C $REPO -c core.sparseCheckoutCone=false read-tree -mu HEAD 2>err &&
325 test_must_be_empty err &&
326 check_files $REPO "$FILES" &&
327 git -C $REPO read-tree -mu HEAD 2>err &&
330 test_must_be_empty err
332 test_i18ngrep "$ERRORS" err
334 check_files $REPO $FILES
337 test_expect_success 'pattern-checks: /A/**' '
338 cat >repo/.git/info/sparse-checkout <<-\EOF &&
343 check_read_tree_errors repo "a folder1" "disabling cone pattern matching"
346 test_expect_success 'pattern-checks: /A/**/B/' '
347 cat >repo/.git/info/sparse-checkout <<-\EOF &&
352 check_read_tree_errors repo "a deep" "disabling cone pattern matching" &&
353 check_files repo/deep "deeper1" &&
354 check_files repo/deep/deeper1 "deepest"
357 test_expect_success 'pattern-checks: too short' '
358 cat >repo/.git/info/sparse-checkout <<-\EOF &&
363 check_read_tree_errors repo "a" "disabling cone pattern matching"
366 test_expect_success 'pattern-checks: trailing "*"' '
367 cat >repo/.git/info/sparse-checkout <<-\EOF &&
372 check_read_tree_errors repo "a" "disabling cone pattern matching"
375 test_expect_success 'pattern-checks: starting "*"' '
376 cat >repo/.git/info/sparse-checkout <<-\EOF &&
381 check_read_tree_errors repo "a deep" "disabling cone pattern matching"
384 test_expect_success 'pattern-checks: contained glob characters' '
385 for c in "[a]" "\\" "?" "*"
387 cat >repo/.git/info/sparse-checkout <<-EOF &&
392 check_read_tree_errors repo "a" "disabling cone pattern matching"
396 test_expect_success BSLASHPSPEC 'pattern-checks: escaped characters' '
397 git clone repo escaped &&
398 TREEOID=$(git -C escaped rev-parse HEAD:folder1) &&
399 NEWTREE=$(git -C escaped mktree <<-EOF
400 $(git -C escaped ls-tree HEAD)
401 040000 tree $TREEOID zbad\\dir
402 040000 tree $TREEOID zdoes*exist
403 040000 tree $TREEOID zglob[!a]?
406 COMMIT=$(git -C escaped commit-tree $NEWTREE -p HEAD) &&
407 git -C escaped reset --hard $COMMIT &&
408 check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist" zglob[!a]? &&
409 git -C escaped sparse-checkout init --cone &&
410 git -C escaped sparse-checkout set zbad\\dir/bogus "zdoes*not*exist" "zdoes*exist" "zglob[!a]?" &&
411 cat >expect <<-\EOF &&
421 test_cmp expect escaped/.git/info/sparse-checkout &&
422 check_read_tree_errors escaped "a zbad\\dir zdoes*exist zglob[!a]?" &&
423 git -C escaped ls-tree -d --name-only HEAD >list-expect &&
424 git -C escaped sparse-checkout set --stdin <list-expect &&
425 cat >expect <<-\EOF &&
435 test_cmp expect escaped/.git/info/sparse-checkout &&
436 check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist" zglob[!a]? &&
437 git -C escaped sparse-checkout list >list-actual &&
438 test_cmp list-expect list-actual