diff options
Diffstat (limited to 'builtin/clean.c')
-rw-r--r-- | builtin/clean.c | 83 |
1 files changed, 53 insertions, 30 deletions
diff --git a/builtin/clean.c b/builtin/clean.c index 4ca12bc0c0..687ab473c2 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -162,7 +162,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_nonbare_repository_dir(path)) { if (!quiet) { - quote_path_relative(path->buf, prefix, "ed); + quote_path(path->buf, prefix, "ed, 0); printf(dry_run ? _(msg_would_skip_git_dir) : _(msg_skip_git_dir), quoted.buf); } @@ -177,7 +177,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, res = dry_run ? 0 : rmdir(path->buf); if (res) { int saved_errno = errno; - quote_path_relative(path->buf, prefix, "ed); + quote_path(path->buf, prefix, "ed, 0); errno = saved_errno; warning_errno(_(msg_warn_remove_failed), quoted.buf); *dir_gone = 0; @@ -202,7 +202,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, if (remove_dirs(path, prefix, force_flag, dry_run, quiet, &gone)) ret = 1; if (gone) { - quote_path_relative(path->buf, prefix, "ed); + quote_path(path->buf, prefix, "ed, 0); string_list_append(&dels, quoted.buf); } else *dir_gone = 0; @@ -210,11 +210,11 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, } else { res = dry_run ? 0 : unlink(path->buf); if (!res) { - quote_path_relative(path->buf, prefix, "ed); + quote_path(path->buf, prefix, "ed, 0); string_list_append(&dels, quoted.buf); } else { int saved_errno = errno; - quote_path_relative(path->buf, prefix, "ed); + quote_path(path->buf, prefix, "ed, 0); errno = saved_errno; warning_errno(_(msg_warn_remove_failed), quoted.buf); *dir_gone = 0; @@ -238,7 +238,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, *dir_gone = 1; else { int saved_errno = errno; - quote_path_relative(path->buf, prefix, "ed); + quote_path(path->buf, prefix, "ed, 0); errno = saved_errno; warning_errno(_(msg_warn_remove_failed), quoted.buf); *dir_gone = 0; @@ -266,7 +266,7 @@ static void pretty_print_dels(void) struct column_options copts; for_each_string_list_item(item, &del_list) { - qname = quote_path_relative(item->string, NULL, &buf); + qname = quote_path(item->string, NULL, &buf, 0); string_list_append(&list, qname); } @@ -667,7 +667,7 @@ static int filter_by_patterns_cmd(void) if (!confirm.len) break; - memset(&dir, 0, sizeof(dir)); + dir_init(&dir); pl = add_pattern_list(&dir, EXC_CMDL, "manual exclude"); ignore_list = strbuf_split_max(&confirm, ' ', 0); @@ -698,7 +698,7 @@ static int filter_by_patterns_cmd(void) } strbuf_list_free(ignore_list); - clear_directory(&dir); + dir_clear(&dir); } strbuf_release(&confirm); @@ -753,7 +753,7 @@ static int ask_each_cmd(void) for_each_string_list_item(item, &del_list) { /* Ctrl-D should stop removing files */ if (!eof) { - qname = quote_path_relative(item->string, NULL, &buf); + qname = quote_path(item->string, NULL, &buf, 0); /* TRANSLATORS: Make sure to keep [y/N] as is */ printf(_("Remove %s [y/N]? "), qname); if (git_read_line_interactively(&confirm) == EOF) { @@ -923,13 +923,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, builtin_clean_usage, 0); - memset(&dir, 0, sizeof(dir)); - if (ignored_only) - dir.flags |= DIR_SHOW_IGNORED; - - if (ignored && ignored_only) - die(_("-x and -X cannot be used together")); - + dir_init(&dir); if (!interactive && !dry_run && !force) { if (config_set) die(_("clean.requireForce set to true and neither -i, -n, nor -f given; " @@ -946,6 +940,13 @@ int cmd_clean(int argc, const char **argv, const char *prefix) dir.flags |= DIR_SHOW_OTHER_DIRECTORIES; + if (ignored && ignored_only) + die(_("-x and -X cannot be used together")); + if (!ignored) + setup_standard_excludes(&dir); + if (ignored_only) + dir.flags |= DIR_SHOW_IGNORED; + if (argc) { /* * Remaining args implies pathspecs specified, and we should @@ -954,15 +955,41 @@ int cmd_clean(int argc, const char **argv, const char *prefix) remove_directories = 1; } - if (remove_directories) - dir.flags |= DIR_SHOW_IGNORED_TOO | DIR_KEEP_UNTRACKED_CONTENTS; + if (remove_directories && !ignored_only) { + /* + * We need to know about ignored files too: + * + * If (ignored), then we will delete ignored files as well. + * + * If (!ignored), then even though we not are doing + * anything with ignored files, we need to know about them + * so that we can avoid deleting a directory of untracked + * files that also contains an ignored file within it. + * + * For the (!ignored) case, since we only need to avoid + * deleting ignored files, we can set + * DIR_SHOW_IGNORED_TOO_MODE_MATCHING in order to avoid + * recursing into a directory which is itself ignored. + */ + dir.flags |= DIR_SHOW_IGNORED_TOO; + if (!ignored) + dir.flags |= DIR_SHOW_IGNORED_TOO_MODE_MATCHING; + + /* + * Let the fill_directory() machinery know that we aren't + * just recursing to collect the ignored files; we want all + * the untracked ones so that we can delete them. (Note: + * we could also set DIR_KEEP_UNTRACKED_CONTENTS when + * ignored_only is true, since DIR_KEEP_UNTRACKED_CONTENTS + * only has effect in combination with DIR_SHOW_IGNORED_TOO. It makes + * the code clearer to exclude it, though. + */ + dir.flags |= DIR_KEEP_UNTRACKED_CONTENTS; + } if (read_cache() < 0) die(_("index file corrupt")); - if (!ignored) - setup_standard_excludes(&dir); - pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option"); for (i = 0; i < exclude_list.nr; i++) add_pattern(exclude_list.items[i].string, "", 0, pl, -(i+1)); @@ -994,11 +1021,7 @@ 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]); + dir_clear(&dir); if (interactive && del_list.nr > 0) interactive_main_loop(); @@ -1024,19 +1047,19 @@ int cmd_clean(int argc, const char **argv, const char *prefix) if (remove_dirs(&abs_path, prefix, rm_flags, dry_run, quiet, &gone)) errors++; if (gone && !quiet) { - qname = quote_path_relative(item->string, NULL, &buf); + qname = quote_path(item->string, NULL, &buf, 0); printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname); } } else { res = dry_run ? 0 : unlink(abs_path.buf); if (res) { int saved_errno = errno; - qname = quote_path_relative(item->string, NULL, &buf); + qname = quote_path(item->string, NULL, &buf, 0); errno = saved_errno; warning_errno(_(msg_warn_remove_failed), qname); errors++; } else if (!quiet) { - qname = quote_path_relative(item->string, NULL, &buf); + qname = quote_path(item->string, NULL, &buf, 0); printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname); } } |