radicle-heartwood-lfs/crates/radicle-cli
Fintan Halpenny 1a31a9f541 cli: Handle broken pipe (SIGPIPE) gracefully
Prevent `rad` from panicking when its stdout is a closed pipe, e.g.
when running `rad config | head`.

The broken pipes are handled at the output boundaries using three
layers of defence:

1. Inner: Route all stdout output through `term::print()` and
   `term::print_inline()`, which use explicit `writeln!`/`write!` to
   a locked stdout and silently ignore write errors. All `println!`
   calls in `radicle-cli` and `radicle-term` are converted.
2. Middle: Catch `BrokenPipe` errors that propagate up via `anyhow`
   from subcommands in `main::run()`, and exit cleanly with code 0.
3. Outer: Install a panic hook that intercepts `println!` panics
   containing "Broken pipe" (from dependencies like clap) and exits
   cleanly, chained in front of human_panic's hook.

To prevent regressions, `#![deny(clippy::print_stdout)]` is added to
`radicle-cli`, requiring all future stdout output to go through the
safe `term::` functions.

Note: `eprintln!` calls (stderr) are not handled, as broken stderr
pipes are extremely rare in practice.
2026-04-29 10:57:24 +02:00
..
examples treewide: radicle.{xyz → dev,network} 2026-04-27 18:34:30 +02:00
src cli: Handle broken pipe (SIGPIPE) gracefully 2026-04-29 10:57:24 +02:00
tests term: Catch EPIPE and swallow 2026-04-29 10:57:24 +02:00
CHANGELOG.md cli: Update to 0.20.0 2026-03-26 15:32:43 +00:00
Cargo.toml cli: Handle broken pipe (SIGPIPE) gracefully 2026-04-29 10:57:24 +02:00
build.rs repo: Move workspace crates into `crates` subdirectory 2025-06-09 15:09:21 +02:00