summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 0a53e9d)
raw | patch | inline | side by side (parent: 0a53e9d)
author | Junio C Hamano <gitster@pobox.com> | |
Tue, 30 Jun 2009 22:33:45 +0000 (15:33 -0700) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Wed, 29 Jul 2009 19:22:30 +0000 (12:22 -0700) |
When you have an embedded git work tree in your work tree (be it
an orphaned submodule, or an independent checkout of an unrelated
project), "git clean -d -f" blindly descended into it and removed
everything. This is rarely what the user wants.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
an orphaned submodule, or an independent checkout of an unrelated
project), "git clean -d -f" blindly descended into it and removed
everything. This is rarely what the user wants.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-clean.txt | patch | blob | history | |
builtin-clean.c | patch | blob | history | |
dir.c | patch | blob | history | |
dir.h | patch | blob | history | |
refs.c | patch | blob | history | |
t/t7300-clean.sh | patch | blob | history |
index be894af39ff6559affbf0617e4c5d8fe68c33fe8..ae8938b2de9a5930ab18a220a6e8dd90ee6db3b1 100644 (file)
-------
-d::
Remove untracked directories in addition to untracked files.
+ If an untracked directory is managed by a different git
+ repository, it is not removed by default. Use -f option twice
+ if you really want to remove such a directory.
-f::
If the git configuration specifies clean.requireForce as true,
diff --git a/builtin-clean.c b/builtin-clean.c
index 2d8c735d4881a005e4aa5006d9781b71631bb0af..05c763cbec61cd41bde3b424c22563c155105fd0 100644 (file)
--- a/builtin-clean.c
+++ b/builtin-clean.c
int i;
int show_only = 0, remove_directories = 0, quiet = 0, ignored = 0;
int ignored_only = 0, baselen = 0, config_set = 0, errors = 0;
+ int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
struct strbuf directory = STRBUF_INIT;
struct dir_struct dir;
static const char **pathspec;
die("clean.requireForce%s set and -n or -f not given; "
"refusing to clean", config_set ? "" : " not");
+ if (force > 1)
+ rm_flags = 0;
+
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
if (!ignored)
(matches == MATCHED_EXACTLY)) {
if (!quiet)
printf("Removing %s\n", qname);
- if (remove_dir_recursively(&directory, 0) != 0) {
+ if (remove_dir_recursively(&directory,
+ rm_flags) != 0) {
warning("failed to remove '%s'", qname);
errors++;
}
index e05b850acf69867f2b931e7ca2f7430a9e7fc22d..d0999ba055367c31571b251fb34bb46ed6c7051d 100644 (file)
--- a/dir.c
+++ b/dir.c
return ret;
}
-int remove_dir_recursively(struct strbuf *path, int only_empty)
+int remove_dir_recursively(struct strbuf *path, int flag)
{
- DIR *dir = opendir(path->buf);
+ DIR *dir;
struct dirent *e;
int ret = 0, original_len = path->len, len;
+ int only_empty = (flag & REMOVE_DIR_EMPTY_ONLY);
+ unsigned char submodule_head[20];
+ if ((flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
+ !resolve_gitlink_ref(path->buf, "HEAD", submodule_head))
+ /* Do not descend and nuke a nested git work tree. */
+ return 0;
+
+ dir = opendir(path->buf);
if (!dir)
return -1;
if (path->buf[original_len - 1] != '/')
index a6314464f9e0d896f131e08434228d5b1130a4f5..320b6a2f38b9289f910141148b5dddb4cb80815f 100644 (file)
--- a/dir.h
+++ b/dir.h
extern int is_empty_dir(const char *dir);
extern void setup_standard_excludes(struct dir_struct *dir);
-extern int remove_dir_recursively(struct strbuf *path, int only_empty);
+
+#define REMOVE_DIR_EMPTY_ONLY 01
+#define REMOVE_DIR_KEEP_NESTED_GIT 02
+extern int remove_dir_recursively(struct strbuf *path, int flag);
/* tries to remove the path with empty directories along it, ignores ENOENT */
extern int remove_path(const char *path);
index e49eaa3089c39028e3c0af90422672db63fff198..dd9c9ba3f6cb1b7e742adaee89cc406c44d77367 100644 (file)
--- a/refs.c
+++ b/refs.c
strbuf_init(&path, 20);
strbuf_addstr(&path, file);
- result = remove_dir_recursively(&path, 1);
+ result = remove_dir_recursively(&path, REMOVE_DIR_EMPTY_ONLY);
strbuf_release(&path);
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 929d5d4d3b9d55f570cef1617a0716b17265c988..118c6ebb182b5cd4700e533d6a951b31529149af 100755 (executable)
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
'
chmod 755 foo
+test_expect_success 'nested git work tree' '
+ rm -fr foo bar &&
+ mkdir foo bar &&
+ (
+ cd foo &&
+ git init &&
+ >hello.world
+ git add . &&
+ git commit -a -m nested
+ ) &&
+ (
+ cd bar &&
+ >goodbye.people
+ ) &&
+ git clean -f -d &&
+ test -f foo/.git/index &&
+ test -f foo/hello.world &&
+ ! test -d bar
+'
+
+test_expect_success 'force removal of nested git work tree' '
+ rm -fr foo bar &&
+ mkdir foo bar &&
+ (
+ cd foo &&
+ git init &&
+ >hello.world
+ git add . &&
+ git commit -a -m nested
+ ) &&
+ (
+ cd bar &&
+ >goodbye.people
+ ) &&
+ git clean -f -f -d &&
+ ! test -d foo &&
+ ! test -d bar
+'
+
test_done