From 9945cb38b7ba068531f0619343f704c3f63e7e22 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 9 Apr 2019 19:40:13 +0200 Subject: [PATCH 1/2] Refactor: Move contact-by-hash finding to utils Signed-off-by: Matthias Beyer --- bin/domain/imag-contact/src/main.rs | 28 ++------------------ bin/domain/imag-contact/src/util.rs | 40 +++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/bin/domain/imag-contact/src/main.rs b/bin/domain/imag-contact/src/main.rs index bc950fa1..bd429bd5 100644 --- a/bin/domain/imag-contact/src/main.rs +++ b/bin/domain/imag-contact/src/main.rs @@ -217,34 +217,10 @@ fn show(rt: &Runtime) { let out = rt.stdout(); let mut outlock = out.lock(); - rt.store() - .all_contacts() - .map_err_trace_exit_unwrap() - .into_get_iter() - .trace_unwrap_exit() - .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(); - - 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) - { - let _ = rt.report_touched(entry.get_location()).unwrap_or_exit(); - Some(deser) - } else { - None - } - }) + util::find_contact_by_hash(rt, hash) .enumerate() .for_each(|(i, elem)| { + let elem = elem.deser().map_err_trace_exit_unwrap(); let data = build_data_object_for_handlebars(i, &elem); let s = show_format diff --git a/bin/domain/imag-contact/src/util.rs b/bin/domain/imag-contact/src/util.rs index ccd13ed6..0ed8be05 100644 --- a/bin/domain/imag-contact/src/util.rs +++ b/bin/domain/imag-contact/src/util.rs @@ -18,8 +18,17 @@ // use std::collections::BTreeMap; +use std::process::exit; use libimagcontact::deser::DeserVcard; +use libimagcontact::store::ContactStore; +use libimagcontact::contact::Contact; +use libimagerror::exit::ExitUnwrap; +use libimagerror::iter::TraceIterator; +use libimagerror::trace::MapErrTrace; +use libimagrt::runtime::Runtime; +use libimagstore::store::FileLockEntry; + pub fn build_data_object_for_handlebars<'a>(i: usize, vcard: &DeserVcard) -> BTreeMap<&'static str, String> { let mut data = BTreeMap::new(); @@ -75,3 +84,34 @@ pub fn build_data_object_for_handlebars<'a>(i: usize, vcard: &DeserVcard) -> BTr data } +pub fn find_contact_by_hash<'a, H: AsRef>(rt: &'a Runtime, hash: H) + -> impl Iterator> +{ + rt.store() + .all_contacts() + .map_err_trace_exit_unwrap() + .into_get_iter() + .trace_unwrap_exit() + .map(|o| o.unwrap_or_else(|| { + error!("Failed to get entry"); + exit(1) + })) + .filter_map(move |entry| { + let deser = entry.deser().map_err_trace_exit_unwrap(); + + 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.as_ref()) + { + let _ = rt.report_touched(entry.get_location()).unwrap_or_exit(); + Some(entry) + } else { + None + } + }) +} + From 37d8ae74302e90990489e1121083ff80e729ed62 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 9 Apr 2019 19:43:36 +0200 Subject: [PATCH 2/2] Add contact editing. Signed-off-by: Matthias Beyer --- bin/domain/imag-contact/src/edit.rs | 91 +++++++++++++++++++++++++++++ bin/domain/imag-contact/src/main.rs | 4 ++ bin/domain/imag-contact/src/ui.rs | 12 ++++ 3 files changed, 107 insertions(+) create mode 100644 bin/domain/imag-contact/src/edit.rs diff --git a/bin/domain/imag-contact/src/edit.rs b/bin/domain/imag-contact/src/edit.rs new file mode 100644 index 00000000..77cca375 --- /dev/null +++ b/bin/domain/imag-contact/src/edit.rs @@ -0,0 +1,91 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +use std::process::exit; + +use failure::Error; +use failure::err_msg; + +use libimagrt::runtime::Runtime; +use libimagerror::trace::MapErrTrace; +use libimagcontact::store::ContactStore; +use libimagentryref::reference::fassade::RefFassade; +use libimagentryref::hasher::default::DefaultHasher; +use libimagentryref::reference::Ref; + +const TEMPLATE : &'static str = include_str!("../static/new-contact-template.toml"); + +pub fn edit(rt: &Runtime) { + let scmd = rt.cli().subcommand_matches("edit").unwrap(); + let collection_name = rt.cli().value_of("contact-ref-collection-name").unwrap(); // default by clap + let ref_config = libimagentryref::util::get_ref_config(&rt, "imag-contact").map_err_trace_exit_unwrap(); + let hash = scmd.value_of("hash").map(String::from).unwrap(); // safed by clap + let force_override = true; // when editing, we want to override, right? + + if rt.output_is_pipe() { + error!("Cannot spawn editor if output is a pipe!"); + exit(1); + } + + ::util::find_contact_by_hash(rt, hash) + .for_each(|contact| { + let filepath = contact + .as_ref_with_hasher::() + .get_path(&ref_config) + .map_err_trace_exit_unwrap(); + + let success = rt.editor() + .map_err_trace_exit_unwrap() + .ok_or_else(|| { + err_msg("I have no editor configured. Cannot continue!") + }) + .map_err_trace_exit_unwrap() + .arg(&filepath) + .status() + .map_err(Error::from) + .map_err_trace_exit_unwrap() + .success(); + + if !success { + error!("Editor failed!"); + exit(1); + } + + let _ = rt + .store() + .retrieve_from_path(&filepath, &ref_config, &collection_name, force_override) + .map_err_trace_exit_unwrap(); + }); +} + diff --git a/bin/domain/imag-contact/src/main.rs b/bin/domain/imag-contact/src/main.rs index bd429bd5..40ab8a09 100644 --- a/bin/domain/imag-contact/src/main.rs +++ b/bin/domain/imag-contact/src/main.rs @@ -52,6 +52,7 @@ extern crate libimagerror; extern crate libimagutil; extern crate libimaginteraction; extern crate libimagentryedit; +extern crate libimagentryref; use std::process::exit; use std::path::PathBuf; @@ -79,10 +80,12 @@ use libimagcontact::deser::DeserVcard; mod ui; mod util; mod create; +mod edit; use ui::build_ui; use util::build_data_object_for_handlebars; use create::create; +use edit::edit; fn main() { let version = make_imag_version!(); @@ -100,6 +103,7 @@ fn main() { "list" => list(&rt), "import" => import(&rt), "show" => show(&rt), + "edit" => edit(&rt), "find" => find(&rt), "create" => create(&rt), other => { diff --git a/bin/domain/imag-contact/src/ui.rs b/bin/domain/imag-contact/src/ui.rs index c07a938d..e4cf657c 100644 --- a/bin/domain/imag-contact/src/ui.rs +++ b/bin/domain/imag-contact/src/ui.rs @@ -92,6 +92,18 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .help("Format to format the contact when printing it")) ) + .subcommand(SubCommand::with_name("edit") + .about("Edit contacts") + .version("0.1") + .arg(Arg::with_name("hash") + .index(1) + .takes_value(true) + .required(true) + .multiple(true) + .value_name("HASH") + .help("Edit the contact pointed to by this reference hash(es)")) + ) + .subcommand(SubCommand::with_name("find") .about("Find contact by grepping for a string (no regex yet)") .version("0.1")