Skip to content

Commit d3cb76a

Browse files
authored
Merge pull request #21 from epage/fail
Remove `failure` from API
2 parents 1cf53cd + 7bd71a8 commit d3cb76a

File tree

6 files changed

+105
-44
lines changed

6 files changed

+105
-44
lines changed

Cargo.toml

+1-3
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,8 @@ keywords = ["cli", "test", "assert", "command", "duct"]
1515
name = "bin_fixture"
1616

1717
[dependencies]
18-
failure = "0.1"
19-
failure_derive = "0.1"
2018
predicates = "0.5.1"
21-
escargot = "0.1"
19+
escargot = "0.2"
2220
serde = { version = "1.0", features = ["derive"] }
2321

2422
[dev-dependencies]

examples/example_fixture.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
extern crate failure;
2-
31
use std::env;
2+
use std::error::Error;
43
use std::io;
54
use std::io::Write;
65
use std::process;
76

8-
use failure::ResultExt;
9-
10-
fn run() -> Result<(), failure::Error> {
7+
fn run() -> Result<(), Box<Error>> {
118
if let Ok(text) = env::var("stdout") {
129
println!("{}", text);
1310
}
@@ -18,8 +15,7 @@ fn run() -> Result<(), failure::Error> {
1815
let code = env::var("exit")
1916
.ok()
2017
.map(|v| v.parse::<i32>())
21-
.map_or(Ok(None), |r| r.map(Some))
22-
.context("Invalid exit code")?
18+
.map_or(Ok(None), |r| r.map(Some))?
2319
.unwrap_or(0);
2420
process::exit(code);
2521
}

src/bin/bin_fixture.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
extern crate failure;
2-
31
use std::env;
2+
use std::error::Error;
43
use std::io;
54
use std::io::Write;
65
use std::process;
76

8-
use failure::ResultExt;
9-
10-
fn run() -> Result<(), failure::Error> {
7+
fn run() -> Result<(), Box<Error>> {
118
if let Ok(text) = env::var("stdout") {
129
println!("{}", text);
1310
}
@@ -18,8 +15,7 @@ fn run() -> Result<(), failure::Error> {
1815
let code = env::var("exit")
1916
.ok()
2017
.map(|v| v.parse::<i32>())
21-
.map_or(Ok(None), |r| r.map(Some))
22-
.context("Invalid exit code")?
18+
.map_or(Ok(None), |r| r.map(Some))?
2319
.unwrap_or(0);
2420
process::exit(code);
2521
}

src/cargo.rs

+78-15
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
//! .unwrap();
1313
//! ```
1414
15+
use std::error::Error;
1516
use std::ffi;
17+
use std::fmt;
1618
use std::path;
1719
use std::process;
1820

1921
use escargot;
20-
use failure;
2122

2223
/// Create a `Command` for a `bin` in the Cargo project.
2324
pub trait CommandCargoExt
@@ -39,7 +40,7 @@ where
3940
/// .unwrap()
4041
/// .unwrap();
4142
/// ```
42-
fn main_binary() -> Result<Self, failure::Error>;
43+
fn main_binary() -> Result<Self, CargoError>;
4344

4445
/// Create a `Command` to run a specific binary of the current crate.
4546
///
@@ -54,7 +55,7 @@ where
5455
/// .unwrap()
5556
/// .unwrap();
5657
/// ```
57-
fn cargo_bin<S: AsRef<ffi::OsStr>>(name: S) -> Result<Self, failure::Error>;
58+
fn cargo_bin<S: AsRef<ffi::OsStr>>(name: S) -> Result<Self, CargoError>;
5859

5960
/// Create a `Command` to run a specific example of the current crate.
6061
///
@@ -69,21 +70,21 @@ where
6970
/// .unwrap()
7071
/// .unwrap();
7172
/// ```
72-
fn cargo_example<S: AsRef<ffi::OsStr>>(name: S) -> Result<Self, failure::Error>;
73+
fn cargo_example<S: AsRef<ffi::OsStr>>(name: S) -> Result<Self, CargoError>;
7374
}
7475

7576
impl CommandCargoExt for process::Command {
76-
fn main_binary() -> Result<Self, failure::Error> {
77+
fn main_binary() -> Result<Self, CargoError> {
7778
let cmd = main_binary_path()?;
7879
Ok(process::Command::new(&cmd))
7980
}
8081

81-
fn cargo_bin<S: AsRef<ffi::OsStr>>(name: S) -> Result<Self, failure::Error> {
82+
fn cargo_bin<S: AsRef<ffi::OsStr>>(name: S) -> Result<Self, CargoError> {
8283
let cmd = cargo_bin_path(name)?;
8384
Ok(process::Command::new(&cmd))
8485
}
8586

86-
fn cargo_example<S: AsRef<ffi::OsStr>>(name: S) -> Result<Self, failure::Error> {
87+
fn cargo_example<S: AsRef<ffi::OsStr>>(name: S) -> Result<Self, CargoError> {
8788
let cmd = cargo_example_path(name)?;
8889
Ok(process::Command::new(&cmd))
8990
}
@@ -126,41 +127,103 @@ fn extract_filenames(msg: &escargot::Message, kind: &str) -> Option<path::PathBu
126127
/// Get the path to the crate's main binary.
127128
///
128129
/// Note: only works if there one bin in the crate.
129-
pub fn main_binary_path() -> Result<path::PathBuf, failure::Error> {
130+
pub fn main_binary_path() -> Result<path::PathBuf, CargoError> {
130131
let cargo = escargot::Cargo::new().build().current_release();
131132
let bins: Vec<_> = cargo
132-
.exec()?
133+
.exec()
134+
.map_err(|e| CargoError::with_cause(e))?
133135
.filter_map(|m| extract_filenames(&m, "bin"))
134136
.collect();
135137
if bins.is_empty() {
136-
bail!("No binaries in crate");
138+
return Err(CargoError::with_context("No binaries in crate"));
137139
} else if bins.len() != 1 {
138-
bail!("Ambiguous which binary is intended: {:?}", bins);
140+
return Err(CargoError::with_context(format!(
141+
"Ambiguous which binary is intended: {:?}",
142+
bins
143+
)));
139144
}
140145
Ok(bins.into_iter().next().expect("already validated"))
141146
}
142147

143148
/// Get the path to the specified binary of the current crate.
144-
pub fn cargo_bin_path<S: AsRef<ffi::OsStr>>(name: S) -> Result<path::PathBuf, failure::Error> {
149+
pub fn cargo_bin_path<S: AsRef<ffi::OsStr>>(name: S) -> Result<path::PathBuf, CargoError> {
145150
let cargo = escargot::Cargo::new().build().bin(name).current_release();
146151
let bins: Vec<_> = cargo
147-
.exec()?
152+
.exec()
153+
.map_err(|e| CargoError::with_cause(e))?
148154
.filter_map(|m| extract_filenames(&m, "bin"))
149155
.collect();
150156
assert_eq!(bins.len(), 1);
151157
Ok(bins.into_iter().next().expect("already validated"))
152158
}
153159

154160
/// Get the path to the specified example of the current crate.
155-
pub fn cargo_example_path<S: AsRef<ffi::OsStr>>(name: S) -> Result<path::PathBuf, failure::Error> {
161+
pub fn cargo_example_path<S: AsRef<ffi::OsStr>>(name: S) -> Result<path::PathBuf, CargoError> {
156162
let cargo = escargot::Cargo::new()
157163
.build()
158164
.example(name)
159165
.current_release();
160166
let bins: Vec<_> = cargo
161-
.exec()?
167+
.exec()
168+
.map_err(|e| CargoError::with_cause(e))?
162169
.filter_map(|m| extract_filenames(&m, "example"))
163170
.collect();
164171
assert_eq!(bins.len(), 1);
165172
Ok(bins.into_iter().next().expect("already validated"))
166173
}
174+
175+
/// Error when finding crate binary.
176+
#[derive(Debug)]
177+
pub struct CargoError {
178+
context: Option<String>,
179+
cause: Option<Box<Error + Send + Sync + 'static>>,
180+
}
181+
182+
impl CargoError {
183+
fn with_context<S>(context: S) -> Self
184+
where
185+
S: Into<String>,
186+
{
187+
let context = context.into();
188+
Self {
189+
context: Some(context),
190+
cause: None,
191+
}
192+
}
193+
194+
fn with_cause<E>(cause: E) -> Self
195+
where
196+
E: Error + Send + Sync + 'static,
197+
{
198+
let cause = Box::new(cause);
199+
Self {
200+
context: None,
201+
cause: Some(cause),
202+
}
203+
}
204+
}
205+
206+
impl Error for CargoError {
207+
fn description(&self) -> &str {
208+
"Cargo command failed."
209+
}
210+
211+
fn cause(&self) -> Option<&Error> {
212+
self.cause.as_ref().map(|c| {
213+
let c: &Error = c.as_ref();
214+
c
215+
})
216+
}
217+
}
218+
219+
impl fmt::Display for CargoError {
220+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221+
if let Some(ref context) = self.context {
222+
writeln!(f, "{}", context)?;
223+
}
224+
if let Some(ref cause) = self.cause {
225+
writeln!(f, "Cause: {}", cause)?;
226+
}
227+
Ok(())
228+
}
229+
}

src/errors.rs

+20-8
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
use std::error::Error;
12
use std::fmt;
23
use std::process;
34
use std::str;
45

5-
use failure;
6-
76
/// `std::process::Output` represented as a `Result`.
87
///
98
/// # Examples
@@ -34,15 +33,15 @@ pub type OutputResult = Result<process::Output, OutputError>;
3433
/// .env("exit", "42")
3534
/// .unwrap_err();
3635
/// ```
37-
#[derive(Fail, Debug)]
36+
#[derive(Debug)]
3837
pub struct OutputError {
3938
cmd: Option<String>,
4039
stdin: Option<Vec<u8>>,
4140
cause: OutputCause,
4241
}
4342

4443
impl OutputError {
45-
/// Convert `std::process::Output` into a `Fail`.
44+
/// Convert `std::process::Output` into an `Error`.
4645
pub fn new(output: process::Output) -> Self {
4746
Self {
4847
cmd: None,
@@ -54,12 +53,12 @@ impl OutputError {
5453
/// For errors that happen in creating a `std::process::Output`.
5554
pub fn with_cause<E>(cause: E) -> Self
5655
where
57-
E: Into<failure::Error>,
56+
E: Error + Send + Sync + 'static,
5857
{
5958
Self {
6059
cmd: None,
6160
stdin: None,
62-
cause: OutputCause::Unexpected(cause.into()),
61+
cause: OutputCause::Unexpected(Box::new(cause)),
6362
}
6463
}
6564

@@ -101,6 +100,19 @@ impl OutputError {
101100
}
102101
}
103102

103+
impl Error for OutputError {
104+
fn description(&self) -> &str {
105+
"Command failed."
106+
}
107+
108+
fn cause(&self) -> Option<&Error> {
109+
if let &OutputCause::Unexpected(ref err) = &self.cause {
110+
Some(err.as_ref())
111+
} else {
112+
None
113+
}
114+
}
115+
}
104116
impl fmt::Display for OutputError {
105117
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106118
if let Some(ref cmd) = self.cmd {
@@ -120,7 +132,7 @@ impl fmt::Display for OutputError {
120132
#[derive(Debug)]
121133
enum OutputCause {
122134
Expected(Output),
123-
Unexpected(failure::Error),
135+
Unexpected(Box<Error + Send + Sync + 'static>),
124136
}
125137

126138
impl fmt::Display for OutputCause {
@@ -133,7 +145,7 @@ impl fmt::Display for OutputCause {
133145
}
134146

135147
/// Wrap `Output` to be `Dislay`able.
136-
#[derive(Fail, Debug)]
148+
#[derive(Debug)]
137149
struct Output {
138150
output: process::Output,
139151
}

src/lib.rs

-4
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@
3737
#![warn(missing_docs)]
3838

3939
extern crate escargot;
40-
#[macro_use]
41-
extern crate failure;
42-
#[macro_use]
43-
extern crate failure_derive;
4440
extern crate predicates;
4541
#[macro_use]
4642
extern crate serde;

0 commit comments

Comments
 (0)