summaryrefslogtreecommitdiffstats
path: root/bin/domain/imag-contact/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'bin/domain/imag-contact/src/lib.rs')
-rw-r--r--bin/domain/imag-contact/src/lib.rs320
1 files changed, 150 insertions, 170 deletions
diff --git a/bin/domain/imag-contact/src/lib.rs b/bin/domain/imag-contact/src/lib.rs
index 0285f128..873c822a 100644
--- a/bin/domain/imag-contact/src/lib.rs
+++ b/bin/domain/imag-contact/src/lib.rs
@@ -44,6 +44,7 @@ extern crate walkdir;
extern crate uuid;
extern crate serde_json;
#[macro_use] extern crate failure;
+extern crate resiter;
extern crate libimagcontact;
extern crate libimagstore;
@@ -54,7 +55,6 @@ extern crate libimaginteraction;
extern crate libimagentryedit;
extern crate libimagentryref;
-use std::process::exit;
use std::path::PathBuf;
use std::io::Write;
@@ -67,13 +67,13 @@ use walkdir::WalkDir;
use failure::Error;
use failure::err_msg;
use failure::Fallible as Result;
+use resiter::AndThen;
+use resiter::IterInnerOkOrElse;
+use resiter::Map;
+use resiter::Filter;
use libimagrt::runtime::Runtime;
use libimagrt::application::ImagApplication;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::io::ToExitCode;
-use libimagerror::exit::ExitUnwrap;
-use libimagerror::iter::TraceIterator;
use libimagcontact::store::ContactStore;
use libimagcontact::contact::Contact;
use libimagcontact::deser::DeserVcard;
@@ -94,26 +94,22 @@ use crate::edit::edit;
pub enum ImagContact {}
impl ImagApplication for ImagContact {
fn run(rt: Runtime) -> Result<()> {
- if let Some(name) = rt.cli().subcommand_name() {
- debug!("Call {}", name);
- match name {
- "list" => list(&rt),
- "import" => import(&rt),
- "show" => show(&rt),
- "edit" => edit(&rt),
- "find" => find(&rt),
- "create" => create(&rt),
- other => {
- debug!("Unknown command");
- let _ = rt.handle_unknown_subcommand("imag-contact", 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"))? {
+ "list" => list(&rt),
+ "import" => import(&rt),
+ "show" => show(&rt),
+ "edit" => edit(&rt),
+ "find" => find(&rt),
+ "create" => create(&rt),
+ other => {
+ debug!("Unknown command");
+ if rt.handle_unknown_subcommand("imag-contact", 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> {
@@ -133,128 +129,117 @@ impl ImagApplication for ImagContact {
}
}
-fn list(rt: &Runtime) {
+fn list(rt: &Runtime) -> Result<()> {
let scmd = rt.cli().subcommand_matches("list").unwrap();
- let list_format = get_contact_print_format("contact.list_format", rt, &scmd);
+ let list_format = get_contact_print_format("contact.list_format", rt, &scmd)?;
debug!("List format: {:?}", list_format);
let iterator = rt
.store()
- .all_contacts()
- .map_err_trace_exit_unwrap()
+ .all_contacts()?
.into_get_iter()
- .trace_unwrap_exit()
- .map(|fle| fle.ok_or_else(|| err_msg("StoreId not found".to_owned())))
- .trace_unwrap_exit()
- .map(|fle| {
- rt.report_touched(fle.get_location()).unwrap_or_exit();
- fle
+ .map_inner_ok_or_else(|| err_msg("Did not find one entry"))
+ .and_then_ok(|fle| {
+ rt.report_touched(fle.get_location())?;
+ Ok(fle)
})
- .map(|e| e.deser())
- .trace_unwrap_exit()
- .enumerate();
+ .and_then_ok(|e| e.deser());
if scmd.is_present("json") {
debug!("Listing as JSON");
- let v : Vec<DeserVcard> = iterator.map(|tpl| tpl.1).collect();
-
- match ::serde_json::to_string(&v) {
- Ok(s) => writeln!(rt.stdout(), "{}", s).to_exit_code().unwrap_or_exit(),
- Err(e) => {
- error!("Error generating JSON: {:?}", e);
- ::std::process::exit(1)
- }
- }
+ let v = iterator.collect::<Result<Vec<DeserVcard>>>()?;
+ let s = ::serde_json::to_string(&v)?;
+ writeln!(rt.stdout(), "{}", s).map_err(Error::from)
} else {
debug!("Not listing as JSON");
let output = rt.stdout();
let mut output = output.lock();
+ let mut i = 0;
iterator
- .map(|(i, dvcard)| build_data_object_for_handlebars(i, &dvcard))
- .map(|data| list_format.render("format", &data).map_err(Error::from))
- .trace_unwrap_exit()
- .for_each(|s| {
- writeln!(output, "{}", s).to_exit_code().unwrap_or_exit()
- });
+ .map_ok(|dvcard| {
+ i += 1;
+ build_data_object_for_handlebars(i, &dvcard)
+ })
+ .and_then_ok(|data| list_format.render("format", &data).map_err(Error::from))
+ .and_then_ok(|s| writeln!(output, "{}", s).map_err(Error::from))
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
}
}
-fn import(rt: &Runtime) {
+fn import(rt: &Runtime) -> Result<()> {
let scmd = rt.cli().subcommand_matches("import").unwrap(); // secured by main
let force_override = scmd.is_present("force-override");
let path = scmd.value_of("path").map(PathBuf::from).unwrap(); // secured by clap
let collection_name = rt.cli().value_of("contact-ref-collection-name").unwrap(); // default by clap
let ref_config = rt.config()
- .ok_or_else(|| format_err!("No configuration, cannot continue!"))
- .map_err_trace_exit_unwrap()
- .read_partial::<libimagentryref::reference::Config>()
- .map_err(Error::from)
- .map_err_trace_exit_unwrap()
- .ok_or_else(|| format_err!("Configuration missing: {}", libimagentryref::reference::Config::LOCATION))
- .map_err_trace_exit_unwrap();
- // TODO: Refactor the above to libimagutil or libimagrt?
+ .ok_or_else(|| format_err!("No configuration, cannot continue!"))?
+ .read_partial::<libimagentryref::reference::Config>()?
+ .ok_or_else(|| format_err!("Configuration missing: {}", libimagentryref::reference::Config::LOCATION))?;
+ // TODO: Refactor the above to libimagutil or libimagrt?
if !path.exists() {
- error!("Path does not exist");
- exit(1)
+ return Err(format_err!("Path does not exist: {}", path.display()))
}
if path.is_file() {
let entry = rt
.store()
- .retrieve_from_path(&path, &ref_config, &collection_name, force_override)
- .map_err_trace_exit_unwrap();
+ .retrieve_from_path(&path, &ref_config, &collection_name, force_override)?;
- rt.report_touched(entry.get_location()).unwrap_or_exit();
+ rt.report_touched(entry.get_location()).map_err(Error::from)
} else if path.is_dir() {
- for entry in WalkDir::new(path).min_depth(1).into_iter() {
- let entry = entry
- .map_err(Error::from)
- .map_err_trace_exit_unwrap();
-
- if entry.file_type().is_file() {
- let pb = PathBuf::from(entry.path());
- let fle = rt
- .store()
- .retrieve_from_path(&pb, &ref_config, &collection_name, force_override)
- .map_err_trace_exit_unwrap();
-
- rt.report_touched(fle.get_location()).unwrap_or_exit();
- info!("Imported: {}", entry.path().to_str().unwrap_or("<non UTF-8 path>"));
- } else {
- warn!("Ignoring non-file: {}", entry.path().to_str().unwrap_or("<non UTF-8 path>"));
- }
- }
+ WalkDir::new(path)
+ .min_depth(1)
+ .into_iter()
+ .map(|r| r.map_err(Error::from))
+ .and_then_ok(|entry| {
+ if entry.file_type().is_file() {
+ let pb = PathBuf::from(entry.path());
+ let fle = rt
+ .store()
+ .retrieve_from_path(&pb, &ref_config, &collection_name, force_override)?;
+
+ rt.report_touched(fle.get_location())?;
+ info!("Imported: {}", entry.path().to_str().unwrap_or("<non UTF-8 path>"));
+ Ok(())
+ } else {
+ warn!("Ignoring non-file: {}", entry.path().to_str().unwrap_or("<non UTF-8 path>"));
+ Ok(())
+ }
+ })
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
} else {
- error!("Path is neither directory nor file");
- exit(1)
+ Err(err_msg("Path is neither directory nor file"))
}
}
-fn show(rt: &Runtime) {
+fn show(rt: &Runtime) -> Result<()> {
let scmd = rt.cli().subcommand_matches("show").unwrap();
let hash = scmd.value_of("hash").map(String::from).unwrap(); // safed by clap
- let show_format = get_contact_print_format("contact.show_format", rt, &scmd);
+ let show_format = get_contact_print_format("contact.show_format", rt, &scmd)?;
let out = rt.stdout();
let mut outlock = out.lock();
- util::find_contact_by_hash(rt, hash)
+ util::find_contact_by_hash(rt, hash)?
+ .filter_ok(|tpl| tpl.0)
+ .map_ok(|tpl| tpl.1)
.enumerate()
- .for_each(|(i, elem)| {
- let elem = elem.deser().map_err_trace_exit_unwrap();
+ .map(|(i, elem)| {
+ let elem = elem?.deser()?;
let data = build_data_object_for_handlebars(i, &elem);
- let s = show_format
- .render("format", &data)
- .map_err(Error::from)
- .map_err_trace_exit_unwrap();
- writeln!(outlock, "{}", s).to_exit_code().unwrap_or_exit();
- });
+ let s = show_format.render("format", &data)?;
+ writeln!(outlock, "{}", s).map_err(Error::from)
+ })
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
}
-fn find(rt: &Runtime) {
+fn find(rt: &Runtime) -> Result<()> {
let scmd = rt.cli().subcommand_matches("find").unwrap();
let grepstring = scmd
.values_of("string")
@@ -263,24 +248,16 @@ fn find(rt: &Runtime) {
.collect::<Vec<String>>();
// We don't know yet which we need, but we pay that price for simplicity of the codebase
- let show_format = get_contact_print_format("contact.show_format", rt, &scmd);
- let list_format = get_contact_print_format("contact.list_format", rt, &scmd);
+ let show_format = get_contact_print_format("contact.show_format", rt, &scmd)?;
+ let list_format = get_contact_print_format("contact.list_format", rt, &scmd)?;
let iterator = rt
.store()
- .all_contacts()
- .map_err_trace_exit_unwrap()
+ .all_contacts()?
.into_get_iter()
- .map(|el| {
- el.map_err_trace_exit_unwrap()
- .ok_or_else(|| {
- error!("Could not get StoreId from Store::all_contacts(). This is a BUG!");
- ::std::process::exit(1)
- })
- .unwrap() // safed above
- })
- .filter_map(|entry| {
- let card = entry.deser().map_err_trace_exit_unwrap();
+ .map_inner_ok_or_else(|| err_msg("Did not find one entry"))
+ .and_then_ok(|entry| {
+ let card = entry.deser()?;
let str_contains_any = |s: &String, v: &Vec<String>| {
v.iter().any(|i| s.contains(i))
@@ -291,91 +268,94 @@ fn find(rt: &Runtime) {
|| card.fullname().iter().any(|a| str_contains_any(a, &grepstring));
if take {
- rt.report_touched(entry.get_location()).unwrap_or_exit();
+ rt.report_touched(entry.get_location())?;
// optimization so we don't have to parse again in the next step
- Some((entry, card))
+ Ok((true, entry, card))
} else {
- None
+ Ok((false, entry, card))
}
- })
- .enumerate();
+ });
+
+ let mut i = 0;
if !rt.output_is_pipe() || rt.ignore_ids() {
if scmd.is_present("json") {
- let v : Vec<DeserVcard> = iterator.map(|(_, tlp)| tlp.1).collect();
-
- match ::serde_json::to_string(&v) {
- Ok(s) => writeln!(rt.stdout(), "{}", s).to_exit_code().unwrap_or_exit(),
- Err(e) => {
- error!("Error generating JSON: {:?}", e);
- ::std::process::exit(1)
- }
- }
+ iterator
+ .filter_ok(|tpl| tpl.0)
+ .map_ok(|tpl| tpl.2)
+ .and_then_ok(|v| {
+ let s = ::serde_json::to_string(&v)?;
+ writeln!(rt.stdout(), "{}", s).map_err(Error::from)
+ })
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
} else if scmd.is_present("find-id") {
iterator
- .for_each(|(_i, (entry, _))| {
- writeln!(rt.stdout(), "{}", entry.get_location())
- .to_exit_code()
- .unwrap_or_exit();
+ .and_then_ok(|(take, entry, _)| {
+ if take {
+ writeln!(rt.stdout(), "{}", entry.get_location()).map_err(Error::from)
+ } else {
+ Ok(())
+ }
})
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
} else if scmd.is_present("find-full-id") {
let storepath = rt.store().path().display();
iterator
- .for_each(|(_i, (entry, _))| {
- writeln!(rt.stdout(), "{}/{}", storepath, entry.get_location())
- .to_exit_code()
- .unwrap_or_exit();
+ .and_then_ok(|(take, entry, _)| {
+ if take {
+ writeln!(rt.stdout(), "{}/{}", storepath, entry.get_location()).map_err(Error::from)
+ } else {
+ Ok(())
+ }
})
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
} else {
iterator
- .for_each(|(i, (_, card))| {
- let fmt = if scmd.is_present("find-show") {
- &show_format
- } else { // default: find-list
- &list_format
- };
-
- let data = build_data_object_for_handlebars(i, &card);
- let s = fmt
- .render("format", &data)
- .map_err(Error::from)
- .map_err_trace_exit_unwrap();
-
- writeln!(rt.stdout(), "{}", s)
- .to_exit_code()
- .unwrap_or_exit();
- });
+ .and_then_ok(|(take, _, card)| {
+ if take {
+ i += 1;
+ let fmt = if scmd.is_present("find-show") {
+ &show_format
+ } else { // default: find-list
+ &list_format
+ };
+
+ let data = build_data_object_for_handlebars(i, &card);
+ let s = fmt.render("format", &data)?;
+
+ writeln!(rt.stdout(), "{}", s).map_err(Error::from)
+ } else {
+ Ok(())
+ }
+ })
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
}
} else { // if not printing, we still have to consume the iterator to report the touched IDs
let _ = iterator.collect::<Vec<_>>();
+ Ok(())
}
}
-fn get_contact_print_format(config_value_path: &'static str, rt: &Runtime, scmd: &ArgMatches) -> Handlebars {
- let fmt = scmd
- .value_of("format")
- .map(String::from)
- .unwrap_or_else(|| {
- rt.config()
- .ok_or_else(|| err_msg("No configuration file"))
- .map_err_trace_exit_unwrap()
- .read_string(config_value_path)
- .map_err(Error::from)
- .map_err_trace_exit_unwrap()
- .ok_or_else(|| err_msg("Configuration 'contact.list_format' does not exist"))
- .map_err_trace_exit_unwrap()
- });
+fn get_contact_print_format(config_value_path: &'static str, rt: &Runtime, scmd: &ArgMatches) -> Result<Handlebars> {
+ let fmt = match scmd.value_of("format").map(String::from) {
+ Some(s) => Ok(s),
+ None => rt.config()
+ .ok_or_else(|| err_msg("No configuration file"))?
+ .read_string(config_value_path)?
+ .ok_or_else(|| err_msg("Configuration 'contact.list_format' does not exist")),
+ }?;
let mut hb = Handlebars::new();
- hb
- .register_template_string("format", fmt)
- .map_err(Error::from)
- .map_err_trace_exit_unwrap();
+ hb.register_template_string("format", fmt)?;
hb.register_escape_fn(::handlebars::no_escape);
::libimaginteraction::format::register_all_color_helpers(&mut hb);
::libimaginteraction::format::register_all_format_helpers(&mut hb);
- hb
+ Ok(hb)
}