use std::fs;
use std::path::Path;
use crate::files::walk_targets;
fn build(root: &Path, entries: &[(&str, &str)]) {
for (rel, body) in entries {
let path = root.join(rel);
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).expect("create parents");
}
fs::write(&path, body).expect("write file");
}
}
fn relative(root: &Path, paths: Vec<std::path::PathBuf>) -> Vec<String> {
paths
.into_iter()
.map(|p| {
p.strip_prefix(root)
.unwrap_or(&p)
.to_string_lossy()
.into_owned()
})
.collect()
}
#[test]
fn finds_files_nested_multiple_levels_deep() {
let temp = tempfile::TempDir::new().expect("tempdir");
let root = temp.path();
build(
root,
&[
("top.rs", ""),
("a/one.rs", ""),
("a/b/two.rs", ""),
("a/b/c/three.rs", ""),
],
);
let found = relative(root, walk_targets(root, is_rs_file));
assert!(found.contains(&"top.rs".to_owned()), "{found:?}");
assert!(found.contains(&"a/b/c/three.rs".to_owned()), "{found:?}");
assert_eq!(found.len(), 4);
}
fn is_rs_file(path: &Path) -> bool {
path.extension().is_some_and(|e| e == "rs")
}
#[test]
fn does_not_descend_into_an_ignored_directory() {
let temp = tempfile::TempDir::new().expect("tempdir");
let root = temp.path();
build(
root,
&[
("kept.rs", ""),
("node_modules/should_skip.rs", ""),
("node_modules/dep/nested.rs", ""),
("venv/also_skip.py", ""),
],
);
let found = relative(root, walk_targets(root, is_scan_targetish));
assert_eq!(
found,
vec!["kept.rs".to_owned()],
"ignored directory contents must not appear: {found:?}"
);
}
#[test]
fn does_not_return_non_target_files() {
let temp = tempfile::TempDir::new().expect("tempdir");
let root = temp.path();
build(
root,
&[
("keep.rs", ""),
("notes.txt", ""),
("Cargo.lock", ""),
("logo.png", ""),
("README.md", ""),
("Makefile", ""),
],
);
let found = relative(root, walk_targets(root, is_scan_targetish));
assert_eq!(found, vec!["README.md".to_owned(), "keep.rs".to_owned()]);
}
#[test]
fn respects_a_gitignore_in_the_walked_tree() {
let temp = tempfile::TempDir::new().expect("tempdir");
let root = temp.path();
build(
root,
&[
(".gitignore", "ignored/\n"),
("keep.rs", ""),
("ignored/skipped.rs", ""),
],
);
let found = relative(root, walk_targets(root, is_rs_file));
assert_eq!(
found,
vec!["keep.rs".to_owned()],
"gitignored entries should not be returned: {found:?}"
);
}
fn is_scan_targetish(path: &Path) -> bool {
matches!(
path.extension().and_then(|e| e.to_str()),
Some("rs" | "py" | "md")
)
}