mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-10-06 05:36:58 +02:00
ignore: add min_depth
option
This mimics the eponymous option in `walkdir`. Closes #3158, PR #3162
This commit is contained in:
committed by
Andrew Gallant
parent
9d8016d10c
commit
2924d0c4c0
@@ -484,6 +484,7 @@ pub struct WalkBuilder {
|
||||
paths: Vec<PathBuf>,
|
||||
ig_builder: IgnoreBuilder,
|
||||
max_depth: Option<usize>,
|
||||
min_depth: Option<usize>,
|
||||
max_filesize: Option<u64>,
|
||||
follow_links: bool,
|
||||
same_file_system: bool,
|
||||
@@ -508,6 +509,7 @@ impl std::fmt::Debug for WalkBuilder {
|
||||
.field("paths", &self.paths)
|
||||
.field("ig_builder", &self.ig_builder)
|
||||
.field("max_depth", &self.max_depth)
|
||||
.field("min_depth", &self.min_depth)
|
||||
.field("max_filesize", &self.max_filesize)
|
||||
.field("follow_links", &self.follow_links)
|
||||
.field("threads", &self.threads)
|
||||
@@ -528,6 +530,7 @@ impl WalkBuilder {
|
||||
paths: vec![path.as_ref().to_path_buf()],
|
||||
ig_builder: IgnoreBuilder::new(),
|
||||
max_depth: None,
|
||||
min_depth: None,
|
||||
max_filesize: None,
|
||||
follow_links: false,
|
||||
same_file_system: false,
|
||||
@@ -542,6 +545,7 @@ impl WalkBuilder {
|
||||
pub fn build(&self) -> Walk {
|
||||
let follow_links = self.follow_links;
|
||||
let max_depth = self.max_depth;
|
||||
let min_depth = self.min_depth;
|
||||
let sorter = self.sorter.clone();
|
||||
let its = self
|
||||
.paths
|
||||
@@ -556,6 +560,9 @@ impl WalkBuilder {
|
||||
if let Some(max_depth) = max_depth {
|
||||
wd = wd.max_depth(max_depth);
|
||||
}
|
||||
if let Some(min_depth) = min_depth {
|
||||
wd = wd.min_depth(min_depth);
|
||||
}
|
||||
if let Some(ref sorter) = sorter {
|
||||
match sorter.clone() {
|
||||
Sorter::ByName(cmp) => {
|
||||
@@ -597,6 +604,7 @@ impl WalkBuilder {
|
||||
paths: self.paths.clone().into_iter(),
|
||||
ig_root: self.ig_builder.build(),
|
||||
max_depth: self.max_depth,
|
||||
min_depth: self.min_depth,
|
||||
max_filesize: self.max_filesize,
|
||||
follow_links: self.follow_links,
|
||||
same_file_system: self.same_file_system,
|
||||
@@ -621,6 +629,26 @@ impl WalkBuilder {
|
||||
/// The default, `None`, imposes no depth restriction.
|
||||
pub fn max_depth(&mut self, depth: Option<usize>) -> &mut WalkBuilder {
|
||||
self.max_depth = depth;
|
||||
if self.min_depth.is_some()
|
||||
&& self.max_depth.is_some()
|
||||
&& self.max_depth < self.min_depth
|
||||
{
|
||||
self.max_depth = self.min_depth;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// The minimum depth to recurse.
|
||||
///
|
||||
/// The default, `None`, imposes no minimum depth restriction.
|
||||
pub fn min_depth(&mut self, depth: Option<usize>) -> &mut WalkBuilder {
|
||||
self.min_depth = depth;
|
||||
if self.max_depth.is_some()
|
||||
&& self.min_depth.is_some()
|
||||
&& self.min_depth > self.max_depth
|
||||
{
|
||||
self.min_depth = self.max_depth;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
@@ -1199,6 +1227,7 @@ pub struct WalkParallel {
|
||||
ig_root: Ignore,
|
||||
max_filesize: Option<u64>,
|
||||
max_depth: Option<usize>,
|
||||
min_depth: Option<usize>,
|
||||
follow_links: bool,
|
||||
same_file_system: bool,
|
||||
threads: usize,
|
||||
@@ -1298,6 +1327,7 @@ impl WalkParallel {
|
||||
quit_now: quit_now.clone(),
|
||||
active_workers: active_workers.clone(),
|
||||
max_depth: self.max_depth,
|
||||
min_depth: self.min_depth,
|
||||
max_filesize: self.max_filesize,
|
||||
follow_links: self.follow_links,
|
||||
skip: self.skip.clone(),
|
||||
@@ -1487,6 +1517,8 @@ struct Worker<'s> {
|
||||
/// The maximum depth of directories to descend. A value of `0` means no
|
||||
/// descension at all.
|
||||
max_depth: Option<usize>,
|
||||
/// The minimum depth of directories to descend.
|
||||
min_depth: Option<usize>,
|
||||
/// The maximum size a searched file can be (in bytes). If a file exceeds
|
||||
/// this size it will be skipped.
|
||||
max_filesize: Option<u64>,
|
||||
@@ -1515,10 +1547,19 @@ impl<'s> Worker<'s> {
|
||||
}
|
||||
|
||||
fn run_one(&mut self, mut work: Work) -> WalkState {
|
||||
let should_visit = self
|
||||
.min_depth
|
||||
.map(|min_depth| work.dent.depth() >= min_depth)
|
||||
.unwrap_or(true);
|
||||
|
||||
// If the work is not a directory, then we can just execute the
|
||||
// caller's callback immediately and move on.
|
||||
if work.is_symlink() || !work.is_dir() {
|
||||
return self.visitor.visit(Ok(work.dent));
|
||||
return if should_visit {
|
||||
self.visitor.visit(Ok(work.dent))
|
||||
} else {
|
||||
WalkState::Continue
|
||||
};
|
||||
}
|
||||
if let Some(err) = work.add_parents() {
|
||||
let state = self.visitor.visit(Err(err));
|
||||
@@ -1551,9 +1592,11 @@ impl<'s> Worker<'s> {
|
||||
// entry before passing the error value.
|
||||
let readdir = work.read_dir();
|
||||
let depth = work.dent.depth();
|
||||
let state = self.visitor.visit(Ok(work.dent));
|
||||
if !state.is_continue() {
|
||||
return state;
|
||||
if should_visit {
|
||||
let state = self.visitor.visit(Ok(work.dent));
|
||||
if !state.is_continue() {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
if !descend {
|
||||
return WalkState::Skip;
|
||||
@@ -2156,6 +2199,51 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn min_depth() {
|
||||
let td = tmpdir();
|
||||
mkdirp(td.path().join("a/b/c"));
|
||||
wfile(td.path().join("foo"), "");
|
||||
wfile(td.path().join("a/foo"), "");
|
||||
wfile(td.path().join("a/b/foo"), "");
|
||||
wfile(td.path().join("a/b/c/foo"), "");
|
||||
|
||||
let builder = WalkBuilder::new(td.path());
|
||||
assert_paths(
|
||||
td.path(),
|
||||
&builder,
|
||||
&["a", "a/b", "a/b/c", "foo", "a/foo", "a/b/foo", "a/b/c/foo"],
|
||||
);
|
||||
let mut builder = WalkBuilder::new(td.path());
|
||||
assert_paths(
|
||||
td.path(),
|
||||
&builder.min_depth(Some(0)),
|
||||
&["a", "a/b", "a/b/c", "foo", "a/foo", "a/b/foo", "a/b/c/foo"],
|
||||
);
|
||||
assert_paths(
|
||||
td.path(),
|
||||
&builder.min_depth(Some(1)),
|
||||
&["a", "a/b", "a/b/c", "foo", "a/foo", "a/b/foo", "a/b/c/foo"],
|
||||
);
|
||||
assert_paths(
|
||||
td.path(),
|
||||
builder.min_depth(Some(2)),
|
||||
&["a/b", "a/b/c", "a/b/c/foo", "a/b/foo", "a/foo"],
|
||||
);
|
||||
assert_paths(
|
||||
td.path(),
|
||||
builder.min_depth(Some(3)),
|
||||
&["a/b/c", "a/b/c/foo", "a/b/foo"],
|
||||
);
|
||||
assert_paths(td.path(), builder.min_depth(Some(10)), &[]);
|
||||
|
||||
assert_paths(
|
||||
td.path(),
|
||||
builder.min_depth(Some(2)).max_depth(Some(1)),
|
||||
&["a/b", "a/foo"],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_filesize() {
|
||||
let td = tmpdir();
|
||||
|
Reference in New Issue
Block a user