Terminate process gracefully on error in diff() (#685)

As noted in the comment in main(), process::exit should be avoided
because it does not call certain destructors.

Fixes #681
This commit is contained in:
Dan Davison 2021-08-12 13:17:32 -07:00 committed by GitHub
parent 0541c5b3d8
commit 35ba0dc1a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -53,7 +53,9 @@ pub mod errors {
} }
#[cfg(not(tarpaulin_include))] #[cfg(not(tarpaulin_include))]
/// `Ok` of the `Result` contains with the exit code value // An Ok result contains the desired process exit code. Note that 1 is used to
// report that two files differ when delta is called with two positional
// arguments and without standard input; 2 is used to report a real problem.
fn run_app() -> std::io::Result<i32> { fn run_app() -> std::io::Result<i32> {
let assets = HighlightingAssets::new(); let assets = HighlightingAssets::new();
let opt = cli::Opt::from_args_and_git_config(&mut git_config::GitConfig::try_create(), assets); let opt = cli::Opt::from_args_and_git_config(&mut git_config::GitConfig::try_create(), assets);
@ -120,31 +122,38 @@ fn diff(
writer: &mut dyn Write, writer: &mut dyn Write,
) -> i32 { ) -> i32 {
use std::io::BufReader; use std::io::BufReader;
let die = || { if minus_file.is_none() || plus_file.is_none() {
eprintln!( eprintln!(
"\ "\
The main way to use delta is to configure it as the pager for git: \ The main way to use delta is to configure it as the pager for git: \
see https://github.com/dandavison/delta#configuration. \ see https://github.com/dandavison/delta#configuration. \
You can also use delta to diff two files: `delta file_A file_B`." You can also use delta to diff two files: `delta file_A file_B`."
); );
process::exit(config.error_exit_code); return config.error_exit_code;
}; }
let minus_file = minus_file.unwrap();
let plus_file = plus_file.unwrap();
let diff_command = "git"; let diff_command = "git";
let minus_file = minus_file.unwrap_or_else(die);
let plus_file = plus_file.unwrap_or_else(die);
let diff_command_path = match grep_cli::resolve_binary(PathBuf::from(diff_command)) { let diff_command_path = match grep_cli::resolve_binary(PathBuf::from(diff_command)) {
Ok(path) => path, Ok(path) => path,
Err(_) => return config.error_exit_code, Err(err) => {
eprintln!("Failed to resolve command '{}': {}", diff_command, err);
return config.error_exit_code;
}
}; };
let mut diff_process = process::Command::new(diff_command_path)
let diff_process = process::Command::new(diff_command_path)
.args(&["diff", "--no-index"]) .args(&["diff", "--no-index"])
.args(&[minus_file, plus_file]) .args(&[minus_file, plus_file])
.stdout(process::Stdio::piped()) .stdout(process::Stdio::piped())
.spawn() .spawn();
.unwrap_or_else(|err| {
eprintln!("Failed to execute the command '{}': {}", diff_command, err); if let Err(err) = diff_process {
process::exit(config.error_exit_code); eprintln!("Failed to execute the command '{}': {}", diff_command, err);
}); return config.error_exit_code;
}
let mut diff_process = diff_process.unwrap();
let exit_code = diff_process let exit_code = diff_process
.wait() .wait()
@ -154,7 +163,7 @@ You can also use delta to diff two files: `delta file_A file_B`."
.code() .code()
.unwrap_or_else(|| { .unwrap_or_else(|| {
eprintln!("'{}' process terminated without exit status.", diff_command); eprintln!("'{}' process terminated without exit status.", diff_command);
process::exit(config.error_exit_code); config.error_exit_code
}); });
if let Err(error) = delta( if let Err(error) = delta(
@ -163,10 +172,10 @@ You can also use delta to diff two files: `delta file_A file_B`."
&config, &config,
) { ) {
match error.kind() { match error.kind() {
ErrorKind::BrokenPipe => process::exit(0), ErrorKind::BrokenPipe => return 0,
_ => { _ => {
eprintln!("{}", error); eprintln!("{}", error);
process::exit(config.error_exit_code); return config.error_exit_code;
} }
} }
}; };