diff options
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 81 |
1 files changed, 64 insertions, 17 deletions
@@ -18,6 +18,7 @@ #include "utf8.h" #include "varint.h" #include "ewah/ewok.h" +#include "fsmonitor.h" /* * Tells read_directory_recursive how a file or directory should be treated. @@ -1459,10 +1460,34 @@ static enum path_treatment treat_directory(struct dir_struct *dir, case index_nonexistent: if (dir->flags & DIR_SHOW_OTHER_DIRECTORIES) break; + if (exclude && + (dir->flags & DIR_SHOW_IGNORED_TOO) && + (dir->flags & DIR_SHOW_IGNORED_TOO_MODE_MATCHING)) { + + /* + * This is an excluded directory and we are + * showing ignored paths that match an exclude + * pattern. (e.g. show directory as ignored + * only if it matches an exclude pattern). + * This path will either be 'path_excluded` + * (if we are showing empty directories or if + * the directory is not empty), or will be + * 'path_none' (empty directory, and we are + * not showing empty directories). + */ + if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES)) + return path_excluded; + + if (read_directory_recursive(dir, istate, dirname, len, + untracked, 1, 1, pathspec) == path_excluded) + return path_excluded; + + return path_none; + } if (!(dir->flags & DIR_NO_GITLINKS)) { - unsigned char sha1[20]; - if (resolve_gitlink_ref(dirname, "HEAD", sha1) == 0) - return path_untracked; + struct object_id oid; + if (resolve_gitlink_ref(dirname, "HEAD", &oid) == 0) + return exclude ? path_excluded : path_untracked; } return path_recurse; } @@ -1631,6 +1656,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir, { int exclude; int has_path_in_index = !!index_file_exists(istate, path->buf, path->len, ignore_case); + enum path_treatment path_treatment; if (dtype == DT_UNKNOWN) dtype = get_dtype(de, istate, path->buf, path->len); @@ -1677,8 +1703,23 @@ static enum path_treatment treat_one_path(struct dir_struct *dir, return path_none; case DT_DIR: strbuf_addch(path, '/'); - return treat_directory(dir, istate, untracked, path->buf, path->len, - baselen, exclude, pathspec); + path_treatment = treat_directory(dir, istate, untracked, + path->buf, path->len, + baselen, exclude, pathspec); + /* + * If 1) we only want to return directories that + * match an exclude pattern and 2) this directory does + * not match an exclude pattern but all of its + * contents are excluded, then indicate that we should + * recurse into this directory (instead of marking the + * directory itself as an ignored path). + */ + if (!exclude && + path_treatment == path_excluded && + (dir->flags & DIR_SHOW_IGNORED_TOO) && + (dir->flags & DIR_SHOW_IGNORED_TOO_MODE_MATCHING)) + return path_recurse; + return path_treatment; case DT_REG: case DT_LNK: return exclude ? path_excluded : path_untracked; @@ -1763,17 +1804,23 @@ static int valid_cached_dir(struct dir_struct *dir, if (!untracked) return 0; - if (stat(path->len ? path->buf : ".", &st)) { - invalidate_directory(dir->untracked, untracked); - memset(&untracked->stat_data, 0, sizeof(untracked->stat_data)); - return 0; - } - if (!untracked->valid || - match_stat_data_racy(istate, &untracked->stat_data, &st)) { - if (untracked->valid) + /* + * With fsmonitor, we can trust the untracked cache's valid field. + */ + refresh_fsmonitor(istate); + if (!(dir->untracked->use_fsmonitor && untracked->valid)) { + if (stat(path->len ? path->buf : ".", &st)) { invalidate_directory(dir->untracked, untracked); - fill_stat_data(&untracked->stat_data, &st); - return 0; + memset(&untracked->stat_data, 0, sizeof(untracked->stat_data)); + return 0; + } + if (!untracked->valid || + match_stat_data_racy(istate, &untracked->stat_data, &st)) { + if (untracked->valid) + invalidate_directory(dir->untracked, untracked); + fill_stat_data(&untracked->stat_data, &st); + return 0; + } } if (untracked->check_only != !!check_only) { @@ -2349,10 +2396,10 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up) int ret = 0, original_len = path->len, len, kept_down = 0; int only_empty = (flag & REMOVE_DIR_EMPTY_ONLY); int keep_toplevel = (flag & REMOVE_DIR_KEEP_TOPLEVEL); - unsigned char submodule_head[20]; + struct object_id submodule_head; if ((flag & REMOVE_DIR_KEEP_NESTED_GIT) && - !resolve_gitlink_ref(path->buf, "HEAD", submodule_head)) { + !resolve_gitlink_ref(path->buf, "HEAD", &submodule_head)) { /* Do not descend and nuke a nested git work tree. */ if (kept_up) *kept_up = 1; |