use ito_config::types::ItoConfig;
use super::rule::{Rule, RuleId, RuleSeverity};
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct ActiveRule {
pub rule_id: RuleId,
pub severity: RuleSeverity,
pub description: &'static str,
pub active: bool,
pub gate: Option<&'static str>,
}
#[derive(Default)]
pub struct RuleRegistry {
rules: Vec<Box<dyn Rule>>,
}
impl RuleRegistry {
#[must_use]
pub fn empty() -> Self {
Self::default()
}
#[must_use]
pub fn built_in() -> Self {
use super::audit_rules::MirrorBranchSetRule;
use super::backend_rules::{
ProjectOrgRepoSetRule, TokenNotCommittedRule, UrlSchemeValidRule,
};
use super::repository_rules::{SqliteDbNotCommittedRule, SqliteDbPathSetRule};
use super::worktrees_rules::{LayoutConsistentRule, NoWriteOnControlRule};
let registry = Self::empty();
#[cfg(feature = "coordination-branch")]
let registry = {
use super::audit_rules::MirrorBranchDistinctRule;
use super::coordination_rules::{
BranchNameSetRule, GitignoreEntriesRule, StagedSymlinkedPathsRule,
SymlinksWiredRule,
};
registry
.with_rule(Box::new(SymlinksWiredRule))
.with_rule(Box::new(GitignoreEntriesRule))
.with_rule(Box::new(StagedSymlinkedPathsRule))
.with_rule(Box::new(BranchNameSetRule))
.with_rule(Box::new(MirrorBranchDistinctRule))
};
registry
.with_rule(Box::new(NoWriteOnControlRule))
.with_rule(Box::new(LayoutConsistentRule))
.with_rule(Box::new(MirrorBranchSetRule))
.with_rule(Box::new(SqliteDbPathSetRule))
.with_rule(Box::new(SqliteDbNotCommittedRule))
.with_rule(Box::new(TokenNotCommittedRule))
.with_rule(Box::new(UrlSchemeValidRule))
.with_rule(Box::new(ProjectOrgRepoSetRule))
}
#[must_use]
pub fn with_rule(mut self, rule: Box<dyn Rule>) -> Self {
self.rules.push(rule);
self
}
pub fn iter(&self) -> impl Iterator<Item = &dyn Rule> {
self.rules.iter().map(Box::as_ref)
}
#[must_use]
pub fn len(&self) -> usize {
self.rules.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.rules.is_empty()
}
}
impl std::fmt::Debug for RuleRegistry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RuleRegistry")
.field(
"rules",
&self
.rules
.iter()
.map(|r| r.id().as_str())
.collect::<Vec<_>>(),
)
.finish()
}
}
#[must_use]
pub fn list_active_rules(config: &ItoConfig) -> Vec<ActiveRule> {
list_active_rules_for(&RuleRegistry::built_in(), config)
}
#[must_use]
pub fn list_active_rules_for(registry: &RuleRegistry, config: &ItoConfig) -> Vec<ActiveRule> {
let mut active: Vec<ActiveRule> = registry
.iter()
.map(|rule| ActiveRule {
rule_id: rule.id(),
severity: rule.severity(),
description: rule.description(),
active: rule.is_active(config),
gate: rule.gate(),
})
.collect();
active.sort_by_key(|item| item.rule_id);
active
}
#[cfg(test)]
#[path = "registry_tests.rs"]
mod registry_tests;