weavatrix-scan 0.4.6

Deterministic, safe repository scanner for code intelligence
Documentation
use super::{IgnoreError, RepositoryMatch, RuleAction, RuleSet, parse_file, source_evidence};
use crate::report::{IgnoreSourceEvidence, IgnoreSourceKind};
use std::path::Path;

#[derive(Debug, Clone, Default)]
pub(super) struct OverrideRules {
    rules: RuleSet,
    has_includes: bool,
}

impl OverrideRules {
    pub(super) fn new(
        patterns: &[String],
        case_insensitive: bool,
    ) -> (Self, Vec<IgnoreError>, Option<IgnoreSourceEvidence>) {
        if patterns.is_empty() {
            return (Self::default(), Vec::new(), None);
        }
        let contents = patterns.join("\n");
        let mut rules = RuleSet::default();
        let mut errors = Vec::new();
        parse_file(
            Path::new("<overrides>"),
            &contents,
            case_insensitive,
            &mut rules,
            &mut errors,
        );
        for rule in &mut rules.rules {
            rule.action = match rule.action {
                RuleAction::Ignore => RuleAction::Include,
                RuleAction::Include => RuleAction::Ignore,
            };
        }
        let has_includes = rules
            .rules
            .iter()
            .any(|rule| rule.action == RuleAction::Include);
        let evidence = source_evidence(
            IgnoreSourceKind::Override,
            "<overrides>".to_owned(),
            contents.as_bytes(),
        );
        (
            Self {
                rules,
                has_includes,
            },
            errors,
            Some(evidence),
        )
    }

    pub(super) fn matched(&self, path: &str, is_directory: bool) -> RepositoryMatch {
        if self.rules.rules.is_empty() {
            return RepositoryMatch::None;
        }
        let matched = self
            .rules
            .matches_exact(path, is_directory)
            .map(|action| match action {
                RuleAction::Ignore => RepositoryMatch::OverrideIgnore,
                RuleAction::Include => RepositoryMatch::OverrideInclude,
            });
        matched.unwrap_or({
            if self.has_includes && !is_directory {
                RepositoryMatch::OverrideIgnore
            } else {
                RepositoryMatch::None
            }
        })
    }
}