From 1ffa2866e1bb91a0eca129ce4593ef62d97fc42f Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 22 Dec 2019 11:47:39 +0100 Subject: Rewrite imag-wiki to propagate errors instead of calling exit() Signed-off-by: Matthias Beyer --- bin/domain/imag-wiki/Cargo.toml | 1 + bin/domain/imag-wiki/src/lib.rs | 203 +++++++++++++++------------------------- 2 files changed, 78 insertions(+), 126 deletions(-) diff --git a/bin/domain/imag-wiki/Cargo.toml b/bin/domain/imag-wiki/Cargo.toml index eca68017..820bd90a 100644 --- a/bin/domain/imag-wiki/Cargo.toml +++ b/bin/domain/imag-wiki/Cargo.toml @@ -22,6 +22,7 @@ is-match = "0.1.0" regex = "1.1.7" filters = "0.3.0" failure = "0.1.5" +resiter = "0.4.0" libimagentryedit = { version = "0.10.0", path = "../../../lib/entry/libimagentryedit" } libimagentrylink = { version = "0.10.0", path = "../../../lib/entry/libimagentrylink" } diff --git a/bin/domain/imag-wiki/src/lib.rs b/bin/domain/imag-wiki/src/lib.rs index f541c14f..10be8af9 100644 --- a/bin/domain/imag-wiki/src/lib.rs +++ b/bin/domain/imag-wiki/src/lib.rs @@ -23,7 +23,8 @@ extern crate clap; extern crate regex; extern crate filters; #[macro_use] extern crate log; -extern crate failure; +#[macro_use] extern crate failure; +extern crate resiter; extern crate libimagrt; extern crate libimagerror; @@ -35,16 +36,17 @@ extern crate libimagutil; use std::io::Write; use failure::Fallible as Result; +use failure::ResultExt; +use failure::Error; +use failure::err_msg; use clap::App; +use resiter::AndThen; use libimagrt::runtime::Runtime; use libimagrt::application::ImagApplication; -use libimagerror::iter::TraceIterator; -use libimagerror::trace::MapErrTrace; -use libimagerror::exit::ExitUnwrap; -use libimagerror::io::ToExitCode; -use libimagwiki::store::WikiStore; use libimagentryedit::edit::{Edit, EditHeader}; +use libimagwiki::store::WikiStore; +use libimagwiki::entry::WikiEntry; mod ui; @@ -59,24 +61,22 @@ impl ImagApplication for ImagWiki { trace!("wiki_name = {}", wiki_name); trace!("calling = {:?}", rt.cli().subcommand_name()); - match rt.cli().subcommand_name() { - Some("list") => list(&rt, wiki_name), - Some("idof") => idof(&rt, wiki_name), - Some("create") => create(&rt, wiki_name), - Some("create-wiki") => create_wiki(&rt), - Some("show") => show(&rt, wiki_name), - Some("delete") => delete(&rt, wiki_name), - Some(other) => { + match rt.cli().subcommand_name().ok_or_else(|| err_msg("No subcommand called"))? { + "list" => list(&rt, wiki_name), + "idof" => idof(&rt, wiki_name), + "create" => create(&rt, wiki_name), + "create-wiki" => create_wiki(&rt), + "show" => show(&rt, wiki_name), + "delete" => delete(&rt, wiki_name), + other => { debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-wiki", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(std::process::exit); + if rt.handle_unknown_subcommand("imag-wiki", other, rt.cli())?.success() { + Ok(()) + } else { + Err(err_msg("Failed to handle unknown subcommand")) + } } - None => warn!("No command"), } // end match scmd - - Ok(()) } fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { @@ -97,7 +97,7 @@ impl ImagApplication for ImagWiki { } -fn list(rt: &Runtime, wiki_name: &str) { +fn list(rt: &Runtime, wiki_name: &str) -> Result<()> { let scmd = rt.cli().subcommand_matches("list").unwrap(); // safed by clap let prefix = if scmd.is_present("list-full") { format!("{}/", rt.store().path().display()) @@ -109,23 +109,15 @@ fn list(rt: &Runtime, wiki_name: &str) { let mut outlock = out.lock(); rt.store() - .get_wiki(wiki_name) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No wiki '{}' found", wiki_name); - ::std::process::exit(1) - }) - .all_ids() - .map_err_trace_exit_unwrap() - .trace_unwrap_exit() - .for_each(|id| { - writeln!(outlock, "{}{}", prefix, id) - .to_exit_code() - .unwrap_or_exit(); - }); + .get_wiki(wiki_name)? + .ok_or_else(|| format_err!("No wiki '{}' found", wiki_name))? + .all_ids()? + .and_then_ok(|id| writeln!(outlock, "{}{}", prefix, id).map_err(Error::from)) + .collect::>>() + .map(|_| ()) } -fn idof(rt: &Runtime, wiki_name: &str) { +fn idof(rt: &Runtime, wiki_name: &str) -> Result<()> { let scmd = rt.cli().subcommand_matches("idof").unwrap(); // safed by clap let entryname = scmd @@ -137,15 +129,11 @@ fn idof(rt: &Runtime, wiki_name: &str) { let mut lock = out.lock(); rt.store() - .get_wiki(wiki_name) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No wiki '{}' found", wiki_name); - ::std::process::exit(1) - }) - .get_entry(&entryname) - .map_err_trace_exit_unwrap() - .map(|entry| { + .get_wiki(wiki_name)? + .ok_or_else(|| format_err!("No wiki '{}' found", wiki_name))? + .get_entry(&entryname)? + .ok_or_else(|| format_err!("Entry '{}' in wiki '{}' not found!", entryname, wiki_name)) + .and_then(|entry| { let id = entry.get_location().clone(); let prefix = if scmd.is_present("idof-full") { format!("{}/", rt.store().path().display()) @@ -153,48 +141,36 @@ fn idof(rt: &Runtime, wiki_name: &str) { String::from("") }; - writeln!(lock, "{}{}", prefix, id).to_exit_code().unwrap_or_exit() + writeln!(lock, "{}{}", prefix, id).map_err(Error::from) }) - .unwrap_or_else(|| { - error!("Entry '{}' in wiki '{}' not found!", entryname, wiki_name); - ::std::process::exit(1) - }); } -fn create(rt: &Runtime, wiki_name: &str) { - use libimagwiki::entry::WikiEntry; - use libimagutil::warn_result::WarnResult; - +fn create(rt: &Runtime, wiki_name: &str) -> Result<()> { let scmd = rt.cli().subcommand_matches("create").unwrap(); // safed by clap let name = String::from(scmd.value_of("create-name").unwrap()); // safe by clap let wiki = rt .store() - .get_wiki(&wiki_name) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No wiki '{}' found", wiki_name); - ::std::process::exit(1) - }); + .get_wiki(&wiki_name)? + .ok_or_else(|| format_err!("No wiki '{}' found", wiki_name))?; - let mut entry = wiki.create_entry(name).map_err_trace_exit_unwrap(); + let mut entry = wiki.create_entry(name)?; if !scmd.is_present("create-noedit") { if scmd.is_present("create-editheader") { - entry.edit_header_and_content(rt).map_err_trace_exit_unwrap(); + entry.edit_header_and_content(rt)?; } else { - entry.edit_content(rt).map_err_trace_exit_unwrap(); + entry.edit_content(rt)?; } } - entry.autolink(rt.store()) - .map_warn_err_str("Linking has failed. Trying to safe the entry now. Please investigate by hand if this succeeds.") - .map_err(|e| { - rt.store().update(&mut entry).map_err_trace_exit_unwrap(); - e - }) - .map_warn_err_str("Safed entry") - .map_err_trace_exit_unwrap(); + if let Err(e) = entry + .autolink(rt.store()) + .context("Linking has failed. Trying to safe the entry now. Please investigate by hand if this succeeds.") + { + rt.store().update(&mut entry).context("Safed entry")?; + return Err(e).map_err(Error::from) + } let id = entry.get_location(); @@ -202,21 +178,21 @@ fn create(rt: &Runtime, wiki_name: &str) { let out = rt.stdout(); let mut lock = out.lock(); - writeln!(lock, "{}", id).to_exit_code().unwrap_or_exit() + writeln!(lock, "{}", id)?; } - rt.report_touched(&id).unwrap_or_exit(); + rt.report_touched(&id).map_err(Error::from) } -fn create_wiki(rt: &Runtime) { +fn create_wiki(rt: &Runtime) -> Result<()> { let scmd = rt.cli().subcommand_matches("create-wiki").unwrap(); // safed by clap let wiki_name = String::from(scmd.value_of("create-wiki-name").unwrap()); // safe by clap - let (_, index) = rt.store().create_wiki(&wiki_name).map_err_trace_exit_unwrap(); + let (_, index) = rt.store().create_wiki(&wiki_name)?; - rt.report_touched(index.get_location()).unwrap_or_exit(); + rt.report_touched(index.get_location()).map_err(Error::from) } -fn show(rt: &Runtime, wiki_name: &str) { +fn show(rt: &Runtime, wiki_name: &str) -> Result<()> { use filters::filter::Filter; let scmd = rt.cli().subcommand_matches("show").unwrap(); // safed by clap @@ -235,47 +211,33 @@ fn show(rt: &Runtime, wiki_name: &str) { .values_of("show-name") .map(|v| v.map(String::from).collect::>())); - let names = scmd - .values_of("show-name") - .unwrap() // safe by clap - .map(String::from) - .filter(|e| namefilter.filter(e)) - .collect::>(); - let wiki = rt .store() - .get_wiki(&wiki_name) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No wiki '{}' found", wiki_name); - ::std::process::exit(1) - }); + .get_wiki(&wiki_name)? + .ok_or_else(|| format_err!("No wiki '{}' found", wiki_name))?; let out = rt.stdout(); let mut outlock = out.lock(); - for name in names { - let entry = wiki - .get_entry(&name) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No wiki entry '{}' found in wiki '{}'", name, wiki_name); - ::std::process::exit(1) - }); - - writeln!(outlock, "{}", entry.get_location()) - .to_exit_code() - .unwrap_or_exit(); + scmd.values_of("show-name") + .unwrap() // safe by clap + .map(String::from) + .filter(|e| namefilter.filter(e)) + .map(|name| { + let entry = wiki + .get_entry(&name)? + .ok_or_else(|| format_err!("No wiki entry '{}' found in wiki '{}'", name, wiki_name))?; - writeln!(outlock, "{}", entry.get_content()) - .to_exit_code() - .unwrap_or_exit(); + writeln!(outlock, "{}", entry.get_location())?; + writeln!(outlock, "{}", entry.get_content())?; - rt.report_touched(entry.get_location()).unwrap_or_exit(); - } + rt.report_touched(entry.get_location()).map_err(Error::from) + }) + .collect::>>() + .map(|_| ()) } -fn delete(rt: &Runtime, wiki_name: &str) { +fn delete(rt: &Runtime, wiki_name: &str) -> Result<()> { use libimagentrylink::linkable::Linkable; let scmd = rt.cli().subcommand_matches("delete").unwrap(); // safed by clap @@ -284,26 +246,15 @@ fn delete(rt: &Runtime, wiki_name: &str) { let wiki = rt .store() - .get_wiki(&wiki_name) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No wiki '{}' found", wiki_name); - ::std::process::exit(1) - }); + .get_wiki(&wiki_name)? + .ok_or_else(|| format_err!("No wiki '{}' found", wiki_name))?; if unlink { - wiki.get_entry(&name) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No wiki entry '{}' in '{}' found", name, wiki_name); - ::std::process::exit(1) - }) - .unlink(rt.store()) - .map_err_trace_exit_unwrap(); + wiki.get_entry(&name)? + .ok_or_else(|| format_err!("No wiki entry '{}' in '{}' found", name, wiki_name))? + .unlink(rt.store())?; } - wiki - .delete_entry(&name) - .map_err_trace_exit_unwrap(); + wiki.delete_entry(&name) } -- cgit v1.2.3