diff --git a/bin/domain/imag-contact/src/main.rs b/bin/domain/imag-contact/src/main.rs index 821d271f..bc950fa1 100644 --- a/bin/domain/imag-contact/src/main.rs +++ b/bin/domain/imag-contact/src/main.rs @@ -157,8 +157,9 @@ fn list(rt: &Runtime) { } fn import(rt: &Runtime) { - let scmd = rt.cli().subcommand_matches("import").unwrap(); // secured by main - let path = scmd.value_of("path").map(PathBuf::from).unwrap(); // secured by clap + 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() @@ -180,7 +181,7 @@ fn import(rt: &Runtime) { if path.is_file() { let entry = rt .store() - .retrieve_from_path(&path, &ref_config, &collection_name) + .retrieve_from_path(&path, &ref_config, &collection_name, force_override) .map_err_trace_exit_unwrap(); let _ = rt.report_touched(entry.get_location()).unwrap_or_exit(); @@ -194,7 +195,7 @@ fn import(rt: &Runtime) { let pb = PathBuf::from(entry.path()); let fle = rt .store() - .retrieve_from_path(&pb, &ref_config, &collection_name) + .retrieve_from_path(&pb, &ref_config, &collection_name, force_override) .map_err_trace_exit_unwrap(); let _ = rt.report_touched(fle.get_location()).unwrap_or_exit(); diff --git a/bin/domain/imag-contact/src/ui.rs b/bin/domain/imag-contact/src/ui.rs index 4a0b1095..c07a938d 100644 --- a/bin/domain/imag-contact/src/ui.rs +++ b/bin/domain/imag-contact/src/ui.rs @@ -65,6 +65,12 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .value_name("PATH") .help("Import from this file/directory")) + .arg(Arg::with_name("force-override") + .long("force") + .takes_value(false) + .required(false) + .multiple(false) + .help("Force to override existing entries")) ) .subcommand(SubCommand::with_name("show") diff --git a/lib/domain/libimagcontact/src/store.rs b/lib/domain/libimagcontact/src/store.rs index 3fd3771d..eac759ab 100644 --- a/lib/domain/libimagcontact/src/store.rs +++ b/lib/domain/libimagcontact/src/store.rs @@ -45,7 +45,11 @@ pub trait ContactStore<'a> { -> Result> where CN: AsRef; - fn retrieve_from_path(&'a self, p: &PathBuf, rc: &RefConfig, collection_name: CN) + fn retrieve_from_path(&'a self, + p: &PathBuf, + rc: &RefConfig, + collection_name: CN, + force: bool) -> Result> where CN: AsRef; @@ -54,7 +58,12 @@ pub trait ContactStore<'a> { where CN: AsRef, P: AsRef; - fn retrieve_from_buf(&'a self, buf: &str, path: P, rc: &RefConfig, collection_name: CN) + fn retrieve_from_buf(&'a self, + buf: &str, + path: P, + rc: &RefConfig, + collection_name: CN, + force: bool) -> Result> where CN: AsRef, P: AsRef; @@ -82,11 +91,12 @@ impl<'a> ContactStore<'a> for Store { /// /// Uses the collection with `collection_name` from RefConfig to store the reference to the /// file. - fn retrieve_from_path(&'a self, p: &PathBuf, rc: &RefConfig, collection_name: CN) + fn retrieve_from_path(&'a self, p: &PathBuf, rc: &RefConfig, collection_name: CN, force: bool) -> Result> where CN: AsRef { - util::read_to_string(p).and_then(|buf| self.retrieve_from_buf(&buf, p, rc, collection_name)) + util::read_to_string(p) + .and_then(|buf| self.retrieve_from_buf(&buf, p, rc, collection_name, force)) } /// Create a contact from a buffer @@ -96,13 +106,19 @@ impl<'a> ContactStore<'a> for Store { /// /// Needs the `path` passed where the buffer was read from, because we want to create a /// reference to it. + /// + /// # Note + /// + /// This does _never_ force-override existing reference data, thus the `force` parameter of + /// `postprocess_fetched_entry()` is hardcoded to `false`. + /// fn create_from_buf(&'a self, buf: &str, path: P, rc: &RefConfig, collection_name: CN) -> Result> where CN: AsRef, P: AsRef { let (sid, value) = prepare_fetching_from_store(buf)?; - postprocess_fetched_entry(self.create(sid)?, value, path, rc, collection_name) + postprocess_fetched_entry(self.create(sid)?, value, path, rc, collection_name, false) } /// Retrieve a contact from a buffer @@ -112,13 +128,18 @@ impl<'a> ContactStore<'a> for Store { /// /// Needs the `path` passed where the buffer was read from, because we want to create a /// reference to it. - fn retrieve_from_buf(&'a self, buf: &str, path: P, rc: &RefConfig, collection_name: CN) + fn retrieve_from_buf(&'a self, + buf: &str, + path: P, + rc: &RefConfig, + collection_name: CN, + force: bool) -> Result> where CN: AsRef, P: AsRef { let (sid, value) = prepare_fetching_from_store(buf)?; - postprocess_fetched_entry(self.retrieve(sid)?, value, path, rc, collection_name) + postprocess_fetched_entry(self.retrieve(sid)?, value, path, rc, collection_name, force) } fn all_contacts(&'a self) -> Result> { @@ -159,7 +180,8 @@ fn postprocess_fetched_entry<'a, CN, P>(mut entry: FileLockEntry<'a>, value: Value, path: P, rc: &RefConfig, - collection_name: CN) + collection_name: CN, + force: bool) -> Result> where CN: AsRef, P: AsRef @@ -169,7 +191,7 @@ fn postprocess_fetched_entry<'a, CN, P>(mut entry: FileLockEntry<'a>, entry.set_isflag::()?; entry.get_header_mut().insert("contact.data", value)?; - entry.as_ref_with_hasher_mut::().make_ref(path, collection_name, rc, false)?; + entry.as_ref_with_hasher_mut::().make_ref(path, collection_name, rc, force)?; Ok(entry) }