Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 30 additions & 23 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,9 +618,9 @@ impl io::AsyncRead for ChildStderr {
/// ```
pub struct Command {
inner: std::process::Command,
stdin: Option<Stdio>,
stdout: Option<Stdio>,
stderr: Option<Stdio>,
stdin: bool,
stdout: bool,
stderr: bool,
reap_on_drop: bool,
kill_on_drop: bool,
}
Expand All @@ -641,9 +641,9 @@ impl Command {
pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
Command {
inner: std::process::Command::new(program),
stdin: None,
stdout: None,
stderr: None,
stdin: false,
stdout: false,
stderr: false,
reap_on_drop: true,
kill_on_drop: false,
}
Expand Down Expand Up @@ -785,7 +785,8 @@ impl Command {
/// cmd.stdin(Stdio::null());
/// ```
pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
self.stdin = Some(cfg.into());
self.stdin = true;
self.inner.stdin(cfg);
self
}

Expand All @@ -800,7 +801,8 @@ impl Command {
/// cmd.stdout(Stdio::piped());
/// ```
pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
self.stdout = Some(cfg.into());
self.stdout = true;
self.inner.stdout(cfg);
self
}

Expand All @@ -815,7 +817,8 @@ impl Command {
/// cmd.stderr(Stdio::piped());
/// ```
pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
self.stderr = Some(cfg.into());
self.stderr = true;
self.inner.stderr(cfg);
self
}

Expand Down Expand Up @@ -865,8 +868,6 @@ impl Command {
///
/// If not configured, stdin, stdout and stderr will be set to [`Stdio::inherit()`].
///
/// After spawning the process, stdin, stdout, and stderr become unconfigured again.
///
/// # Examples
///
/// ```no_run
Expand All @@ -877,10 +878,15 @@ impl Command {
/// # std::io::Result::Ok(()) });
/// ```
pub fn spawn(&mut self) -> io::Result<Child> {
let (stdin, stdout, stderr) = (self.stdin.take(), self.stdout.take(), self.stderr.take());
self.inner.stdin(stdin.unwrap_or_else(Stdio::inherit));
self.inner.stdout(stdout.unwrap_or_else(Stdio::inherit));
self.inner.stderr(stderr.unwrap_or_else(Stdio::inherit));
if !self.stdin {
self.inner.stdin(Stdio::inherit());
}
if !self.stdout {
self.inner.stdout(Stdio::inherit());
}
if !self.stderr {
self.inner.stderr(Stdio::inherit());
}

Child::new(self)
}
Expand All @@ -889,8 +895,6 @@ impl Command {
///
/// If not configured, stdin, stdout and stderr will be set to [`Stdio::inherit()`].
///
/// After spawning the process, stdin, stdout, and stderr become unconfigured again.
///
/// # Examples
///
/// ```no_run
Expand All @@ -914,8 +918,6 @@ impl Command {
/// If not configured, stdin will be set to [`Stdio::null()`], and stdout and stderr will be
/// set to [`Stdio::piped()`].
///
/// After spawning the process, stdin, stdout, and stderr become unconfigured again.
///
/// # Examples
///
/// ```no_run
Expand All @@ -929,10 +931,15 @@ impl Command {
/// # std::io::Result::Ok(()) });
/// ```
pub fn output(&mut self) -> impl Future<Output = io::Result<Output>> {
let (stdin, stdout, stderr) = (self.stdin.take(), self.stdout.take(), self.stderr.take());
self.inner.stdin(stdin.unwrap_or_else(Stdio::null));
self.inner.stdout(stdout.unwrap_or_else(Stdio::piped));
self.inner.stderr(stderr.unwrap_or_else(Stdio::piped));
if !self.stdin {
self.inner.stdin(Stdio::null());
}
if !self.stdout {
self.inner.stdout(Stdio::piped());
}
if !self.stderr {
self.inner.stderr(Stdio::piped());
}

let child = Child::new(self);
async { child?.output().await }
Expand Down
22 changes: 22 additions & 0 deletions tests/std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,3 +407,25 @@ fn child_as_raw_handle() {
assert_eq!(win_pid, std_pid);
})
}

#[test]
#[cfg(unix)]
fn test_spawn_multiple_with_stdio() {
let mut cmd = Command::new("/bin/sh");
cmd.arg("-c")
.arg("echo foo; echo bar 1>&2")
.stdout(Stdio::piped())
.stderr(Stdio::piped());

future::block_on(async move {
let p1 = cmd.spawn().unwrap();
let out1 = p1.output().await.unwrap();
assert_eq!(out1.stdout, b"foo\n");
assert_eq!(out1.stderr, b"bar\n");

let p2 = cmd.spawn().unwrap();
let out2 = p2.output().await.unwrap();
assert_eq!(out2.stdout, b"foo\n");
assert_eq!(out2.stderr, b"bar\n");
});
}