From 641c6c77616831abdc145d776287fe2c8964ad0b Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 27 Oct 2019 10:50:30 +0100 Subject: Transform imag-bookmark to not call exit() but propagate errors to main() Signed-off-by: Matthias Beyer --- bin/domain/imag-bookmark/Cargo.toml | 1 + bin/domain/imag-bookmark/src/lib.rs | 186 +++++++++++++++--------------------- 2 files changed, 79 insertions(+), 108 deletions(-) diff --git a/bin/domain/imag-bookmark/Cargo.toml b/bin/domain/imag-bookmark/Cargo.toml index b66a6f69..7e039df1 100644 --- a/bin/domain/imag-bookmark/Cargo.toml +++ b/bin/domain/imag-bookmark/Cargo.toml @@ -24,6 +24,7 @@ log = "0.4.6" toml = "0.5.1" toml-query = "0.9.2" failure = "0.1.5" +resiter = "0.4.0" libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" } diff --git a/bin/domain/imag-bookmark/src/lib.rs b/bin/domain/imag-bookmark/src/lib.rs index bfa08b10..537c6f4d 100644 --- a/bin/domain/imag-bookmark/src/lib.rs +++ b/bin/domain/imag-bookmark/src/lib.rs @@ -39,6 +39,7 @@ extern crate clap; extern crate toml; extern crate toml_query; #[macro_use] extern crate failure; +extern crate resiter; extern crate libimagbookmark; extern crate libimagrt; @@ -47,12 +48,13 @@ extern crate libimagutil; extern crate libimagentrylink; use std::io::Write; -use std::process::exit; use std::ops::DerefMut; use toml_query::read::TomlValueReadTypeExt; use failure::Error; +use failure::err_msg; use failure::Fallible as Result; +use resiter::AndThen; use clap::App; use libimagrt::runtime::Runtime; @@ -60,10 +62,6 @@ use libimagrt::application::ImagApplication; use libimagbookmark::collection::BookmarkCollection; use libimagbookmark::collection::BookmarkCollectionStore; use libimagbookmark::link::Link as BookmarkLink; -use libimagerror::trace::{MapErrTrace, trace_error}; -use libimagerror::io::ToExitCode; -use libimagerror::exit::ExitUnwrap; -use libimagutil::debug_result::DebugResult; use libimagentrylink::linkable::Linkable; mod ui; @@ -75,24 +73,20 @@ mod ui; pub enum ImagBookmark {} impl ImagApplication for ImagBookmark { fn run(rt: Runtime) -> Result<()> { - if let Some(name) = rt.cli().subcommand_name() { - debug!("Call {}", name); - match name { - "add" => add(&rt), - "collection" => collection(&rt), - "list" => list(&rt), - "remove" => remove(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-bookmark", 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), + "collection" => collection(&rt), + "list" => list(&rt), + "remove" => remove(&rt), + other => { + debug!("Unknown command"); + if rt.handle_unknown_subcommand("imag-bookmark", other, rt.cli())?.success() { + Ok(()) + } else { + Err(err_msg("Failed to handle unknown subcommand")) + } + }, } - - Ok(()) } fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { @@ -112,131 +106,107 @@ impl ImagApplication for ImagBookmark { } } -fn add(rt: &Runtime) { +fn add(rt: &Runtime) -> Result<()> { let scmd = rt.cli().subcommand_matches("add").unwrap(); - let coll = get_collection_name(rt, "add", "collection"); - - let mut collection = BookmarkCollectionStore::get(rt.store(), &coll) - .map_err_trace_exit_unwrap() - .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll)) - .map_err_trace_exit_unwrap(); + let coll = get_collection_name(rt, "add", "collection")?; - rt.report_touched(collection.get_location()).unwrap_or_exit(); + let mut collection = BookmarkCollectionStore::get(rt.store(), &coll)? + .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))?; - for url in scmd.values_of("urls").unwrap() { // unwrap saved by clap - let new_ids = BookmarkCollection::add_link(collection.deref_mut(), rt.store(), BookmarkLink::from(url)) - .map_err_trace_exit_unwrap(); - - rt.report_all_touched(new_ids.into_iter()).unwrap_or_exit(); - } + rt.report_touched(collection.get_location())?; - info!("Ready"); + scmd.values_of("urls") + .unwrap() + .into_iter() + .map(|url| { + let new_ids = BookmarkCollection::add_link(collection.deref_mut(), rt.store(), BookmarkLink::from(url))?; + rt.report_all_touched(new_ids.into_iter()).map_err(Error::from) + }) + .collect() } -fn collection(rt: &Runtime) { +fn collection(rt: &Runtime) -> Result<()> { let scmd = rt.cli().subcommand_matches("collection").unwrap(); if scmd.is_present("add") { // adding a new collection let name = scmd.value_of("add").unwrap(); - if let Ok(id) = BookmarkCollectionStore::new(rt.store(), &name) { - rt.report_touched(id.get_location()).unwrap_or_exit(); - info!("Created: {}", name); - } else { - warn!("Creating collection {} failed", name); - exit(1); - } + let id = BookmarkCollectionStore::new(rt.store(), &name)?; + rt.report_touched(id.get_location())?; + info!("Created: {}", name); } if scmd.is_present("remove") { // remove a collection let name = scmd.value_of("remove").unwrap(); { // remove all links - BookmarkCollectionStore::get(rt.store(), &name) - .map_err_trace_exit_unwrap() - .ok_or_else(|| format_err!("Collection does not exist: {}", name)) - .map_err_trace_exit_unwrap() - .unlink(rt.store()) - .map_err_trace_exit_unwrap(); + BookmarkCollectionStore::get(rt.store(), &name)? + .ok_or_else(|| format_err!("Collection does not exist: {}", name))? + .unlink(rt.store())?; } - if BookmarkCollectionStore::delete(rt.store(), &name).is_ok() { - info!("Deleted: {}", name); - } else { - warn!("Deleting collection {} failed", name); - exit(1); - } + BookmarkCollectionStore::delete(rt.store(), &name)?; + info!("Deleted: {}", name); } + + Ok(()) } -fn list(rt: &Runtime) { - let coll = get_collection_name(rt, "list", "collection"); +fn list(rt: &Runtime) -> Result<()> { + let coll = get_collection_name(rt, "list", "collection")?; - let collection = BookmarkCollectionStore::get(rt.store(), &coll) - .map_err_trace_exit_unwrap() - .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll)) - .map_err_trace_exit_unwrap(); + let collection = BookmarkCollectionStore::get(rt.store(), &coll)? + .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))?; - rt.report_touched(collection.get_location()).unwrap_or_exit(); + rt.report_touched(collection.get_location())?; + + let mut i = 0; // poor mans enumerate() collection - .get_links(rt.store()) - .map_dbg_str("Listing...") - .map_err_trace_exit_unwrap() - .enumerate() - .for_each(|(i, link)| match link { - Ok(link) => writeln!(rt.stdout(), "{: >3}: {}", i, link).to_exit_code().unwrap_or_exit(), - Err(e) => trace_error(&e) - }); - debug!("... ready with listing"); + .get_links(rt.store())? + .and_then_ok(|link| { + let r = writeln!(rt.stdout(), "{: >3}: {}", i, link).map_err(Error::from); + i += 1; + r + }) + .collect() } -fn remove(rt: &Runtime) { +fn remove(rt: &Runtime) -> Result<()> { let scmd = rt.cli().subcommand_matches("remove").unwrap(); - let coll = get_collection_name(rt, "list", "collection"); - - let mut collection = BookmarkCollectionStore::get(rt.store(), &coll) - .map_err_trace_exit_unwrap() - .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll)) - .map_err_trace_exit_unwrap(); - - rt.report_touched(collection.get_location()).unwrap_or_exit(); + let coll = get_collection_name(rt, "list", "collection")?; - for url in scmd.values_of("urls").unwrap() { // enforced by clap - let removed_links = BookmarkCollection::remove_link(collection.deref_mut(), rt.store(), BookmarkLink::from(url)) - .map_err_trace_exit_unwrap(); + let mut collection = BookmarkCollectionStore::get(rt.store(), &coll)? + .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))?; - rt.report_all_touched(removed_links.into_iter()).unwrap_or_exit(); - } + rt.report_touched(collection.get_location())?; - info!("Ready"); + scmd.values_of("urls") + .unwrap() + .into_iter() + .map(|url| { + let removed_links = BookmarkCollection::remove_link(collection.deref_mut(), rt.store(), BookmarkLink::from(url))?; + rt.report_all_touched(removed_links.into_iter()).map_err(Error::from) + }) + .collect() } fn get_collection_name(rt: &Runtime, subcommand_name: &str, collection_argument_name: &str) - -> String + -> Result { - rt.cli() + if let Some(cn) = rt.cli() .subcommand_matches(subcommand_name) .and_then(|scmd| scmd.value_of(collection_argument_name).map(String::from)) - .unwrap_or_else(|| { - rt.config() - .map(|cfg| { - cfg.read_string("bookmark.default_collection") - .map_err(Error::from) - .map_err_trace_exit_unwrap() - .ok_or_else(|| { - error!("Missing config: 'bookmark.default_collection'. Set or use commandline to specify."); - exit(1) - }) - .unwrap() - .clone() - }) - .unwrap_or_else(|| { - error!("Failed to read configuration"); - exit(1) - }) - }) + { + return Ok(cn) + } else { + rt.config().ok_or_else(|| err_msg("No configuration availablew")) + .and_then(|cfg| { + cfg.read_string("bookmark.default_collection")? + .ok_or_else(|| err_msg("Missing config: 'bookmark.default_collection'.")) + }) + } } -- cgit v1.2.3