3 # Copyright (c) 2007 Michael Spang
6 test_description
='git clean basic tests'
10 git config clean.requireForce no
12 test_expect_success
'setup' '
15 touch src/part1.c Makefile &&
16 echo build >.gitignore &&
17 echo \*.o >>.gitignore &&
19 git commit -m setup &&
20 touch src/part2.c README &&
25 test_expect_success
'git clean with skip-worktree .gitignore' '
26 git update-index --skip-worktree .gitignore &&
28 mkdir -p build docs &&
29 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
33 test -f src/part1.c &&
34 test -f src/part2.c &&
36 test ! -f src/part3.c &&
37 test -f docs/manual.txt &&
39 test -f build/lib.so &&
40 git update-index --no-skip-worktree .gitignore &&
41 git checkout .gitignore
44 test_expect_success
'git clean' '
46 mkdir -p build docs &&
47 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
51 test -f src/part1.c &&
52 test -f src/part2.c &&
54 test ! -f src/part3.c &&
55 test -f docs/manual.txt &&
61 test_expect_success
'git clean src/' '
63 mkdir -p build docs &&
64 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
68 test -f src/part1.c &&
69 test -f src/part2.c &&
71 test ! -f src/part3.c &&
72 test -f docs/manual.txt &&
78 test_expect_success
'git clean src/ src/' '
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/ &&
85 test -f src/part1.c &&
86 test -f src/part2.c &&
88 test ! -f src/part3.c &&
89 test -f docs/manual.txt &&
95 test_expect_success
'git clean with prefix' '
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) &&
102 test -f src/part1.c &&
103 test -f src/part2.c &&
105 test ! -f src/part3.c &&
106 test -f src/test/1.c &&
107 test -f docs/manual.txt &&
113 test_expect_success
'git clean with relative prefix' '
115 mkdir -p build docs &&
116 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
119 git clean -n ../src |
121 sed -n -e "s|^Would remove ||p"
123 verbose test "$would_clean" = ../src/part3.c
126 test_expect_success
'git clean with absolute path' '
128 mkdir -p build docs &&
129 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
132 git clean -n "$(pwd)/../src" |
134 sed -n -e "s|^Would remove ||p"
136 verbose test "$would_clean" = ../src/part3.c
139 test_expect_success
'git clean with out of work tree relative path' '
141 mkdir -p build docs &&
142 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
145 test_must_fail git clean -n ../..
149 test_expect_success
'git clean with out of work tree absolute path' '
151 mkdir -p build docs &&
152 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
153 dd=$(cd .. && pwd) &&
156 test_must_fail git clean -n $dd
160 test_expect_success
'git clean -d with prefix and path' '
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/) &&
167 test -f src/part1.c &&
168 test -f src/part2.c &&
170 test -f src/part3.c &&
171 test ! -f src/feature/file.c &&
172 test -f docs/manual.txt &&
178 test_expect_success SYMLINKS
'git clean symbolic link' '
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 &&
186 test -f src/part1.c &&
187 test -f src/part2.c &&
189 test ! -f src/part3.c &&
190 test ! -f src/part4.c &&
191 test -f docs/manual.txt &&
197 test_expect_success
'git clean with wildcard' '
199 touch a.clean b.clean other.c &&
200 git clean "*.clean" &&
203 test -f src/part1.c &&
204 test -f src/part2.c &&
211 test_expect_success
'git clean -n' '
213 mkdir -p build docs &&
214 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
218 test -f src/part1.c &&
219 test -f src/part2.c &&
221 test -f src/part3.c &&
222 test -f docs/manual.txt &&
228 test_expect_success
'git clean -d' '
230 mkdir -p build docs &&
231 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
235 test -f src/part1.c &&
236 test -f src/part2.c &&
238 test ! -f src/part3.c &&
245 test_expect_success
'git clean -d src/ examples/' '
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/ &&
252 test -f src/part1.c &&
253 test -f src/part2.c &&
255 test ! -f src/part3.c &&
256 test ! -f examples/1.c &&
257 test -f docs/manual.txt &&
263 test_expect_success
'git clean -x' '
265 mkdir -p build docs &&
266 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
270 test -f src/part1.c &&
271 test -f src/part2.c &&
273 test ! -f src/part3.c &&
274 test -f docs/manual.txt &&
280 test_expect_success
'git clean -d -x' '
282 mkdir -p build docs &&
283 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
287 test -f src/part1.c &&
288 test -f src/part2.c &&
290 test ! -f src/part3.c &&
297 test_expect_success
'git clean -d -x with ignored tracked directory' '
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 &&
304 test -f src/part1.c &&
305 test -f src/part2.c &&
307 test -f src/part3.c &&
314 test_expect_success
'git clean -X' '
316 mkdir -p build docs &&
317 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
321 test -f src/part1.c &&
322 test -f src/part2.c &&
324 test -f src/part3.c &&
325 test -f docs/manual.txt &&
331 test_expect_success
'git clean -d -X' '
333 mkdir -p build docs &&
334 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
338 test -f src/part1.c &&
339 test -f src/part2.c &&
341 test -f src/part3.c &&
342 test -f docs/manual.txt &&
348 test_expect_success
'git clean -d -X with ignored tracked directory' '
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 &&
355 test -f src/part1.c &&
356 test -f src/part2.c &&
358 test ! -f src/part3.c &&
359 test -f docs/manual.txt &&
365 test_expect_success
'clean.requireForce defaults to true' '
367 git config --unset clean.requireForce &&
368 test_must_fail git clean
372 test_expect_success
'clean.requireForce' '
374 git config clean.requireForce true &&
375 test_must_fail git clean
379 test_expect_success
'clean.requireForce and -n' '
381 mkdir -p build docs &&
382 touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
386 test -f src/part1.c &&
387 test -f src/part2.c &&
389 test -f src/part3.c &&
390 test -f docs/manual.txt &&
396 test_expect_success
'clean.requireForce and -f' '
400 test -f src/part1.c &&
401 test -f src/part2.c &&
403 test ! -f src/part3.c &&
404 test -f docs/manual.txt &&
410 test_expect_success
'core.excludesfile' '
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
421 test_expect_success SANITY
'removal failure' '
425 test_when_finished "chmod 755 foo" &&
428 test_must_fail git clean -f -d)
431 test_expect_success
'nested git work tree' '
432 rm -fr foo bar baz &&
433 mkdir -p foo bar baz/boo &&
437 test_commit nested hello.world
446 test_commit deeply.nested deeper.world
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 &&
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 &&
463 cp -r almost_git/.git/ almost_bare_git &&
464 mkdir almost_submodule/ &&
465 cat >almost_submodule/.git <<-\EOF &&
468 test_when_finished "rm -rf almost_*" &&
470 test_path_is_missing almost_git &&
471 test_path_is_missing almost_bare_git &&
472 test_path_is_missing almost_submodule
475 test_expect_success
'should not clean submodules' '
476 rm -fr repo to_clean sub1 sub2 &&
477 mkdir repo to_clean &&
481 test_commit msg hello.world
483 test_config_global protocol.file.allow always &&
484 git submodule add ./repo/.git sub1 &&
485 git commit -m "sub1" &&
486 git branch before_sub2 &&
487 git submodule add ./repo/.git sub2 &&
488 git commit -m "sub2" &&
489 git checkout before_sub2 &&
490 >to_clean/should_clean.this &&
492 test_path_is_file repo/.git/index &&
493 test_path_is_file repo/hello.world &&
494 test_path_is_file sub1/.git &&
495 test_path_is_file sub1/hello.world &&
496 test_path_is_file sub2/.git &&
497 test_path_is_file sub2/hello.world &&
498 test_path_is_missing to_clean
501 test_expect_success POSIXPERM
,SANITY
'should avoid cleaning possible submodules' '
502 rm -fr to_clean possible_sub1 &&
503 mkdir to_clean possible_sub1 &&
504 test_when_finished "rm -rf possible_sub*" &&
505 echo "gitdir: foo" >possible_sub1/.git &&
506 >possible_sub1/hello.world &&
507 chmod 0 possible_sub1/.git &&
508 >to_clean/should_clean.this &&
510 test_path_is_file possible_sub1/.git &&
511 test_path_is_file possible_sub1/hello.world &&
512 test_path_is_missing to_clean
515 test_expect_success
'nested (empty) git should be kept' '
516 rm -fr empty_repo to_clean &&
517 git init empty_repo &&
519 >to_clean/should_clean.this &&
521 test_path_is_file empty_repo/.git/HEAD &&
522 test_path_is_missing to_clean
525 test_expect_success
'nested bare repositories should be cleaned' '
526 rm -fr bare1 bare2 subdir &&
527 git init --bare bare1 &&
528 git clone --local --bare . bare2 &&
530 cp -r bare2 subdir/bare3 &&
532 test_path_is_missing bare1 &&
533 test_path_is_missing bare2 &&
534 test_path_is_missing subdir
537 test_expect_failure
'nested (empty) bare repositories should be cleaned even when in .git' '
538 rm -fr strange_bare &&
539 mkdir strange_bare &&
540 git init --bare strange_bare/.git &&
542 test_path_is_missing strange_bare
545 test_expect_failure
'nested (non-empty) bare repositories should be cleaned even when in .git' '
546 rm -fr strange_bare &&
547 mkdir strange_bare &&
548 git clone --local --bare . strange_bare/.git &&
550 test_path_is_missing strange_bare
553 test_expect_success
'giving path in nested git work tree will NOT remove it' '
560 test_commit msg bar/baz/hello.world
562 git clean -f -d repo/bar/baz &&
563 test_path_is_file repo/.git/HEAD &&
564 test_path_is_dir repo/bar/ &&
565 test_path_is_file repo/bar/baz/hello.world
568 test_expect_success
'giving path to nested .git will not remove it' '
570 mkdir repo untracked &&
574 test_commit msg hello.world
576 git clean -f -d repo/.git &&
577 test_path_is_file repo/.git/HEAD &&
578 test_path_is_dir repo/.git/refs &&
579 test_path_is_dir repo/.git/objects &&
580 test_path_is_dir untracked/
583 test_expect_success
'giving path to nested .git/ will NOT remove contents' '
584 rm -fr repo untracked &&
585 mkdir repo untracked &&
589 test_commit msg hello.world
591 git clean -f -d repo/.git/ &&
592 test_path_is_dir repo/.git &&
593 test_path_is_file repo/.git/HEAD &&
594 test_path_is_dir untracked/
597 test_expect_success
'force removal of nested git work tree' '
598 rm -fr foo bar baz &&
599 mkdir -p foo bar baz/boo &&
603 test_commit nested hello.world
612 test_commit deeply.nested deeper.world
614 git clean -f -f -d &&
620 test_expect_success
'git clean -e' '
628 git clean -f -e 1 -e 2 &&
636 test_expect_success SANITY
'git clean -d with an unreadable empty directory' '
639 git clean -dfx foo &&
643 test_expect_success
'git clean -d respects pathspecs (dir is prefix of pathspec)' '
646 git clean -df foobar &&
647 test_path_is_dir foo &&
648 test_path_is_missing foobar
651 test_expect_success
'git clean -d respects pathspecs (pathspec is prefix of dir)' '
655 test_path_is_missing foo &&
656 test_path_is_dir foobar
659 test_expect_success
'git clean -d skips untracked dirs containing ignored files' '
660 echo /foo/bar >.gitignore &&
661 echo ignoreme >>.gitignore &&
663 mkdir -p foo/a/aa/aaa foo/b/bb/bbb &&
664 touch foo/bar foo/baz foo/a/aa/ignoreme foo/b/ignoreme foo/b/bb/1 foo/b/bb/2 &&
666 test_path_is_dir foo &&
667 test_path_is_file foo/bar &&
668 test_path_is_missing foo/baz &&
669 test_path_is_file foo/a/aa/ignoreme &&
670 test_path_is_missing foo/a/aa/aaa &&
671 test_path_is_file foo/b/ignoreme &&
672 test_path_is_missing foo/b/bb
675 test_expect_success
'git clean -d skips nested repo containing ignored files' '
676 test_when_finished "rm -rf nested-repo-with-ignored-file" &&
678 git init nested-repo-with-ignored-file &&
680 cd nested-repo-with-ignored-file &&
683 git commit -m Initial &&
685 # This file is ignored by a .gitignore rule in the outer repo
686 # added in the previous test.
692 test_path_is_file nested-repo-with-ignored-file/.git/index &&
693 test_path_is_file nested-repo-with-ignored-file/ignoreme &&
694 test_path_is_file nested-repo-with-ignored-file/file
697 test_expect_success
'git clean handles being told what to clean' '
701 test_path_is_missing d1/ut &&
702 test_path_is_missing d2/ut
705 test_expect_success
'git clean handles being told what to clean, with -d' '
708 git clean -ffd */ut &&
709 test_path_is_missing d1/ut &&
710 test_path_is_missing d2/ut
713 test_expect_success
'git clean works if a glob is passed without -d' '
716 git clean -f "*ut" &&
717 test_path_is_missing d1/ut &&
718 test_path_is_missing d2/ut
721 test_expect_success
'git clean works if a glob is passed with -d' '
724 git clean -ffd "*ut" &&
725 test_path_is_missing d1/ut &&
726 test_path_is_missing d2/ut
729 test_expect_success MINGW
'handle clean & core.longpaths = false nicely' '
730 test_config core.longpaths false &&
731 a50=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
732 mkdir -p $a50$a50/$a50$a50/$a50$a50 &&
733 : >"$a50$a50/test.txt" 2>"$a50$a50/$a50$a50/$a50$a50/test.txt" &&
734 # create a temporary outside the working tree to hide from "git clean"
735 test_must_fail git clean -xdf 2>.git/err &&
736 # grepping for a strerror string is unportable but it is OK here with
738 test_i18ngrep "too long" .git/err
741 test_expect_success
'clean untracked paths by pathspec' '
742 git init untracked &&
743 mkdir untracked/dir &&
744 echo >untracked/dir/file.txt &&
745 git -C untracked clean -f dir/file.txt &&
746 ls untracked/dir >actual &&
747 test_must_be_empty actual
750 test_expect_success
'avoid traversing into ignored directories' '
751 test_when_finished rm -f output error trace.* &&
752 test_create_repo avoid-traversing-deep-hierarchy &&
754 cd avoid-traversing-deep-hierarchy &&
756 mkdir -p untracked/subdir/with/a &&
757 >untracked/subdir/with/a/random-file.txt &&
759 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
760 git clean -ffdxn -e untracked
763 # Make sure we only visited into the top-level directory, and did
764 # not traverse into the "untracked" subdirectory since it was excluded
765 grep data.*read_directo.*directories-visited trace.output |
766 cut -d "|" -f 9 >trace.relevant &&
767 cat >trace.expect <<-EOF &&
768 ..directories-visited:1
770 test_cmp trace.expect trace.relevant
773 test_expect_success
'traverse into directories that may have ignored entries' '
774 test_when_finished rm -f output &&
775 test_create_repo need-to-traverse-into-hierarchy &&
777 cd need-to-traverse-into-hierarchy &&
778 mkdir -p modules/foobar/src/generated &&
779 > modules/foobar/src/generated/code.c &&
780 > modules/foobar/Makefile &&
781 echo "/modules/**/src/generated/" >.gitignore &&
783 git clean -fX modules/foobar >../output &&
785 grep Removing ../output &&
787 test_path_is_missing modules/foobar/src/generated/code.c &&
788 test_path_is_file modules/foobar/Makefile