Skip to main content

reinhardt_admin_cli/migrate_v2/
walker.rs

1//! Directory walker for the migrate-manouche-v2 codemod.
2
3use std::path::{Path, PathBuf};
4
5use walkdir::WalkDir;
6
7/// Returns every `*.rs` file under `root`, skipping `target/` and hidden dirs.
8///
9/// The `root` itself is never skipped even if its file_name starts with `.`
10/// (e.g. macOS `tempdir()` returns paths under `/var/folders/.../T/.tmpXXX`).
11pub fn find_rs_files(root: &Path) -> anyhow::Result<Vec<PathBuf>> {
12	let mut out = Vec::new();
13	for entry in WalkDir::new(root)
14		.into_iter()
15		.filter_entry(|e| !is_skipped_descendant(root, e.path()))
16	{
17		let entry = entry?;
18		if entry.file_type().is_file()
19			&& entry.path().extension().map(|e| e == "rs").unwrap_or(false)
20		{
21			out.push(entry.into_path());
22		}
23	}
24	out.sort();
25	Ok(out)
26}
27
28fn is_skipped_descendant(root: &Path, p: &Path) -> bool {
29	// Never skip the anchor itself.
30	if p == root {
31		return false;
32	}
33	let name = p.file_name().and_then(|s| s.to_str()).unwrap_or("");
34	// Skip the cargo target directory and any hidden directory (e.g. `.git`),
35	// but only when encountered as a descendant of `root`.
36	// Files in hidden directories are not skipped because `filter_entry`
37	// already prevents descent into them — we only need to filter
38	// hidden directories themselves.
39	if name == "target" {
40		return true;
41	}
42	p.is_dir() && name.starts_with('.')
43}