use std::path::Path;
#[derive(Clone, Debug)]
pub(crate) struct HaystackBuilder {
strip_dot_prefix: bool,
}
impl HaystackBuilder {
pub(crate) fn new() -> HaystackBuilder {
HaystackBuilder { strip_dot_prefix: false }
}
pub(crate) fn build_from_result(
&self,
result: Result<ignore::DirEntry, ignore::Error>,
) -> Option<Haystack> {
match result {
Ok(dent) => self.build(dent),
Err(err) => {
err_message!("{err}");
None
}
}
}
fn build(&self, dent: ignore::DirEntry) -> Option<Haystack> {
let hay = Haystack { dent, strip_dot_prefix: self.strip_dot_prefix };
if let Some(err) = hay.dent.error() {
ignore_message!("{err}");
}
if hay.is_explicit() {
return Some(hay);
}
if hay.is_file() {
return Some(hay);
}
if !hay.is_dir() {
log::debug!(
"ignoring {}: failed to pass haystack filter: \
file type: {:?}, metadata: {:?}",
hay.dent.path().display(),
hay.dent.file_type(),
hay.dent.metadata()
);
}
None
}
pub(crate) fn strip_dot_prefix(
&mut self,
yes: bool,
) -> &mut HaystackBuilder {
self.strip_dot_prefix = yes;
self
}
}
#[derive(Clone, Debug)]
pub(crate) struct Haystack {
dent: ignore::DirEntry,
strip_dot_prefix: bool,
}
impl Haystack {
pub(crate) fn path(&self) -> &Path {
if self.strip_dot_prefix && self.dent.path().starts_with("./") {
self.dent.path().strip_prefix("./").unwrap()
} else {
self.dent.path()
}
}
pub(crate) fn is_stdin(&self) -> bool {
self.dent.is_stdin()
}
pub(crate) fn is_explicit(&self) -> bool {
self.is_stdin() || (self.dent.depth() == 0 && !self.is_dir())
}
fn is_dir(&self) -> bool {
let ft = match self.dent.file_type() {
None => return false,
Some(ft) => ft,
};
if ft.is_dir() {
return true;
}
self.dent.path_is_symlink() && self.dent.path().is_dir()
}
fn is_file(&self) -> bool {
self.dent.file_type().map_or(false, |ft| ft.is_file())
}
}