summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2019-02-10 17:07:35 +0100
committerMatthias Beyer <mail@beyermatthias.de>2019-02-10 17:07:35 +0100
commit03e0864268a843309ad7afb6c0c0681e7308d045 (patch)
treebe52573cf8c1dd09ce871446303a1a640e758970
parentd936b611fc0e7ee48c4ad79671d6b1aec25212c3 (diff)
parent53022443abf4970bea452a87aa90cb66893f1e63 (diff)
Merge branch 'unnamed-annotations' into master-ff
This merge adds several patches to improve libimagannotation and imag-annotate.
-rw-r--r--bin/core/imag-annotate/Cargo.toml1
-rw-r--r--bin/core/imag-annotate/src/main.rs77
-rw-r--r--bin/core/imag-annotate/src/ui.rs16
-rw-r--r--lib/entry/libimagentryannotation/Cargo.toml3
-rw-r--r--lib/entry/libimagentryannotation/src/annotateable.rs50
-rw-r--r--lib/entry/libimagentryannotation/src/annotation_fetcher.rs16
-rw-r--r--lib/entry/libimagentryannotation/src/iter.rs77
-rw-r--r--lib/entry/libimagentryannotation/src/lib.rs5
8 files changed, 102 insertions, 143 deletions
diff --git a/bin/core/imag-annotate/Cargo.toml b/bin/core/imag-annotate/Cargo.toml
index 072beeec..67e72a31 100644
--- a/bin/core/imag-annotate/Cargo.toml
+++ b/bin/core/imag-annotate/Cargo.toml
@@ -32,6 +32,7 @@ libimagstore = { version = "0.10.0", path = "../../../lib/core/libimag
libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }
libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" }
libimagentryannotation = { version = "0.10.0", path = "../../../lib/entry/libimagentryannotation" }
+libimagentrylink = { version = "0.10.0", path = "../../../lib/entry/libimagentrylink" }
libimagentryedit = { version = "0.10.0", path = "../../../lib/entry/libimagentryedit" }
libimagutil = { version = "0.10.0", path = "../../../lib/etc/libimagutil" }
diff --git a/bin/core/imag-annotate/src/main.rs b/bin/core/imag-annotate/src/main.rs
index da965d7c..afb5ce6e 100644
--- a/bin/core/imag-annotate/src/main.rs
+++ b/bin/core/imag-annotate/src/main.rs
@@ -37,7 +37,9 @@
extern crate clap;
#[macro_use]
extern crate log;
+#[macro_use]
extern crate failure;
+extern crate toml_query;
extern crate libimagentryannotation;
extern crate libimagentryedit;
@@ -45,10 +47,12 @@ extern crate libimagerror;
#[macro_use] extern crate libimagrt;
extern crate libimagstore;
extern crate libimagutil;
+extern crate libimagentrylink;
use std::io::Write;
use failure::Error;
+use toml_query::read::TomlValueReadTypeExt;
use libimagentryannotation::annotateable::*;
use libimagentryannotation::annotation_fetcher::*;
@@ -57,9 +61,12 @@ use libimagerror::trace::MapErrTrace;
use libimagerror::exit::ExitUnwrap;
use libimagerror::io::ToExitCode;
use libimagerror::errors::ErrorMsg as EM;
+use libimagerror::iter::TraceIterator;
use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagstore::store::FileLockEntry;
+use libimagstore::iter::get::StoreIdGetIteratorExtension;
+use libimagentrylink::internal::InternalLinker;
mod ui;
@@ -89,23 +96,48 @@ fn main() {
}
fn add(rt: &Runtime) {
- let scmd = rt.cli().subcommand_matches("add").unwrap(); // safed by main()
- let annotation_name = scmd.value_of("annotation_name").unwrap(); // safed by clap
- let ids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1);
+ let scmd = rt.cli().subcommand_matches("add").unwrap(); // safed by main()
+ let mut ids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1).into_iter();
- ids.into_iter().for_each(|id| {
- let _ = rt.store()
- .get(id.clone())
+ if let Some(first) = ids.next() {
+ let mut annotation = rt.store()
+ .get(first.clone())
.map_err_trace_exit_unwrap(1)
- .ok_or_else(|| EM::EntryNotFound(id.local_display_string()))
+ .ok_or_else(|| EM::EntryNotFound(first.local_display_string()))
.map_err(Error::from)
.map_err_trace_exit_unwrap(1)
- .annotate(rt.store(), annotation_name)
- .map_err_trace_exit_unwrap(1)
- .edit_content(&rt)
+ .annotate(rt.store())
.map_err_trace_exit_unwrap(1);
- })
+ let _ = annotation.edit_content(&rt).map_err_trace_exit_unwrap(1);
+
+ for id in ids {
+ let mut entry = rt.store().get(id.clone())
+ .map_err_trace_exit_unwrap(1)
+ .ok_or_else(|| format_err!("Not found: {}", id.local_display_string()))
+ .map_err_trace_exit_unwrap(1);
+
+ let _ = entry.add_internal_link(&mut annotation).map_err_trace_exit_unwrap(1);
+ }
+
+ if !scmd.is_present("dont-print-name") {
+ if let Some(annotation_id) = annotation
+ .get_header()
+ .read_string("annotation.name")
+ .map_err(Error::from)
+ .map_err_trace_exit_unwrap(1)
+ {
+ let _ = writeln!(rt.stdout(), "Name of the annotation: {}", annotation_id)
+ .to_exit_code()
+ .unwrap_or_exit();
+ } else {
+ error!("Unnamed annotation: {:?}", annotation.get_location());
+ error!("This is most likely a BUG, please report!");
+ }
+ }
+ } else {
+ debug!("No entries to annotate");
+ }
}
fn remove(rt: &Runtime) {
@@ -162,25 +194,26 @@ fn list(rt: &Runtime) {
.ok_or_else(|| EM::EntryNotFound(id.local_display_string()))
.map_err(Error::from)
.map_err_trace_exit_unwrap(1)
- .annotations(rt.store())
+ .annotations()
.map_err_trace_exit_unwrap(1)
+ .into_get_iter(rt.store())
+ .trace_unwrap_exit(1)
+ .map(|opt| opt.ok_or_else(|| format_err!("Cannot find entry")))
+ .trace_unwrap_exit(1)
.enumerate()
- .map(|(i, a)| {
- list_annotation(&rt, i, a.map_err_trace_exit_unwrap(1), with_text)
- })
- .collect::<Vec<_>>();
+ .for_each(|(i, entry)| list_annotation(&rt, i, entry, with_text));
});
} else { // ids.len() == 0
// show them all
- let _ = rt
- .store()
+ rt.store()
.all_annotations()
.map_err_trace_exit_unwrap(1)
+ .into_get_iter(rt.store())
+ .trace_unwrap_exit(1)
+ .map(|opt| opt.ok_or_else(|| format_err!("Cannot find entry")))
+ .trace_unwrap_exit(1)
.enumerate()
- .map(|(i, a)| {
- list_annotation(&rt, i, a.map_err_trace_exit_unwrap(1), with_text)
- })
- .collect::<Vec<_>>();
+ .for_each(|(i, entry)| list_annotation(&rt, i, entry, with_text));
}
}
diff --git a/bin/core/imag-annotate/src/ui.rs b/bin/core/imag-annotate/src/ui.rs
index 2a3b722f..024d6a3d 100644
--- a/bin/core/imag-annotate/src/ui.rs
+++ b/bin/core/imag-annotate/src/ui.rs
@@ -31,6 +31,15 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
.subcommand(SubCommand::with_name("add")
.about("Add annotation to an entry")
.version("0.1")
+
+ .arg(Arg::with_name("dont-print-name")
+ .short("N")
+ .long("no-name")
+ .takes_value(false)
+ .required(false)
+ .multiple(false)
+ .help("Do not print the name of the annotation after annotating.")
+ )
.arg(Arg::with_name("entry")
.index(1)
.takes_value(true)
@@ -38,13 +47,6 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
.multiple(false)
.help("The entry to add the latitude/longitude to")
.value_name("ENTRY"))
- .arg(Arg::with_name("annotation_name")
- .index(2)
- .takes_value(true)
- .required(true)
- .multiple(false)
- .help("Name of the new annotation")
- .value_name("NAME"))
)
.subcommand(SubCommand::with_name("remove")
diff --git a/lib/entry/libimagentryannotation/Cargo.toml b/lib/entry/libimagentryannotation/Cargo.toml
index a677a6b3..166eef92 100644
--- a/lib/entry/libimagentryannotation/Cargo.toml
+++ b/lib/entry/libimagentryannotation/Cargo.toml
@@ -25,6 +25,9 @@ toml = "0.4"
toml-query = "0.8"
failure = "0.1"
failure_derive = "0.1"
+uuid = { version = "0.7", features = ["v4"] }
+log = "0.4.0"
+
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" }
diff --git a/lib/entry/libimagentryannotation/src/annotateable.rs b/lib/entry/libimagentryannotation/src/annotateable.rs
index 45da1dca..3c915846 100644
--- a/lib/entry/libimagentryannotation/src/annotateable.rs
+++ b/lib/entry/libimagentryannotation/src/annotateable.rs
@@ -18,6 +18,7 @@
//
use toml::Value;
+use uuid::Uuid;
use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
@@ -28,7 +29,6 @@ use libimagentrylink::internal::InternalLinker;
use libimagentryutil::isa::Is;
use libimagentryutil::isa::IsKindHeaderPathProvider;
-use toml_query::read::TomlValueReadTypeExt;
use toml_query::insert::TomlValueInsertExt;
use failure::Fallible as Result;
@@ -36,12 +36,12 @@ use failure::ResultExt;
use failure::Error;
use failure::err_msg;
-use iter::*;
+use module_path::ModuleEntryPath;
pub trait Annotateable {
- fn annotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<FileLockEntry<'a>>;
+ fn annotate<'a>(&mut self, store: &'a Store) -> Result<FileLockEntry<'a>>;
fn denotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<Option<FileLockEntry<'a>>>;
- fn annotations<'a>(&self, store: &'a Store) -> Result<AnnotationIter<'a>>;
+ fn annotations(&self) -> Result<StoreIdIterator>;
fn is_annotation(&self) -> Result<bool>;
}
@@ -50,9 +50,11 @@ provide_kindflag_path!(IsAnnotation, "annotation.is_annotation");
impl Annotateable for Entry {
/// Annotate an entry, returns the new entry which is used to annotate
- fn annotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<FileLockEntry<'a>> {
- use module_path::ModuleEntryPath;
- store.retrieve(ModuleEntryPath::new(ann_name).into_storeid()?)
+ fn annotate<'a>(&mut self, store: &'a Store) -> Result<FileLockEntry<'a>> {
+ let ann_name = Uuid::new_v4().to_hyphenated().to_string();
+ debug!("Creating annotation with name = {}", ann_name);
+
+ store.retrieve(ModuleEntryPath::new(ann_name.clone()).into_storeid()?)
.and_then(|mut anno| {
{
let _ = anno.set_isflag::<IsAnnotation>()?;
@@ -70,30 +72,28 @@ impl Annotateable for Entry {
})
}
- /// Checks the current entry for all annotations and removes the one where the name is
- /// `ann_name`, which is then returned
+ // Removes the annotation `ann_name` from the current entry.
+ // Fails if there's no such annotation entry or if the link to that annotation entry does not
+ // exist.
fn denotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<Option<FileLockEntry<'a>>> {
- for annotation in self.annotations(store)? {
- let mut anno = annotation?;
- let name = match anno.get_header().read_string("annotation.name")? {
- Some(ref name) => name.clone(),
- None => continue,
- };
-
- if name == ann_name {
- let _ = self.remove_internal_link(&mut anno)?;
- return Ok(Some(anno));
- }
+ if let Some(mut annotation) = store.get(ModuleEntryPath::new(ann_name).into_storeid()?)? {
+ let _ = self.remove_internal_link(&mut annotation)?;
+ Ok(Some(annotation))
+ } else {
+ // error: annotation does not exist
+ Err(format_err!("Annotation '{}' does not exist", ann_name)).map_err(Error::from)
}
-
- Ok(None)
}
/// Get all annotations of an entry
- fn annotations<'a>(&self, store: &'a Store) -> Result<AnnotationIter<'a>> {
+ fn annotations(&self) -> Result<StoreIdIterator> {
self.get_internal_links()
- .map(|iter| StoreIdIterator::new(Box::new(iter.map(|e| e.get_store_id().clone()).map(Ok))))
- .map(|i| AnnotationIter::new(i, store))
+ .map(|it| {
+ it.filter(|link| link.get_store_id().is_in_collection(&["annotation"]))
+ .map(|link| Ok(link.get_store_id().clone()))
+ })
+ .map(Box::new)
+ .map(|inner| StoreIdIterator::new(inner))
}
fn is_annotation(&self) -> Result<bool> {
diff --git a/lib/entry/libimagentryannotation/src/annotation_fetcher.rs b/lib/entry/libimagentryannotation/src/annotation_fetcher.rs
index ac903807..dd6c2222 100644
--- a/lib/entry/libimagentryannotation/src/annotation_fetcher.rs
+++ b/lib/entry/libimagentryannotation/src/annotation_fetcher.rs
@@ -18,21 +18,17 @@
//
use libimagstore::store::Store;
+use libimagstore::storeid::StoreIdIterator;
use failure::Fallible as Result;
-use iter::*;
-
-pub trait AnnotationFetcher<'a> {
-
- fn all_annotations(&'a self) -> Result<AnnotationIter<'a>>;
+pub trait AnnotationFetcher {
+ fn all_annotations(&self) -> Result<StoreIdIterator>;
}
-impl<'a> AnnotationFetcher<'a> for Store {
-
- fn all_annotations(&'a self) -> Result<AnnotationIter<'a>> {
- Ok(AnnotationIter::new(self.entries()?.without_store(), self))
+impl<'a> AnnotationFetcher for Store {
+ fn all_annotations(&self) -> Result<StoreIdIterator> {
+ self.entries().map(|iter| iter.in_collection("annotation").without_store())
}
-
}
diff --git a/lib/entry/libimagentryannotation/src/iter.rs b/lib/entry/libimagentryannotation/src/iter.rs
deleted file mode 100644
index e7601a9c..00000000
--- a/lib/entry/libimagentryannotation/src/iter.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015-2019 Matthias Beyer <mail@beyermatthias.de> 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
-//
-
-use toml_query::read::TomlValueReadTypeExt;
-
-use libimagstore::store::Store;
-use libimagstore::store::FileLockEntry;
-use libimagstore::storeid::StoreIdIterator;
-use libimagerror::errors::ErrorMsg as EM;
-
-use failure::Fallible as Result;
-use failure::ResultExt;
-use failure::Error;
-use failure::err_msg;
-
-#[derive(Debug)]
-pub struct AnnotationIter<'a>(StoreIdIterator, &'a Store);
-
-impl<'a> AnnotationIter<'a> {
-
- pub fn new(iter: StoreIdIterator, store: &'a Store) -> AnnotationIter<'a> {
- AnnotationIter(iter, store)
- }
-
-}
-
-impl<'a> Iterator for AnnotationIter<'a> {
- type Item = Result<FileLockEntry<'a>>;
-
- fn next(&mut self) -> Option<Self::Item> {
- loop {
- match self.0.next() {
- None => return None, // iterator consumed
- Some(Err(e)) => return Some(Err(e).map_err(Error::from)),
- Some(Ok(id)) => match self.1.get(id) {
- Err(e) => {
- return Some(Err(e)
- .context(err_msg("Store read error"))
- .map_err(Error::from))
- },
- Ok(Some(entry)) => {
- match entry
- .get_header()
- .read_bool("annotation.is_annotation")
- .context(EM::EntryHeaderReadError)
- .map_err(Error::from)
- {
- Ok(None) => continue, // not an annotation
- Ok(Some(false)) => continue,
- Ok(Some(true)) => return Some(Ok(entry)),
- Err(e) => return Some(Err(e)),
- }
- },
- Ok(None) => continue,
- }
- }
- }
- }
-
-}
-
diff --git a/lib/entry/libimagentryannotation/src/lib.rs b/lib/entry/libimagentryannotation/src/lib.rs
index 24de090b..92da306f 100644
--- a/lib/entry/libimagentryannotation/src/lib.rs
+++ b/lib/entry/libimagentryannotation/src/lib.rs
@@ -39,7 +39,9 @@
extern crate toml;
extern crate toml_query;
-extern crate failure;
+#[macro_use] extern crate failure;
+#[macro_use] extern crate log;
+extern crate uuid;
#[macro_use] extern crate libimagstore;
extern crate libimagerror;
@@ -50,5 +52,4 @@ module_entry_path_mod!("annotations");
pub mod annotateable;
pub mod annotation_fetcher;
-pub mod iter;