diff options
Diffstat (limited to 'builtin/clean.c')
-rw-r--r-- | builtin/clean.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/builtin/clean.c b/builtin/clean.c index 98c103fa8b..df53def63f 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -10,7 +10,6 @@ #include "cache.h" #include "dir.h" #include "parse-options.h" -#include "refs.h" #include "string-list.h" #include "quote.h" #include "column.h" @@ -148,6 +147,31 @@ static int exclude_cb(const struct option *opt, const char *arg, int unset) return 0; } +/* + * Return 1 if the given path is the root of a git repository or + * submodule else 0. Will not return 1 for bare repositories with the + * exception of creating a bare repository in "foo/.git" and calling + * is_git_repository("foo"). + */ +static int is_git_repository(struct strbuf *path) +{ + int ret = 0; + int gitfile_error; + size_t orig_path_len = path->len; + assert(orig_path_len != 0); + if (path->buf[orig_path_len - 1] != '/') + strbuf_addch(path, '/'); + strbuf_addstr(path, ".git"); + if (read_gitfile_gently(path->buf, &gitfile_error) || is_git_directory(path->buf)) + ret = 1; + if (gitfile_error == READ_GITFILE_ERR_OPEN_FAILED || + gitfile_error == READ_GITFILE_ERR_READ_FAILED) + ret = 1; /* This could be a real .git file, take the + * safe option and avoid cleaning */ + strbuf_setlen(path, orig_path_len); + return ret; +} + static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, int dry_run, int quiet, int *dir_gone) { @@ -155,13 +179,11 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, struct strbuf quoted = STRBUF_INIT; struct dirent *e; int res = 0, ret = 0, gone = 1, original_len = path->len, len; - unsigned char submodule_head[20]; struct string_list dels = STRING_LIST_INIT_DUP; *dir_gone = 1; - if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && - !resolve_gitlink_ref(path->buf, "HEAD", submodule_head)) { + if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_git_repository(path)) { if (!quiet) { quote_path_relative(path->buf, prefix, "ed); printf(dry_run ? _(msg_would_skip_git_dir) : _(msg_skip_git_dir), @@ -314,7 +336,6 @@ static void print_highlight_menu_stuff(struct menu_stuff *stuff, int **chosen) { struct string_list menu_list = STRING_LIST_INIT_DUP; struct strbuf menu = STRBUF_INIT; - struct strbuf buf = STRBUF_INIT; struct menu_item *menu_item; struct string_list_item *string_list_item; int i; @@ -363,7 +384,6 @@ static void print_highlight_menu_stuff(struct menu_stuff *stuff, int **chosen) pretty_print_menus(&menu_list); strbuf_release(&menu); - strbuf_release(&buf); string_list_clear(&menu_list, 0); } @@ -941,15 +961,15 @@ int cmd_clean(int argc, const char **argv, const char *prefix) if (!cache_name_is_other(ent->name, ent->len)) continue; - if (lstat(ent->name, &st)) - die_errno("Cannot lstat '%s'", ent->name); - if (pathspec.nr) matches = dir_path_match(ent, &pathspec, 0, NULL); if (pathspec.nr && !matches) continue; + if (lstat(ent->name, &st)) + die_errno("Cannot lstat '%s'", ent->name); + if (S_ISDIR(st.st_mode) && !remove_directories && matches != MATCHED_EXACTLY) continue; |