summaryrefslogtreecommitdiff
path: root/builtin/clean.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2017-06-02 06:06:04 (GMT)
committerJunio C Hamano <gitster@pobox.com>2017-06-02 06:06:05 (GMT)
commitf4fd99bf6e5c27265ee2a9ccb9c2495854f67acb (patch)
tree2fae59f74c523e7e58465b24aa343b4a90debc46 /builtin/clean.c
parentd027b467fcb526433902b024a5d30844d9346e57 (diff)
parent6b1db43109ab3d4c92e61874cd149779c66016db (diff)
downloadgit-f4fd99bf6e5c27265ee2a9ccb9c2495854f67acb.zip
git-f4fd99bf6e5c27265ee2a9ccb9c2495854f67acb.tar.gz
git-f4fd99bf6e5c27265ee2a9ccb9c2495854f67acb.tar.bz2
Merge branch 'sl/clean-d-ignored-fix'
"git clean -d" used to clean directories that has ignored files, even though the command should not lose ignored ones without "-x". "git status --ignored" did not list ignored and untracked files without "-uall". These have been corrected. * sl/clean-d-ignored-fix: clean: teach clean -d to preserve ignored paths dir: expose cmp_name() and check_contains() dir: hide untracked contents of untracked dirs dir: recurse into untracked dirs for ignored files t7061: status --ignored should search untracked dirs t7300: clean -d should skip dirs with ignored files
Diffstat (limited to 'builtin/clean.c')
-rw-r--r--builtin/clean.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/builtin/clean.c b/builtin/clean.c
index 329b68c..142bf66 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -857,6 +857,38 @@ static void interactive_main_loop(void)
}
}
+static void correct_untracked_entries(struct dir_struct *dir)
+{
+ int src, dst, ign;
+
+ for (src = dst = ign = 0; src < dir->nr; src++) {
+ /* skip paths in ignored[] that cannot be inside entries[src] */
+ while (ign < dir->ignored_nr &&
+ 0 <= cmp_dir_entry(&dir->entries[src], &dir->ignored[ign]))
+ ign++;
+
+ if (ign < dir->ignored_nr &&
+ check_dir_entry_contains(dir->entries[src], dir->ignored[ign])) {
+ /* entries[src] contains an ignored path, so we drop it */
+ free(dir->entries[src]);
+ } else {
+ struct dir_entry *ent = dir->entries[src++];
+
+ /* entries[src] does not contain an ignored path, so we keep it */
+ dir->entries[dst++] = ent;
+
+ /* then discard paths in entries[] contained inside entries[src] */
+ while (src < dir->nr &&
+ check_dir_entry_contains(ent, dir->entries[src]))
+ free(dir->entries[src++]);
+
+ /* compensate for the outer loop's loop control */
+ src--;
+ }
+ }
+ dir->nr = dst;
+}
+
int cmd_clean(int argc, const char **argv, const char *prefix)
{
int i, res;
@@ -916,6 +948,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
+ if (remove_directories)
+ dir.flags |= DIR_SHOW_IGNORED_TOO | DIR_KEEP_UNTRACKED_CONTENTS;
+
if (read_cache() < 0)
die(_("index file corrupt"));
@@ -931,6 +966,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
prefix, argv);
fill_directory(&dir, &the_index, &pathspec);
+ correct_untracked_entries(&dir);
for (i = 0; i < dir.nr; i++) {
struct dir_entry *ent = dir.entries[i];
@@ -958,6 +994,12 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
string_list_append(&del_list, rel);
}
+ for (i = 0; i < dir.nr; i++)
+ free(dir.entries[i]);
+
+ for (i = 0; i < dir.ignored_nr; i++)
+ free(dir.ignored[i]);
+
if (interactive && del_list.nr > 0)
interactive_main_loop();