Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: dont do needless search when we reach max depth #2566

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
59 changes: 39 additions & 20 deletions crates/ignore/src/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ impl Ignore {
ig = prebuilt.clone();
continue;
}
let (mut igtmp, err) = ig.add_child_path(parent);
let (mut igtmp, err) = ig.add_child_path(parent, false);
errs.maybe_push(err);
igtmp.is_absolute_parent = true;
igtmp.absolute_base = Some(absolute_base.clone());
Expand Down Expand Up @@ -226,14 +226,32 @@ impl Ignore {
&self,
dir: P,
) -> (Ignore, Option<Error>) {
let (ig, err) = self.add_child_path(dir.as_ref());
let (ig, err) = self.add_child_path(dir.as_ref(), false);
(Ignore(Arc::new(ig)), err)
}

/// Like add_child but takes `is_leaf` boolean, if set to true, we assume that the search won't recurse inside
/// the provided dir which allows us to do some optimizations like not searching for ignore files.
pub(crate) fn add_child2<P: AsRef<Path>>(
&self,
dir: P,
is_leaf: bool,
) -> (Ignore, Option<Error>) {
let (ig, err) = self.add_child_path(dir.as_ref(), is_leaf);
(Ignore(Arc::new(ig)), err)
}

/// Like add_child, but takes a full path and returns an IgnoreInner.
fn add_child_path(&self, dir: &Path) -> (IgnoreInner, Option<Error>) {
let git_type = if self.0.opts.require_git
&& (self.0.opts.git_ignore || self.0.opts.git_exclude)
/// Also takes `is_leaf` boolean, if set to true, we assume that the search won't recurse inside
/// the provided dir which allows us to do some optimizations like not searching for ignore files.
fn add_child_path(
&self,
dir: &Path,
is_leaf: bool,
) -> (IgnoreInner, Option<Error>) {
let git_type = if !is_leaf
&& (self.0.opts.require_git
&& (self.0.opts.git_ignore || self.0.opts.git_exclude))
{
dir.join(".git").metadata().ok().map(|md| md.file_type())
} else {
Expand All @@ -242,19 +260,20 @@ impl Ignore {
let has_git = git_type.map(|_| true).unwrap_or(false);

let mut errs = PartialErrorBuilder::default();
let custom_ig_matcher = if self.0.custom_ignore_filenames.is_empty() {
Gitignore::empty()
} else {
let (m, err) = create_gitignore(
&dir,
&dir,
&self.0.custom_ignore_filenames,
self.0.opts.ignore_case_insensitive,
);
errs.maybe_push(err);
m
};
let ig_matcher = if !self.0.opts.ignore {
let custom_ig_matcher =
if is_leaf || self.0.custom_ignore_filenames.is_empty() {
Gitignore::empty()
} else {
let (m, err) = create_gitignore(
&dir,
&dir,
&self.0.custom_ignore_filenames,
self.0.opts.ignore_case_insensitive,
);
errs.maybe_push(err);
m
};
let ig_matcher = if is_leaf || !self.0.opts.ignore {
Gitignore::empty()
} else {
let (m, err) = create_gitignore(
Expand All @@ -266,7 +285,7 @@ impl Ignore {
errs.maybe_push(err);
m
};
let gi_matcher = if !self.0.opts.git_ignore {
let gi_matcher = if is_leaf || !self.0.opts.git_ignore {
Gitignore::empty()
} else {
let (m, err) = create_gitignore(
Expand All @@ -278,7 +297,7 @@ impl Ignore {
errs.maybe_push(err);
m
};
let gi_exclude_matcher = if !self.0.opts.git_exclude {
let gi_exclude_matcher = if is_leaf || !self.0.opts.git_exclude {
Gitignore::empty()
} else {
match resolve_git_commondir(dir, git_type) {
Expand Down
11 changes: 9 additions & 2 deletions crates/ignore/src/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ impl WalkBuilder {
max_filesize: self.max_filesize,
skip: self.skip.clone(),
filter: self.filter.clone(),
max_depth: max_depth,
}
}

Expand Down Expand Up @@ -918,6 +919,7 @@ pub struct Walk {
max_filesize: Option<u64>,
skip: Option<Arc<Handle>>,
filter: Option<Filter>,
max_depth: Option<usize>,
}

impl Walk {
Expand Down Expand Up @@ -1010,16 +1012,21 @@ impl Iterator for Walk {
Err(err) => return Some(Err(err)),
Ok(should_skip) => should_skip,
};
let is_leaf = self
.max_depth
.map(|max| ent.depth() >= max)
.unwrap_or(false);
if should_skip {
self.it.as_mut().unwrap().it.skip_current_dir();
// Still need to push this on the stack because
// we'll get a WalkEvent::Exit event for this dir.
// We don't care if it errors though.
let (igtmp, _) = self.ig.add_child(ent.path());
let (igtmp, _) =
self.ig.add_child2(ent.path(), is_leaf);
self.ig = igtmp;
continue;
}
let (igtmp, err) = self.ig.add_child(ent.path());
let (igtmp, err) = self.ig.add_child2(ent.path(), is_leaf);
self.ig = igtmp;
ent.err = err;
return Some(Ok(ent));
Expand Down