Skip to content

Commit

Permalink
log/parse: Show log of emerge commands
Browse files Browse the repository at this point in the history
This is a straightforward MVP that doesn't try to handle concurrent emerges or early failures.
  • Loading branch information
vincentdephily committed Nov 4, 2024
1 parent 0bbb248 commit 411a40f
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 20 deletions.
15 changes: 15 additions & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::{collections::{BTreeMap, HashMap, HashSet},
/// We store the start times in a hashmap to compute/print the duration when we reach a stop event.
pub fn cmd_log(gc: Conf, sc: ConfLog) -> Result<bool, Error> {
let hist = get_hist(&gc.logfile, gc.from, gc.to, sc.show, &sc.search, sc.exact)?;
let mut cmd_start: Option<(i64, String)> = None;
let mut merges: HashMap<String, i64> = HashMap::new();
let mut unmerges: HashMap<String, i64> = HashMap::new();
let mut found = 0;
Expand All @@ -17,6 +18,19 @@ pub fn cmd_log(gc: Conf, sc: ConfLog) -> Result<bool, Error> {
Table::new(&gc).align_left(0).align_left(2).margin(2, " ").last(sc.last).header(h);
for p in hist {
match p {
Hist::CmdStart { ts, args, .. } => {
// This'll overwrite any previous entry, if a cmd stops abruptly or multiple cmds run in parallel
cmd_start = Some((ts, args));
},
Hist::CmdStop { ts, .. } => {
found += 1;
let (started, args) = cmd_start.take().unwrap_or((ts + 1, String::from("?")));
if found <= sc.first {
tbl.row([&[&FmtDate(if sc.starttime { started } else { ts })],
&[&FmtDur(ts - started), &gc.clr],
&[&"Emerge ", &args]]);
}
},
Hist::MergeStart { ts, key, .. } => {
// This'll overwrite any previous entry, if a merge started but never finished
merges.insert(key, ts);
Expand Down Expand Up @@ -218,6 +232,7 @@ pub fn cmd_stats(gc: Conf, sc: ConfStats) -> Result<bool, Error> {
warn!("Sync stop without a start at {ts}")
}
},
_ => todo!("cmdevent"),
}
}
let group = sc.group.at(curts, gc.date_offset);
Expand Down
2 changes: 1 addition & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ impl Conf {

impl ConfLog {
fn try_new(cli: &ArgMatches, toml: &Toml) -> Result<Self, Error> {
Ok(Self { show: sel!(cli, toml, log, show, "musa", Show::m())?,
Ok(Self { show: sel!(cli, toml, log, show, "cmusa", Show::m())?,
search: cli.get_many("search").unwrap_or_default().cloned().collect(),
exact: cli.get_flag("exact"),
starttime: sel!(cli, toml, log, starttime, (), false)?,
Expand Down
16 changes: 9 additions & 7 deletions src/config/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ pub fn build_cli() -> Command {
virtual/rust: Matches only `virtual/rust`\n \
RuSt: Matches nothing (case-sensitive)\n \
ru: Matches nothing (whole name only)");
let show_l = Arg::new("show").short('s')
.long("show")
.value_name("m,u,s,a")
.display_order(3)
.help_heading("Filter")
.help("Show (m)erges, (u)nmerges, (s)yncs, and/or (a)ll")
.long_help("Show (any combination of)\n \
let show_l =
Arg::new("show").short('s')
.long("show")
.value_name("c,m,u,s,a")
.display_order(3)
.help_heading("Filter")
.help("Show (c)commands, (m)erges, (u)nmerges, (s)yncs, and/or (a)ll")
.long_help("Show (any combination of)\n \
c: Emerge command\n \
m: Package merges\n \
u: Package unmerges\n \
s: Repository syncs\n \
Expand Down
39 changes: 33 additions & 6 deletions src/config/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ impl ArgParse<String, bool> for OutStyle {

#[derive(Clone, Copy)]
pub struct Show {
pub cmd: bool,
pub pkg: bool,
pub tot: bool,
pub sync: bool,
Expand All @@ -193,23 +194,48 @@ pub struct Show {
}
impl Show {
pub const fn m() -> Self {
Self { pkg: false, tot: false, sync: false, merge: true, unmerge: false, emerge: false }
Self { cmd: false,
pkg: false,
tot: false,
sync: false,
merge: true,
unmerge: false,
emerge: false }
}
pub const fn emt() -> Self {
Self { pkg: false, tot: true, sync: false, merge: true, unmerge: false, emerge: true }
Self { cmd: false,
pkg: false,
tot: true,
sync: false,
merge: true,
unmerge: false,
emerge: true }
}
pub const fn p() -> Self {
Self { pkg: true, tot: false, sync: false, merge: false, unmerge: false, emerge: false }
Self { cmd: false,
pkg: true,
tot: false,
sync: false,
merge: false,
unmerge: false,
emerge: false }
}
pub const fn mt() -> Self {
Self { pkg: false, tot: true, sync: false, merge: true, unmerge: false, emerge: false }
Self { cmd: false,
pkg: false,
tot: true,
sync: false,
merge: true,
unmerge: false,
emerge: false }
}
}
impl ArgParse<String, &'static str> for Show {
fn parse(show: &String, valid: &'static str, src: &'static str) -> Result<Self, ArgError> {
debug_assert!(valid.is_ascii()); // Because we use `chars()` we need to stick to ascii for `valid`.
if show.chars().all(|c| valid.contains(c)) {
Ok(Self { pkg: show.contains('p') || show.contains('a'),
Ok(Self { cmd: show.contains('c') || show.contains('a'),
pkg: show.contains('p') || show.contains('a'),
tot: show.contains('t') || show.contains('a'),
sync: show.contains('s') || show.contains('a'),
merge: show.contains('m') || show.contains('a'),
Expand All @@ -223,7 +249,8 @@ impl ArgParse<String, &'static str> for Show {
impl std::fmt::Display for Show {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut sep = "";
for (b, s) in [(self.pkg, "pkg"),
for (b, s) in [(self.cmd, "command"),
(self.pkg, "pkg"),
(self.tot, "total"),
(self.sync, "sync"),
(self.merge, "merge"),
Expand Down
61 changes: 55 additions & 6 deletions src/parse/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,46 @@ use std::{fs::File,
/// Items sent on the channel returned by `new_hist()`.
#[derive(Debug)]
pub enum Hist {
CmdStart {
ts: i64,
args: String,
},
CmdStop {
ts: i64,
},
/// Merge started (might never complete).
MergeStart { ts: i64, key: String, pos: usize },
MergeStart {
ts: i64,
key: String,
pos: usize,
},
/// Merge completed.
MergeStop { ts: i64, key: String, pos: usize },
MergeStop {
ts: i64,
key: String,
pos: usize,
},
/// Unmerge started (might never complete).
UnmergeStart { ts: i64, key: String, pos: usize },
UnmergeStart {
ts: i64,
key: String,
pos: usize,
},
/// Unmerge completed.
UnmergeStop { ts: i64, key: String, pos: usize },
UnmergeStop {
ts: i64,
key: String,
pos: usize,
},
/// Sync started (might never complete).
SyncStart { ts: i64 },
SyncStart {
ts: i64,
},
/// Sync completed.
SyncStop { ts: i64, repo: String },
SyncStop {
ts: i64,
repo: String,
},
}
impl Hist {
pub fn ebuild(&self) -> &str {
Expand Down Expand Up @@ -59,6 +87,8 @@ impl Hist {
}
pub const fn ts(&self) -> i64 {
match self {
Self::CmdStart { ts, .. } => *ts,
Self::CmdStop { ts, .. } => *ts,
Self::MergeStart { ts, .. } => *ts,
Self::MergeStop { ts, .. } => *ts,
Self::UnmergeStart { ts, .. } => *ts,
Expand Down Expand Up @@ -140,6 +170,14 @@ pub fn get_hist(file: &str,
if tx.send(found).is_err() {
break;
}
} else if let Some(found) = parse_cmdstart(show.cmd, t, s) {
if tx.send(found).is_err() {
break;
}
} else if let Some(found) = parse_cmdstop(show.cmd, t, s) {
if tx.send(found).is_err() {
break;
}
}
}
},
Expand Down Expand Up @@ -244,6 +282,17 @@ fn parse_ts(line: &[u8], min: i64, max: i64) -> Option<(i64, &[u8])> {
}
}

fn parse_cmdstart(enabled: bool, ts: i64, line: &[u8]) -> Option<Hist> {
if !enabled || !line.starts_with(b"*** emerge") {
return None;
}
Some(Hist::CmdStart { ts, args: from_utf8(&line[11..]).ok()?.trim().to_owned() })
}

fn parse_cmdstop(enabled: bool, ts: i64, line: &[u8]) -> Option<Hist> {
(enabled && line.starts_with(b"*** terminating")).then_some(Hist::CmdStop { ts })
}

fn parse_mergestart(enabled: bool, ts: i64, line: &[u8], filter: &FilterStr) -> Option<Hist> {
if !enabled || !line.starts_with(b">>> emer") {
return None;
Expand Down

0 comments on commit 411a40f

Please sign in to comment.