use std::time::Duration;
use strum::{EnumMessage, VariantArray};
use crate::build::Stage;
use crate::{ColumnAlign, PackageState};
pub(crate) const CPU_PREFIX: &str = "cpu:";
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
strum::IntoStaticStr,
strum::VariantArray,
strum::EnumMessage,
strum::EnumProperty,
)]
#[strum(serialize_all = "snake_case")]
pub enum HistoryKind {
#[strum(message = "Build start time")]
Timestamp,
#[strum(message = "Package path in pkgsrc")]
Pkgpath,
#[strum(message = "Package name and version")]
Pkgname,
#[strum(message = "Package name without version")]
Pkgbase,
#[strum(message = "Build result")]
Outcome,
#[strum(message = "Last stage attempted (for failures)")]
Stage,
#[strum(message = "MAKE_JOBS used", props(align = "right"))]
MakeJobs,
#[strum(message = "Total wall-clock duration", props(align = "right"))]
Duration,
#[strum(message = "WRKDIR size at end of build", props(align = "right"))]
DiskUsage,
#[strum(message = "WRKOBJDIR type (tmpfs or disk)")]
Wrkobjdir,
#[strum(message = "Build session identifier")]
BuildId,
}
impl crate::ColumnAlign for HistoryKind {}
impl HistoryKind {
pub fn all_columns() -> Vec<(String, crate::Align)> {
Self::VARIANTS
.iter()
.map(|v| (<&str>::from(v).to_string(), v.align()))
.chain(
Stage::VARIANTS
.iter()
.map(|s| (s.into_str().to_string(), s.align())),
)
.chain(
Stage::VARIANTS
.iter()
.map(|s| (format!("{CPU_PREFIX}{}", s.into_str()), s.align())),
)
.collect()
}
pub fn default_names() -> Vec<&'static str> {
use HistoryKind::*;
[
Timestamp, Pkgname, Outcome, MakeJobs, Wrkobjdir, DiskUsage, Duration,
]
.iter()
.map(|v| v.into())
.collect()
}
pub fn columns_help() -> String {
use std::fmt::Write as _;
let all_cols = Self::all_columns();
let max_name = all_cols.iter().map(|(n, _)| n.len()).max().unwrap_or(0);
let mut help = String::from("Columns to display (comma-separated)\n\nColumns:\n");
for col in Self::VARIANTS {
let name: &str = col.into();
let desc = col.get_message().unwrap_or("");
let _ = writeln!(help, " {:<width$} {}", name, desc, width = max_name);
}
for s in Stage::VARIANTS {
let name = s.into_str();
let _ = writeln!(
help,
" {:<width$} Wall time for {} stage",
name,
name,
width = max_name
);
}
for s in Stage::VARIANTS {
let name = s.into_str();
let _ = writeln!(
help,
" {:<width$} CPU time for {} stage",
format!("{CPU_PREFIX}{name}"),
name,
width = max_name
);
}
let _ = write!(
help,
"\nDefault columns: {}",
Self::default_names().join(",")
);
help
}
pub fn after_help() -> String {
"Examples:\n \
bob history Show all build history\n \
bob history rust Show history matching 'rust'\n \
bob history -o pkgname,build,cpu:build,duration Show build wall+cpu time\n \
bob history -Ho pkgpath Show pkgpaths only, no header"
.to_string()
}
}
pub struct History {
pub timestamp: i64,
pub pkgpath: String,
pub pkgname: String,
pub pkgbase: String,
pub outcome: PackageState,
pub stage: Option<Stage>,
pub make_jobs: Option<usize>,
pub duration: Duration,
pub disk_usage: Option<u64>,
pub wrkobjdir: Option<crate::config::WrkObjKind>,
pub stage_durations: Vec<(Stage, Duration)>,
pub stage_cpu_times: Vec<(Stage, Duration)>,
pub build_id: Option<String>,
}