mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-11-23 21:54:45 +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>,
|
paths: Vec<PathBuf>,
|
||||||
ig_builder: IgnoreBuilder,
|
ig_builder: IgnoreBuilder,
|
||||||
max_depth: Option<usize>,
|
max_depth: Option<usize>,
|
||||||
|
min_depth: Option<usize>,
|
||||||
max_filesize: Option<u64>,
|
max_filesize: Option<u64>,
|
||||||
follow_links: bool,
|
follow_links: bool,
|
||||||
same_file_system: bool,
|
same_file_system: bool,
|
||||||
@@ -508,6 +509,7 @@ impl std::fmt::Debug for WalkBuilder {
|
|||||||
.field("paths", &self.paths)
|
.field("paths", &self.paths)
|
||||||
.field("ig_builder", &self.ig_builder)
|
.field("ig_builder", &self.ig_builder)
|
||||||
.field("max_depth", &self.max_depth)
|
.field("max_depth", &self.max_depth)
|
||||||
|
.field("min_depth", &self.min_depth)
|
||||||
.field("max_filesize", &self.max_filesize)
|
.field("max_filesize", &self.max_filesize)
|
||||||
.field("follow_links", &self.follow_links)
|
.field("follow_links", &self.follow_links)
|
||||||
.field("threads", &self.threads)
|
.field("threads", &self.threads)
|
||||||
@@ -528,6 +530,7 @@ impl WalkBuilder {
|
|||||||
paths: vec![path.as_ref().to_path_buf()],
|
paths: vec![path.as_ref().to_path_buf()],
|
||||||
ig_builder: IgnoreBuilder::new(),
|
ig_builder: IgnoreBuilder::new(),
|
||||||
max_depth: None,
|
max_depth: None,
|
||||||
|
min_depth: None,
|
||||||
max_filesize: None,
|
max_filesize: None,
|
||||||
follow_links: false,
|
follow_links: false,
|
||||||
same_file_system: false,
|
same_file_system: false,
|
||||||
@@ -542,6 +545,7 @@ impl WalkBuilder {
|
|||||||
pub fn build(&self) -> Walk {
|
pub fn build(&self) -> Walk {
|
||||||
let follow_links = self.follow_links;
|
let follow_links = self.follow_links;
|
||||||
let max_depth = self.max_depth;
|
let max_depth = self.max_depth;
|
||||||
|
let min_depth = self.min_depth;
|
||||||
let sorter = self.sorter.clone();
|
let sorter = self.sorter.clone();
|
||||||
let its = self
|
let its = self
|
||||||
.paths
|
.paths
|
||||||
@@ -556,6 +560,9 @@ impl WalkBuilder {
|
|||||||
if let Some(max_depth) = max_depth {
|
if let Some(max_depth) = max_depth {
|
||||||
wd = wd.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 {
|
if let Some(ref sorter) = sorter {
|
||||||
match sorter.clone() {
|
match sorter.clone() {
|
||||||
Sorter::ByName(cmp) => {
|
Sorter::ByName(cmp) => {
|
||||||
@@ -597,6 +604,7 @@ impl WalkBuilder {
|
|||||||
paths: self.paths.clone().into_iter(),
|
paths: self.paths.clone().into_iter(),
|
||||||
ig_root: self.ig_builder.build(),
|
ig_root: self.ig_builder.build(),
|
||||||
max_depth: self.max_depth,
|
max_depth: self.max_depth,
|
||||||
|
min_depth: self.min_depth,
|
||||||
max_filesize: self.max_filesize,
|
max_filesize: self.max_filesize,
|
||||||
follow_links: self.follow_links,
|
follow_links: self.follow_links,
|
||||||
same_file_system: self.same_file_system,
|
same_file_system: self.same_file_system,
|
||||||
@@ -621,6 +629,26 @@ impl WalkBuilder {
|
|||||||
/// The default, `None`, imposes no depth restriction.
|
/// The default, `None`, imposes no depth restriction.
|
||||||
pub fn max_depth(&mut self, depth: Option<usize>) -> &mut WalkBuilder {
|
pub fn max_depth(&mut self, depth: Option<usize>) -> &mut WalkBuilder {
|
||||||
self.max_depth = depth;
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1199,6 +1227,7 @@ pub struct WalkParallel {
|
|||||||
ig_root: Ignore,
|
ig_root: Ignore,
|
||||||
max_filesize: Option<u64>,
|
max_filesize: Option<u64>,
|
||||||
max_depth: Option<usize>,
|
max_depth: Option<usize>,
|
||||||
|
min_depth: Option<usize>,
|
||||||
follow_links: bool,
|
follow_links: bool,
|
||||||
same_file_system: bool,
|
same_file_system: bool,
|
||||||
threads: usize,
|
threads: usize,
|
||||||
@@ -1298,6 +1327,7 @@ impl WalkParallel {
|
|||||||
quit_now: quit_now.clone(),
|
quit_now: quit_now.clone(),
|
||||||
active_workers: active_workers.clone(),
|
active_workers: active_workers.clone(),
|
||||||
max_depth: self.max_depth,
|
max_depth: self.max_depth,
|
||||||
|
min_depth: self.min_depth,
|
||||||
max_filesize: self.max_filesize,
|
max_filesize: self.max_filesize,
|
||||||
follow_links: self.follow_links,
|
follow_links: self.follow_links,
|
||||||
skip: self.skip.clone(),
|
skip: self.skip.clone(),
|
||||||
@@ -1487,6 +1517,8 @@ struct Worker<'s> {
|
|||||||
/// The maximum depth of directories to descend. A value of `0` means no
|
/// The maximum depth of directories to descend. A value of `0` means no
|
||||||
/// descension at all.
|
/// descension at all.
|
||||||
max_depth: Option<usize>,
|
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
|
/// The maximum size a searched file can be (in bytes). If a file exceeds
|
||||||
/// this size it will be skipped.
|
/// this size it will be skipped.
|
||||||
max_filesize: Option<u64>,
|
max_filesize: Option<u64>,
|
||||||
@@ -1515,10 +1547,19 @@ impl<'s> Worker<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_one(&mut self, mut work: Work) -> WalkState {
|
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
|
// If the work is not a directory, then we can just execute the
|
||||||
// caller's callback immediately and move on.
|
// caller's callback immediately and move on.
|
||||||
if work.is_symlink() || !work.is_dir() {
|
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() {
|
if let Some(err) = work.add_parents() {
|
||||||
let state = self.visitor.visit(Err(err));
|
let state = self.visitor.visit(Err(err));
|
||||||
@@ -1551,9 +1592,11 @@ impl<'s> Worker<'s> {
|
|||||||
// entry before passing the error value.
|
// entry before passing the error value.
|
||||||
let readdir = work.read_dir();
|
let readdir = work.read_dir();
|
||||||
let depth = work.dent.depth();
|
let depth = work.dent.depth();
|
||||||
let state = self.visitor.visit(Ok(work.dent));
|
if should_visit {
|
||||||
if !state.is_continue() {
|
let state = self.visitor.visit(Ok(work.dent));
|
||||||
return state;
|
if !state.is_continue() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if !descend {
|
if !descend {
|
||||||
return WalkState::Skip;
|
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]
|
#[test]
|
||||||
fn max_filesize() {
|
fn max_filesize() {
|
||||||
let td = tmpdir();
|
let td = tmpdir();
|
||||||
|
|||||||
Reference in New Issue
Block a user