From 05685a6f2df5d28677185fbf04dacd8be2f05168 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 19 Oct 2019 08:54:57 +0200 Subject: [PATCH] Remove calls to exit() and replace them with error propagation up to main() Signed-off-by: Matthias Beyer --- bin/core/imag-gps/src/lib.rs | 155 ++++++++++++++--------------------- 1 file changed, 61 insertions(+), 94 deletions(-) diff --git a/bin/core/imag-gps/src/lib.rs b/bin/core/imag-gps/src/lib.rs index 6b5ae542..20c3b495 100644 --- a/bin/core/imag-gps/src/lib.rs +++ b/bin/core/imag-gps/src/lib.rs @@ -45,12 +45,11 @@ extern crate libimagerror; extern crate libimagstore; use std::io::Write; -use std::process::exit; use std::str::FromStr; - -use failure::err_msg; +use failure::Error; use failure::Fallible as Result; +use failure::err_msg; use clap::App; use libimagstore::storeid::StoreId; @@ -58,9 +57,6 @@ use libimagentrygps::types::*; use libimagentrygps::entry::*; use libimagrt::application::ImagApplication; use libimagrt::runtime::Runtime; -use libimagerror::trace::MapErrTrace; -use libimagerror::exit::ExitUnwrap; -use libimagerror::io::ToExitCode; mod ui; @@ -71,22 +67,22 @@ mod ui; pub enum ImagGps {} impl ImagApplication for ImagGps { fn run(rt: Runtime) -> Result<()> { - if let Some(name) = rt.cli().subcommand_name() { - match name { - "add" => add(&rt), - "remove" => remove(&rt), - "get" => get(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-gps", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); + match rt.cli().subcommand_name().ok_or_else(|| err_msg("No subcommand called"))? { + "add" => add(&rt), + "remove" => remove(&rt), + "get" => get(&rt), + other => { + debug!("Unknown command"); + if rt.handle_unknown_subcommand("imag-gps", other, rt.cli()) + .map_err(Error::from)? + .success() + { + Ok(()) + } else { + Err(format_err!("Subcommand failed")) } } } - - Ok(()) } fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { @@ -106,46 +102,33 @@ impl ImagApplication for ImagGps { } } -fn rt_get_ids(rt: &Runtime) -> Vec { +fn rt_get_ids(rt: &Runtime) -> Result> { rt - .ids::() - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No ids supplied"); - ::std::process::exit(1); - }) + .ids::()? + .ok_or_else(|| err_msg("No ids supplied")) } -fn add(rt: &Runtime) { +fn add(rt: &Runtime) -> Result<()> { let c = { - let parse = |value: &str| -> (i64, i64, i64) { + let parse = |value: &str| -> Result<(i64, i64, i64)> { debug!("Parsing '{}' into degree, minute and second", value); let ary = value.split('.') .map(|v| {debug!("Parsing = {}", v); v}) .map(FromStr::from_str) - .map(|elem| { - elem.or_else(|_| Err(err_msg("Error while converting number"))) - .map_err_trace_exit_unwrap() - }) - .collect::>(); + .map(|elem| elem.or_else(|_| Err(err_msg("Error while converting number")))) + .collect::>>()?; - let degree = ary.get(0).unwrap_or_else(|| { - error!("Degree missing. This value is required."); - exit(1) - }); - let minute = ary.get(1).unwrap_or_else(|| { - error!("Degree missing. This value is required."); - exit(1) - }); + let degree = ary.get(0).ok_or_else(|| err_msg("Degree missing. This value is required."))?; + let minute = ary.get(1).ok_or_else(|| err_msg("Degree missing. This value is required."))?; let second = ary.get(2).unwrap_or(&0); - (*degree, *minute, *second) + Ok((*degree, *minute, *second)) }; let scmd = rt.cli().subcommand_matches("add").unwrap(); // safed by main() - let long = parse(scmd.value_of("longitude").unwrap()); // unwrap safed by clap - let lati = parse(scmd.value_of("latitude").unwrap()); // unwrap safed by clap + let long = parse(scmd.value_of("longitude").unwrap())?; // unwrap safed by clap + let lati = parse(scmd.value_of("latitude").unwrap())?; // unwrap safed by clap let long = GPSValue::new(long.0, long.1, long.2); let lati = GPSValue::new(lati.0, lati.1, lati.2); @@ -153,82 +136,66 @@ fn add(rt: &Runtime) { Coordinates::new(long, lati) }; - rt_get_ids(&rt) + rt_get_ids(&rt)? .into_iter() - .for_each(|id| { + .map(|id| { rt.store() - .get(id.clone()) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { // if we have Ok(None) - error!("No such entry: {}", id); - exit(1) - }) - .set_coordinates(c.clone()) - .map_err_trace_exit_unwrap(); + .get(id.clone())? + .ok_or_else(|| format_err!("No such entry: {}", id))? + .set_coordinates(c.clone())?; - rt.report_touched(&id).unwrap_or_exit(); - }); + rt.report_touched(&id).map_err(Error::from) + }) + .collect() } -fn remove(rt: &Runtime) { +fn remove(rt: &Runtime) -> Result<()> { let print_removed = rt .cli() .subcommand_matches("remove") .unwrap() .is_present("print-removed"); // safed by main() - rt_get_ids(&rt) + rt_get_ids(&rt)? .into_iter() - .for_each(|id| { - let removed_value = rt + .map(|id| { + let removed_value : Coordinates = rt .store() - .get(id.clone()) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { // if we have Ok(None) - error!("No such entry: {}", id); - exit(1) - }) - .remove_coordinates() - .map_err_trace_exit_unwrap() // The delete action failed - .unwrap_or_else(|| { // if we have Ok(None) - error!("Entry had no coordinates: {}", id); - exit(1) - }) - .map_err_trace_exit_unwrap(); // The parsing of the deleted values failed + .get(id.clone())? + .ok_or_else(|| format_err!("No such entry: {}", id))? + .remove_coordinates()? + .ok_or_else(|| format_err!("Entry had no coordinates: {}", id))??; if print_removed { - writeln!(rt.stdout(), "{}", removed_value).to_exit_code().unwrap_or_exit(); + writeln!(rt.stdout(), "{}", removed_value)?; } - rt.report_touched(&id).unwrap_or_exit(); - }); + rt.report_touched(&id).map_err(Error::from) + }) + .collect() } -fn get(rt: &Runtime) { +fn get(rt: &Runtime) -> Result<()> { let mut stdout = rt.stdout(); - rt_get_ids(&rt) + rt_get_ids(&rt)? .into_iter() - .for_each(|id| { + .map(|id| { let value = rt .store() - .get(id.clone()) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { // if we have Ok(None) - error!("No such entry: {}", id); - exit(1) - }) - .get_coordinates() - .map_err_trace_exit_unwrap() // The get action failed - .unwrap_or_else(|| { // if we have Ok(None) - error!("Entry has no coordinates: {}", id); - exit(1) - }); + .get(id.clone())? + .ok_or_else(|| { // if we have Ok(None) + format_err!("No such entry: {}", id) + })? + .get_coordinates()? + .ok_or_else(|| { // if we have Ok(None) + format_err!("Entry has no coordinates: {}", id) + })?; - writeln!(stdout, "{}", value).to_exit_code().unwrap_or_exit(); + writeln!(stdout, "{}", value)?; - rt.report_touched(&id).unwrap_or_exit(); + rt.report_touched(&id).map_err(Error::from) }) - + .collect() }