Skip to content

Commit e5eaf39

Browse files
committed
Use std::process:Termination
Rust 1.61.0 introduced the std::process::Termination API alongside support for returning a std::process::ExitCode instance from main(). By using this instead of exiting manually we can bump llvm-cov's region coverage another 5 percentage points, to 85%.
1 parent d934d64 commit e5eaf39

1 file changed

Lines changed: 48 additions & 24 deletions

File tree

src/main.rs

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::borrow::Cow;
22
use std::error::Error;
33
use std::fmt;
44
use std::io;
5+
use std::process::ExitCode;
6+
use std::process::Termination;
57

68
mod commitmsgfmt;
79
mod parser;
@@ -107,6 +109,26 @@ impl<'a> Error for CliError<'a> {
107109
}
108110
}
109111

112+
impl Termination for CliError<'_> {
113+
fn report(self) -> ExitCode {
114+
match self {
115+
CliError::EarlyExit(s) => {
116+
println!("{}", s);
117+
ExitCode::SUCCESS
118+
}
119+
CliError::Io(ref e) if e.kind() == io::ErrorKind::BrokenPipe => {
120+
let ret = 128 + 13;
121+
debug_assert!(ret == 141);
122+
ExitCode::from(ret)
123+
}
124+
_ => {
125+
eprintln!("fatal: {}", self);
126+
ExitCode::FAILURE
127+
}
128+
}
129+
}
130+
}
131+
110132
enum CliArgument<'a> {
111133
HelpShort,
112134
HelpLong,
@@ -172,11 +194,11 @@ fn parse_git_config_commentchar(git_output: Result<Vec<u8>, io::Error>) -> char
172194
}
173195
}
174196

175-
fn main() {
197+
fn main() -> ExitCode {
176198
let command_line = std::env::args().collect::<Vec<String>>();
177199
let cfg = try_config_from_command_line(&command_line);
178-
if let Err(ref e) = cfg {
179-
exit_abnormally(e);
200+
if let Err(e) = cfg {
201+
return e.report();
180202
}
181203
let cfg = cfg.unwrap();
182204

@@ -187,8 +209,9 @@ fn main() {
187209
.map(|text| commitmsgfmt.filter(&text))
188210
.and_then(to_stdout);
189211

190-
if let Err(ref e) = result {
191-
exit_abnormally(e);
212+
match result {
213+
Ok(()) => ExitCode::SUCCESS,
214+
Err(e) => e.report(),
192215
}
193216
}
194217

@@ -293,25 +316,6 @@ fn to_stdout<'a>(msg: String) -> CliResult<'a, ()> {
293316
Ok(())
294317
}
295318

296-
fn exit_abnormally(e: &CliError) {
297-
let ret = match e {
298-
CliError::EarlyExit(s) => {
299-
println!("{}", s);
300-
0
301-
}
302-
CliError::Io(ref e) if e.kind() == io::ErrorKind::BrokenPipe => {
303-
let ret = 128 + 13;
304-
debug_assert!(ret == 141);
305-
ret
306-
}
307-
_ => {
308-
eprintln!("fatal: {}", e);
309-
1
310-
}
311-
};
312-
::std::process::exit(ret);
313-
}
314-
315319
#[cfg(test)]
316320
mod tests {
317321
use super::*;
@@ -475,6 +479,26 @@ mod tests {
475479
assert_eq!(expected, actual);
476480
}
477481

482+
#[test]
483+
fn impl_clierror_termination() {
484+
let errs = vec![
485+
(CliError::ArgUnrecognized("foo".into()), ExitCode::FAILURE),
486+
(CliError::ArgWidthNaN("nan".into()), ExitCode::FAILURE),
487+
(CliError::ArgWidthOutOfBounds(0), ExitCode::FAILURE),
488+
(CliError::EarlyExit("help".into()), ExitCode::SUCCESS),
489+
(
490+
CliError::from(io::Error::from(io::ErrorKind::BrokenPipe)),
491+
ExitCode::from(141),
492+
),
493+
(CliError::Other("other".into()), ExitCode::FAILURE),
494+
];
495+
let (actual, expected): (Vec<_>, Vec<_>) = errs
496+
.into_iter()
497+
.map(|(input, ex)| (format!("{:?}", input.report()), format!("{:?}", ex)))
498+
.unzip();
499+
assert_eq!(expected, actual);
500+
}
501+
478502
#[test]
479503
fn smoke_decide_behavior_from_command_line() {
480504
use crate::CliError::*;

0 commit comments

Comments
 (0)