muse2/output/
metadata.rs

1//! Code for writing metadata to file
2use anyhow::Result;
3use chrono::prelude::*;
4use platform_info::{PlatformInfo, PlatformInfoAPI, UNameAPI};
5use serde::Serialize;
6use std::fs;
7use std::path::Path;
8
9/// The output file name for metadata
10const METADATA_FILE_NAME: &str = "metadata.toml";
11
12/// Information about the program build via `built` crate
13mod built_info {
14    // The file has been placed there by the build script.
15    include!(concat!(env!("OUT_DIR"), "/built.rs"));
16}
17
18/// Get information about program version from git
19fn get_git_hash() -> String {
20    let Some(hash) = built_info::GIT_COMMIT_HASH_SHORT else {
21        return "unknown".into();
22    };
23
24    if built_info::GIT_DIRTY == Some(true) {
25        format!("{hash}-dirty")
26    } else {
27        hash.into()
28    }
29}
30
31/// Metadata about the program run, build and version information for MUSE and the user's system
32#[derive(Serialize)]
33struct Metadata<'a> {
34    run: RunMetadata<'a>,
35    program: ProgramMetadata<'a>,
36    platform: PlatformMetadata,
37}
38
39/// Information about the model run
40#[derive(Serialize)]
41struct RunMetadata<'a> {
42    /// Path to the model which was run
43    model_path: &'a Path,
44    /// The date and time on which the run started
45    datetime: String,
46}
47
48impl<'a> RunMetadata<'a> {
49    fn new(model_path: &'a Path) -> Self {
50        let dt = Local::now();
51        Self {
52            model_path,
53            datetime: dt.to_rfc2822(),
54        }
55    }
56}
57
58#[derive(Serialize)]
59struct ProgramMetadata<'a> {
60    /// The program name
61    name: &'a str,
62    /// The program version as specified in Cargo.toml
63    version: &'a str,
64    /// The target architecture for the build (e.g. x86_64-unknown-linux-gnu)
65    target: &'a str,
66    /// Whether it is a debug build
67    is_debug: bool,
68    /// The version of rustc used to compile MUSE
69    rustc_version: &'a str,
70    /// When MUSE was built
71    build_time_utc: &'a str,
72    /// The git commit hash for the version of MUSE (if known)
73    git_commit_hash: String,
74}
75
76impl Default for ProgramMetadata<'_> {
77    fn default() -> Self {
78        Self {
79            name: built_info::PKG_NAME,
80            version: built_info::PKG_VERSION,
81            target: built_info::TARGET,
82            is_debug: built_info::DEBUG,
83            rustc_version: built_info::RUSTC_VERSION,
84            build_time_utc: built_info::BUILT_TIME_UTC,
85            git_commit_hash: get_git_hash(),
86        }
87    }
88}
89
90/// Information about the platform on which MUSE is running.
91///
92/// The fields correspond to different data available from the [`PlatformInfo`] struct.
93#[derive(Serialize)]
94struct PlatformMetadata {
95    sysname: String,
96    nodename: String,
97    release: String,
98    version: String,
99    machine: String,
100    osname: String,
101}
102
103impl Default for PlatformMetadata {
104    fn default() -> Self {
105        let info = PlatformInfo::new().expect("Unable to determine platform info");
106        Self {
107            sysname: info.sysname().to_string_lossy().into(),
108            nodename: info.nodename().to_string_lossy().into(),
109            release: info.release().to_string_lossy().into(),
110            version: info.version().to_string_lossy().into(),
111            machine: info.machine().to_string_lossy().into(),
112            osname: info.osname().to_string_lossy().into(),
113        }
114    }
115}
116
117/// Write metadata to the specified output path in TOML format
118pub fn write_metadata(output_path: &Path, model_path: &Path) -> Result<()> {
119    let metadata = Metadata {
120        run: RunMetadata::new(model_path),
121        program: ProgramMetadata::default(),
122        platform: PlatformMetadata::default(),
123    };
124    let file_path = output_path.join(METADATA_FILE_NAME);
125    fs::write(&file_path, toml::to_string(&metadata)?)?;
126
127    Ok(())
128}