procpilot/lib.rs
1//! Production-grade subprocess runner with typed errors, retry, and timeout.
2//!
3//! `procpilot` provides one entry point — the [`Cmd`] builder — covering every
4//! practical subprocess configuration. Errors are typed: [`RunError`]
5//! distinguishes spawn failure, non-zero exit, and timeout, each carrying
6//! the last 128 KiB of stdout/stderr for diagnosis.
7//!
8//! # Quick start
9//!
10//! ```no_run
11//! use std::time::Duration;
12//! use procpilot::{Cmd, RunError};
13//!
14//! let output = Cmd::new("git")
15//! .args(["show", "maybe-missing-ref"])
16//! .timeout(Duration::from_secs(30))
17//! .run();
18//!
19//! match output {
20//! Ok(o) => println!("{}", o.stdout_lossy()),
21//! Err(RunError::NonZeroExit { .. }) => { /* ref not found */ }
22//! Err(e) => return Err(e.into()),
23//! }
24//! # Ok::<(), anyhow::Error>(())
25//! ```
26//!
27//! # Features
28//!
29//! - **Typed errors**: [`RunError`] variants for spawn / non-zero / timeout,
30//! with shell-quoted command display (secret-redacted via [`Cmd::secret`]).
31//! - **Stdin**: [`Cmd::stdin`] accepts owned bytes (reusable across retries)
32//! or a boxed `Read` (one-shot).
33//! - **Stderr routing**: [`Redirection`] covers capture, inherit, null, and
34//! file redirection.
35//! - **Timeout + deadline**: [`Cmd::timeout`] for per-attempt, [`Cmd::deadline`]
36//! for overall wall-clock budget across retries.
37//! - **Retry with exponential backoff**: [`Cmd::retry`] / [`Cmd::retry_when`].
38//! - **Escape hatches**: [`Cmd::before_spawn`] for pre-spawn hooks,
39//! [`Cmd::to_command`] to drop to raw `std::process::Command`.
40//!
41//! Release history: [CHANGELOG.md](https://github.com/michaeldhopkins/procpilot/blob/main/CHANGELOG.md).
42
43mod cmd;
44mod cmd_display;
45mod error;
46mod redirection;
47mod retry;
48mod runner;
49mod spawned;
50mod stdin;
51
52pub use cmd::{BeforeSpawnHook, Cmd, RunOutput};
53pub use cmd_display::CmdDisplay;
54pub use error::{RunError, STREAM_SUFFIX_SIZE};
55pub use redirection::Redirection;
56pub use retry::{RetryPolicy, default_transient};
57pub use runner::{binary_available, binary_version};
58pub use spawned::SpawnedProcess;
59pub use stdin::StdinData;