Refactor to not call exit() anywhere

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
Matthias Beyer 2019-10-23 19:04:19 +02:00
parent e259015a61
commit b36454ac38

View file

@ -53,17 +53,15 @@ use std::io::Write;
use failure::Error; use failure::Error;
use failure::Fallible as Result; use failure::Fallible as Result;
use failure::ResultExt;
use failure::err_msg;
use toml_query::read::TomlValueReadTypeExt; use toml_query::read::TomlValueReadTypeExt;
use clap::App; use clap::App;
use libimagentryannotation::annotateable::*; use libimagentryannotation::annotateable::*;
use libimagentryannotation::annotation_fetcher::*; use libimagentryannotation::annotation_fetcher::*;
use libimagentryedit::edit::*; use libimagentryedit::edit::*;
use libimagerror::trace::MapErrTrace;
use libimagerror::exit::ExitUnwrap;
use libimagerror::io::ToExitCode;
use libimagerror::errors::ErrorMsg as EM; use libimagerror::errors::ErrorMsg as EM;
use libimagerror::iter::TraceIterator;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagrt::application::ImagApplication; use libimagrt::application::ImagApplication;
use libimagstore::store::FileLockEntry; use libimagstore::store::FileLockEntry;
@ -75,22 +73,19 @@ mod ui;
pub enum ImagAnnotate {} pub enum ImagAnnotate {}
impl ImagApplication for ImagAnnotate { impl ImagApplication for ImagAnnotate {
fn run(rt: Runtime) -> Result<()> { fn run(rt: Runtime) -> Result<()> {
if let Some(name) = rt.cli().subcommand_name() { match rt.cli().subcommand_name().ok_or_else(|| err_msg("No command called"))? {
match name { "add" => add(&rt),
"add" => add(&rt), "remove" => remove(&rt),
"remove" => remove(&rt), "list" => list(&rt),
"list" => list(&rt), other => {
other => { debug!("Unknown command");
debug!("Unknown command"); if rt.handle_unknown_subcommand("imag-annotation", other, rt.cli())?.success() {
let _ = rt.handle_unknown_subcommand("imag-annotation", other, rt.cli()) Ok(())
.map_err_trace_exit_unwrap() } else {
.code() Err(err_msg("Failed to handle unknown subcommand"))
.map(::std::process::exit); }
}, },
}
} }
Ok(())
} }
fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
@ -110,149 +105,119 @@ impl ImagApplication for ImagAnnotate {
} }
} }
fn add(rt: &Runtime) { fn add(rt: &Runtime) -> Result<()> {
let scmd = rt.cli().subcommand_matches("add").unwrap(); // safed by main() let scmd = rt.cli().subcommand_matches("add").unwrap(); // safed by main()
let mut ids = rt let mut ids = rt
.ids::<crate::ui::PathProvider>() .ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap() .context("No StoreId supplied")?
.unwrap_or_else(|| { .ok_or_else(|| err_msg("No ids supplied"))?
error!("No StoreId supplied");
::std::process::exit(1);
})
.into_iter(); .into_iter();
if let Some(first) = ids.next() { if let Some(first) = ids.next() {
let mut annotation = rt.store() let mut annotation = rt.store()
.get(first.clone()) .get(first.clone())?
.map_err_trace_exit_unwrap() .ok_or_else(|| EM::EntryNotFound(first.local_display_string()))?
.ok_or_else(|| EM::EntryNotFound(first.local_display_string())) .annotate(rt.store())?;
.map_err(Error::from)
.map_err_trace_exit_unwrap()
.annotate(rt.store())
.map_err_trace_exit_unwrap();
annotation.edit_content(&rt).map_err_trace_exit_unwrap(); annotation.edit_content(&rt)?;
for id in ids { for id in ids {
let mut entry = rt.store().get(id.clone()) let mut entry = rt.store().get(id.clone())?
.map_err_trace_exit_unwrap() .ok_or_else(|| format_err!("Not found: {}", id.local_display_string()))?;
.ok_or_else(|| format_err!("Not found: {}", id.local_display_string()))
.map_err_trace_exit_unwrap();
entry.add_link(&mut annotation).map_err_trace_exit_unwrap(); entry.add_link(&mut annotation)?;
} }
if !scmd.is_present("dont-print-name") { if !scmd.is_present("dont-print-name") {
if let Some(annotation_id) = annotation if let Some(annotation_id) = annotation
.get_header() .get_header()
.read_string("annotation.name") .read_string("annotation.name")?
.map_err(Error::from)
.map_err_trace_exit_unwrap()
{ {
writeln!(rt.stdout(), "Name of the annotation: {}", annotation_id) writeln!(rt.stdout(), "Name of the annotation: {}", annotation_id)?;
.to_exit_code()
.unwrap_or_exit();
} else { } else {
error!("Unnamed annotation: {:?}", annotation.get_location()); Err(format_err!("Unnamed annotation: {:?}", annotation.get_location()))
error!("This is most likely a BUG, please report!"); .context("This is most likely a BUG, please report!")?;
} }
} }
} else { } else {
debug!("No entries to annotate"); debug!("No entries to annotate");
} }
Ok(())
} }
fn remove(rt: &Runtime) { fn remove(rt: &Runtime) -> Result<()> {
let scmd = rt.cli().subcommand_matches("remove").unwrap(); // safed by main() let scmd = rt.cli().subcommand_matches("remove").unwrap(); // safed by main()
let annotation_name = scmd.value_of("annotation_name").unwrap(); // safed by clap let annotation_name = scmd.value_of("annotation_name").unwrap(); // safed by clap
let delete = scmd.is_present("delete-annotation"); let delete = scmd.is_present("delete-annotation");
let ids = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter();
ids.for_each(|id| { rt.ids::<crate::ui::PathProvider>()
let mut entry = rt.store() .context("No ids supplied")?
.get(id.clone()) .ok_or_else(|| err_msg("No ids supplied"))?
.map_err_trace_exit_unwrap() .into_iter()
.ok_or_else(|| EM::EntryNotFound(id.local_display_string())) .map(|id| {
.map_err(Error::from) let mut entry = rt.store()
.map_err_trace_exit_unwrap(); .get(id.clone())?
.ok_or_else(|| EM::EntryNotFound(id.local_display_string()))?;
let annotation = entry let annotation = entry.denotate(rt.store(), annotation_name)?;
.denotate(rt.store(), annotation_name)
.map_err_trace_exit_unwrap();
if delete { if delete {
debug!("Deleting annotation object"); debug!("Deleting annotation object");
if let Some(an) = annotation { if let Some(an) = annotation {
let loc = an.get_location().clone(); let loc = an.get_location().clone();
drop(an); drop(an);
rt rt.store().delete(loc)?;
.store() } else {
.delete(loc) warn!("Not having annotation object, cannot delete!");
.map_err_trace_exit_unwrap(); }
} else { } else {
warn!("Not having annotation object, cannot delete!"); debug!("Not deleting annotation object");
} }
} else {
debug!("Not deleting annotation object");
}
})
Ok(())
})
.collect()
} }
fn list(rt: &Runtime) { fn list(rt: &Runtime) -> Result<()> {
let scmd = rt.cli().subcommand_matches("list").unwrap(); // safed by clap let scmd = rt.cli().subcommand_matches("list").unwrap(); // safed by clap
let with_text = scmd.is_present("list-with-text"); let with_text = scmd.is_present("list-with-text");
let ids = rt let ids = rt
.ids::<crate::ui::PathProvider>() .ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap() .context("No ids supplied")?
.unwrap_or_else(|| { .ok_or_else(|| err_msg("No ids supplied"))?;
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter();
if ids.len() != 0 { if ids.len() != 0 {
ids ids.into_iter()
.for_each(|id| { .map(|id| -> Result<_> {
rt let lds = id.local_display_string();
.store() Ok(rt.store()
.get(id.clone()) .get(id)?
.map_err_trace_exit_unwrap() .ok_or_else(|| EM::EntryNotFound(lds))?
.ok_or_else(|| EM::EntryNotFound(id.local_display_string())) .annotations()?
.map_err(Error::from)
.map_err_trace_exit_unwrap()
.annotations()
.map_err_trace_exit_unwrap()
.into_get_iter(rt.store()) .into_get_iter(rt.store())
.trace_unwrap_exit() .map(|el| el.and_then(|o| o.ok_or_else(|| format_err!("Cannot find entry"))))
.map(|opt| opt.ok_or_else(|| format_err!("Cannot find entry")))
.trace_unwrap_exit()
.enumerate() .enumerate()
.for_each(|(i, entry)| list_annotation(&rt, i, entry, with_text)); .map(|(i, entry)| entry.and_then(|e| list_annotation(&rt, i, e, with_text)))
}); .collect())
})
.flatten()
.collect()
} else { // ids.len() == 0 } else { // ids.len() == 0
// show them all // show them all
rt.store() rt.store()
.all_annotations() .all_annotations()?
.map_err_trace_exit_unwrap()
.into_get_iter() .into_get_iter()
.trace_unwrap_exit() .map(|el| el.and_then(|opt| opt.ok_or_else(|| format_err!("Cannot find entry"))))
.map(|opt| opt.ok_or_else(|| format_err!("Cannot find entry")))
.trace_unwrap_exit()
.enumerate() .enumerate()
.for_each(|(i, entry)| list_annotation(&rt, i, entry, with_text)); .map(|(i, entry)| entry.and_then(|e| list_annotation(&rt, i, e, with_text)))
.collect()
} }
} }
fn list_annotation<'a>(rt: &Runtime, i: usize, a: FileLockEntry<'a>, with_text: bool) { fn list_annotation<'a>(rt: &Runtime, i: usize, a: FileLockEntry<'a>, with_text: bool) -> Result<()> {
if with_text { if with_text {
writeln!(rt.stdout(), writeln!(rt.stdout(),
"--- {i: >5} | {id}\n{text}\n\n", "--- {i: >5} | {id}\n{text}\n\n",
@ -261,8 +226,6 @@ fn list_annotation<'a>(rt: &Runtime, i: usize, a: FileLockEntry<'a>, with_text:
text = a.get_content()) text = a.get_content())
} else { } else {
writeln!(rt.stdout(), "{: >5} | {}", i, a.get_location()) writeln!(rt.stdout(), "{: >5} | {}", i, a.get_location())
} }.map_err(Error::from)
.to_exit_code()
.unwrap_or_exit();
} }