lintel_validate/
discover.rs1use std::path::{Path, PathBuf};
2
3use crate::parsers;
4
5pub fn discover_files(root: &str, excludes: &[String]) -> Result<Vec<PathBuf>, anyhow::Error> {
13 let walker = ignore::WalkBuilder::new(root)
14 .hidden(false) .git_ignore(true)
16 .git_global(true)
17 .git_exclude(true)
18 .build();
19
20 let mut files = Vec::new();
21 for entry in walker {
22 let entry = entry?;
23 let path = entry.path();
24 if !path.is_file() {
25 continue;
26 }
27 if parsers::detect_format(path).is_none() {
28 continue;
29 }
30 if is_excluded(path, excludes) {
31 continue;
32 }
33 files.push(path.to_path_buf());
34 }
35
36 files.sort();
37 Ok(files)
38}
39
40fn is_excluded(path: &Path, excludes: &[String]) -> bool {
41 let path_str = match path.to_str() {
42 Some(s) => s.strip_prefix("./").unwrap_or(s),
43 None => return false,
44 };
45 excludes
46 .iter()
47 .any(|pattern| glob_match::glob_match(pattern, path_str))
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use std::fs;
54
55 #[test]
56 fn discovers_known_extensions() -> anyhow::Result<()> {
57 let tmp = tempfile::tempdir()?;
58 fs::write(tmp.path().join("a.json"), "{}")?;
59 fs::write(tmp.path().join("b.yaml"), "key: val")?;
60 fs::write(tmp.path().join("c.yml"), "key: val")?;
61 fs::write(tmp.path().join("d.json5"), "{}")?;
62 fs::write(tmp.path().join("e.jsonc"), "{}")?;
63 fs::write(tmp.path().join("f.txt"), "nope")?;
64 fs::write(tmp.path().join("g.nix"), "{ }")?;
65
66 let root = tmp.path().to_str().expect("temp dir should be valid UTF-8");
67 let files = discover_files(root, &[])?;
68 assert_eq!(files.len(), 5);
69 assert!(files.iter().all(|f| parsers::detect_format(f).is_some()));
70 Ok(())
71 }
72
73 #[test]
74 fn respects_exclude_patterns() -> anyhow::Result<()> {
75 let tmp = tempfile::tempdir()?;
76 let sub = tmp.path().join("vendor");
77 fs::create_dir_all(&sub)?;
78 fs::write(tmp.path().join("a.json"), "{}")?;
79 fs::write(sub.join("b.json"), "{}")?;
80
81 let root = tmp.path().to_str().expect("temp dir should be valid UTF-8");
82 let files = discover_files(root, &["**/vendor/**".to_string()])?;
83 assert_eq!(files.len(), 1);
84 Ok(())
85 }
86
87 #[test]
88 fn discovers_dotfiles() -> anyhow::Result<()> {
89 let tmp = tempfile::tempdir()?;
90 fs::write(tmp.path().join(".eslintrc.json"), "{}")?;
91
92 let root = tmp.path().to_str().expect("temp dir should be valid UTF-8");
93 let files = discover_files(root, &[])?;
94 assert_eq!(files.len(), 1);
95 Ok(())
96 }
97}