stern4rust/
exclusion_set.rs1use anyhow::Result;
6use std::path::Path;
7use std::path::PathBuf;
8
9use crate::exclusion::Exclusion;
10use crate::exclusion_outcome::ExclusionOutcome;
11
12pub struct ExclusionSet {
23 exclusions: Vec<Exclusion>,
24}
25
26impl ExclusionSet {
27 pub fn new(patterns: &[String]) -> Result<Self> {
28 let exclusions = patterns
29 .iter()
30 .map(|pattern| Exclusion::new(pattern))
31 .collect::<Result<Vec<_>>>()?;
32 Ok(Self { exclusions })
33 }
34
35 pub fn is_empty(&self) -> bool {
36 self.exclusions.is_empty()
37 }
38
39 pub fn apply(&self, paths: Vec<PathBuf>, root: &Path) -> ExclusionOutcome {
40 let mut counts = vec![0usize; self.exclusions.len()];
41 let mut kept = Vec::new();
42 for path in paths {
43 match self.covering(&path, root) {
44 Some(index) => counts[index] += 1,
45 None => kept.push(path),
46 }
47 }
48 let excluded = self
49 .exclusions
50 .iter()
51 .zip(counts)
52 .map(|(exclusion, count)| (exclusion.pattern().to_string(), count))
53 .collect();
54 ExclusionOutcome::new(kept, excluded)
55 }
56
57 fn covering(&self, path: &Path, root: &Path) -> Option<usize> {
58 let relative = path.strip_prefix(root).unwrap_or(path);
59 self.exclusions
60 .iter()
61 .position(|exclusion| exclusion.matches(relative))
62 }
63}