use crate::core::progress::{ProgressBus, ProgressEvent, Stage};
pub(super) fn progress(bus: &ProgressBus, target: &str, line: &str) {
if emit(bus, target, line) {
return;
}
println!("{line}");
}
pub(super) fn warning(bus: &ProgressBus, target: &str, line: &str) {
if emit(bus, target, line) {
return;
}
eprintln!("{line}");
}
fn emit(bus: &ProgressBus, target: &str, line: &str) -> bool {
if !bus.is_active() {
return false;
}
bus.emit(ProgressEvent::advanced(Stage::Collect, target, 0, None).with_detail(line));
true
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn progress_reaches_the_bus_instead_of_stdout() {
let bus = ProgressBus::new();
progress(
&bus,
"trusty-tools",
"Collected W31 2026: 104 commits [trusty-tools]",
);
let events = bus.drain();
assert_eq!(events.len(), 1, "an active bus must receive the line");
assert_eq!(events[0].stage, Stage::Collect);
assert_eq!(events[0].target, "trusty-tools");
assert_eq!(
events[0].detail.as_deref(),
Some("Collected W31 2026: 104 commits [trusty-tools]")
);
assert!(
!events[0].is_terminal(),
"a chatter line must not settle the row"
);
}
#[test]
fn warning_reaches_the_bus_instead_of_stderr() {
let bus = ProgressBus::new();
warning(&bus, "repo", "warning: [repo] no since_date");
let events = bus.drain();
assert_eq!(events.len(), 1);
assert_eq!(
events[0].detail.as_deref(),
Some("warning: [repo] no since_date")
);
}
#[test]
fn progress_prints_when_no_bus_is_attached() {
let bus = ProgressBus::disabled();
assert!(
!emit(&bus, "repo", "Collected W31 2026: 1 commits [repo]"),
"a disabled bus must fall through to println!"
);
progress(&bus, "repo", "Collected W31 2026: 1 commits [repo]");
warning(&bus, "repo", "warning: something");
assert!(bus.drain().is_empty());
}
}