X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=dir.c;h=d0999ba055367c31571b251fb34bb46ed6c7051d;hb=b7eb912b0d3352d43a11c79fab97cd7f92f0646e;hp=b0671f59c8d210cc2becdae55da4e55a1d098bdc;hpb=dba2e2037f40685bffc87d3e7114a02c5bda1eff;p=git.git diff --git a/dir.c b/dir.c index b0671f59c..d0999ba05 100644 --- a/dir.c +++ b/dir.c @@ -16,7 +16,7 @@ struct path_simplify { static int read_directory_recursive(struct dir_struct *dir, const char *path, int len, int check_only, const struct path_simplify *simplify); -static int get_dtype(struct dirent *de, const char *path); +static int get_dtype(struct dirent *de, const char *path, int len); static int common_prefix(const char **pathspec) { @@ -326,7 +326,7 @@ static int excluded_1(const char *pathname, if (x->flags & EXC_FLAG_MUSTBEDIR) { if (*dtype == DT_UNKNOWN) - *dtype = get_dtype(NULL, pathname); + *dtype = get_dtype(NULL, pathname, pathlen); if (*dtype != DT_DIR) continue; } @@ -566,11 +566,52 @@ static int in_pathspec(const char *path, int len, const struct path_simplify *si return 0; } -static int get_dtype(struct dirent *de, const char *path) +static int get_index_dtype(const char *path, int len) +{ + int pos; + struct cache_entry *ce; + + ce = cache_name_exists(path, len, 0); + if (ce) { + if (!ce_uptodate(ce)) + return DT_UNKNOWN; + if (S_ISGITLINK(ce->ce_mode)) + return DT_DIR; + /* + * Nobody actually cares about the + * difference between DT_LNK and DT_REG + */ + return DT_REG; + } + + /* Try to look it up as a directory */ + pos = cache_name_pos(path, len); + if (pos >= 0) + return DT_UNKNOWN; + pos = -pos-1; + while (pos < active_nr) { + ce = active_cache[pos++]; + if (strncmp(ce->name, path, len)) + break; + if (ce->name[len] > '/') + break; + if (ce->name[len] < '/') + continue; + if (!ce_uptodate(ce)) + break; /* continue? */ + return DT_DIR; + } + return DT_UNKNOWN; +} + +static int get_dtype(struct dirent *de, const char *path, int len) { int dtype = de ? DTYPE(de) : DT_UNKNOWN; struct stat st; + if (dtype != DT_UNKNOWN) + return dtype; + dtype = get_index_dtype(path, len); if (dtype != DT_UNKNOWN) return dtype; if (lstat(path, &st)) @@ -633,7 +674,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *base, in continue; if (dtype == DT_UNKNOWN) - dtype = get_dtype(de, path); + dtype = get_dtype(de, path, len); /* * Do we want to see just the ignored files? @@ -820,12 +861,20 @@ int is_empty_dir(const char *path) 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] != '/')