index-pack: make quantum of work smaller
[git] / t / t7300-clean.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2007 Michael Spang
4 #
5
6 test_description='git clean basic tests'
7
8 . ./test-lib.sh
9
10 git config clean.requireForce no
11
12 test_expect_success 'setup' '
13
14         mkdir -p src &&
15         touch src/part1.c Makefile &&
16         echo build >.gitignore &&
17         echo \*.o >>.gitignore &&
18         git add . &&
19         git commit -m setup &&
20         touch src/part2.c README &&
21         git add .
22
23 '
24
25 test_expect_success 'git clean with skip-worktree .gitignore' '
26         git update-index --skip-worktree .gitignore &&
27         rm .gitignore &&
28         mkdir -p build docs &&
29         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
30         git clean &&
31         test -f Makefile &&
32         test -f README &&
33         test -f src/part1.c &&
34         test -f src/part2.c &&
35         test ! -f a.out &&
36         test ! -f src/part3.c &&
37         test -f docs/manual.txt &&
38         test -f obj.o &&
39         test -f build/lib.so &&
40         git update-index --no-skip-worktree .gitignore &&
41         git checkout .gitignore
42 '
43
44 test_expect_success 'git clean' '
45
46         mkdir -p build docs &&
47         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
48         git clean &&
49         test -f Makefile &&
50         test -f README &&
51         test -f src/part1.c &&
52         test -f src/part2.c &&
53         test ! -f a.out &&
54         test ! -f src/part3.c &&
55         test -f docs/manual.txt &&
56         test -f obj.o &&
57         test -f build/lib.so
58
59 '
60
61 test_expect_success 'git clean src/' '
62
63         mkdir -p build docs &&
64         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
65         git clean src/ &&
66         test -f Makefile &&
67         test -f README &&
68         test -f src/part1.c &&
69         test -f src/part2.c &&
70         test -f a.out &&
71         test ! -f src/part3.c &&
72         test -f docs/manual.txt &&
73         test -f obj.o &&
74         test -f build/lib.so
75
76 '
77
78 test_expect_success 'git clean src/ src/' '
79
80         mkdir -p build docs &&
81         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
82         git clean src/ src/ &&
83         test -f Makefile &&
84         test -f README &&
85         test -f src/part1.c &&
86         test -f src/part2.c &&
87         test -f a.out &&
88         test ! -f src/part3.c &&
89         test -f docs/manual.txt &&
90         test -f obj.o &&
91         test -f build/lib.so
92
93 '
94
95 test_expect_success 'git clean with prefix' '
96
97         mkdir -p build docs src/test &&
98         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so src/test/1.c &&
99         (cd src/ && git clean) &&
100         test -f Makefile &&
101         test -f README &&
102         test -f src/part1.c &&
103         test -f src/part2.c &&
104         test -f a.out &&
105         test ! -f src/part3.c &&
106         test -f src/test/1.c &&
107         test -f docs/manual.txt &&
108         test -f obj.o &&
109         test -f build/lib.so
110
111 '
112
113 test_expect_success C_LOCALE_OUTPUT 'git clean with relative prefix' '
114
115         mkdir -p build docs &&
116         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
117         would_clean=$(
118                 cd docs &&
119                 git clean -n ../src |
120                 grep part3 |
121                 sed -n -e "s|^Would remove ||p"
122         ) &&
123         verbose test "$would_clean" = ../src/part3.c
124 '
125
126 test_expect_success C_LOCALE_OUTPUT 'git clean with absolute path' '
127
128         mkdir -p build docs &&
129         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
130         would_clean=$(
131                 cd docs &&
132                 git clean -n "$(pwd)/../src" |
133                 grep part3 |
134                 sed -n -e "s|^Would remove ||p"
135         ) &&
136         verbose test "$would_clean" = ../src/part3.c
137 '
138
139 test_expect_success 'git clean with out of work tree relative path' '
140
141         mkdir -p build docs &&
142         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
143         (
144                 cd docs &&
145                 test_must_fail git clean -n ../..
146         )
147 '
148
149 test_expect_success 'git clean with out of work tree absolute path' '
150
151         mkdir -p build docs &&
152         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
153         dd=$(cd .. && pwd) &&
154         (
155                 cd docs &&
156                 test_must_fail git clean -n $dd
157         )
158 '
159
160 test_expect_success 'git clean -d with prefix and path' '
161
162         mkdir -p build docs src/feature &&
163         touch a.out src/part3.c src/feature/file.c docs/manual.txt obj.o build/lib.so &&
164         (cd src/ && git clean -d feature/) &&
165         test -f Makefile &&
166         test -f README &&
167         test -f src/part1.c &&
168         test -f src/part2.c &&
169         test -f a.out &&
170         test -f src/part3.c &&
171         test ! -f src/feature/file.c &&
172         test -f docs/manual.txt &&
173         test -f obj.o &&
174         test -f build/lib.so
175
176 '
177
178 test_expect_success SYMLINKS 'git clean symbolic link' '
179
180         mkdir -p build docs &&
181         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
182         ln -s docs/manual.txt src/part4.c &&
183         git clean &&
184         test -f Makefile &&
185         test -f README &&
186         test -f src/part1.c &&
187         test -f src/part2.c &&
188         test ! -f a.out &&
189         test ! -f src/part3.c &&
190         test ! -f src/part4.c &&
191         test -f docs/manual.txt &&
192         test -f obj.o &&
193         test -f build/lib.so
194
195 '
196
197 test_expect_success 'git clean with wildcard' '
198
199         touch a.clean b.clean other.c &&
200         git clean "*.clean" &&
201         test -f Makefile &&
202         test -f README &&
203         test -f src/part1.c &&
204         test -f src/part2.c &&
205         test ! -f a.clean &&
206         test ! -f b.clean &&
207         test -f other.c
208
209 '
210
211 test_expect_success 'git clean -n' '
212
213         mkdir -p build docs &&
214         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
215         git clean -n &&
216         test -f Makefile &&
217         test -f README &&
218         test -f src/part1.c &&
219         test -f src/part2.c &&
220         test -f a.out &&
221         test -f src/part3.c &&
222         test -f docs/manual.txt &&
223         test -f obj.o &&
224         test -f build/lib.so
225
226 '
227
228 test_expect_success 'git clean -d' '
229
230         mkdir -p build docs &&
231         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
232         git clean -d &&
233         test -f Makefile &&
234         test -f README &&
235         test -f src/part1.c &&
236         test -f src/part2.c &&
237         test ! -f a.out &&
238         test ! -f src/part3.c &&
239         test ! -d docs &&
240         test -f obj.o &&
241         test -f build/lib.so
242
243 '
244
245 test_expect_success 'git clean -d src/ examples/' '
246
247         mkdir -p build docs examples &&
248         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so examples/1.c &&
249         git clean -d src/ examples/ &&
250         test -f Makefile &&
251         test -f README &&
252         test -f src/part1.c &&
253         test -f src/part2.c &&
254         test -f a.out &&
255         test ! -f src/part3.c &&
256         test ! -f examples/1.c &&
257         test -f docs/manual.txt &&
258         test -f obj.o &&
259         test -f build/lib.so
260
261 '
262
263 test_expect_success 'git clean -x' '
264
265         mkdir -p build docs &&
266         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
267         git clean -x &&
268         test -f Makefile &&
269         test -f README &&
270         test -f src/part1.c &&
271         test -f src/part2.c &&
272         test ! -f a.out &&
273         test ! -f src/part3.c &&
274         test -f docs/manual.txt &&
275         test ! -f obj.o &&
276         test -f build/lib.so
277
278 '
279
280 test_expect_success 'git clean -d -x' '
281
282         mkdir -p build docs &&
283         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
284         git clean -d -x &&
285         test -f Makefile &&
286         test -f README &&
287         test -f src/part1.c &&
288         test -f src/part2.c &&
289         test ! -f a.out &&
290         test ! -f src/part3.c &&
291         test ! -d docs &&
292         test ! -f obj.o &&
293         test ! -d build
294
295 '
296
297 test_expect_success 'git clean -d -x with ignored tracked directory' '
298
299         mkdir -p build docs &&
300         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
301         git clean -d -x -e src &&
302         test -f Makefile &&
303         test -f README &&
304         test -f src/part1.c &&
305         test -f src/part2.c &&
306         test ! -f a.out &&
307         test -f src/part3.c &&
308         test ! -d docs &&
309         test ! -f obj.o &&
310         test ! -d build
311
312 '
313
314 test_expect_success 'git clean -X' '
315
316         mkdir -p build docs &&
317         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
318         git clean -X &&
319         test -f Makefile &&
320         test -f README &&
321         test -f src/part1.c &&
322         test -f src/part2.c &&
323         test -f a.out &&
324         test -f src/part3.c &&
325         test -f docs/manual.txt &&
326         test ! -f obj.o &&
327         test -f build/lib.so
328
329 '
330
331 test_expect_success 'git clean -d -X' '
332
333         mkdir -p build docs &&
334         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
335         git clean -d -X &&
336         test -f Makefile &&
337         test -f README &&
338         test -f src/part1.c &&
339         test -f src/part2.c &&
340         test -f a.out &&
341         test -f src/part3.c &&
342         test -f docs/manual.txt &&
343         test ! -f obj.o &&
344         test ! -d build
345
346 '
347
348 test_expect_success 'git clean -d -X with ignored tracked directory' '
349
350         mkdir -p build docs &&
351         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
352         git clean -d -X -e src &&
353         test -f Makefile &&
354         test -f README &&
355         test -f src/part1.c &&
356         test -f src/part2.c &&
357         test -f a.out &&
358         test ! -f src/part3.c &&
359         test -f docs/manual.txt &&
360         test ! -f obj.o &&
361         test ! -d build
362
363 '
364
365 test_expect_success 'clean.requireForce defaults to true' '
366
367         git config --unset clean.requireForce &&
368         test_must_fail git clean
369
370 '
371
372 test_expect_success 'clean.requireForce' '
373
374         git config clean.requireForce true &&
375         test_must_fail git clean
376
377 '
378
379 test_expect_success 'clean.requireForce and -n' '
380
381         mkdir -p build docs &&
382         touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
383         git clean -n &&
384         test -f Makefile &&
385         test -f README &&
386         test -f src/part1.c &&
387         test -f src/part2.c &&
388         test -f a.out &&
389         test -f src/part3.c &&
390         test -f docs/manual.txt &&
391         test -f obj.o &&
392         test -f build/lib.so
393
394 '
395
396 test_expect_success 'clean.requireForce and -f' '
397
398         git clean -f &&
399         test -f README &&
400         test -f src/part1.c &&
401         test -f src/part2.c &&
402         test ! -f a.out &&
403         test ! -f src/part3.c &&
404         test -f docs/manual.txt &&
405         test -f obj.o &&
406         test -f build/lib.so
407
408 '
409
410 test_expect_success C_LOCALE_OUTPUT 'core.excludesfile' '
411
412         echo excludes >excludes &&
413         echo included >included &&
414         git config core.excludesfile excludes &&
415         output=$(git clean -n excludes included 2>&1) &&
416         expr "$output" : ".*included" >/dev/null &&
417         ! expr "$output" : ".*excludes" >/dev/null
418
419 '
420
421 test_expect_success SANITY 'removal failure' '
422
423         mkdir foo &&
424         touch foo/bar &&
425         test_when_finished "chmod 755 foo" &&
426         (exec <foo/bar &&
427          chmod 0 foo &&
428          test_must_fail git clean -f -d)
429 '
430
431 test_expect_success 'nested git work tree' '
432         rm -fr foo bar baz &&
433         mkdir -p foo bar baz/boo &&
434         (
435                 cd foo &&
436                 git init &&
437                 test_commit nested hello.world
438         ) &&
439         (
440                 cd bar &&
441                 >goodbye.people
442         ) &&
443         (
444                 cd baz/boo &&
445                 git init &&
446                 test_commit deeply.nested deeper.world
447         ) &&
448         git clean -f -d &&
449         test -f foo/.git/index &&
450         test -f foo/hello.world &&
451         test -f baz/boo/.git/index &&
452         test -f baz/boo/deeper.world &&
453         ! test -d bar
454 '
455
456 test_expect_success 'should clean things that almost look like git but are not' '
457         rm -fr almost_git almost_bare_git almost_submodule &&
458         mkdir -p almost_git/.git/objects &&
459         mkdir -p almost_git/.git/refs &&
460         cat >almost_git/.git/HEAD <<-\EOF &&
461         garbage
462         EOF
463         cp -r almost_git/.git/ almost_bare_git &&
464         mkdir almost_submodule/ &&
465         cat >almost_submodule/.git <<-\EOF &&
466         garbage
467         EOF
468         test_when_finished "rm -rf almost_*" &&
469         git clean -f -d &&
470         test_path_is_missing almost_git &&
471         test_path_is_missing almost_bare_git &&
472         test_path_is_missing almost_submodule
473 '
474
475 test_expect_success 'should not clean submodules' '
476         rm -fr repo to_clean sub1 sub2 &&
477         mkdir repo to_clean &&
478         (
479                 cd repo &&
480                 git init &&
481                 test_commit msg hello.world
482         ) &&
483         git submodule add ./repo/.git sub1 &&
484         git commit -m "sub1" &&
485         git branch before_sub2 &&
486         git submodule add ./repo/.git sub2 &&
487         git commit -m "sub2" &&
488         git checkout before_sub2 &&
489         >to_clean/should_clean.this &&
490         git clean -f -d &&
491         test_path_is_file repo/.git/index &&
492         test_path_is_file repo/hello.world &&
493         test_path_is_file sub1/.git &&
494         test_path_is_file sub1/hello.world &&
495         test_path_is_file sub2/.git &&
496         test_path_is_file sub2/hello.world &&
497         test_path_is_missing to_clean
498 '
499
500 test_expect_success POSIXPERM,SANITY 'should avoid cleaning possible submodules' '
501         rm -fr to_clean possible_sub1 &&
502         mkdir to_clean possible_sub1 &&
503         test_when_finished "rm -rf possible_sub*" &&
504         echo "gitdir: foo" >possible_sub1/.git &&
505         >possible_sub1/hello.world &&
506         chmod 0 possible_sub1/.git &&
507         >to_clean/should_clean.this &&
508         git clean -f -d &&
509         test_path_is_file possible_sub1/.git &&
510         test_path_is_file possible_sub1/hello.world &&
511         test_path_is_missing to_clean
512 '
513
514 test_expect_success 'nested (empty) git should be kept' '
515         rm -fr empty_repo to_clean &&
516         git init empty_repo &&
517         mkdir to_clean &&
518         >to_clean/should_clean.this &&
519         git clean -f -d &&
520         test_path_is_file empty_repo/.git/HEAD &&
521         test_path_is_missing to_clean
522 '
523
524 test_expect_success 'nested bare repositories should be cleaned' '
525         rm -fr bare1 bare2 subdir &&
526         git init --bare bare1 &&
527         git clone --local --bare . bare2 &&
528         mkdir subdir &&
529         cp -r bare2 subdir/bare3 &&
530         git clean -f -d &&
531         test_path_is_missing bare1 &&
532         test_path_is_missing bare2 &&
533         test_path_is_missing subdir
534 '
535
536 test_expect_failure 'nested (empty) bare repositories should be cleaned even when in .git' '
537         rm -fr strange_bare &&
538         mkdir strange_bare &&
539         git init --bare strange_bare/.git &&
540         git clean -f -d &&
541         test_path_is_missing strange_bare
542 '
543
544 test_expect_failure 'nested (non-empty) bare repositories should be cleaned even when in .git' '
545         rm -fr strange_bare &&
546         mkdir strange_bare &&
547         git clone --local --bare . strange_bare/.git &&
548         git clean -f -d &&
549         test_path_is_missing strange_bare
550 '
551
552 test_expect_success 'giving path in nested git work tree will NOT remove it' '
553         rm -fr repo &&
554         mkdir repo &&
555         (
556                 cd repo &&
557                 git init &&
558                 mkdir -p bar/baz &&
559                 test_commit msg bar/baz/hello.world
560         ) &&
561         git clean -f -d repo/bar/baz &&
562         test_path_is_file repo/.git/HEAD &&
563         test_path_is_dir repo/bar/ &&
564         test_path_is_file repo/bar/baz/hello.world
565 '
566
567 test_expect_success 'giving path to nested .git will not remove it' '
568         rm -fr repo &&
569         mkdir repo untracked &&
570         (
571                 cd repo &&
572                 git init &&
573                 test_commit msg hello.world
574         ) &&
575         git clean -f -d repo/.git &&
576         test_path_is_file repo/.git/HEAD &&
577         test_path_is_dir repo/.git/refs &&
578         test_path_is_dir repo/.git/objects &&
579         test_path_is_dir untracked/
580 '
581
582 test_expect_success 'giving path to nested .git/ will NOT remove contents' '
583         rm -fr repo untracked &&
584         mkdir repo untracked &&
585         (
586                 cd repo &&
587                 git init &&
588                 test_commit msg hello.world
589         ) &&
590         git clean -f -d repo/.git/ &&
591         test_path_is_dir repo/.git &&
592         test_path_is_file repo/.git/HEAD &&
593         test_path_is_dir untracked/
594 '
595
596 test_expect_success 'force removal of nested git work tree' '
597         rm -fr foo bar baz &&
598         mkdir -p foo bar baz/boo &&
599         (
600                 cd foo &&
601                 git init &&
602                 test_commit nested hello.world
603         ) &&
604         (
605                 cd bar &&
606                 >goodbye.people
607         ) &&
608         (
609                 cd baz/boo &&
610                 git init &&
611                 test_commit deeply.nested deeper.world
612         ) &&
613         git clean -f -f -d &&
614         ! test -d foo &&
615         ! test -d bar &&
616         ! test -d baz
617 '
618
619 test_expect_success 'git clean -e' '
620         rm -fr repo &&
621         mkdir repo &&
622         (
623                 cd repo &&
624                 git init &&
625                 touch known 1 2 3 &&
626                 git add known &&
627                 git clean -f -e 1 -e 2 &&
628                 test -e 1 &&
629                 test -e 2 &&
630                 ! (test -e 3) &&
631                 test -e known
632         )
633 '
634
635 test_expect_success SANITY 'git clean -d with an unreadable empty directory' '
636         mkdir foo &&
637         chmod a= foo &&
638         git clean -dfx foo &&
639         ! test -d foo
640 '
641
642 test_expect_success 'git clean -d respects pathspecs (dir is prefix of pathspec)' '
643         mkdir -p foo &&
644         mkdir -p foobar &&
645         git clean -df foobar &&
646         test_path_is_dir foo &&
647         test_path_is_missing foobar
648 '
649
650 test_expect_success 'git clean -d respects pathspecs (pathspec is prefix of dir)' '
651         mkdir -p foo &&
652         mkdir -p foobar &&
653         git clean -df foo &&
654         test_path_is_missing foo &&
655         test_path_is_dir foobar
656 '
657
658 test_expect_success 'git clean -d skips untracked dirs containing ignored files' '
659         echo /foo/bar >.gitignore &&
660         echo ignoreme >>.gitignore &&
661         rm -rf foo &&
662         mkdir -p foo/a/aa/aaa foo/b/bb/bbb &&
663         touch foo/bar foo/baz foo/a/aa/ignoreme foo/b/ignoreme foo/b/bb/1 foo/b/bb/2 &&
664         git clean -df &&
665         test_path_is_dir foo &&
666         test_path_is_file foo/bar &&
667         test_path_is_missing foo/baz &&
668         test_path_is_file foo/a/aa/ignoreme &&
669         test_path_is_missing foo/a/aa/aaa &&
670         test_path_is_file foo/b/ignoreme &&
671         test_path_is_missing foo/b/bb
672 '
673
674 test_expect_success 'git clean -d skips nested repo containing ignored files' '
675         test_when_finished "rm -rf nested-repo-with-ignored-file" &&
676
677         git init nested-repo-with-ignored-file &&
678         (
679                 cd nested-repo-with-ignored-file &&
680                 >file &&
681                 git add file &&
682                 git commit -m Initial &&
683
684                 # This file is ignored by a .gitignore rule in the outer repo
685                 # added in the previous test.
686                 >ignoreme
687         ) &&
688
689         git clean -fd &&
690
691         test_path_is_file nested-repo-with-ignored-file/.git/index &&
692         test_path_is_file nested-repo-with-ignored-file/ignoreme &&
693         test_path_is_file nested-repo-with-ignored-file/file
694 '
695
696 test_expect_success 'git clean handles being told what to clean' '
697         mkdir -p d1 d2 &&
698         touch d1/ut d2/ut &&
699         git clean -f */ut &&
700         test_path_is_missing d1/ut &&
701         test_path_is_missing d2/ut
702 '
703
704 test_expect_success 'git clean handles being told what to clean, with -d' '
705         mkdir -p d1 d2 &&
706         touch d1/ut d2/ut &&
707         git clean -ffd */ut &&
708         test_path_is_missing d1/ut &&
709         test_path_is_missing d2/ut
710 '
711
712 test_expect_success 'git clean works if a glob is passed without -d' '
713         mkdir -p d1 d2 &&
714         touch d1/ut d2/ut &&
715         git clean -f "*ut" &&
716         test_path_is_missing d1/ut &&
717         test_path_is_missing d2/ut
718 '
719
720 test_expect_success 'git clean works if a glob is passed with -d' '
721         mkdir -p d1 d2 &&
722         touch d1/ut d2/ut &&
723         git clean -ffd "*ut" &&
724         test_path_is_missing d1/ut &&
725         test_path_is_missing d2/ut
726 '
727
728 test_expect_success MINGW 'handle clean & core.longpaths = false nicely' '
729         test_config core.longpaths false &&
730         a50=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
731         mkdir -p $a50$a50/$a50$a50/$a50$a50 &&
732         : >"$a50$a50/test.txt" 2>"$a50$a50/$a50$a50/$a50$a50/test.txt" &&
733         # create a temporary outside the working tree to hide from "git clean"
734         test_must_fail git clean -xdf 2>.git/err &&
735         # grepping for a strerror string is unportable but it is OK here with
736         # MINGW prereq
737         test_i18ngrep "too long" .git/err
738 '
739
740 test_expect_success 'clean untracked paths by pathspec' '
741         git init untracked &&
742         mkdir untracked/dir &&
743         echo >untracked/dir/file.txt &&
744         git -C untracked clean -f dir/file.txt &&
745         ls untracked/dir >actual &&
746         test_must_be_empty actual
747 '
748
749 test_done