use std::path::PathBuf;
use glob::glob;
pub(crate) fn expand_glob(
input: PathBuf,
) -> anyhow::Result<impl Iterator<Item = PathBuf>> {
let input = input.to_string_lossy();
let paths = glob(&input)?.filter_map(Result::ok);
Ok(paths)
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use super::expand_glob;
fn sorted_matches(pattern: &str) -> Vec<String> {
let mut v: Vec<_> = expand_glob(PathBuf::from(pattern))
.unwrap()
.map(|p| p.to_string_lossy().into_owned())
.collect();
v.sort();
v
}
#[test]
fn literal_path_round_trips() {
let out = sorted_matches("Cargo.toml");
assert_eq!(out, vec!["Cargo.toml".to_string()]);
}
#[test]
fn no_such_file_yields_empty() {
let out = sorted_matches("no-such-file-xyz.tree");
assert!(out.is_empty());
}
#[test]
fn simple_star_glob() {
let out = sorted_matches("src/*.rs");
assert!(out.iter().any(|e| e.ends_with("main.rs")));
assert!(out.iter().any(|e| e.ends_with("check.rs")));
}
#[test]
fn recursive_double_star_glob() {
let out = sorted_matches("tests/scaffold/**/*.tree");
assert!(out.iter().any(|e| e.ends_with("basic.tree")));
assert!(out.iter().any(|e| e.ends_with("complex.tree")));
}
#[test]
fn forward_slash_glob_works_everywhere() {
let out = sorted_matches("tests/scaffold/*.tree");
assert!(out.iter().any(|e| e.ends_with("basic.tree")));
}
#[test]
#[cfg(windows)]
fn backslash_glob_works_the_same() {
let fwd = sorted_matches("tests/scaffold/*.tree");
let bwd = sorted_matches("tests\\scaffold\\*.tree");
assert_eq!(
fwd, bwd,
"backslash‐based glob must match forward‐slash one"
);
}
#[test]
fn invalid_pattern_returns_error() {
let bad = PathBuf::from("tests/scaffold/*[.tree");
let res = expand_glob(bad);
assert!(res.is_err(), "expected invalid glob to Err");
}
}