Skip to main content

code_moniker_cli/
walk.rs

1use std::path::{Path, PathBuf};
2
3use crate::lang::path_to_lang;
4use code_moniker_core::lang::Lang;
5
6pub struct WalkedFile {
7	pub path: PathBuf,
8	pub lang: Lang,
9}
10
11pub fn walk_lang_files(root: &Path) -> Vec<WalkedFile> {
12	ignore::WalkBuilder::new(root)
13		.build()
14		.filter_map(|entry| entry.ok())
15		.filter(|e| e.file_type().is_some_and(|t| t.is_file()))
16		.filter_map(|e| {
17			let p = e.into_path();
18			let lang = path_to_lang(&p).ok()?;
19			Some(WalkedFile { path: p, lang })
20		})
21		.collect()
22}
23
24#[cfg(test)]
25mod tests {
26	use super::*;
27	use std::collections::HashSet;
28	use std::fs;
29
30	fn write(root: &Path, rel: &str, body: &str) {
31		let p = root.join(rel);
32		if let Some(parent) = p.parent() {
33			fs::create_dir_all(parent).unwrap();
34		}
35		fs::write(p, body).unwrap();
36	}
37
38	#[test]
39	fn walks_supported_extensions_only() {
40		let tmp = tempfile::tempdir().unwrap();
41		let root = tmp.path();
42		write(root, "a.ts", "");
43		write(root, "b.rs", "");
44		write(root, "c.txt", "ignored");
45		write(root, "nested/d.py", "");
46		let mut files: HashSet<(String, Lang)> = walk_lang_files(root)
47			.into_iter()
48			.map(|f| {
49				let rel = f.path.strip_prefix(root).unwrap().to_string_lossy().into();
50				(rel, f.lang)
51			})
52			.collect();
53		assert!(files.remove(&("a.ts".into(), Lang::Ts)));
54		assert!(files.remove(&("b.rs".into(), Lang::Rs)));
55		assert!(files.remove(&("nested/d.py".into(), Lang::Python)));
56		assert!(files.is_empty(), "unexpected files: {files:?}");
57	}
58
59	#[test]
60	fn respects_gitignore() {
61		let tmp = tempfile::tempdir().unwrap();
62		let root = tmp.path();
63		write(root, ".gitignore", "skip/\n");
64		write(root, "kept.ts", "");
65		write(root, "skip/dropped.ts", "");
66		fs::create_dir_all(root.join(".git")).unwrap();
67		let files: Vec<String> = walk_lang_files(root)
68			.into_iter()
69			.map(|f| f.path.strip_prefix(root).unwrap().to_string_lossy().into())
70			.collect();
71		assert_eq!(files, vec!["kept.ts".to_string()]);
72	}
73}