use forge::signal::compactor;
use once_cell::sync::Lazy;
use regex::Regex;
static HOUSEKEEPING_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(
r"(?m)^\s*(Reading package lists|Building dependency tree|Reading state information|Reading database)[^\n]*\n?",
)
.unwrap()
});
static FETCH_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(
r"(?m)^\s*(Get:\d+|Hit:\d+|Ign:\d+|Fetched|Selecting previously|Preparing to unpack|Unpacking|Processing triggers)[^\n]*\n?",
)
.unwrap()
});
pub fn compress_install(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let s = HOUSEKEEPING_RE.replace_all(&cleaned, "");
let s = FETCH_RE.replace_all(&s, "");
compactor::collapse_blanks(&s)
}
pub fn compress_list(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let lines: Vec<&str> = cleaned.lines().collect();
if lines.len() <= 30 {
return cleaned;
}
format!(
"{}\n... [{} more packages] ...",
lines[..30].join("\n"),
lines.len() - 30
)
}
pub fn compress_apt(subcmd: &str, raw: &str) -> String {
let sub = subcmd.trim();
if sub.starts_with("install")
|| sub.starts_with("upgrade")
|| sub.starts_with("dist-upgrade")
|| sub.starts_with("full-upgrade")
|| sub.starts_with("remove")
|| sub.starts_with("purge")
|| sub.starts_with("update")
|| sub.starts_with("build-dep")
{
return compress_install(raw);
}
if sub.starts_with("list") || sub.starts_with("search") || sub.starts_with("show") {
return compress_list(raw);
}
compactor::normalise(raw)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn install_strips_housekeeping_and_fetch() {
let raw = "Reading package lists... Done\nBuilding dependency tree... Done\nReading state information... Done\nThe following NEW packages will be installed:\n curl git\n0 upgraded, 2 newly installed, 0 to remove and 5 not upgraded.\nGet:1 http://deb.debian.org/debian bookworm/main amd64 curl amd64 7.88.1 [315 kB]\nFetched 2345 kB in 1s\nSelecting previously unselected package curl.\nPreparing to unpack .../curl_7.88.1.deb ...\nUnpacking curl (7.88.1) ...\nSetting up curl (7.88.1) ...\n";
let out = compress_install(raw);
assert!(!out.contains("Reading package lists"), "{out}");
assert!(!out.contains("Get:1"), "{out}");
assert!(!out.contains("Unpacking curl"), "{out}");
assert!(out.contains("newly installed"), "{out}");
assert!(out.contains("Setting up curl"), "{out}");
}
#[test]
fn list_truncates_long_output() {
let raw = (0..50)
.map(|i| format!("pkg{i}/stable 1.{i}.0 amd64"))
.collect::<Vec<_>>()
.join("\n");
let out = compress_list(&raw);
assert!(out.contains("more packages"), "{out}");
}
}