1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//! Subprocess runner for Rust. Typed errors, retry, timeout, stdin piping,
//! pipelines, secret redaction, optional async.
//!
//! `procpilot` provides one entry point — the [`Cmd`] builder — with four
//! terminators: [`Cmd::run`] / [`Cmd::spawn`] for the sync runner, and
//! (behind the `tokio` feature) [`Cmd::run_async`](crate::Cmd::run_async) /
//! [`Cmd::spawn_async`](crate::Cmd::spawn_async) for the async runner.
//!
//! # Quick start
//!
//! ```no_run
//! use std::time::Duration;
//! use procpilot::{Cmd, RunError};
//!
//! let output = Cmd::new("git")
//! .args(["show", "maybe-missing-ref"])
//! .timeout(Duration::from_secs(30))
//! .run();
//!
//! match output {
//! Ok(o) => println!("{}", o.stdout_lossy()),
//! Err(RunError::NonZeroExit { .. }) => { /* ref not found */ }
//! Err(e) => return Err(e.into()),
//! }
//! # Ok::<(), anyhow::Error>(())
//! ```
//!
//! # What's on offer
//!
//! - **Typed errors**: [`RunError`] variants for spawn / non-zero / timeout,
//! with shell-quoted command display (secret-redacted via [`Cmd::secret`]).
//! - **Stdin**: [`Cmd::stdin`] accepts owned bytes (reusable across retries),
//! a boxed `Read` (one-shot), or — with the `tokio` feature —
//! [`StdinData::from_async_reader`] for true async streaming.
//! - **Stdout/stderr routing**: [`Redirection`] covers capture, inherit,
//! null, and file redirection via [`Cmd::stdout`] / [`Cmd::stderr`] (or
//! the [`Cmd::stdout_file`] / [`Cmd::stderr_file`] shortcuts).
//! - **Timeout + deadline**: [`Cmd::timeout`] for per-attempt,
//! [`Cmd::deadline`] for overall wall-clock budget across retries.
//! - **Retry with exponential backoff**: [`Cmd::retry`] / [`Cmd::retry_when`].
//! - **Pipelines**: [`Cmd::pipe`] or the `|` operator chains commands
//! (`a | b | c`) with pipefail semantics — non-success on any stage
//! fails the pipeline, rightmost non-success wins. Works on both
//! [`run`](Cmd::run) and [`spawn`](Cmd::spawn).
//! - **Streaming / bidirectional**: [`Cmd::spawn`] returns a
//! [`SpawnedProcess`] with `take_stdin` / `take_stdout`, `Read` impls,
//! `kill`, and idempotent `wait` / `wait_timeout`.
//! - **Async (tokio, opt-in)**: enable the `tokio` feature for
//! [`Cmd::run_async`](Cmd::run_async) and
//! [`Cmd::spawn_async`](Cmd::spawn_async). Returns an
//! [`AsyncSpawnedProcess`] for the spawn path. All builder knobs work
//! identically.
//! - **Cloneable `Cmd`**: configure a base once, `.clone()` to branch off
//! variants.
//! - **Escape hatches**: [`Cmd::before_spawn`] for arbitrary
//! pre-spawn mutation; [`Cmd::to_rightmost_command`] /
//! [`Cmd::to_commands`] to drop to raw `std::process::Command`.
//!
//! # Platform support
//!
//! Tested on macOS and Linux. Windows is best-effort — core functionality
//! should work but edge cases (e.g. [`Redirection::File`]) are not CI-covered.
//!
//! Release history: [CHANGELOG.md](https://github.com/michaeldhopkins/procpilot/blob/main/CHANGELOG.md).
pub use AsyncSpawnedProcess;
pub use ;
pub use CmdDisplay;
pub use ;
pub use Redirection;
pub use ;
pub use ;
pub use SpawnedProcess;
pub use StdinData;
/// Common types for everyday use.
///
/// `use procpilot::prelude::*;` brings in the handful of items most callers
/// will reach for: the [`Cmd`] builder, [`RunError`] / [`RunOutput`] for
/// dispatching results, [`Redirection`] for stdio routing, [`StdinData`]
/// for the `.stdin(...)` argument, [`RetryPolicy`] for `.retry(...)`, and
/// the spawn handles ([`SpawnedProcess`] always; [`AsyncSpawnedProcess`]
/// behind the `tokio` feature).
///
/// The prelude intentionally omits [`CmdDisplay`] and [`STREAM_SUFFIX_SIZE`]
/// — useful but rarely named in client code. Reach for those by full path
/// when needed.