Skip to content

Commit 3feb056

Browse files
committed
Replace error-chain with thiserror
This patch replaces error-chain with the current version of thiserror. There's nothing done more, so no cleanup of .expect() or .unwrap() calls, just a plain conversion from one crate to another. Signed-off-by: Matthias Beyer <[email protected]>
1 parent 0a933d7 commit 3feb056

File tree

5 files changed

+109
-106
lines changed

5 files changed

+109
-106
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ readme = "README.md"
1616
[dependencies]
1717
nix = "0.14"
1818
regex = "1"
19-
error-chain = "0.12"
2019
tempfile = "3"
20+
thiserror = "1.0.34"
2121

2222
[badges]
2323
maintenance = { status = "passively-maintained" }

src/error.rs

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,39 @@
11
use std::time;
22

3-
error_chain::error_chain! {
4-
errors {
5-
EOF(expected:String, got:String, exit_code:Option<String>) {
6-
description("End of filestream (usually stdout) occurred, most probably\
7-
because the process terminated")
8-
display("EOF (End of File): Expected {} but got EOF after reading \"{}\", \
9-
process terminated with {:?}", expected, got,
10-
exit_code.as_ref()
11-
.unwrap_or(& "unknown".to_string()))
12-
}
13-
BrokenPipe {
14-
description("The pipe to the process is broken. Most probably because\
15-
the process died.")
16-
display("PipeError")
17-
}
18-
Timeout(expected:String, got:String, timeout:time::Duration) {
19-
description("The process didn't end within the given timeout")
20-
display("Timeout Error: Expected {} but got \"{}\" (after waiting {} ms)",
21-
expected, got, (timeout.as_secs() * 1000) as u32
22-
+ timeout.subsec_millis())
23-
}
24-
EmptyProgramName {
25-
description("The provided program name is empty.")
26-
display("EmptyProgramName")
27-
}
28-
}
3+
#[derive(Debug, thiserror::Error)]
4+
pub enum Error {
5+
#[error("EOF (End of File): Expected {} but got EOF after reading \"{}\" process terminated with {:?}", .expected, .got, .exit_code.as_ref().unwrap_or(&"unknown".to_string()))]
6+
EOF {
7+
expected: String,
8+
got: String,
9+
exit_code: Option<String>,
10+
},
11+
12+
#[error("PipeError")]
13+
BrokenPipe,
14+
15+
#[error("Timeout Error: Expected {} but got \"{}\" (after waiting {} ms)", .expected, .got, (.timeout.as_secs() * 1000) as u32 + .timeout.subsec_millis())]
16+
Timeout {
17+
expected: String,
18+
got: String,
19+
timeout: time::Duration,
20+
},
21+
22+
#[error("The provided program name is empty.")]
23+
EmptyProgramName,
24+
25+
#[error(transparent)]
26+
Nix(#[from] nix::Error),
27+
28+
#[error(transparent)]
29+
Io(#[from] std::io::Error),
30+
31+
#[error("Did not understand Ctrl-{}", .0)]
32+
SendContolError(char),
33+
34+
#[error("Failed to send via MPSC channel")]
35+
MpscSendError,
36+
37+
#[error(transparent)]
38+
Regex(#[from] regex::Error),
2939
}

src/process.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Start a process via pty
22
3-
use crate::error::*;
3+
use crate::error::Error;
44
use nix;
55
use nix::fcntl::{open, OFlag};
66
use nix::libc::{STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO};
@@ -13,7 +13,7 @@ use std::fs::File;
1313
use std::os::unix::io::{AsRawFd, FromRawFd};
1414
use std::os::unix::process::CommandExt;
1515
use std::process::Command;
16-
use std::{thread, time}; // load error-chain
16+
use std::{thread, time};
1717

1818
/// Start a process in a forked tty so you can interact with it the same as you would
1919
/// within a terminal
@@ -87,7 +87,7 @@ fn ptsname_r(fd: &PtyMaster) -> nix::Result<String> {
8787

8888
impl PtyProcess {
8989
/// Start a process in a forked pty
90-
pub fn new(mut command: Command) -> Result<Self> {
90+
pub fn new(mut command: Command) -> Result<Self, Error> {
9191
|| -> nix::Result<Self> {
9292
// Open a new PTY master
9393
let master_fd = posix_openpt(OFlag::O_RDWR)?;
@@ -128,7 +128,7 @@ impl PtyProcess {
128128
}),
129129
}
130130
}()
131-
.chain_err(|| format!("could not execute {:?}", command))
131+
.map_err(Error::from)
132132
}
133133

134134
/// Get handle to pty fork for reading/writing
@@ -177,19 +177,18 @@ impl PtyProcess {
177177

178178
/// Wait until process has exited. This is a blocking call.
179179
/// If the process doesn't terminate this will block forever.
180-
pub fn wait(&self) -> Result<wait::WaitStatus> {
181-
wait::waitpid(self.child_pid, None).chain_err(|| "wait: cannot read status")
180+
pub fn wait(&self) -> Result<wait::WaitStatus, Error> {
181+
wait::waitpid(self.child_pid, None).map_err(Error::from)
182182
}
183183

184184
/// Regularly exit the process, this method is blocking until the process is dead
185-
pub fn exit(&mut self) -> Result<wait::WaitStatus> {
186-
self.kill(signal::SIGTERM)
185+
pub fn exit(&mut self) -> Result<wait::WaitStatus, Error> {
186+
self.kill(signal::SIGTERM).map_err(Error::from)
187187
}
188188

189189
/// Non-blocking variant of `kill()` (doesn't wait for process to be killed)
190-
pub fn signal(&mut self, sig: signal::Signal) -> Result<()> {
191-
signal::kill(self.child_pid, sig).chain_err(|| "failed to send signal to process")?;
192-
Ok(())
190+
pub fn signal(&mut self, sig: signal::Signal) -> Result<(), Error> {
191+
signal::kill(self.child_pid, sig).map_err(Error::from)
193192
}
194193

195194
/// Kill the process with a specific signal. This method blocks, until the process is dead
@@ -200,7 +199,7 @@ impl PtyProcess {
200199
///
201200
/// if `kill_timeout` is set and a repeated sending of signal does not result in the process
202201
/// being killed, then `kill -9` is sent after the `kill_timeout` duration has elapsed.
203-
pub fn kill(&mut self, sig: signal::Signal) -> Result<wait::WaitStatus> {
202+
pub fn kill(&mut self, sig: signal::Signal) -> Result<wait::WaitStatus, Error> {
204203
let start = time::Instant::now();
205204
loop {
206205
match signal::kill(self.child_pid, sig) {
@@ -209,7 +208,7 @@ impl PtyProcess {
209208
Err(nix::Error::Sys(nix::errno::Errno::ESRCH)) => {
210209
return Ok(wait::WaitStatus::Exited(Pid::from_raw(0), 0))
211210
}
212-
Err(e) => return Err(format!("kill resulted in error: {:?}", e).into()),
211+
Err(e) => return Err(Error::from(e)),
213212
}
214213

215214
match self.status() {
@@ -219,7 +218,7 @@ impl PtyProcess {
219218
// kill -9 if timout is reached
220219
if let Some(timeout) = self.kill_timeout {
221220
if start.elapsed() > timeout {
222-
signal::kill(self.child_pid, signal::Signal::SIGKILL).chain_err(|| "")?
221+
signal::kill(self.child_pid, signal::Signal::SIGKILL).map_err(Error::from)?
223222
}
224223
}
225224
}

src/reader.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Unblocking reader which supports waiting for strings/regexes and EOF to be present
22
3-
use crate::error::*; // load error-chain
3+
use crate::error::Error;
44
pub use regex::Regex;
55
use std::io::prelude::*;
66
use std::io::{self, BufReader};
@@ -120,22 +120,20 @@ impl NBReader {
120120

121121
// spawn a thread which reads one char and sends it to tx
122122
thread::spawn(move || {
123-
let _ = || -> Result<()> {
123+
let _ = || -> Result<(), Error> {
124124
let mut reader = BufReader::new(f);
125125
let mut byte = [0u8];
126126
loop {
127127
match reader.read(&mut byte) {
128128
Ok(0) => {
129-
tx.send(Ok(PipedChar::EOF)).chain_err(|| "cannot send")?;
129+
tx.send(Ok(PipedChar::EOF)).map_err(|_| Error::MpscSendError)?;
130130
break;
131131
}
132132
Ok(_) => {
133-
tx.send(Ok(PipedChar::Char(byte[0])))
134-
.chain_err(|| "cannot send")?;
133+
tx.send(Ok(PipedChar::Char(byte[0]))).map_err(|_| Error::MpscSendError)?;
135134
}
136135
Err(error) => {
137-
tx.send(Err(PipeError::IO(error)))
138-
.chain_err(|| "cannot send")?;
136+
tx.send(Err(PipeError::IO(error))).map_err(|_| Error::MpscSendError)?;
139137
}
140138
}
141139
}
@@ -155,7 +153,7 @@ impl NBReader {
155153
}
156154

157155
/// reads all available chars from the read channel and stores them in self.buffer
158-
fn read_into_buffer(&mut self) -> Result<()> {
156+
fn read_into_buffer(&mut self) -> Result<(), Error> {
159157
if self.eof {
160158
return Ok(());
161159
}
@@ -222,7 +220,7 @@ impl NBReader {
222220
/// assert_eq!("?", &until_end);
223221
/// ```
224222
///
225-
pub fn read_until(&mut self, needle: &ReadUntil) -> Result<(String, String)> {
223+
pub fn read_until(&mut self, needle: &ReadUntil) -> Result<(String, String), Error> {
226224
let start = time::Instant::now();
227225

228226
loop {
@@ -237,22 +235,25 @@ impl NBReader {
237235
// we don't know the reason of eof yet, so we provide an empty string
238236
// this will be filled out in session::exp()
239237
if self.eof {
240-
return Err(ErrorKind::EOF(needle.to_string(), self.buffer.clone(), None).into());
238+
return Err(Error::EOF {
239+
expected: needle.to_string(),
240+
got: self.buffer.clone(),
241+
exit_code: None,
242+
});
241243
}
242244

243245
// ran into timeout
244246
if let Some(timeout) = self.timeout {
245247
if start.elapsed() > timeout {
246-
return Err(ErrorKind::Timeout(
247-
needle.to_string(),
248-
self.buffer
248+
return Err(Error::Timeout {
249+
expected: needle.to_string(),
250+
got: self.buffer
249251
.clone()
250252
.replace('\n', "`\\n`\n")
251253
.replace('\r', "`\\r`")
252254
.replace('\u{1b}', "`^`"),
253255
timeout,
254-
)
255-
.into());
256+
});
256257
}
257258
}
258259
// nothing matched: wait a little
@@ -289,8 +290,8 @@ mod tests {
289290
// check for EOF
290291
match r.read_until(&ReadUntil::NBytes(10)) {
291292
Ok(_) => panic!(),
292-
Err(Error(ErrorKind::EOF(_, _, _), _)) => {}
293-
Err(Error(_, _)) => panic!(),
293+
Err(Error::EOF { .. }) => {}
294+
Err(_) => panic!(),
294295
}
295296
}
296297

0 commit comments

Comments
 (0)