amont_runtime/
attest_inputs.rs1use std::path::Path;
11
12use git_attest::spec::{at, coverage, plan_exempt, PlanExempt, DEPRECATED_OPT_OUT};
13
14pub use git_attest::spec::{conf_says_plan_exempt_off, CoverageError, Findings, Spec, EXEMPT};
15
16fn here() -> &'static Path {
18 Path::new(".")
19}
20
21pub(crate) fn spec_at(tree: &str) -> Option<Spec> {
25 match at(here(), tree) {
26 Ok(Some((_, spec))) => Some(spec),
27 _ => None,
28 }
29}
30
31pub(crate) fn fingerprint(tree: &str, spec: &Spec, gate: &str) -> Option<String> {
33 git_attest::fingerprint::fingerprint(here(), tree, spec, gate).ok()
34}
35
36pub(crate) fn input_key(gate: &str, fp: &str) -> Option<String> {
38 git_attest::fingerprint::key(here(), gate, fp).ok()
39}
40
41pub(crate) fn declares(spec: &Spec, gate: &str, file: &str) -> bool {
44 coverage(
45 spec,
46 &[gate.to_string()],
47 &[file.as_bytes().to_vec()],
48 |_| true,
49 )
50 .is_empty()
51}
52
53pub(crate) fn canonical_route(tree: &str) -> Option<String> {
59 match at(here(), tree) {
60 Ok(None) => {}
61 _ => return None,
62 }
63 if plan_exempt(here(), tree).is_off() {
64 return None;
65 }
66 git_attest::fingerprint::canon(here(), tree).ok()
67}
68
69pub(crate) fn canon_gate_key(canon: &str) -> Option<String> {
74 crate::git::stdout_piped_in(
75 here(),
76 &["hash-object", "--stdin"],
77 format!("amont-gate-canon {canon}\n").as_bytes(),
78 )
79 .filter(|s| git_attest::format::is_oid(s))
80}
81
82pub fn deprecated_opt_out() -> Option<&'static str> {
86 let tree = crate::git::stdout(&["rev-parse", "--verify", "--quiet", "HEAD^{tree}"])?;
87 (plan_exempt(here(), &tree) == PlanExempt::OffByAmontConf).then_some(DEPRECATED_OPT_OUT)
88}
89
90pub fn check(tree: &str, required: &[String]) -> Result<Findings, CoverageError> {
93 git_attest::spec::check_coverage(here(), tree, required)
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
103 fn a_tree_git_cannot_list_opens_no_route() {
104 let bogus = "0123456789012345678901234567890123456789";
105 assert_eq!(spec_at(bogus), None);
106 assert_eq!(canonical_route(bogus), None);
107 assert!(plan_exempt(here(), bogus).is_off());
108 }
109
110 #[test]
111 fn a_gate_declares_a_file_or_a_directory_above_it() {
112 let spec = git_attest::spec::parse_spec(b"lint src amont.conf\ntest src\n").unwrap();
113 assert!(declares(&spec, "lint", "amont.conf"));
114 assert!(declares(&spec, "lint", "src/main.rs"));
115 assert!(!declares(&spec, "test", "amont.conf"));
116 assert!(
117 !declares(&spec, "fmt", "amont.conf"),
118 "an undeclared gate declares nothing"
119 );
120 }
121}