use crate::gitconfig as config;
use crate::rules::{Rule, Stance};
pub const KEY_ENABLED: &str = "amont.agent.enabled";
pub const KEY_STANCE: &str = "amont.agent.stance";
pub const ENV_OFF: &str = "AMONT_AGENT_OFF";
const ALLOWED: &[&str] = &["observe", "advise", "deny"];
pub fn switched_off() -> bool {
std::env::var_os(ENV_OFF).is_some_and(|v| !v.is_empty() && v != "0")
}
pub fn key_for(rule: &Rule) -> String {
format!("amont.agent.{}.stance", rule.id)
}
pub fn resolve(rule: &Rule) -> Stance {
if switched_off() || !config::boolean_or(KEY_ENABLED, true) {
return Stance::Observe;
}
let floor = config::enumerated_or(KEY_STANCE, ALLOWED, rule.default_stance.as_str());
let mine = config::enumerated_or(&key_for(rule), ALLOWED, floor);
Stance::parse(mine).unwrap_or(rule.default_stance)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::rules::RULES;
#[test]
fn rule_ids_are_lowercase_kebab() {
for r in RULES {
assert!(
r.id.bytes()
.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == b'-'),
"rule id `{}` is not lowercase kebab-case",
r.id
);
assert!(!r.id.starts_with('-') && !r.id.ends_with('-'), "{}", r.id);
}
}
#[test]
fn the_key_names_the_rule() {
let r = &RULES[0];
assert_eq!(key_for(r), format!("amont.agent.{}.stance", r.id));
}
#[test]
fn rule_ids_are_unique() {
let mut seen = std::collections::BTreeSet::new();
for r in RULES {
assert!(seen.insert(r.id), "duplicate rule id `{}`", r.id);
}
}
}