Skip to content

Commit

Permalink
predict: Find the currently-emerging pkg using emerge's sandbox proce…
Browse files Browse the repository at this point in the history
…ss commandline

This should be a bit more reliable than looking at the emerge logs since the oldest emerge
process. See bugs 5 and 45 for failure examples. Will need to play with this code for a while to
make sure it behaves as we want. Genlop and qlop use a similar technique, but they don't handle as
many cases and don't seem to have a fallback.
  • Loading branch information
vincentdephily committed Feb 10, 2024
1 parent 5a97ba9 commit fe359d1
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
17 changes: 14 additions & 3 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,18 +329,28 @@ pub fn cmd_predict(gc: &Conf, sc: &ConfPred) -> Result<bool, Error> {

// Build list of pending merges
let pkgs: Vec<Pkg> = if std::io::stdin().is_terminal() {
// From resume data + emerge.log after current merge process start time
// From resume list
let mut r = get_resume(sc.resume);
for p in started.iter().filter(|&(_, t)| *t > einfo.start).map(|(p, _)| p) {
// From specific emerge processes
for p in einfo.pkgs.iter() {
if !r.contains(p) {
r.push(p.clone())
}
}
// From emerge.log after main emerge process start time, if we didn't spot any specific process
if einfo.pkgs.is_empty() {
for (p, t) in started.iter() {
if *t > einfo.start && !r.contains(p) {
r.push(p.clone())
}
}
}
r
} else {
// From portage's stdout
get_pretend(stdin(), "STDIN")
};
trace!("pending: {pkgs:?}");

// Gather and print per-package and indivudual stats.
let mut totcount = 0;
Expand All @@ -352,7 +362,8 @@ pub fn cmd_predict(gc: &Conf, sc: &ConfPred) -> Result<bool, Error> {
// Find the elapsed time, if any (heuristic is that emerge process started before
// this merge finished, it's not failsafe but IMHO no worse than genlop).
let elapsed = match started.remove(&p) {
Some(s) if s > einfo.start => now - s,
Some(s) if einfo.pkgs.contains(&p) => now - s,
Some(s) if einfo.pkgs.is_empty() && s > einfo.start => now - s,
_ => 0,
};

Expand Down
19 changes: 16 additions & 3 deletions src/parse/current.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,19 +135,32 @@ fn read_buildlog(file: File, max: usize) -> String {
pub struct EmergeInfo {
pub start: i64,
pub cmds: Vec<Proc>,
pub pkgs: Vec<Pkg>,
}

/// Get info from currently running emerge processes
///
/// * emerge /usr/lib/python-exec/python3.11/emerge -Ov1 dummybuild
/// gives us the emerge command, and the tmpdir (looking at open fds)
/// * python3.11 /usr/lib/portage/python3.11/pid-ns-init 250 250 250 18 0,1,2 /usr/bin/sandbox
/// [app-portage/dummybuild-0.1.600] sandbox /usr/lib/portage/python3.11/ebuild.sh unpack
/// gives us the actually emerging ebuild and stage (depends on portage FEATURES=sandbox, which
/// should be the case for almost all users)
pub fn get_emerge(tmpdirs: &mut Vec<PathBuf>) -> EmergeInfo {
let mut res = EmergeInfo { start: i64::MAX, cmds: vec![], pkgs: vec![] };
let re_python = Regex::new("^[a-z/-]+python[0-9.]* [a-z/-]+python[0-9.]*/").unwrap();
for mut proc in get_all_info(&["emerge"], tmpdirs) {
for mut proc in get_all_info(&["emerge", "python"], tmpdirs) {
res.start = std::cmp::min(res.start, proc.start);
proc.cmdline = re_python.replace(&proc.cmdline, "").to_string();
res.cmds.push(proc);
if proc.idx == 0 {
proc.cmdline = re_python.replace(&proc.cmdline, "").to_string();
res.cmds.push(proc);
} else if let Some(a) = proc.cmdline.find("sandbox [") {
if let Some(b) = proc.cmdline.find("] sandbox") {
if let Some(p) = Pkg::try_new(&proc.cmdline[(a + 9)..b]) {
res.pkgs.push(p);
}
}
}
}
trace!("{:?}", res);
res
Expand Down

0 comments on commit fe359d1

Please sign in to comment.