Skip to content

Commit

Permalink
feat(stdin): Support piping in files
Browse files Browse the repository at this point in the history
There is just enough overlap between how people expect paths and strings
to be used, I felt we couldn't just have an `IntoStdIn`.

Long term, we should consider streaming the content from file / reader
to stdin.

Fixes #24

BREAKING CHANGE: `with_stdin(buffer)` is now
`with_stdin().buffer(buffer)`.
  • Loading branch information
epage committed Jul 19, 2018
1 parent 0b4fce7 commit 7bb3014
Showing 1 changed file with 68 additions and 7 deletions.
75 changes: 68 additions & 7 deletions src/stdin.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use std::fs;
use std::io;
use std::io::Read;
use std::io::Write;
use std::path;
use std::process;

use assert::Assert;
Expand All @@ -22,24 +25,81 @@ pub trait CommandStdInExt {
///
/// Command::new("cat")
/// .arg("-A")
/// .with_stdin("42")
/// .with_stdin()
/// .buffer("42")
/// .unwrap();
/// ```
fn with_stdin<S>(&mut self, buffer: S) -> StdInCommand
where
S: Into<Vec<u8>>;
fn with_stdin(&mut self) -> StdInCommandBuilder;
}

impl CommandStdInExt for process::Command {
fn with_stdin<S>(&mut self, buffer: S) -> StdInCommand
fn with_stdin(&mut self) -> StdInCommandBuilder {
StdInCommandBuilder { cmd: self }
}
}

/// For adding a stdin to a `Command`.
#[derive(Debug)]
pub struct StdInCommandBuilder<'a> {
cmd: &'a mut process::Command,
}

impl<'a> StdInCommandBuilder<'a> {
/// Write `buffer` to `stdin` when the command is run.
///
/// # Examples
///
/// ```rust
/// use assert_cmd::prelude::*;
///
/// use std::process::Command;
///
/// Command::new("cat")
/// .arg("-A")
/// .with_stdin()
/// .buffer("42")
/// .unwrap();
/// ```
pub fn buffer<S>(&mut self, buffer: S) -> StdInCommand
where
S: Into<Vec<u8>>,
{
StdInCommand {
cmd: self,
cmd: self.cmd,
stdin: buffer.into(),
}
}

/// Write `path`s content to `stdin` when the command is run.
///
/// Paths are relative to the `env::current_dir` and not `Command::current_dir`.
///
/// # Examples
///
/// ```rust
/// use assert_cmd::prelude::*;
///
/// use std::process::Command;
///
/// Command::new("cat")
/// .arg("-A")
/// .with_stdin()
/// .path("Cargo.toml")
/// .unwrap()
/// .unwrap();
/// ```
pub fn path<P>(&mut self, file: P) -> io::Result<StdInCommand>
where
P: AsRef<path::Path>,
{
let file = file.as_ref();
let mut buffer = Vec::new();
fs::File::open(file)?.read_to_end(&mut buffer)?;
Ok(StdInCommand {
cmd: self.cmd,
stdin: buffer,
})
}
}

/// `Command` that carries the `stdin` buffer.
Expand All @@ -54,7 +114,8 @@ impl CommandStdInExt for process::Command {
/// use std::process::Command;
///
/// Command::new("cat")
/// .with_stdin("42")
/// .with_stdin()
/// .buffer("42")
/// .unwrap();
/// ```
#[derive(Debug)]
Expand Down

0 comments on commit 7bb3014

Please sign in to comment.