Skip to main content

greentic_runner/info/
human.rs

1//! Human-readable rendering of [`super::InfoReport`].
2//!
3//! The output is terminal-oriented: fixed-width label columns, one blank line
4//! between sections, no colour. CLI wiring (E5) will select between this and
5//! `serde_json::to_string_pretty` based on `--format`.
6
7use super::report::InfoReport;
8use std::fmt::Write;
9
10pub fn render(r: &InfoReport) -> String {
11    let mut s = String::new();
12    let _ = writeln!(s, "greentic-runner {}", r.runner_version);
13    let _ = writeln!(s, "Wasmtime      {}", r.wasmtime_version);
14    let _ = writeln!(s, "Target        {}", r.target_triple);
15    let build_line = match &r.git_sha {
16        Some(sha) => format!(
17            "{} {} {} {} {}",
18            r.build_profile, "\u{00B7}", r.build_timestamp_utc, "\u{00B7}", sha
19        ),
20        None => format!(
21            "{} {} {}",
22            r.build_profile, "\u{00B7}", r.build_timestamp_utc
23        ),
24    };
25    let _ = writeln!(s, "Build         {build_line}");
26
27    let _ = writeln!(
28        s,
29        "\nPack format versions   {}",
30        r.pack_format_versions
31            .iter()
32            .map(|v| v.to_string())
33            .collect::<Vec<_>>()
34            .join(", ")
35    );
36    let enabled = if r.features.enabled.is_empty() {
37        "(none)".to_string()
38    } else {
39        r.features.enabled.join(", ")
40    };
41    let disabled = if r.features.disabled.is_empty() {
42        "(none)".to_string()
43    } else {
44        r.features.disabled.join(", ")
45    };
46    let _ = writeln!(s, "Enabled features       {enabled}");
47    let _ = writeln!(s, "Disabled features      {disabled}");
48
49    let _ = writeln!(s, "\nWASI imports (host-provided)");
50    for b in &r.wasi_imports {
51        let v = b.version.as_deref().unwrap_or("");
52        let _ = writeln!(s, "  {:<22} {v}", b.interface);
53    }
54
55    let _ = writeln!(s, "\nGreentic imports (host-provided)");
56    for b in &r.greentic_imports {
57        let v = if b.versions.is_empty() {
58            b.version.clone().unwrap_or_default()
59        } else {
60            b.versions.join(", ")
61        };
62        let extra = if b.opt_in_per_pack {
63            " (opt-in per pack)"
64        } else {
65            ""
66        };
67        let _ = writeln!(s, "  {:<45} {v}{extra}", b.interface);
68    }
69
70    s
71}
72
73#[cfg(test)]
74mod tests {
75    use super::super::report::collect;
76    use super::*;
77
78    #[test]
79    fn renders_real_collect() {
80        let out = render(&collect());
81        assert!(out.contains("greentic-runner "));
82        assert!(out.contains("Wasmtime "));
83        assert!(out.contains("WASI imports"));
84        assert!(out.contains("Greentic imports"));
85        assert!(out.contains("Pack format versions"));
86    }
87
88    #[test]
89    fn renders_build_without_git_sha() {
90        let mut r = collect();
91        r.git_sha = None;
92        let out = render(&r);
93        // Absent sha must not produce consecutive middle-dots.
94        assert!(!out.contains("\u{00B7} \u{00B7}"));
95    }
96}