release_kit/projection/
evidence.rs1use std::collections::BTreeMap;
10
11use camino::Utf8Path;
12
13use super::{BLOCK_DESTINATIONS, CrateShape, TargetEvidence};
14use crate::landing::manifest::Manifest;
15
16impl TargetEvidence {
17 pub fn gather(target: &Utf8Path, recorded: Option<&Manifest>) -> std::io::Result<Self> {
24 gather(target, recorded)
25 }
26}
27
28pub fn gather(target: &Utf8Path, recorded: Option<&Manifest>) -> std::io::Result<TargetEvidence> {
36 let mut documents = BTreeMap::new();
37 for destination in BLOCK_DESTINATIONS {
38 if let Some(bytes) = read_optional(&target.join(destination))? {
39 documents.insert(destination.to_owned(), bytes);
40 }
41 }
42 let (flake_nix_present, flake_lock_present) = flake_presence(target)?;
43 Ok(TargetEvidence {
44 documents,
45 crate_shape: crate_shape(target),
46 flake_nix_present,
47 flake_lock_present,
48 flake_recorded: flake_recorded(recorded),
49 root_pipeline_present: present(target, super::GITLAB_ROOT_PIPELINE)?,
50 root_pipeline_recorded: recorded
51 .is_some_and(|record| record.file(super::GITLAB_ROOT_PIPELINE).is_some()),
52 })
53}
54
55#[must_use]
58pub fn flake_recorded(recorded: Option<&Manifest>) -> bool {
59 recorded.is_some_and(|record| record.file("flake.nix").is_some())
60}
61
62#[must_use]
65pub fn crate_shape(target: &Utf8Path) -> CrateShape {
66 CrateShape {
67 cargo_toml: std::fs::read_to_string(target.join("Cargo.toml")).ok(),
68 cargo_lock: target.join("Cargo.lock").is_file(),
69 main_rs: target.join("src/main.rs").is_file(),
70 }
71}
72
73pub fn flake_presence(target: &Utf8Path) -> std::io::Result<(bool, bool)> {
81 Ok((
82 present(target, "flake.nix")?,
83 present(target, "flake.lock")?,
84 ))
85}
86
87fn present(target: &Utf8Path, name: &str) -> std::io::Result<bool> {
90 match std::fs::symlink_metadata(target.join(name).as_std_path()) {
91 Ok(_) => Ok(true),
92 Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(false),
93 Err(e) => Err(e),
94 }
95}
96
97fn read_optional(path: &Utf8Path) -> std::io::Result<Option<Vec<u8>>> {
99 match std::fs::read(path) {
100 Ok(bytes) => Ok(Some(bytes)),
101 Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),
102 Err(e) => Err(e),
103 }
104}