Trait command_error::CommandExt
source · pub trait CommandExt {
type Error: From<Error>;
// Required methods
fn output_checked_as<O, R, E>(
&mut self,
succeeded: impl Fn(OutputContext<O>) -> Result<R, E>
) -> Result<R, E>
where O: Debug + OutputLike + 'static + TryFrom<Output>,
<O as TryFrom<Output>>::Error: Display,
E: From<Self::Error>;
fn status_checked_as<R, E>(
&mut self,
succeeded: impl Fn(OutputContext<ExitStatus>) -> Result<R, E>
) -> Result<R, E>
where E: From<Self::Error>;
fn log(&self) -> Result<(), Self::Error>;
// Provided methods
fn output_checked_with<O, E>(
&mut self,
succeeded: impl Fn(&O) -> Result<(), Option<E>>
) -> Result<O, Self::Error>
where O: Debug + OutputLike + TryFrom<Output> + 'static,
<O as TryFrom<Output>>::Error: Display,
E: Debug + Display + 'static { ... }
fn output_checked(&mut self) -> Result<Output, Self::Error> { ... }
fn output_checked_utf8(&mut self) -> Result<Utf8Output, Self::Error> { ... }
fn output_checked_with_utf8<E>(
&mut self,
succeeded: impl Fn(&Utf8Output) -> Result<(), Option<E>>
) -> Result<Utf8Output, Self::Error>
where E: Display + Debug + 'static { ... }
fn status_checked_with<E>(
&mut self,
succeeded: impl Fn(ExitStatus) -> Result<(), Option<E>>
) -> Result<ExitStatus, Self::Error>
where E: Debug + Display + 'static { ... }
fn status_checked(&mut self) -> Result<ExitStatus, Self::Error> { ... }
}Expand description
Extension trait for Command.
CommandExt methods check the exit status of the command (or perform user-supplied
validation logic) and produced detailed, helpful error messages when they fail:
use std::process::Command;
use command_error::CommandExt;
let err = Command::new("sh")
.args(["-c", "echo puppy; false"])
.output_checked_utf8()
.unwrap_err();
assert_eq!(
err.to_string(),
indoc!(
"`sh` failed: exit status: 1
Command failed: `sh -c 'echo puppy; false'`
Stdout:
puppy"
)
);With the tracing feature enabled, commands will be logged before they run.
§Method overview
| Method | Output decoding | Validation |
|---|---|---|
output_checked | Bytes | Non-zero exit codes are errors |
output_checked_utf8 | UTF-8 | Non-zero exit codes are errors |
output_checked_with | Arbitrary | Custom |
output_checked_with_utf8 | UTF-8 | Custom |
output_checked_as | Arbitrary | Custom, with arbitrary error type |
status_checked_as | None | Custom, with arbitrary error type |
status_checked | None | Non-zero exit codes are errors |
Required Associated Types§
Required Methods§
sourcefn output_checked_as<O, R, E>(
&mut self,
succeeded: impl Fn(OutputContext<O>) -> Result<R, E>
) -> Result<R, E>
fn output_checked_as<O, R, E>( &mut self, succeeded: impl Fn(OutputContext<O>) -> Result<R, E> ) -> Result<R, E>
Run a command, capturing its output. succeeded is called and returned to determine if the
command succeeded.
This is the most general CommandExt method, and gives the caller full control over
success logic and the output and errors produced.
let err = Command::new("cat")
.arg("tests/data/incomplete.json")
.output_checked_as(|context: OutputContext<Output>| {
serde_json::from_slice(&context.output().stdout)
.map_err(|err| context.error_msg(err))
})
.unwrap_err();
assert_eq!(
err.to_string(),
indoc!(
r#"`cat` failed: EOF while parsing a list at line 4 column 11
exit status: 0
Command failed: `cat tests/data/incomplete.json`
Stdout:
[
"cuppy",
"dog",
"city","#
)
);Note that the closure takes the output as raw bytes but the error message contains the
output decoded as UTF-8. In this example, the decoding only happens in the error case, but
if you request an OutputContext<Utf8Output>, the decoded data will be reused for the
error message.
The OutputContext passed to the closure contains information about the command’s
Output (including its ExitStatus), the command that ran (the program name and its
arguments), and methods for constructing detailed error messages (with or without
additional context information).
sourcefn status_checked_as<R, E>(
&mut self,
succeeded: impl Fn(OutputContext<ExitStatus>) -> Result<R, E>
) -> Result<R, E>
fn status_checked_as<R, E>( &mut self, succeeded: impl Fn(OutputContext<ExitStatus>) -> Result<R, E> ) -> Result<R, E>
Run a command without capturing its output. succeeded is called and returned to determine
if the command succeeded.
This gives the caller full control over success logic and the output and errors produced.
let succeeded = |context: OutputContext<ExitStatus>| {
match context.status().code() {
Some(code) => Ok(code),
None => Err(context.error_msg("no exit code")),
}
};
let code = Command::new("true")
.status_checked_as(succeeded)
.unwrap();
assert_eq!(code, 0);
let err = Command::new("sh")
.args(["-c", "kill \"$$\""])
.status_checked_as(succeeded)
.unwrap_err();
assert_eq!(
err.to_string(),
indoc!(
r#"`sh` failed: no exit code
signal: 15 (SIGTERM)
Command failed: `sh -c 'kill "$$"'`"#
)
);To error on non-zero exit codes, use CommandExt::status_checked.
Provided Methods§
sourcefn output_checked_with<O, E>(
&mut self,
succeeded: impl Fn(&O) -> Result<(), Option<E>>
) -> Result<O, Self::Error>
fn output_checked_with<O, E>( &mut self, succeeded: impl Fn(&O) -> Result<(), Option<E>> ) -> Result<O, Self::Error>
Run a command, capturing its output. succeeded is called and used to determine if the
command succeeded and (optionally) to add an additional message to the error returned.
This method is best if you want to consider a command successful if it has a non-zero exit
code, or if its output contains some special string. If you’d like to additionally produce
output that can’t be produced with TryFrom<Output> (such as to deserialize a data
structure), CommandExt::output_checked_as provides full control over the produced
result.
let output = Command::new("sh")
.args(["-c", "echo puppy && exit 2"])
.output_checked_with(|output: &Output| {
if let Some(2) = output.status.code() {
Ok(())
} else {
// Don't add any additional context to the error message:
Err(None::<String>)
}
})
.unwrap();
assert_eq!(
output.status.code(),
Some(2),
);Note that due to the generic error parameter, you’ll need to annotate None return
values with a Displayable type — try String or any std::error::Error type in
scope.
Command::output_checked_with can also be used to convert the output to any type that
implements TryFrom<Output> before running succeeded:
let err = Command::new("sh")
.args(["-c", "echo kitty && kill -9 \"$$\""])
.output_checked_with(|output: &Utf8Output| {
if output.status.success() && output.stdout.trim() == "puppy" {
Ok(())
} else {
Err(Some("didn't find any puppy!"))
}
})
.unwrap_err();
assert_eq!(
err.to_string(),
indoc!(
r#"`sh` failed: didn't find any puppy!
signal: 9 (SIGKILL)
Command failed: `sh -c 'echo kitty && kill -9 "$$"'`
Stdout:
kitty"#
)
);sourcefn output_checked(&mut self) -> Result<Output, Self::Error>
fn output_checked(&mut self) -> Result<Output, Self::Error>
Run a command, capturing its output. If the command exits with a non-zero exit code, an error is raised. Error messages are detailed and contain information about the command that was run and its output:
let err = Command::new("ooby-gooby")
.output_checked()
.unwrap_err();
assert_eq!(
err.to_string(),
"Failed to execute `ooby-gooby`: No such file or directory (os error 2)"
);
let err = Command::new("sh")
.args(["-c", "echo puppy && exit 1"])
.output_checked()
.unwrap_err();
assert_eq!(
err.to_string(),
indoc!(
"`sh` failed: exit status: 1
Command failed: `sh -c 'echo puppy && exit 1'`
Stdout:
puppy"
)
);If the command fails, output will be decoded as UTF-8 for display in error messages, but
otherwise no output decoding is performed. To decode output as UTF-8, use
CommandExt::output_checked_utf8. To decode as other formats, use
CommandExt::output_checked_with.
sourcefn output_checked_utf8(&mut self) -> Result<Utf8Output, Self::Error>
fn output_checked_utf8(&mut self) -> Result<Utf8Output, Self::Error>
Run a command, capturing its output and decoding it as UTF-8. If the command exits with a non-zero exit code or if its output contains invalid UTF-8, an error is raised.
See CommandExt::output_checked for more information.
let output = Command::new("echo")
.arg("puppy")
.output_checked_utf8()
.unwrap();
assert_eq!(
output,
Utf8Output {
status: ExitStatus::default(),
stdout: "puppy\n".into(),
stderr: "".into(),
},
);sourcefn output_checked_with_utf8<E>(
&mut self,
succeeded: impl Fn(&Utf8Output) -> Result<(), Option<E>>
) -> Result<Utf8Output, Self::Error>
fn output_checked_with_utf8<E>( &mut self, succeeded: impl Fn(&Utf8Output) -> Result<(), Option<E>> ) -> Result<Utf8Output, Self::Error>
Run a command, capturing its output and decoding it as UTF-8. succeeded is called and
used to determine if the command succeeded and (optionally) to add an additional message to
the error returned.
See CommandExt::output_checked_with for more information.
let output = Command::new("sh")
.args(["-c", "echo puppy; exit 1"])
.output_checked_with_utf8(|output| {
if output.stdout.contains("puppy") {
Ok(())
} else {
Err(None::<String>)
}
})
.unwrap();
assert_eq!(output.stdout, "puppy\n");
assert_eq!(output.status.code(), Some(1));sourcefn status_checked_with<E>(
&mut self,
succeeded: impl Fn(ExitStatus) -> Result<(), Option<E>>
) -> Result<ExitStatus, Self::Error>
fn status_checked_with<E>( &mut self, succeeded: impl Fn(ExitStatus) -> Result<(), Option<E>> ) -> Result<ExitStatus, Self::Error>
Run a command without capturing its output. succeeded is called and used to determine
if the command succeeded and (optionally) to add an additional message to the error
returned.
let status = Command::new("false")
.status_checked_with(|status| {
match status.code() {
// Exit codes 0 and 1 are OK.
Some(0) | Some(1) => Ok(()),
// Other exit codes are errors.
_ => Err(None::<String>)
}
})
.unwrap();
assert_eq!(status.code(), Some(1));sourcefn status_checked(&mut self) -> Result<ExitStatus, Self::Error>
fn status_checked(&mut self) -> Result<ExitStatus, Self::Error>
Run a command without capturing its output. If the command exits with a non-zero status code, an error is raised containing information about the command that was run:
let err = Command::new("sh")
.args(["-c", "exit 1"])
.status_checked()
.unwrap_err();
assert_eq!(
err.to_string(),
indoc!(
"`sh` failed: exit status: 1
Command failed: `sh -c 'exit 1'`"
)
);