Remove calls to exit() and replace them with error propagation up to main()

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
Matthias Beyer 2019-10-19 08:54:57 +02:00
parent fd40715b29
commit 4b8ca2b110

View file

@ -38,12 +38,11 @@ extern crate clap;
#[macro_use] extern crate log; #[macro_use] extern crate log;
extern crate toml; extern crate toml;
extern crate toml_query; extern crate toml_query;
extern crate failure; #[macro_use] extern crate failure;
extern crate libimagrt; extern crate libimagrt;
extern crate libimagerror; extern crate libimagerror;
use std::io::Write;
use std::io::ErrorKind; use std::io::ErrorKind;
use std::process::Command; use std::process::Command;
@ -51,9 +50,9 @@ use toml::Value;
use toml_query::read::TomlValueReadExt; use toml_query::read::TomlValueReadExt;
use clap::App; use clap::App;
use failure::Fallible as Result; use failure::Fallible as Result;
use failure::ResultExt;
use failure::err_msg;
use libimagerror::exit::ExitUnwrap;
use libimagerror::io::ToExitCode;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagrt::application::ImagApplication; use libimagrt::application::ImagApplication;
@ -68,29 +67,19 @@ impl ImagApplication for ImagGit {
fn run(rt: Runtime) -> Result<()> { fn run(rt: Runtime) -> Result<()> {
let execute_in_store = rt let execute_in_store = rt
.config() .config()
.unwrap_or_else(|| { .ok_or_else(|| err_msg("No configuration. Please use git yourself, not via imag-git"))
error!("No configuration. Please use git yourself, not via imag-git"); .context("Won't continue without configuration.")
error!("Won't continue without configuration."); ?
::std::process::exit(1);
})
.read("git.execute_in_store") .read("git.execute_in_store")
.unwrap_or_else(|e| { .context("Failed to read config setting 'git.execute_in_store'")
error!("Failed to read config setting 'git.execute_in_store'"); ?
error!("-> {:?}", e); .ok_or_else(|| err_msg("Missing config setting 'git.execute_in_store'"))
::std::process::exit(1) ?;
})
.unwrap_or_else(|| {
error!("Missing config setting 'git.execute_in_store'");
::std::process::exit(1)
});
let execute_in_store = match *execute_in_store { let execute_in_store = match *execute_in_store {
Value::Boolean(b) => b, Value::Boolean(b) => Ok(b),
_ => { _ => Err(err_msg("Type error: 'git.execute_in_store' is not a boolean!")),
error!("Type error: 'git.execute_in_store' is not a boolean!"); }?;
::std::process::exit(1)
}
};
let execpath = if execute_in_store { let execpath = if execute_in_store {
rt.store().path().to_str() rt.store().path().to_str()
@ -98,11 +87,7 @@ impl ImagApplication for ImagGit {
rt.rtp().to_str() rt.rtp().to_str()
} }
.map(String::from) .map(String::from)
.unwrap_or_else(|| { .ok_or_else(|| format_err!("Cannot parse to string: {:?}", rt.store().path()))?;
error!("Cannot parse to string: {:?}", rt.store().path());
::std::process::exit(1)
});
let mut command = Command::new("git"); let mut command = Command::new("git");
command command
@ -120,63 +105,39 @@ impl ImagApplication for ImagGit {
debug!("Adding args = {:?}", args); debug!("Adding args = {:?}", args);
command.args(&args); command.args(&args);
match rt.cli().subcommand() { if let (external, Some(ext_m)) = rt.cli().subcommand() {
(external, Some(ext_m)) => { command.arg(external);
command.arg(external); let args = ext_m
let args = ext_m .values_of("")
.values_of("") .map(|vs| vs.map(String::from).collect())
.map(|vs| vs.map(String::from).collect()) .unwrap_or_else(|| vec![]);
.unwrap_or_else(|| vec![]);
debug!("Adding subcommand '{}' and args = {:?}", external, args); debug!("Adding subcommand '{}' and args = {:?}", external, args);
command.args(&args); command.args(&args);
},
_ => {},
} }
let mut out = rt.stdout();
debug!("Calling: {:?}", command); debug!("Calling: {:?}", command);
match command.spawn().and_then(|mut c| c.wait()) { match command.spawn().and_then(|mut c| c.wait()) {
Ok(exit_status) => { Ok(exit_status) => {
if !exit_status.success() { if !exit_status.success() {
debug!("git exited with non-zero exit code: {:?}", exit_status); debug!("git exited with non-zero exit code: {:?}", exit_status);
let mut err = rt.stderr(); Err(format_err!("git exited with non-zero exit code: {:?}", exit_status))
writeln!(err, "git exited with non-zero exit code") } else {
.to_exit_code() debug!("Successful exit!");
.unwrap_or_exit(); Ok(())
::std::process::exit(exit_status.code().unwrap_or(1));
} }
debug!("Successful exit!");
}, },
Err(e) => { Err(e) => {
debug!("Error calling git"); debug!("Error calling git");
match e.kind() { Err(match e.kind() {
ErrorKind::NotFound => { ErrorKind::NotFound => err_msg("Cannot find 'git' executable"),
let _ = writeln!(out, "Cannot find 'git' executable") ErrorKind::PermissionDenied => err_msg("No permission to execute: 'git'"),
.to_exit_code() _ => format_err!("Error spawning: {:?}", e),
.unwrap_or_exit(); })
::std::process::exit(1);
},
ErrorKind::PermissionDenied => {
let _ = writeln!(out, "No permission to execute: 'git'")
.to_exit_code()
.unwrap_or_exit();
::std::process::exit(1);
},
_ => {
let _ = writeln!(out, "Error spawning: {:?}", e)
.to_exit_code()
.unwrap_or_exit();
::std::process::exit(1);
}
}
} }
} }
Ok(())
} }
fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> {