tag2upload_service_manager/
version.rs

1
2use crate::prelude::*;
3
4use std::hint::black_box;
5use std::option_env;
6use std::process::Command;
7
8#[derive(Serialize, Debug, derive_more::Display)]
9#[serde(rename_all = "snake_case")]
10pub enum Info {
11    #[display("debug build")]
12    Debug,
13    #[display("ad-hoc release build")]
14    Adhoc,
15    #[display("unattested release build")]
16    Unattested,
17    /// no `files.self_git_dir`, or `maint/build-repro describe` failed
18    #[display("{raw_source}")]
19    #[serde(untagged)]
20    RawSource { raw_source: String },
21    /// `maint/build-repro describe` succeeded
22    #[display("{attested}")]
23    #[serde(untagged)]
24    Attested { raw_source: String, attested: String },
25}
26
27pub fn raw_info() -> Info {
28    if cfg!(debug_assertions) { return Info::Debug }
29
30    let Some(reference_commit) = option_env!("T2USM_REPRO_GIT_COMMIT")
31    else { return Info::Adhoc };
32
33    // Using `black_box` will hopefully limit the additional delta in
34    // the dirty case.  See maint/build-repro.
35    let reference_commit = black_box(reference_commit);
36
37    if reference_commit == "0000000000000000000000000000000000000000"
38    { return Info::Unattested }
39
40    let raw_source = reference_commit.to_owned();
41
42    return Info::RawSource { raw_source };
43}
44
45pub fn calculate_describe(config: &config::Files) -> Info {
46    let info = raw_info();
47
48    let Some(self_git_dir) = &config.self_git_dir
49    else { return info };
50
51    let Info::RawSource { raw_source } = &info
52    else { return info };
53
54    let attested = match (|| {
55
56        let output = Command::new("bash")
57            .env("GIT_DIR", self_git_dir)
58            .args([
59                "-c",
60                // Using embedded copy makes us self-contained and avoids any
61                // trouble with (possibly concurrent) udpates.
62                include_str!("../maint/build-repro"),
63                "maint/build-repro (embedded)",
64                "describe",
65                &raw_source,
66            ])
67            .output().context("spawn")?;
68
69        if !(output.status.success() && output.stderr.is_empty()) {
70            let stderr = String::from_utf8_lossy(&output.stderr);
71            return Err(anyhow!(
72                "failed: {} ({})",
73                output.status, stderr.trim_end(),
74            ));
75        }
76
77        let attested = str::from_utf8(&output.stdout)
78            .context("output")?
79            .trim_end();
80
81        info!(raw_source, attested, "resolved self git commit");
82
83        Ok(attested.to_owned())
84
85    })() {
86        Err(error) => {
87            warn!(%error, "maint/build-repro describe (embedded)");
88            return info;
89        }
90        Ok(y) => y,
91    };
92
93    let raw_source = raw_source.to_owned();
94
95    return Info::Attested { raw_source, attested }
96}