## Subcommands
-Cargo is organized as a set of subcommands. All subcommands live in
-`src/bin` directory. However, only `src/bin/cargo.rs` file produces an
-executable, other files inside the `bin` directory are submodules. See
-`src/bin/cargo.rs` for how these subcommands get wired up with the
-main executable.
+Cargo is organized as a set of `clap` subcommands. All subcommands live in
+`src/bin/commands` directory. `src/bin/cargo.rs` is the entry point.
-A typical subcommand, such as `src/bin/build.rs`, parses command line
+A typical subcommand, such as `src/bin/commands/build.rs`, parses command line
options, reads the configuration files, discovers the Cargo project in
the current directory and delegates the actual implementation to one
of the functions in `src/cargo/ops/mod.rs`. This short file is a good
macros of the form `[MACRO]` are used in the expected output. For
example, `[..]` matches any string and `[/]` matches `/` on Unixes and
`\` on windows.
+
+To see stdout and stderr streams of the subordinate process, add `.stream()`
+call to `execs()`:
+
+```rust
+// Before
+assert_that(
+ p.cargo("run"),
+ execs().with_status(0)
+);
+
+// After
+assert_that(
+ p.cargo("run"),
+ execs().stream().with_status(0)
+);
+
+```
expect_stderr_not_contains: Vec<String>,
expect_neither_contains: Vec<String>,
expect_json: Option<Vec<Value>>,
+ stream_output: bool,
}
impl Execs {
self
}
+ /// Forward subordinate process stdout/stderr to the terminal.
+ /// Useful for prtintf debugging of the tests.
+ #[allow(unused)]
+ pub fn stream(mut self) -> Execs {
+ self.stream_output = true;
+ self
+ }
+
fn match_output(&self, actual: &Output) -> ham::MatchResult {
self.match_status(actual)
.and(self.match_stdout(actual))
impl<'a> ham::Matcher<&'a mut ProcessBuilder> for Execs {
fn matches(&self, process: &'a mut ProcessBuilder) -> ham::MatchResult {
println!("running {}", process);
- let res = process.exec_with_output();
+ let res = if self.stream_output {
+ if env::var("CI").is_ok() {
+ panic!("`.stream()` is for local debugging")
+ }
+ process.exec_with_streaming(
+ &mut |out| Ok(println!("{}", out)),
+ &mut |err| Ok(eprintln!("{}", err)),
+ false,
+ )
+ } else {
+ process.exec_with_output()
+ };
match res {
Ok(out) => self.match_output(&out),
expect_stderr_not_contains: Vec::new(),
expect_neither_contains: Vec::new(),
expect_json: None,
+ stream_output: false,
}
}