summaryrefslogtreecommitdiff
path: root/builtin/clean.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/clean.c')
-rw-r--r--builtin/clean.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/builtin/clean.c b/builtin/clean.c
index 329b68c40b..057fc97fe4 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -8,6 +8,7 @@
#include "builtin.h"
#include "cache.h"
+#include "config.h"
#include "dir.h"
#include "parse-options.h"
#include "string-list.h"
@@ -837,8 +838,7 @@ static void interactive_main_loop(void)
int ret;
ret = menus[*chosen].fn();
if (ret != MENU_RETURN_NO_LOOP) {
- free(chosen);
- chosen = NULL;
+ FREE_AND_NULL(chosen);
if (!del_list.nr) {
clean_print_color(CLEAN_COLOR_ERROR);
printf_ln(_("No more files to clean, exiting."));
@@ -851,12 +851,43 @@ static void interactive_main_loop(void)
quit_cmd();
}
- free(chosen);
- chosen = NULL;
+ FREE_AND_NULL(chosen);
break;
}
}
+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 +947,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 +965,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 +993,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();