1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
use std::{
ops::{Deref, DerefMut},
path::{Path, PathBuf},
};
use ignore::WalkBuilder;
pub struct Search {
inner: WalkBuilder,
paths: Vec<PathBuf>,
}
impl Search {
pub fn new<P: AsRef<Path>>(path: P) -> Self {
Self {
inner: WalkBuilder::new(&path),
paths: Vec::from([path.as_ref().to_owned()]),
}
}
pub fn add<P: AsRef<Path>>(&mut self, path: P) {
self.paths.push(path.as_ref().to_owned());
self.inner.add(path);
}
pub fn build(mut self) -> impl Iterator<Item = PathBuf> {
self.inner
.standard_filters(true)
.build()
.flat_map(move |res| match res.map(|d| d.into_path()) {
Ok(p) if self.paths.contains(&p) => {
tracing::debug!(?p, "Ignoring search directory");
None
}
Ok(p) => Some(p),
Err(err) => {
tracing::error!(%err, "Ignoring errored path");
None
}
})
}
}
impl Deref for Search {
type Target = WalkBuilder;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for Search {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl IntoIterator for Search {
type Item = PathBuf;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.build().collect::<Vec<_>>().into_iter()
}
}
impl TryFrom<crate::config::Search> for Search {
type Error = ();
fn try_from(value: crate::config::Search) -> Result<Self, Self::Error> {
if value.paths.is_empty() {
return Err(());
}
let (init, paths) = value.paths.split_first().unwrap();
let mut search = Search::new(init);
for path in paths {
search.add(path);
}
search.max_depth(value.max_depth);
search.hidden(!value.hidden);
Ok(search)
}
}
|