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 --ignoredmaint
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,
|
static enum path_treatment read_directory_recursive(struct dir_struct *dir,
|
||||||
struct index_state *istate, const char *path, int len,
|
struct index_state *istate, const char *path, int len,
|
||||||
struct untracked_cache_dir *untracked,
|
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,
|
static int get_dtype(struct dirent *de, struct index_state *istate,
|
||||||
const char *path, int len);
|
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,
|
untracked = lookup_untracked(dir->untracked, untracked,
|
||||||
dirname + baselen, len - baselen);
|
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,
|
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.
|
* with check_only set.
|
||||||
*/
|
*/
|
||||||
return read_directory_recursive(dir, istate, path->buf, path->len,
|
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
|
* We get path_recurse in the first run when
|
||||||
* directory_exists_in_index() returns index_nonexistent. We
|
* 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).
|
* Also, we ignore the name ".git" (even if it is not a directory).
|
||||||
* That likely will not change.
|
* 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.
|
* 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,
|
static enum path_treatment read_directory_recursive(struct dir_struct *dir,
|
||||||
struct index_state *istate, const char *base, int baselen,
|
struct index_state *istate, const char *base, int baselen,
|
||||||
struct untracked_cache_dir *untracked, int check_only,
|
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;
|
struct cached_dir cdir;
|
||||||
enum path_treatment state, subdir_state, dir_state = path_none;
|
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 =
|
subdir_state =
|
||||||
read_directory_recursive(dir, istate, path.buf,
|
read_directory_recursive(dir, istate, path.buf,
|
||||||
path.len, ud,
|
path.len, ud,
|
||||||
check_only, pathspec);
|
check_only, stop_at_first_file, pathspec);
|
||||||
if (subdir_state > dir_state)
|
if (subdir_state > dir_state)
|
||||||
dir_state = subdir_state;
|
dir_state = subdir_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_only) {
|
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 */
|
/* abort early if maximum state has been reached */
|
||||||
if (dir_state == path_untracked) {
|
if (dir_state == path_untracked) {
|
||||||
if (cdir.fdir)
|
if (cdir.fdir)
|
||||||
|
|
@ -2108,7 +2143,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
|
||||||
*/
|
*/
|
||||||
dir->untracked = NULL;
|
dir->untracked = NULL;
|
||||||
if (!len || treat_leading_path(dir, istate, path, len, pathspec))
|
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->entries, dir->nr, cmp_dir_entry);
|
||||||
QSORT(dir->ignored, dir->ignored_nr, cmp_dir_entry);
|
QSORT(dir->ignored, dir->ignored_nr, cmp_dir_entry);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue