From d6f8751f6e8cdb25dfffd5c6ca2b247902b97d41 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 25 Apr 2018 13:34:46 +0200 Subject: [PATCH] Reimplement imag-contact --- bin/domain/imag-contact/src/create.rs | 6 +- bin/domain/imag-contact/src/main.rs | 130 +++++++++++------------- bin/domain/imag-contact/src/util.rs | 139 +++++++++----------------- 3 files changed, 108 insertions(+), 167 deletions(-) diff --git a/bin/domain/imag-contact/src/create.rs b/bin/domain/imag-contact/src/create.rs index 15d885b2..a9573c11 100644 --- a/bin/domain/imag-contact/src/create.rs +++ b/bin/domain/imag-contact/src/create.rs @@ -44,14 +44,13 @@ use toml_query::read::TomlValueReadExt; use toml::Value; use uuid::Uuid; +use libimagcontact::store::ContactStore; use libimagcontact::error::ContactError as CE; -use libimagcontact::store::UniqueContactPathGenerator; use libimagrt::runtime::Runtime; use libimagerror::str::ErrFromStr; use libimagerror::trace::MapErrTrace; use libimagerror::trace::trace_error; use libimagutil::warn_result::WarnResult; -use libimagentryref::refstore::RefStore; const TEMPLATE : &'static str = include_str!("../static/new-contact-template.toml"); @@ -158,7 +157,8 @@ pub fn create(rt: &Runtime) { if let Some(location) = location { if !scmd.is_present("dont-track") { - RefStore::create_ref::(rt.store(), location) + rt.store() + .create_from_path(&location) .map_err_trace_exit_unwrap(1); info!("Created entry in store"); diff --git a/bin/domain/imag-contact/src/main.rs b/bin/domain/imag-contact/src/main.rs index 031c2169..86c98457 100644 --- a/bin/domain/imag-contact/src/main.rs +++ b/bin/domain/imag-contact/src/main.rs @@ -48,7 +48,6 @@ extern crate libimagstore; extern crate libimagerror; extern crate libimagutil; extern crate libimaginteraction; -extern crate libimagentryref; extern crate libimagentryedit; use std::process::exit; @@ -57,7 +56,6 @@ use std::io::Write; use handlebars::Handlebars; use clap::ArgMatches; -use vobject::vcard::Vcard; use toml_query::read::TomlValueReadTypeExt; use walkdir::WalkDir; @@ -67,14 +65,12 @@ use libimagerror::str::ErrFromStr; use libimagerror::trace::MapErrTrace; use libimagerror::io::ToExitCode; use libimagerror::exit::ExitUnwrap; +use libimagerror::iter::TraceIterator; use libimagcontact::store::ContactStore; -use libimagcontact::store::UniqueContactPathGenerator; use libimagcontact::error::ContactError as CE; use libimagcontact::contact::Contact; use libimagcontact::deser::DeserVcard; use libimagstore::iter::get::StoreIdGetIteratorExtension; -use libimagentryref::reference::Ref; -use libimagentryref::refstore::RefStore; mod ui; mod util; @@ -128,24 +124,13 @@ fn list(rt: &Runtime) { .ok_or_else(|| CE::from("StoreId not found".to_owned())) .map_err_trace_exit_unwrap(1); - fle - .get_contact_data() - .map(|cd| (fle, cd)) - .map(|(fle, cd)| (fle, cd.into_inner())) - .map(|(fle, cd)| { - let card = Vcard::from_component(cd).unwrap_or_else(|e| { - error!("Element is not a VCARD object: {:?}", e); - exit(1) - }); - (fle, card) - }) - .map_err_trace_exit_unwrap(1) + fle.deser().map_err_trace_exit_unwrap(1) }) .enumerate(); if scmd.is_present("json") { - let v : Vec = iterator - .map(|(_, (_, vcard))| DeserVcard::from(vcard)).collect(); + let v : Vec = 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) => { @@ -155,9 +140,8 @@ fn list(rt: &Runtime) { } } else { iterator - .map(|(i, (fle, vcard))| { - let hash = String::from(fle.get_hash().map_err_trace_exit_unwrap(1)); - let data = build_data_object_for_handlebars(i, hash, &vcard); + .map(|(i, deservcard)| { + let data = build_data_object_for_handlebars(i, &deservcard); list_format.render("format", &data) .err_from_str() @@ -217,32 +201,47 @@ fn import(rt: &Runtime) { } fn show(rt: &Runtime) { - let scmd = rt.cli().subcommand_matches("show").unwrap(); - let hash = scmd.value_of("hash").map(String::from).unwrap(); // safed by clap - - let contact_data = rt.store() - .get_ref::(hash.clone()) - .map_err_trace_exit_unwrap(1) - .ok_or(CE::from(format!("No entry for hash {}", hash))) - .map_err_trace_exit_unwrap(1) - .get_contact_data() - .map_err_trace_exit_unwrap(1) - .into_inner(); - let vcard = Vcard::from_component(contact_data) - .unwrap_or_else(|e| { - error!("Element is not a VCARD object: {:?}", e); - exit(1) - }); - + 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 data = build_data_object_for_handlebars(0, hash, &vcard); + let out = rt.stdout(); + let mut outlock = out.lock(); - let s = show_format - .render("format", &data) - .err_from_str() - .map_err(CE::from) - .map_err_trace_exit_unwrap(1); - let _ = writeln!(::std::io::stdout(), "{}", s).to_exit_code().unwrap_or_exit(); + rt.store() + .all_contacts() + .map_err_trace_exit_unwrap(1) + .into_get_iter(rt.store()) + .trace_unwrap_exit(1) + .map(|o| o.unwrap_or_else(|| { + error!("Failed to get entry"); + exit(1) + })) + .filter_map(|entry| { + let deser = entry.deser().map_err_trace_exit_unwrap(1); + + if deser.uid() + .ok_or_else(|| { + error!("Could not get StoreId from Store::all_contacts(). This is a BUG!"); + ::std::process::exit(1) + }) + .unwrap() // exited above + .starts_with(&hash) + { + Some(deser) + } else { + None + } + }) + .for_each(|elem| { + let data = build_data_object_for_handlebars(0, &elem); + + let s = show_format + .render("format", &data) + .err_from_str() + .map_err(CE::from) + .map_err_trace_exit_unwrap(1); + let _ = writeln!(outlock, "{}", s).to_exit_code().unwrap_or_exit(); + }); } fn find(rt: &Runtime) { @@ -270,30 +269,20 @@ fn find(rt: &Runtime) { }) .unwrap() // safed above }) - .filter_map(|cont| { - let comp = cont - .get_contact_data() - .map_err_trace_exit_unwrap(1) - .into_inner(); - - let card = Vcard::from_component(comp) - .map_err(|_| { - error!("Could not build Vcard from {:?}", cont.get_location()); - ::std::process::exit(1) - }) - .unwrap(); // safed above + .filter_map(|entry| { + let card = entry.deser().map_err_trace_exit_unwrap(1); let str_contains_any = |s: &String, v: &Vec| { v.iter().any(|i| s.contains(i)) }; - let take = card.adr().iter().any(|a| str_contains_any(a.raw(), &grepstring)) - || card.email().iter().any(|a| str_contains_any(a.raw(), &grepstring)) - || card.fullname().iter().any(|a| str_contains_any(a.raw(), &grepstring)); + let take = card.adr().iter().any(|a| str_contains_any(a, &grepstring)) + || card.email().iter().any(|a| str_contains_any(a, &grepstring)) + || card.fullname().iter().any(|a| str_contains_any(a, &grepstring)); if take { // optimization so we don't have to parse again in the next step - Some((cont, card)) + Some((entry, card)) } else { None } @@ -301,8 +290,8 @@ fn find(rt: &Runtime) { .enumerate(); if scmd.is_present("json") { - let v : Vec = iterator - .map(|(_, (_, vcard))| DeserVcard::from(vcard)).collect(); + let v : Vec = 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) => { @@ -312,22 +301,22 @@ fn find(rt: &Runtime) { } } else if scmd.is_present("find-id") { iterator - .for_each(|(_i, (fle, _card))| { - writeln!(rt.stdout(), "{}", fle.get_location()) + .for_each(|(_i, (entry, _))| { + writeln!(rt.stdout(), "{}", entry.get_location()) .to_exit_code() .unwrap_or_exit(); }) } else if scmd.is_present("find-full-id") { let storepath = rt.store().path().display(); iterator - .for_each(|(_i, (fle, _card))| { - writeln!(rt.stdout(), "{}/{}", storepath, fle.get_location()) + .for_each(|(_i, (entry, _))| { + writeln!(rt.stdout(), "{}/{}", storepath, entry.get_location()) .to_exit_code() .unwrap_or_exit(); }) } else { iterator - .for_each(|(i, (fle, card))| { + .for_each(|(i, (_, card))| { let fmt = if scmd.is_present("find-show") { &show_format } else if scmd.is_present("find-list") { @@ -336,8 +325,7 @@ fn find(rt: &Runtime) { &list_format }; - let hash = fle.get_hash().map(String::from).map_err_trace_exit_unwrap(1); - let data = build_data_object_for_handlebars(i, hash, &card); + let data = build_data_object_for_handlebars(i, &card); let s = fmt .render("format", &data) .err_from_str() diff --git a/bin/domain/imag-contact/src/util.rs b/bin/domain/imag-contact/src/util.rs index 12730a91..91e00783 100644 --- a/bin/domain/imag-contact/src/util.rs +++ b/bin/domain/imag-contact/src/util.rs @@ -18,105 +18,58 @@ // use std::collections::BTreeMap; -use vobject::vcard::Vcard; -pub fn build_data_object_for_handlebars<'a>(i: usize, hash: String, vcard: &Vcard) -> BTreeMap<&'static str, String> { +use libimagcontact::deser::DeserVcard; + +pub fn build_data_object_for_handlebars<'a>(i: usize, vcard: &DeserVcard) -> BTreeMap<&'static str, String> { let mut data = BTreeMap::new(); + + let process_list = |list: &Vec| { + list.iter() + .map(String::clone) + .collect::>() + .join(", ") + }; + + let process_opt = |opt: Option<&String>| { + opt.map(String::clone).unwrap_or_else(String::new) + }; + { data.insert("i" , format!("{}", i)); // The hash (as in libimagentryref) of the contact - data.insert("id" , hash); - - data.insert("ADR" , vcard.adr() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("ANNIVERSARY" , vcard.anniversary() - .map(|c| c.raw().clone()).unwrap_or(String::new())); - - data.insert("BDAY" , vcard.bday() - .map(|c| c.raw().clone()).unwrap_or(String::new())); - - data.insert("CATEGORIES" , vcard.categories() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("CLIENTPIDMAP" , vcard.clientpidmap() - .map(|c| c.raw().clone()).unwrap_or(String::new())); - - data.insert("EMAIL" , vcard.email() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("FN" , vcard.fullname() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("GENDER" , vcard.gender() - .map(|c| c.raw().clone()).unwrap_or(String::new())); - - data.insert("GEO" , vcard.geo() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("IMPP" , vcard.impp() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("KEY" , vcard.key() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("LANG" , vcard.lang() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("LOGO" , vcard.logo() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("MEMBER" , vcard.member() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("N" , vcard.name() - .map(|c| c.raw().clone()).unwrap_or(String::new())); - - data.insert("NICKNAME" , vcard.nickname() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("NOTE" , vcard.note() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("ORG" , vcard.org() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("PHOTO" , vcard.photo() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("PRIOD" , vcard.proid() - .map(|c| c.raw().clone()).unwrap_or(String::new())); - - data.insert("RELATED" , vcard.related() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("REV" , vcard.rev() - .map(|c| c.raw().clone()).unwrap_or(String::new())); - - data.insert("ROLE" , vcard.role() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("SOUND" , vcard.sound() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("TEL" , vcard.tel() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("TITLE" , vcard.title() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("TZ" , vcard.tz() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("UID" , vcard.uid() - .map(|c| c.raw().clone()).unwrap_or(String::new())); - - data.insert("URL" , vcard.url() - .into_iter().map(|c| c.raw().clone()).collect::>().join(", ")); - - data.insert("VERSION" , vcard.version() - .map(|c| c.raw().clone()).unwrap_or(String::new())); + data.insert("id" , process_opt(vcard.uid())); + data.insert("ADR" , process_list(vcard.adr())); + data.insert("ANNIVERSARY" , process_opt(vcard.anniversary())); + data.insert("BDAY" , process_opt(vcard.bday())); + data.insert("CATEGORIES" , process_list(vcard.categories())); + data.insert("CLIENTPIDMAP" , process_opt(vcard.clientpidmap())); + data.insert("EMAIL" , process_list(vcard.email())); + data.insert("FN" , process_list(vcard.fullname())); + data.insert("GENDER" , process_opt(vcard.gender())); + data.insert("GEO" , process_list(vcard.geo())); + data.insert("IMPP" , process_list(vcard.impp())); + data.insert("KEY" , process_list(vcard.key())); + data.insert("LANG" , process_list(vcard.lang())); + data.insert("LOGO" , process_list(vcard.logo())); + data.insert("MEMBER" , process_list(vcard.member())); + data.insert("N" , process_opt(vcard.name())); + data.insert("NICKNAME" , process_list(vcard.nickname())); + data.insert("NOTE" , process_list(vcard.note())); + data.insert("ORG" , process_list(vcard.org())); + data.insert("PHOTO" , process_list(vcard.photo())); + data.insert("PRIOD" , process_opt(vcard.proid())); + data.insert("RELATED" , process_list(vcard.related())); + data.insert("REV" , process_opt(vcard.rev())); + data.insert("ROLE" , process_list(vcard.role())); + data.insert("SOUND" , process_list(vcard.sound())); + data.insert("TEL" , process_list(vcard.tel())); + data.insert("TITLE" , process_list(vcard.title())); + data.insert("TZ" , process_list(vcard.tz())); + data.insert("UID" , process_opt(vcard.uid())); + data.insert("URL" , process_list(vcard.url())); + data.insert("VERSION" , process_opt(vcard.version())); } data