Merge branch 'jm/status-ignored-directory-optim'
"git status --ignored", when noticing that a directory without any tracked path is ignored, still enumerated all the ignored paths in the directory, which is unnecessary. The codepath has been optimized to avoid this overhead. * jm/status-ignored-directory-optim: Improve performance of git status --ignored
This commit is contained in:
commit
075bc9c798
47
dir.c
47
dir.c
@ -49,7 +49,7 @@ struct cached_dir {
|
||||
static enum path_treatment read_directory_recursive(struct dir_struct *dir,
|
||||
struct index_state *istate, const char *path, int len,
|
||||
struct untracked_cache_dir *untracked,
|
||||
int check_only, const struct pathspec *pathspec);
|
||||
int check_only, int stop_at_first_file, const struct pathspec *pathspec);
|
||||
static int get_dtype(struct dirent *de, struct index_state *istate,
|
||||
const char *path, int len);
|
||||
|
||||
@ -1404,8 +1404,13 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
|
||||
|
||||
untracked = lookup_untracked(dir->untracked, untracked,
|
||||
dirname + baselen, len - baselen);
|
||||
|
||||
/*
|
||||
* If this is an excluded directory, then we only need to check if
|
||||
* the directory contains any files.
|
||||
*/
|
||||
return read_directory_recursive(dir, istate, dirname, len,
|
||||
untracked, 1, pathspec);
|
||||
untracked, 1, exclude, pathspec);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1633,7 +1638,7 @@ static enum path_treatment treat_path_fast(struct dir_struct *dir,
|
||||
* with check_only set.
|
||||
*/
|
||||
return read_directory_recursive(dir, istate, path->buf, path->len,
|
||||
cdir->ucd, 1, pathspec);
|
||||
cdir->ucd, 1, 0, pathspec);
|
||||
/*
|
||||
* We get path_recurse in the first run when
|
||||
* directory_exists_in_index() returns index_nonexistent. We
|
||||
@ -1793,12 +1798,20 @@ static void close_cached_dir(struct cached_dir *cdir)
|
||||
* Also, we ignore the name ".git" (even if it is not a directory).
|
||||
* That likely will not change.
|
||||
*
|
||||
* If 'stop_at_first_file' is specified, 'path_excluded' is returned
|
||||
* to signal that a file was found. This is the least significant value that
|
||||
* indicates that a file was encountered that does not depend on the order of
|
||||
* whether an untracked or exluded path was encountered first.
|
||||
*
|
||||
* Returns the most significant path_treatment value encountered in the scan.
|
||||
* If 'stop_at_first_file' is specified, `path_excluded` is the most
|
||||
* significant path_treatment value that will be returned.
|
||||
*/
|
||||
|
||||
static enum path_treatment read_directory_recursive(struct dir_struct *dir,
|
||||
struct index_state *istate, const char *base, int baselen,
|
||||
struct untracked_cache_dir *untracked, int check_only,
|
||||
const struct pathspec *pathspec)
|
||||
int stop_at_first_file, const struct pathspec *pathspec)
|
||||
{
|
||||
struct cached_dir cdir;
|
||||
enum path_treatment state, subdir_state, dir_state = path_none;
|
||||
@ -1832,12 +1845,34 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
|
||||
subdir_state =
|
||||
read_directory_recursive(dir, istate, path.buf,
|
||||
path.len, ud,
|
||||
check_only, pathspec);
|
||||
check_only, stop_at_first_file, pathspec);
|
||||
if (subdir_state > dir_state)
|
||||
dir_state = subdir_state;
|
||||
}
|
||||
|
||||
if (check_only) {
|
||||
if (stop_at_first_file) {
|
||||
/*
|
||||
* If stopping at first file, then
|
||||
* signal that a file was found by
|
||||
* returning `path_excluded`. This is
|
||||
* to return a consistent value
|
||||
* regardless of whether an ignored or
|
||||
* excluded file happened to be
|
||||
* encountered 1st.
|
||||
*
|
||||
* In current usage, the
|
||||
* `stop_at_first_file` is passed when
|
||||
* an ancestor directory has matched
|
||||
* an exclude pattern, so any found
|
||||
* files will be excluded.
|
||||
*/
|
||||
if (dir_state >= path_excluded) {
|
||||
dir_state = path_excluded;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* abort early if maximum state has been reached */
|
||||
if (dir_state == path_untracked) {
|
||||
if (cdir.fdir)
|
||||
@ -2108,7 +2143,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
|
||||
*/
|
||||
dir->untracked = NULL;
|
||||
if (!len || treat_leading_path(dir, istate, path, len, pathspec))
|
||||
read_directory_recursive(dir, istate, path, len, untracked, 0, pathspec);
|
||||
read_directory_recursive(dir, istate, path, len, untracked, 0, 0, pathspec);
|
||||
QSORT(dir->entries, dir->nr, cmp_dir_entry);
|
||||
QSORT(dir->ignored, dir->ignored_nr, cmp_dir_entry);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user