om_context/
ignore.rs

1use glob::Pattern;
2use std::fs;
3use std::path::Path;
4
5pub struct IgnorePatterns {
6    patterns: Vec<Pattern>,
7}
8
9impl IgnorePatterns {
10    pub fn load(root: &Path) -> Self {
11        let mut patterns = Vec::new();
12
13        if let Some(home) = dirs::home_dir() {
14            let global_ignore = home.join(".omignore");
15            if let Ok(ps) = Self::parse_file(&global_ignore) {
16                patterns.extend(ps);
17            }
18        }
19
20        let local_ignore = root.join(".omignore");
21        if let Ok(ps) = Self::parse_file(&local_ignore) {
22            patterns.extend(ps);
23        }
24
25        IgnorePatterns { patterns }
26    }
27
28    fn parse_file(path: &Path) -> Result<Vec<Pattern>, Box<dyn std::error::Error>> {
29        let content = fs::read_to_string(path)?;
30        let mut patterns = Vec::new();
31
32        for line in content.lines() {
33            let line = line.trim();
34            if line.is_empty() || line.starts_with('#') {
35                continue;
36            }
37
38            let pattern = if line.starts_with("**/") {
39                line.to_string()
40            } else if line.ends_with('/') {
41                format!("{}**", line)
42            } else if line.contains('*') || line.contains('?') {
43                format!("**/{}", line)
44            } else {
45                line.to_string()
46            };
47
48            if let Ok(p) = Pattern::new(&pattern) {
49                patterns.push(p);
50            }
51        }
52
53        Ok(patterns)
54    }
55
56    pub fn is_ignored(&self, path: &str) -> bool {
57        self.patterns.iter().any(|p| p.matches(path))
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn test_pattern_matching() {
67        let patterns = vec![
68            Pattern::new("**/*.lock").unwrap(),
69            Pattern::new("**/*-lock.*").unwrap(),
70            Pattern::new("**/node_modules/**").unwrap(),
71            Pattern::new("dist/**").unwrap(),
72        ];
73
74        let ignore = IgnorePatterns { patterns };
75
76        assert!(ignore.is_ignored("package-lock.json"));
77        assert!(ignore.is_ignored("Cargo.lock"));
78        assert!(ignore.is_ignored("src/node_modules/foo/bar.js"));
79        assert!(ignore.is_ignored("dist/bundle.js"));
80        assert!(!ignore.is_ignored("src/main.rs"));
81    }
82}