use forge::signal::compactor;
use once_cell::sync::Lazy;
use regex::Regex;
static INFO_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"(?m)^INFO\s+\[alembic\.[^\]]+\]\s+").unwrap());
pub fn compress_migrate(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let s = INFO_RE.replace_all(&cleaned, "");
let useful: Vec<&str> = s
.lines()
.filter(|l| {
let t = l.trim();
!t.is_empty()
&& (t.contains("Running upgrade")
|| t.contains("Running downgrade")
|| t.contains("->")
|| t.contains("<-")
|| t.contains("Done")
|| t.contains("error")
|| t.contains("Error"))
})
.collect();
if useful.is_empty() {
return compactor::collapse_blanks(&s);
}
useful.join("\n")
}
pub fn compress_current(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let s = INFO_RE.replace_all(&cleaned, "");
compactor::collapse_blanks(&s)
}
pub fn compress_history(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let s = INFO_RE.replace_all(&cleaned, "");
let lines: Vec<&str> = s.lines().filter(|l| !l.trim().is_empty()).collect();
if lines.len() > 20 {
return format!(
"{}\n… [{} more revisions]",
lines[..20].join("\n"),
lines.len() - 20
);
}
lines.join("\n")
}
pub fn compress_alembic(subcmd: &str, raw: &str) -> String {
let sub = subcmd.trim();
if sub.starts_with("upgrade") || sub.starts_with("downgrade") {
return compress_migrate(raw);
}
if sub.starts_with("current") {
return compress_current(raw);
}
if sub.starts_with("history") {
return compress_history(raw);
}
let cleaned = compactor::normalise(raw);
let s = INFO_RE.replace_all(&cleaned, "");
compactor::collapse_blanks(&s)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn upgrade_strips_info_prefix() {
let raw = "INFO [alembic.runtime.migration] Context impl PostgresqlImpl.\nINFO [alembic.runtime.migration] Will assume transactional DDL.\nINFO [alembic.runtime.migration] Running upgrade -> abc123, add users table\nINFO [alembic.runtime.migration] Running upgrade abc123 -> def456, add orders table\n";
let out = compress_alembic("upgrade head", raw);
assert!(!out.contains("INFO [alembic"), "{out}");
assert!(
out.contains("add users table") || out.contains("->"),
"{out}"
);
}
#[test]
fn history_truncates() {
let lines: Vec<String> = (0..25)
.map(|i| format!("rev{i:03} -> rev{:03}, migration {i}", i + 1))
.collect();
let out = compress_history(&lines.join("\n"));
assert!(out.contains("more revisions"), "{out}");
}
}