use anyhow::anyhow;
use globwalk::GlobWalkerBuilder;
use std::path::PathBuf;
pub fn glob_builder_base<PAT: AsRef<str>>(
pattern: PAT,
filters: &[PAT],
) -> anyhow::Result<GlobWalkerBuilder> {
let (base, pat) = glob_base_unrooted(pattern.as_ref())?;
let base_str: &str = base
.to_str()
.ok_or_else(|| anyhow!("Glob base path is not valid"))?;
let pat_str: &str = pat
.to_str()
.ok_or_else(|| anyhow!("Glob pattern is not valid"))?;
let mut filters = filters
.iter()
.map(|f| f.as_ref())
.map(when_starts_with_dot_path)
.collect::<Vec<_>>();
filters.push(when_starts_with_dot_path(pat_str));
Ok(GlobWalkerBuilder::from_patterns(
when_starts_with_dot_path(base_str),
&filters,
))
}
fn when_starts_with_dot_path(path: &str) -> &str {
if path.starts_with("./") || path.starts_with(".\\") {
&path[2..]
} else {
path
}
}
pub type BasePath = PathBuf;
pub type Pattern = PathBuf;
fn glob_base_unrooted(path_pattern: &str) -> anyhow::Result<(BasePath, Pattern)> {
let path_buf = path_pattern.parse::<PathBuf>()?;
Ok(if path_buf.is_absolute() {
let mut base = PathBuf::new();
let mut pattern = PathBuf::new();
let mut globbing = false;
for c in path_buf.components() {
let os = c.as_os_str().to_str().unwrap();
for c in &["*", "{", "}"][..] {
if os.contains(c) {
globbing = true;
break;
}
}
if globbing {
pattern.push(c);
} else {
base.push(c);
}
}
(base, pattern)
} else {
(".".parse().unwrap(), path_buf)
})
}