otto_cli/output/
history.rs1use crate::model::{RunSource, RunStatus};
2use crate::output::{accent, failure, format_duration_ms, info, number, success};
3use std::io::Write;
4use time::OffsetDateTime;
5
6#[derive(Debug, Clone)]
7pub struct HistoryRow {
8 pub name: String,
9 pub source: RunSource,
10 pub status: RunStatus,
11 pub exit_code: i32,
12 pub started_at: OffsetDateTime,
13 pub duration_ms: i64,
14}
15
16pub fn print_history(mut w: impl Write, rows: &[HistoryRow]) -> std::io::Result<()> {
17 if rows.is_empty() {
18 writeln!(w, "{} No run history yet.", info("i"))?;
19 return Ok(());
20 }
21
22 for (idx, row) in rows.iter().enumerate() {
23 let source = match row.source {
24 RunSource::Task => "task",
25 RunSource::Inline => "inline",
26 };
27
28 let status = match row.status {
29 RunStatus::Success => success("ok success"),
30 RunStatus::Failed => failure("x failed"),
31 };
32
33 let started = row
34 .started_at
35 .format(&time::macros::format_description!(
36 "[year]-[month]-[day] [hour]:[minute]:[second]"
37 ))
38 .unwrap_or_else(|_| "-".to_string());
39
40 writeln!(w, "{} {}", accent(&row.name), status)?;
41 writeln!(w, " source: {}", source)?;
42 writeln!(w, " exit: {}", number(&row.exit_code.to_string()))?;
43 writeln!(w, " started (UTC): {}", started)?;
44 writeln!(
45 w,
46 " duration: {}",
47 number(&format_duration_ms(row.duration_ms))
48 )?;
49
50 if idx + 1 < rows.len() {
51 writeln!(w)?;
52 }
53 }
54
55 Ok(())
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61 use crate::output::style::set_color_enabled;
62
63 #[test]
64 fn print_history_empty() {
65 set_color_enabled(false);
66 let mut out = Vec::new();
67 print_history(&mut out, &[]).expect("print history");
68 let text = String::from_utf8(out).expect("utf8");
69 assert!(text.contains("No run history yet"));
70 set_color_enabled(true);
71 }
72
73 #[test]
74 fn print_history_rows() {
75 set_color_enabled(false);
76 let mut out = Vec::new();
77 let rows = vec![HistoryRow {
78 name: "inline".to_string(),
79 source: RunSource::Inline,
80 status: RunStatus::Success,
81 exit_code: 0,
82 started_at: OffsetDateTime::now_utc(),
83 duration_ms: 25,
84 }];
85 print_history(&mut out, &rows).expect("print history");
86 let text = String::from_utf8(out).expect("utf8");
87 assert!(text.contains("inline"));
88 assert!(text.contains("success"));
89 assert!(text.contains("source: inline"));
90 set_color_enabled(true);
91 }
92}