#!/bin/sh # # Copyright (c) 2007 Michael Spang # test_description='git clean basic tests' . ./test-lib.sh git config clean.requireForce no test_expect_success 'setup' ' mkdir -p src && touch src/part1.c Makefile && echo build >.gitignore && echo \*.o >>.gitignore && git add . && git commit -m setup && touch src/part2.c README && git add . ' test_expect_success 'git clean with skip-worktree .gitignore' ' git update-index --skip-worktree .gitignore && rm .gitignore && mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test ! -f a.out && test ! -f src/part3.c && test -f docs/manual.txt && test -f obj.o && test -f build/lib.so && git update-index --no-skip-worktree .gitignore && git checkout .gitignore ' test_expect_success 'git clean' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test ! -f a.out && test ! -f src/part3.c && test -f docs/manual.txt && test -f obj.o && test -f build/lib.so ' test_expect_success 'git clean src/' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean src/ && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test -f a.out && test ! -f src/part3.c && test -f docs/manual.txt && test -f obj.o && test -f build/lib.so ' test_expect_success 'git clean src/ src/' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean src/ src/ && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test -f a.out && test ! -f src/part3.c && test -f docs/manual.txt && test -f obj.o && test -f build/lib.so ' test_expect_success 'git clean with prefix' ' mkdir -p build docs src/test && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so src/test/1.c && (cd src/ && git clean) && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test -f a.out && test ! -f src/part3.c && test -f src/test/1.c && test -f docs/manual.txt && test -f obj.o && test -f build/lib.so ' test_expect_success C_LOCALE_OUTPUT 'git clean with relative prefix' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && would_clean=$( cd docs && git clean -n ../src | sed -n -e "s|^Would remove ||p" ) && verbose test "$would_clean" = ../src/part3.c ' test_expect_success C_LOCALE_OUTPUT 'git clean with absolute path' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && would_clean=$( cd docs && git clean -n "$(pwd)/../src" | sed -n -e "s|^Would remove ||p" ) && verbose test "$would_clean" = ../src/part3.c ' test_expect_success 'git clean with out of work tree relative path' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && ( cd docs && test_must_fail git clean -n ../.. ) ' test_expect_success 'git clean with out of work tree absolute path' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && dd=$(cd .. && pwd) && ( cd docs && test_must_fail git clean -n $dd ) ' test_expect_success 'git clean -d with prefix and path' ' mkdir -p build docs src/feature && touch a.out src/part3.c src/feature/file.c docs/manual.txt obj.o build/lib.so && (cd src/ && git clean -d feature/) && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test -f a.out && test -f src/part3.c && test ! -f src/feature/file.c && test -f docs/manual.txt && test -f obj.o && test -f build/lib.so ' test_expect_success SYMLINKS 'git clean symbolic link' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && ln -s docs/manual.txt src/part4.c && git clean && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test ! -f a.out && test ! -f src/part3.c && test ! -f src/part4.c && test -f docs/manual.txt && test -f obj.o && test -f build/lib.so ' test_expect_success 'git clean with wildcard' ' touch a.clean b.clean other.c && git clean "*.clean" && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test ! -f a.clean && test ! -f b.clean && test -f other.c ' test_expect_success 'git clean -n' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -n && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test -f a.out && test -f src/part3.c && test -f docs/manual.txt && test -f obj.o && test -f build/lib.so ' test_expect_success 'git clean -d' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -d && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test ! -f a.out && test ! -f src/part3.c && test ! -d docs && test -f obj.o && test -f build/lib.so ' test_expect_success 'git clean -d src/ examples/' ' mkdir -p build docs examples && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so examples/1.c && git clean -d src/ examples/ && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test -f a.out && test ! -f src/part3.c && test ! -f examples/1.c && test -f docs/manual.txt && test -f obj.o && test -f build/lib.so ' test_expect_success 'git clean -x' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -x && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test ! -f a.out && test ! -f src/part3.c && test -f docs/manual.txt && test ! -f obj.o && test -f build/lib.so ' test_expect_success 'git clean -d -x' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -d -x && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test ! -f a.out && test ! -f src/part3.c && test ! -d docs && test ! -f obj.o && test ! -d build ' test_expect_success 'git clean -d -x with ignored tracked directory' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -d -x -e src && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test ! -f a.out && test -f src/part3.c && test ! -d docs && test ! -f obj.o && test ! -d build ' test_expect_success 'git clean -X' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -X && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test -f a.out && test -f src/part3.c && test -f docs/manual.txt && test ! -f obj.o && test -f build/lib.so ' test_expect_success 'git clean -d -X' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -d -X && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test -f a.out && test -f src/part3.c && test -f docs/manual.txt && test ! -f obj.o && test ! -d build ' test_expect_success 'git clean -d -X with ignored tracked directory' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -d -X -e src && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test -f a.out && test ! -f src/part3.c && test -f docs/manual.txt && test ! -f obj.o && test ! -d build ' test_expect_success 'clean.requireForce defaults to true' ' git config --unset clean.requireForce && test_must_fail git clean ' test_expect_success 'clean.requireForce' ' git config clean.requireForce true && test_must_fail git clean ' test_expect_success 'clean.requireForce and -n' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -n && test -f Makefile && test -f README && test -f src/part1.c && test -f src/part2.c && test -f a.out && test -f src/part3.c && test -f docs/manual.txt && test -f obj.o && test -f build/lib.so ' test_expect_success 'clean.requireForce and -f' ' git clean -f && test -f README && test -f src/part1.c && test -f src/part2.c && test ! -f a.out && test ! -f src/part3.c && test -f docs/manual.txt && test -f obj.o && test -f build/lib.so ' test_expect_success C_LOCALE_OUTPUT 'core.excludesfile' ' echo excludes >excludes && echo included >included && git config core.excludesfile excludes && output=$(git clean -n excludes included 2>&1) && expr "$output" : ".*included" >/dev/null && ! expr "$output" : ".*excludes" >/dev/null ' test_expect_success SANITY 'removal failure' ' mkdir foo && touch foo/bar && test_when_finished "chmod 755 foo" && (exec goodbye.people ) && ( cd baz/boo && git init && test_commit deeply.nested deeper.world ) && git clean -f -d && test -f foo/.git/index && test -f foo/hello.world && test -f baz/boo/.git/index && test -f baz/boo/deeper.world && ! test -d bar ' test_expect_success 'should clean things that almost look like git but are not' ' rm -fr almost_git almost_bare_git almost_submodule && mkdir -p almost_git/.git/objects && mkdir -p almost_git/.git/refs && cat >almost_git/.git/HEAD <<-\EOF && garbage EOF cp -r almost_git/.git/ almost_bare_git && mkdir almost_submodule/ && cat >almost_submodule/.git <<-\EOF && garbage EOF test_when_finished "rm -rf almost_*" && git clean -f -d && test_path_is_missing almost_git && test_path_is_missing almost_bare_git && test_path_is_missing almost_submodule ' test_expect_success 'should not clean submodules' ' rm -fr repo to_clean sub1 sub2 && mkdir repo to_clean && ( cd repo && git init && test_commit msg hello.world ) && git submodule add ./repo/.git sub1 && git commit -m "sub1" && git branch before_sub2 && git submodule add ./repo/.git sub2 && git commit -m "sub2" && git checkout before_sub2 && >to_clean/should_clean.this && git clean -f -d && test_path_is_file repo/.git/index && test_path_is_file repo/hello.world && test_path_is_file sub1/.git && test_path_is_file sub1/hello.world && test_path_is_file sub2/.git && test_path_is_file sub2/hello.world && test_path_is_missing to_clean ' test_expect_success POSIXPERM,SANITY 'should avoid cleaning possible submodules' ' rm -fr to_clean possible_sub1 && mkdir to_clean possible_sub1 && test_when_finished "rm -rf possible_sub*" && echo "gitdir: foo" >possible_sub1/.git && >possible_sub1/hello.world && chmod 0 possible_sub1/.git && >to_clean/should_clean.this && git clean -f -d && test_path_is_file possible_sub1/.git && test_path_is_file possible_sub1/hello.world && test_path_is_missing to_clean ' test_expect_success 'nested (empty) git should be kept' ' rm -fr empty_repo to_clean && git init empty_repo && mkdir to_clean && >to_clean/should_clean.this && git clean -f -d && test_path_is_file empty_repo/.git/HEAD && test_path_is_missing to_clean ' test_expect_success 'nested bare repositories should be cleaned' ' rm -fr bare1 bare2 subdir && git init --bare bare1 && git clone --local --bare . bare2 && mkdir subdir && cp -r bare2 subdir/bare3 && git clean -f -d && test_path_is_missing bare1 && test_path_is_missing bare2 && test_path_is_missing subdir ' test_expect_failure 'nested (empty) bare repositories should be cleaned even when in .git' ' rm -fr strange_bare && mkdir strange_bare && git init --bare strange_bare/.git && git clean -f -d && test_path_is_missing strange_bare ' test_expect_failure 'nested (non-empty) bare repositories should be cleaned even when in .git' ' rm -fr strange_bare && mkdir strange_bare && git clone --local --bare . strange_bare/.git && git clean -f -d && test_path_is_missing strange_bare ' test_expect_success 'giving path in nested git work tree will remove it' ' rm -fr repo && mkdir repo && ( cd repo && git init && mkdir -p bar/baz && test_commit msg bar/baz/hello.world ) && git clean -f -d repo/bar/baz && test_path_is_file repo/.git/HEAD && test_path_is_dir repo/bar/ && test_path_is_missing repo/bar/baz ' test_expect_success 'giving path to nested .git will not remove it' ' rm -fr repo && mkdir repo untracked && ( cd repo && git init && test_commit msg hello.world ) && git clean -f -d repo/.git && test_path_is_file repo/.git/HEAD && test_path_is_dir repo/.git/refs && test_path_is_dir repo/.git/objects && test_path_is_dir untracked/ ' test_expect_success 'giving path to nested .git/ will remove contents' ' rm -fr repo untracked && mkdir repo untracked && ( cd repo && git init && test_commit msg hello.world ) && git clean -f -d repo/.git/ && test_path_is_dir repo/.git && test_dir_is_empty repo/.git && test_path_is_dir untracked/ ' test_expect_success 'force removal of nested git work tree' ' rm -fr foo bar baz && mkdir -p foo bar baz/boo && ( cd foo && git init && test_commit nested hello.world ) && ( cd bar && >goodbye.people ) && ( cd baz/boo && git init && test_commit deeply.nested deeper.world ) && git clean -f -f -d && ! test -d foo && ! test -d bar && ! test -d baz ' test_expect_success 'git clean -e' ' rm -fr repo && mkdir repo && ( cd repo && git init && touch known 1 2 3 && git add known && git clean -f -e 1 -e 2 && test -e 1 && test -e 2 && ! (test -e 3) && test -e known ) ' test_expect_success SANITY 'git clean -d with an unreadable empty directory' ' mkdir foo && chmod a= foo && git clean -dfx foo && ! test -d foo ' test_expect_success 'git clean -d respects pathspecs (dir is prefix of pathspec)' ' mkdir -p foo && mkdir -p foobar && git clean -df foobar && test_path_is_dir foo && test_path_is_missing foobar ' test_expect_success 'git clean -d respects pathspecs (pathspec is prefix of dir)' ' mkdir -p foo && mkdir -p foobar && git clean -df foo && test_path_is_missing foo && test_path_is_dir foobar ' test_expect_success 'git clean -d skips untracked dirs containing ignored files' ' echo /foo/bar >.gitignore && echo ignoreme >>.gitignore && rm -rf foo && mkdir -p foo/a/aa/aaa foo/b/bb/bbb && touch foo/bar foo/baz foo/a/aa/ignoreme foo/b/ignoreme foo/b/bb/1 foo/b/bb/2 && git clean -df && test_path_is_dir foo && test_path_is_file foo/bar && test_path_is_missing foo/baz && test_path_is_file foo/a/aa/ignoreme && test_path_is_missing foo/a/aa/aaa && test_path_is_file foo/b/ignoreme && test_path_is_missing foo/b/bb ' test_expect_failure 'git clean -d skips nested repo containing ignored files' ' test_when_finished "rm -rf nested-repo-with-ignored-file" && git init nested-repo-with-ignored-file && ( cd nested-repo-with-ignored-file && >file && git add file && git commit -m Initial && # This file is ignored by a .gitignore rule in the outer repo # added in the previous test. >ignoreme ) && git clean -fd && test_path_is_file nested-repo-with-ignored-file/.git/index && test_path_is_file nested-repo-with-ignored-file/ignoreme && test_path_is_file nested-repo-with-ignored-file/file ' test_expect_failure 'git clean handles being told what to clean' ' mkdir -p d1 d2 && touch d1/ut d2/ut && git clean -f */ut && test_path_is_missing d1/ut && test_path_is_missing d2/ut ' test_expect_failure 'git clean handles being told what to clean, with -d' ' mkdir -p d1 d2 && touch d1/ut d2/ut && git clean -ffd */ut && test_path_is_missing d1/ut && test_path_is_missing d2/ut ' test_expect_failure 'git clean works if a glob is passed without -d' ' mkdir -p d1 d2 && touch d1/ut d2/ut && git clean -f "*ut" && test_path_is_missing d1/ut && test_path_is_missing d2/ut ' test_expect_failure 'git clean works if a glob is passed with -d' ' mkdir -p d1 d2 && touch d1/ut d2/ut && git clean -ffd "*ut" && test_path_is_missing d1/ut && test_path_is_missing d2/ut ' test_expect_success MINGW 'handle clean & core.longpaths = false nicely' ' test_config core.longpaths false && a50=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && mkdir -p $a50$a50/$a50$a50/$a50$a50 && : >"$a50$a50/test.txt" 2>"$a50$a50/$a50$a50/$a50$a50/test.txt" && # create a temporary outside the working tree to hide from "git clean" test_must_fail git clean -xdf 2>.git/err && # grepping for a strerror string is unportable but it is OK here with # MINGW prereq test_i18ngrep "too long" .git/err ' test_done