feat(fb-26): extend ProgressMode with quiet field, update from_flags signature
Add `quiet: bool` to `Human` variant and expand `from_flags` to three args (`json`, `quiet`, `plain_env`). Update `handle`/`handle_human` accordingly; add four targeted unit tests (TDD). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -370,7 +370,7 @@ fn run(cli: &Cli) -> anyhow::Result<()> {
|
|||||||
// the channel and emits per-step events into it. When the
|
// the channel and emits per-step events into it. When the
|
||||||
// call returns, the `Sender` drops and the display thread
|
// call returns, the `Sender` drops and the display thread
|
||||||
// sees `recv()` return Err — exits cleanly.
|
// sees `recv()` return Err — exits cleanly.
|
||||||
let mode = progress::ProgressMode::from_flags(cli.json);
|
let mode = progress::ProgressMode::from_flags(cli.json, false, false);
|
||||||
let (tx, rx) = std::sync::mpsc::channel::<kebab_app::IngestEvent>();
|
let (tx, rx) = std::sync::mpsc::channel::<kebab_app::IngestEvent>();
|
||||||
let display_handle = std::thread::spawn(move || {
|
let display_handle = std::thread::spawn(move || {
|
||||||
progress::ProgressDisplay::new(mode).run(rx)
|
progress::ProgressDisplay::new(mode).run(rx)
|
||||||
|
|||||||
@@ -39,18 +39,22 @@ pub enum ProgressMode {
|
|||||||
Json,
|
Json,
|
||||||
/// stdout reserved for the final report; stderr gets an indicatif
|
/// stdout reserved for the final report; stderr gets an indicatif
|
||||||
/// `ProgressBar` (TTY) or one short line per event (non-TTY).
|
/// `ProgressBar` (TTY) or one short line per event (non-TTY).
|
||||||
Human { tty: bool },
|
Human { tty: bool, quiet: bool },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProgressMode {
|
impl ProgressMode {
|
||||||
/// Pick the right mode from caller flags.
|
/// Pick the right mode from caller flags.
|
||||||
pub fn from_flags(json: bool) -> Self {
|
///
|
||||||
|
/// - `json`: `--json` flag — takes priority, returns `Json`.
|
||||||
|
/// - `quiet`: `--quiet` flag — suppresses human-readable stderr when `Human`.
|
||||||
|
/// - `plain_env`: `KEBAB_PROGRESS=plain` — forces `tty=false` even in a TTY,
|
||||||
|
/// for CI environments that emulate a TTY with a pty wrapper.
|
||||||
|
pub fn from_flags(json: bool, quiet: bool, plain_env: bool) -> Self {
|
||||||
if json {
|
if json {
|
||||||
Self::Json
|
Self::Json
|
||||||
} else {
|
} else {
|
||||||
Self::Human {
|
let tty = !plain_env && std::io::stderr().is_terminal();
|
||||||
tty: std::io::stderr().is_terminal(),
|
Self::Human { tty, quiet }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +87,7 @@ impl ProgressDisplay {
|
|||||||
fn handle(&mut self, event: &IngestEvent) -> anyhow::Result<()> {
|
fn handle(&mut self, event: &IngestEvent) -> anyhow::Result<()> {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
ProgressMode::Json => emit_json(event),
|
ProgressMode::Json => emit_json(event),
|
||||||
ProgressMode::Human { tty } => self.handle_human(event, tty),
|
ProgressMode::Human { tty, quiet } => self.handle_human(event, tty, quiet),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +100,8 @@ impl ProgressDisplay {
|
|||||||
/// `ScanStarted` arm and §2.4a's ordering invariant
|
/// `ScanStarted` arm and §2.4a's ordering invariant
|
||||||
/// (`ScanStarted` < everything else) guarantees it is `Some` by
|
/// (`ScanStarted` < everything else) guarantees it is `Some` by
|
||||||
/// the time later events arrive.
|
/// the time later events arrive.
|
||||||
fn handle_human(&mut self, event: &IngestEvent, tty: bool) -> anyhow::Result<()> {
|
fn handle_human(&mut self, event: &IngestEvent, tty: bool, quiet: bool) -> anyhow::Result<()> {
|
||||||
|
let _ = quiet; // used in Task 3; suppress unused warning for now
|
||||||
match event {
|
match event {
|
||||||
IngestEvent::ScanStarted { root } => {
|
IngestEvent::ScanStarted { root } => {
|
||||||
let bar = ProgressBar::new_spinner().with_message(format!("scanning {root}"));
|
let bar = ProgressBar::new_spinner().with_message(format!("scanning {root}"));
|
||||||
@@ -216,20 +221,35 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_flags_json_takes_priority_over_tty() {
|
fn from_flags_json_takes_priority_over_tty() {
|
||||||
// --json forces Json regardless of TTY state.
|
assert_eq!(ProgressMode::from_flags(true, false, false), ProgressMode::Json);
|
||||||
assert_eq!(ProgressMode::from_flags(true), ProgressMode::Json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_flags_human_reflects_stderr_tty() {
|
fn from_flags_human_reflects_stderr_tty() {
|
||||||
// We can't synthesize a TTY in tests, but we can assert the
|
// We can't synthesize a TTY in tests, but we can assert the
|
||||||
// shape — mode is Human { tty: <something> } when --json=false.
|
// shape — mode is Human { tty: <something> } when --json=false.
|
||||||
match ProgressMode::from_flags(false) {
|
match ProgressMode::from_flags(false, false, false) {
|
||||||
ProgressMode::Human { .. } => {}
|
ProgressMode::Human { .. } => {}
|
||||||
other => panic!("expected Human mode, got {other:?}"),
|
other => panic!("expected Human mode, got {other:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_flags_quiet_sets_quiet_field() {
|
||||||
|
match ProgressMode::from_flags(false, true, false) {
|
||||||
|
ProgressMode::Human { quiet: true, .. } => {}
|
||||||
|
other => panic!("expected Human{{quiet:true}}, got {other:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_flags_plain_env_forces_tty_false() {
|
||||||
|
match ProgressMode::from_flags(false, false, true) {
|
||||||
|
ProgressMode::Human { tty: false, .. } => {}
|
||||||
|
other => panic!("expected Human{{tty:false}}, got {other:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn now_rfc3339_parses_back() {
|
fn now_rfc3339_parses_back() {
|
||||||
let s = now_rfc3339().unwrap();
|
let s = now_rfc3339().unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user