use std::path::Path;
use git_attest::spec::{at, coverage, plan_exempt, PlanExempt, DEPRECATED_OPT_OUT};
pub use git_attest::spec::{conf_says_plan_exempt_off, CoverageError, Findings, Spec, EXEMPT};
fn here() -> &'static Path {
Path::new(".")
}
pub(crate) fn spec_at(tree: &str) -> Option<Spec> {
match at(here(), tree) {
Ok(Some((_, spec))) => Some(spec),
_ => None,
}
}
pub(crate) fn fingerprint(tree: &str, spec: &Spec, gate: &str) -> Option<String> {
git_attest::fingerprint::fingerprint(here(), tree, spec, gate).ok()
}
pub(crate) fn input_key(gate: &str, fp: &str) -> Option<String> {
git_attest::fingerprint::key(here(), gate, fp).ok()
}
pub(crate) fn declares(spec: &Spec, gate: &str, file: &str) -> bool {
coverage(
spec,
&[gate.to_string()],
&[file.as_bytes().to_vec()],
|_| true,
)
.is_empty()
}
pub(crate) fn canonical_route(tree: &str) -> Option<String> {
match at(here(), tree) {
Ok(None) => {}
_ => return None,
}
if plan_exempt(here(), tree).is_off() {
return None;
}
git_attest::fingerprint::canon(here(), tree).ok()
}
pub(crate) fn canon_gate_key(canon: &str) -> Option<String> {
crate::git::stdout_piped_in(
here(),
&["hash-object", "--stdin"],
format!("amont-gate-canon {canon}\n").as_bytes(),
)
.filter(|s| git_attest::format::is_oid(s))
}
pub fn deprecated_opt_out() -> Option<&'static str> {
let tree = crate::git::stdout(&["rev-parse", "--verify", "--quiet", "HEAD^{tree}"])?;
(plan_exempt(here(), &tree) == PlanExempt::OffByAmontConf).then_some(DEPRECATED_OPT_OUT)
}
pub fn check(tree: &str, required: &[String]) -> Result<Findings, CoverageError> {
git_attest::spec::check_coverage(here(), tree, required)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_tree_git_cannot_list_opens_no_route() {
let bogus = "0123456789012345678901234567890123456789";
assert_eq!(spec_at(bogus), None);
assert_eq!(canonical_route(bogus), None);
assert!(plan_exempt(here(), bogus).is_off());
}
#[test]
fn a_gate_declares_a_file_or_a_directory_above_it() {
let spec = git_attest::spec::parse_spec(b"lint src amont.conf\ntest src\n").unwrap();
assert!(declares(&spec, "lint", "amont.conf"));
assert!(declares(&spec, "lint", "src/main.rs"));
assert!(!declares(&spec, "test", "amont.conf"));
assert!(
!declares(&spec, "fmt", "amont.conf"),
"an undeclared gate declares nothing"
);
}
}