Trait command_error::CommandExt
source · pub trait CommandExt: Sized {
type Error: From<Error> + Send + Sync;
type Child;
// 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 + TryFrom<Output> + Send + Sync + 'static,
<O as TryFrom<Output>>::Error: Display + Send + Sync,
E: From<Self::Error> + Send + Sync;
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 spawn_checked(&mut self) -> Result<Self::Child, 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> + Send + Sync + 'static,
<O as TryFrom<Output>>::Error: Display + Send + Sync,
E: Debug + Display + Send + Sync + '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 + Send + Sync + 'static { ... }
fn status_checked_with<E>(
&mut self,
succeeded: impl Fn(ExitStatus) -> Result<(), Option<E>>
) -> Result<ExitStatus, Self::Error>
where E: Debug + Display + Send + Sync + '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 | Errors |
---|---|---|
output_checked | Bytes | If non-zero exit code |
output_checked_with | Arbitrary | Custom |
output_checked_as | Arbitrary | Custom, with arbitrary error type |
output_checked_utf8 | UTF-8 | If non-zero exit code |
output_checked_with_utf8 | UTF-8 | Custom |
status_checked | None | If non-zero exit code |
status_checked_with | None | Custom |
status_checked_as | None | Custom, with arbitrary error type |
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.
See Command::output
for more information.
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
.
See Command::status
for more information.
sourcefn spawn_checked(&mut self) -> Result<Self::Child, Self::Error>
fn spawn_checked(&mut self) -> Result<Self::Child, Self::Error>
Spawn a command.
The returned child contains context information about the command that produced it, which can be used to produce detailed error messages if the child process fails.
See Command::spawn
for more information.
let err = Command::new("ooga booga")
.spawn_checked()
.unwrap_err();
assert_eq!(
err.to_string(),
"Failed to execute `'ooga booga'`: No such file or directory (os error 2)"
);
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.
See Command::output
for more information.
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 Display
able 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
.
See Command::output
for more information.
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
and Command::output
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
and Command::output
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));
See Command::status
for more information.
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'`"
)
);
See Command::status
for more information.