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