use std::{collections::HashMap, ops::Deref, path::PathBuf};
use cargo_metadata::MetadataCommand;
use chrono::{DateTime, Local};
use serde::{Deserialize, Serialize};
use crate::utils::{self, lockfile::load_lockfiles};
use super::harness::{CargoConfig, Profile};
#[derive(Debug, Serialize, Deserialize)]
pub struct ProfileWithName {
pub name: String,
#[serde(flatten)]
pub profile: Profile,
}
impl Deref for ProfileWithName {
type Target = Profile;
fn deref(&self) -> &Self::Target {
&self.profile
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RunInfo {
pub version: i32,
pub runid: String,
pub project: String,
#[serde(rename = "start-time-utc")]
pub start_timestamp_utc: i64,
#[serde(rename = "finish-time-utc")]
pub finish_timestamp_utc: Option<i64>,
pub commit: String,
#[serde(rename = "crate")]
pub crate_info: CrateInfo,
pub profile: ProfileWithName,
pub system: SystemInfo,
pub lockfiles: Lockfiles,
}
impl RunInfo {
pub(crate) fn new_v0(
crate_info: CrateInfo,
profile: Profile,
runid: String,
profile_name: String,
project: Option<String>,
start_time: DateTime<Local>,
) -> anyhow::Result<Self> {
let lockfiles = load_lockfiles(&crate_info, &profile)?;
let project = project.unwrap_or_else(|| crate_info.name.clone());
Ok(Self {
version: 0,
crate_info,
project,
system: utils::sys::get_current_system_info(),
profile: ProfileWithName {
name: profile_name,
profile,
},
runid,
commit: utils::git::get_git_hash()?,
start_timestamp_utc: start_time.to_utc().timestamp(),
finish_timestamp_utc: None,
lockfiles,
})
}
pub(crate) fn load(path: &PathBuf) -> anyhow::Result<Self> {
let content = std::fs::read_to_string(path)?;
Ok(toml::from_str(&content)?)
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CrateInfo {
pub name: String,
pub target_dir: PathBuf,
pub benches: Vec<String>,
pub workspace_root: PathBuf,
}
impl CrateInfo {
pub(crate) fn get_target_path() -> anyhow::Result<PathBuf> {
let Ok(meta) = MetadataCommand::new().manifest_path("./Cargo.toml").exec() else {
anyhow::bail!("Failed to get metadata from ./Cargo.toml");
};
let target_dir = meta.target_directory.as_std_path();
Ok(target_dir.to_owned())
}
pub(crate) fn load() -> anyhow::Result<Self> {
let Ok(meta) = MetadataCommand::new().manifest_path("./Cargo.toml").exec() else {
anyhow::bail!("Failed to get metadata from ./Cargo.toml");
};
let target_dir = meta.target_directory.as_std_path();
let Some(pkg) = meta.root_package() else {
anyhow::bail!("No root package found");
};
let benches = CargoConfig::load_benches()?;
Ok(CrateInfo {
name: pkg.name.clone(),
target_dir: target_dir.to_owned(),
benches,
workspace_root: meta.workspace_root.as_std_path().to_owned(),
})
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SystemInfo {
pub host: String,
pub os: String,
pub arch: String,
#[serde(rename = "kernel-version")]
pub kernel: String,
#[serde(rename = "cpu-model")]
pub cpu_model: String,
#[serde(rename = "cpu-frequency")]
pub cpu_frequency: Vec<usize>,
pub memory_size: usize,
pub swap_size: usize,
#[cfg(target_os = "linux")]
pub users: Vec<String>,
pub processes: usize,
pub env: HashMap<String, String>,
pub pid: usize,
pub rustc: String,
#[cfg(target_os = "linux")]
#[serde(rename = "scaling-governor")]
pub scaling_governor: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Lockfiles {
#[serde(flatten)]
pub lockfiles: HashMap<String, toml::Value>,
}