use forge::signal::compactor;
use once_cell::sync::Lazy;
use regex::Regex;
static BANNER_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"(?m)^(?:Flyway(?:\s+Community)?[^\n]*\n|[+\-|]+\n|_{10,}\n)").unwrap()
});
static DB_CONN_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"(?m)^Database: jdbc:[^\n]+\n?").unwrap());
pub fn compress_migrate(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let s = BANNER_RE.replace_all(&cleaned, "");
let s = DB_CONN_RE.replace_all(&s, "");
let useful: Vec<&str> = s
.lines()
.filter(|l| {
let t = l.trim();
!t.is_empty()
&& (t.contains("Migrating schema")
|| t.contains("Successfully applied")
|| t.contains("Successfully validated")
|| t.contains("Schema version")
|| t.contains("No migration")
|| t.contains("ERROR")
|| t.contains("error")
|| t.contains("FAILED")
|| t.contains("V") && t.contains("__"))
})
.collect();
if useful.is_empty() {
return compactor::collapse_blanks(&s);
}
useful.join("\n")
}
pub fn compress_info(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let s = BANNER_RE.replace_all(&cleaned, "");
let s = DB_CONN_RE.replace_all(&s, "");
let lines: Vec<&str> = s.lines().filter(|l| !l.trim().is_empty()).collect();
if lines.len() > 30 {
return format!(
"{}\n… [{} more migrations]",
lines[..30].join("\n"),
lines.len() - 30
);
}
lines.join("\n")
}
pub fn compress_validate(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let s = BANNER_RE.replace_all(&cleaned, "");
let s = DB_CONN_RE.replace_all(&s, "");
compactor::collapse_blanks(&s)
}
pub fn compress_flyway(subcmd: &str, raw: &str) -> String {
let sub = subcmd.trim();
if sub.starts_with("migrate") {
return compress_migrate(raw);
}
if sub.starts_with("info") {
return compress_info(raw);
}
if sub.starts_with("validate") || sub.starts_with("repair") {
return compress_validate(raw);
}
let cleaned = compactor::normalise(raw);
let s = BANNER_RE.replace_all(&cleaned, "");
let s = DB_CONN_RE.replace_all(&s, "");
compactor::collapse_blanks(&s)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn migrate_strips_banner_and_keeps_migrations() {
let raw = "Flyway Community Edition 9.22.3 by Redgate\n____________________________\nDatabase: jdbc:postgresql://localhost:5432/mydb (PostgreSQL 14.5)\nSuccessfully validated 3 migrations (execution time 00:00.025s)\nCurrent version of schema \"public\": 2\nMigrating schema \"public\" to version \"3 - add orders table\" [V3__add_orders_table.sql]\nSuccessfully applied 1 migration to schema \"public\", now at version v3 (execution time 00:00.123s)\n";
let out = compress_flyway("migrate", raw);
assert!(!out.contains("Flyway Community"), "{out}");
assert!(!out.contains("jdbc:postgresql"), "{out}");
assert!(
out.contains("Successfully applied") || out.contains("Migrating schema"),
"{out}"
);
}
#[test]
fn info_truncates_long_history() {
let mut lines = vec![
"+-----------+---------+---------------------+------+---------------------+---------+"
.to_string(),
];
for i in 0..35 {
lines.push(format!("| {i:<9} | migrate | V{i}__migration.sql | SQL | 2024-01-{i:02} 00:00:00 | Success |"));
}
let out = compress_info(&lines.join("\n"));
assert!(out.contains("more migrations"), "{out}");
}
}