From 5cb641044f46751217181ee95b9c4edb81183437 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 29 May 2019 17:43:24 +0200 Subject: [PATCH 01/11] Add libimagentryurl Signed-off-by: Matthias Beyer --- Cargo.toml | 1 + lib/entry/libimagentryurl/Cargo.toml | 41 ++++++++++++++++++++++++++++ lib/entry/libimagentryurl/src/lib.rs | 7 +++++ scripts/release.sh | 1 + 4 files changed, 50 insertions(+) create mode 100644 lib/entry/libimagentryurl/Cargo.toml create mode 100644 lib/entry/libimagentryurl/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 25f73c91..23c9969b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ members = [ "lib/entry/libimagentryfilter", "lib/entry/libimagentrygps", "lib/entry/libimagentrylink", + "lib/entry/libimagentryurl", "lib/entry/libimagentrymarkdown", "lib/entry/libimagentryref", "lib/entry/libimagentrytag", diff --git a/lib/entry/libimagentryurl/Cargo.toml b/lib/entry/libimagentryurl/Cargo.toml new file mode 100644 index 00000000..2c8ede95 --- /dev/null +++ b/lib/entry/libimagentryurl/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "libimagentryurl" +version = "0.10.0" +authors = ["Matthias Beyer "] + +description = "Library for the imag core distribution" + +keywords = ["imag", "PIM", "personal", "information", "management"] +readme = "../../../README.md" +license = "LGPL-2.1" + +documentation = "https://imag-pim.org/doc/" +repository = "https://github.com/matthiasbeyer/imag" +homepage = "http://imag-pim.org" + +[badges] +travis-ci = { repository = "matthiasbeyer/imag" } +is-it-maintained-issue-resolution = { repository = "matthiasbeyer/imag" } +is-it-maintained-open-issues = { repository = "matthiasbeyer/imag" } +maintenance = { status = "actively-developed" } + +[dependencies] +itertools = "0.7" +log = "0.4.0" +toml = "0.5" +url = "1.5" +sha-1 = "0.7" +hex = "0.3" +is-match = "0.1" +toml-query = "0.9" +failure = "0.1" +failure_derive = "0.1" + +libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" } +libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" } +libimagutil = { version = "0.10.0", path = "../../../lib/etc/libimagutil" } +libimagentrylink = { version = "0.10.0", path = "../../../lib/entry/libimagentrylink" } + +[dev-dependencies] +env_logger = "0.5" + diff --git a/lib/entry/libimagentryurl/src/lib.rs b/lib/entry/libimagentryurl/src/lib.rs new file mode 100644 index 00000000..31e1bb20 --- /dev/null +++ b/lib/entry/libimagentryurl/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} diff --git a/scripts/release.sh b/scripts/release.sh index 09fc299b..ff1598db 100644 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -16,6 +16,7 @@ CRATES=( ./lib/etc/libimaginteraction ./lib/core/libimagrt ./lib/entry/libimagentrylink + ./lib/entry/libimagentryurl ./lib/entry/libimagentrytag ./lib/entry/libimagentryfilter ./lib/entry/libimagentrygps From 098d25db896dd4ba627f36d172c300dc65033985 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 29 May 2019 18:03:46 +0200 Subject: [PATCH 02/11] Move code from external libimagentrylink module to libimagentryurl Signed-off-by: Matthias Beyer --- lib/entry/libimagentrylink/src/lib.rs | 1 - lib/entry/libimagentryurl/src/iter.rs | 195 +++++++++++++ lib/entry/libimagentryurl/src/lib.rs | 79 ++++- lib/entry/libimagentryurl/src/link.rs | 76 +++++ .../src/linker.rs} | 276 +----------------- lib/entry/libimagentryurl/src/util.rs | 28 ++ 6 files changed, 384 insertions(+), 271 deletions(-) create mode 100644 lib/entry/libimagentryurl/src/iter.rs create mode 100644 lib/entry/libimagentryurl/src/link.rs rename lib/entry/{libimagentrylink/src/external.rs => libimagentryurl/src/linker.rs} (50%) create mode 100644 lib/entry/libimagentryurl/src/util.rs diff --git a/lib/entry/libimagentrylink/src/lib.rs b/lib/entry/libimagentrylink/src/lib.rs index ce258815..992d3dd2 100644 --- a/lib/entry/libimagentrylink/src/lib.rs +++ b/lib/entry/libimagentrylink/src/lib.rs @@ -56,6 +56,5 @@ extern crate libimagutil; module_entry_path_mod!("links"); -pub mod external; pub mod internal; diff --git a/lib/entry/libimagentryurl/src/iter.rs b/lib/entry/libimagentryurl/src/iter.rs new file mode 100644 index 00000000..f5ef6ed0 --- /dev/null +++ b/lib/entry/libimagentryurl/src/iter.rs @@ -0,0 +1,195 @@ +// +// 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 +// + +//! Iterator helpers for external linking stuff +//! +//! Contains also helpers to filter iterators for external/internal links +//! +//! +//! # Warning +//! +//! This module uses `internal::Link` as link type, so we operate on _store ids_ here. +//! +//! Not to confuse with `external::Link` which is a real `FileLockEntry` under the hood. +//! + +use libimagentrylink::internal::Link; +use libimagentrylink::internal::iter::LinkIter; +use libimagstore::store::Store; +use libimagutil::debug_result::DebugResult; + +use failure::Fallible as Result; +use url::Url; + +/// Helper for building `OnlyExternalIter` and `NoExternalIter` +/// +/// The boolean value defines, how to interpret the `is_external_link_storeid()` return value +/// (here as "pred"): +/// +/// ```ignore +/// pred | bool | xor | take? +/// ---- | ---- | --- | ---- +/// 0 | 0 | 0 | 1 +/// 0 | 1 | 1 | 0 +/// 1 | 0 | 1 | 0 +/// 1 | 1 | 0 | 1 +/// ``` +/// +/// If `bool` says "take if return value is false", we take the element if the `pred` returns +/// false... and so on. +/// +/// As we can see, the operator between these two operants is `!(a ^ b)`. +pub struct ExternalFilterIter(LinkIter, bool); + +impl Iterator for ExternalFilterIter { + type Item = Link; + + fn next(&mut self) -> Option { + use crate::util::is_external_link_storeid; + + while let Some(elem) = self.0.next() { + trace!("Check whether is external: {:?}", elem); + if !(self.1 ^ is_external_link_storeid(&elem)) { + trace!("Is external id: {:?}", elem); + return Some(elem); + } + } + None + } +} + +/// Helper trait to be implemented on `LinkIter` to select or deselect all external links +/// +/// # See also +/// +/// Also see `OnlyExternalIter` and `NoExternalIter` and the helper traits/functions +/// `OnlyInteralLinks`/`only_internal_links()` and `OnlyExternalLinks`/`only_external_links()`. +pub trait SelectExternal { + fn select_external_links(self, b: bool) -> ExternalFilterIter; +} + +impl SelectExternal for LinkIter { + fn select_external_links(self, b: bool) -> ExternalFilterIter { + ExternalFilterIter(self, b) + } +} + + +pub struct OnlyExternalIter(ExternalFilterIter); + +impl OnlyExternalIter { + pub fn new(li: LinkIter) -> OnlyExternalIter { + OnlyExternalIter(ExternalFilterIter(li, true)) + } + + pub fn urls<'a>(self, store: &'a Store) -> UrlIter<'a> { + UrlIter(self, store) + } +} + +impl Iterator for OnlyExternalIter { + type Item = Link; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +pub struct NoExternalIter(ExternalFilterIter); + +impl NoExternalIter { + pub fn new(li: LinkIter) -> NoExternalIter { + NoExternalIter(ExternalFilterIter(li, false)) + } +} + +impl Iterator for NoExternalIter { + type Item = Link; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +pub trait OnlyExternalLinks : Sized { + fn only_external_links(self) -> OnlyExternalIter ; + + fn no_internal_links(self) -> OnlyExternalIter { + self.only_external_links() + } +} + +impl OnlyExternalLinks for LinkIter { + fn only_external_links(self) -> OnlyExternalIter { + OnlyExternalIter::new(self) + } +} + +pub trait OnlyInternalLinks : Sized { + fn only_internal_links(self) -> NoExternalIter; + + fn no_external_links(self) -> NoExternalIter { + self.only_internal_links() + } +} + +impl OnlyInternalLinks for LinkIter { + fn only_internal_links(self) -> NoExternalIter { + NoExternalIter::new(self) + } +} + +pub struct UrlIter<'a>(OnlyExternalIter, &'a Store); + +impl<'a> Iterator for UrlIter<'a> { + type Item = Result; + + fn next(&mut self) -> Option { + use crate::link::Link; + + loop { + let next = self.0 + .next() + .map(|id| { + debug!("Retrieving entry for id: '{:?}'", id); + self.1 + .retrieve(id.clone()) + .map_dbg_err(|_| format!("Retrieving entry for id: '{:?}' failed", id)) + .map_err(From::from) + .and_then(|f| { + debug!("Store::retrieve({:?}) succeeded", id); + debug!("getting external link from file now"); + f.get_link_uri_from_filelockentry() + .map_dbg_str("Error happened while getting link URI from FLE") + .map_dbg_err(|e| format!("URL -> Err = {:?}", e)) + }) + }); + + match next { + Some(Ok(Some(link))) => return Some(Ok(link)), + Some(Ok(None)) => continue, + Some(Err(e)) => return Some(Err(e)), + None => return None + } + } + } + +} + + diff --git a/lib/entry/libimagentryurl/src/lib.rs b/lib/entry/libimagentryurl/src/lib.rs index 31e1bb20..7d08ba14 100644 --- a/lib/entry/libimagentryurl/src/lib.rs +++ b/lib/entry/libimagentryurl/src/lib.rs @@ -1,7 +1,74 @@ +// +// 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 +// + +#![forbid(unsafe_code)] + +#![deny( + dead_code, + 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, +)] + +//! External linking is a complex implementation to be able to serve a clean and easy-to-use +//! interface. +//! +//! Internally, there are no such things as "external links" (plural). Each Entry in the store can +//! only have _one_ external link. +//! +//! This library does the following therefor: It allows you to have several external links with one +//! entry, which are internally one file in the store for each link, linked with "internal +//! linking". +//! +//! This helps us greatly with deduplication of URLs. +//! + +extern crate itertools; +#[macro_use] extern crate log; +extern crate toml; +extern crate toml_query; +extern crate url; +extern crate sha1; +extern crate hex; +#[macro_use] extern crate failure; + #[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } -} +extern crate env_logger; + +#[macro_use] extern crate libimagstore; +extern crate libimagerror; +extern crate libimagutil; +extern crate libimagentrylink; + +module_entry_path_mod!("url"); + +pub mod iter; +pub mod link; +pub mod linker; +pub mod util; + diff --git a/lib/entry/libimagentryurl/src/link.rs b/lib/entry/libimagentryurl/src/link.rs new file mode 100644 index 00000000..60f0bf88 --- /dev/null +++ b/lib/entry/libimagentryurl/src/link.rs @@ -0,0 +1,76 @@ +// +// 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 +// + +use failure::Error; +use failure::ResultExt; +use failure::Fallible as Result; +use failure::err_msg; +use url::Url; + +use libimagstore::store::Entry; +use libimagerror::errors::ErrorMsg as EM; + +use toml_query::read::TomlValueReadTypeExt; + +pub trait Link { + + fn get_link_uri_from_filelockentry(&self) -> Result>; + + fn get_url(&self) -> Result>; + +} + +impl Link for Entry { + + fn get_link_uri_from_filelockentry(&self) -> Result> { + self.get_header() + .read_string("links.external.content.url") + .context(format_err!("Error reading header 'links.external.content.url' from '{}'", self.get_location())) + .context(EM::EntryHeaderReadError) + .map_err(Error::from) + .and_then(|opt| match opt { + None => Ok(None), + Some(ref s) => { + debug!("Found url, parsing: {:?}", s); + Url::parse(&s[..]) + .map_err(Error::from) + .context(format_err!("Failed to parse URL: '{}'", s)) + .context(err_msg("Invalid URI")) + .map_err(Error::from) + .map(Some) + }, + }) + .context("Failed to get link URI from entry") + .map_err(Error::from) + } + + fn get_url(&self) -> Result> { + match self.get_header().read_string("links.external.url")? { + None => Ok(None), + Some(ref s) => Url::parse(&s[..]) + .context(format_err!("Failed to parse URL: '{}'", s)) + .map(Some) + .map_err(Error::from) + .context(EM::EntryHeaderReadError) + .map_err(Error::from), + } + } + +} + diff --git a/lib/entry/libimagentrylink/src/external.rs b/lib/entry/libimagentryurl/src/linker.rs similarity index 50% rename from lib/entry/libimagentrylink/src/external.rs rename to lib/entry/libimagentryurl/src/linker.rs index 95398785..8e409743 100644 --- a/lib/entry/libimagentrylink/src/external.rs +++ b/lib/entry/libimagentryurl/src/linker.rs @@ -17,93 +17,26 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -/// External linking is a complex implementation to be able to serve a clean and easy-to-use -/// interface. -/// -/// Internally, there are no such things as "external links" (plural). Each Entry in the store can -/// only have _one_ external link. -/// -/// This library does the following therefor: It allows you to have several external links with one -/// entry, which are internally one file in the store for each link, linked with "internal -/// linking". -/// -/// This helps us greatly with deduplication of URLs. -/// - use std::ops::DerefMut; -use std::fmt::Debug; -use libimagstore::store::Entry; -use libimagstore::store::Store; use libimagstore::storeid::StoreId; -use libimagutil::debug_result::*; -use libimagerror::errors::ErrorMsg as EM; +use libimagstore::store::Store; +use libimagstore::store::Entry; +use libimagutil::debug_result::DebugResult; +use libimagentrylink::internal::InternalLinker; -use toml_query::read::TomlValueReadExt; -use toml_query::read::TomlValueReadTypeExt; -use toml_query::insert::TomlValueInsertExt; -use toml::map::Map; -use failure::Error; use failure::Fallible as Result; -use failure::ResultExt; -use failure::err_msg; - -use crate::internal::InternalLinker; - -use self::iter::*; - use toml::Value; +use toml::map::Map; +use toml_query::read::TomlValueReadExt; +use toml_query::insert::TomlValueInsertExt; use url::Url; use sha1::{Sha1, Digest}; use hex; -pub trait Link { +use crate::iter::UrlIter; - fn get_link_uri_from_filelockentry(&self) -> Result>; - - fn get_url(&self) -> Result>; - -} - -impl Link for Entry { - - fn get_link_uri_from_filelockentry(&self) -> Result> { - self.get_header() - .read_string("links.external.content.url") - .context(format_err!("Error reading header 'links.external.content.url' from '{}'", self.get_location())) - .context(EM::EntryHeaderReadError) - .map_err(Error::from) - .and_then(|opt| match opt { - None => Ok(None), - Some(ref s) => { - debug!("Found url, parsing: {:?}", s); - Url::parse(&s[..]) - .map_err(Error::from) - .context(format_err!("Failed to parse URL: '{}'", s)) - .context(err_msg("Invalid URI")) - .map_err(Error::from) - .map(Some) - }, - }) - .context("Failed to get link URI from entry") - .map_err(Error::from) - } - - fn get_url(&self) -> Result> { - match self.get_header().read_string("links.external.url")? { - None => Ok(None), - Some(ref s) => Url::parse(&s[..]) - .context(format_err!("Failed to parse URL: '{}'", s)) - .map(Some) - .map_err(Error::from) - .context(EM::EntryHeaderReadError) - .map_err(Error::from), - } - } - -} - -pub trait ExternalLinker : InternalLinker { +pub trait UrlLinker : InternalLinker { /// Get the external links from the implementor object fn get_external_links<'a>(&self, store: &'a Store) -> Result>; @@ -119,199 +52,15 @@ pub trait ExternalLinker : InternalLinker { } -pub mod iter { - //! Iterator helpers for external linking stuff - //! - //! Contains also helpers to filter iterators for external/internal links - //! - //! - //! # Warning - //! - //! This module uses `internal::Link` as link type, so we operate on _store ids_ here. - //! - //! Not to confuse with `external::Link` which is a real `FileLockEntry` under the hood. - //! - - use libimagutil::debug_result::*; - use libimagstore::store::Store; - - use crate::internal::Link; - use crate::internal::iter::LinkIter; - use failure::Fallible as Result; - - use url::Url; - - /// Helper for building `OnlyExternalIter` and `NoExternalIter` - /// - /// The boolean value defines, how to interpret the `is_external_link_storeid()` return value - /// (here as "pred"): - /// - /// ```ignore - /// pred | bool | xor | take? - /// ---- | ---- | --- | ---- - /// 0 | 0 | 0 | 1 - /// 0 | 1 | 1 | 0 - /// 1 | 0 | 1 | 0 - /// 1 | 1 | 0 | 1 - /// ``` - /// - /// If `bool` says "take if return value is false", we take the element if the `pred` returns - /// false... and so on. - /// - /// As we can see, the operator between these two operants is `!(a ^ b)`. - pub struct ExternalFilterIter(LinkIter, bool); - - impl Iterator for ExternalFilterIter { - type Item = Link; - - fn next(&mut self) -> Option { - use super::is_external_link_storeid; - - while let Some(elem) = self.0.next() { - trace!("Check whether is external: {:?}", elem); - if !(self.1 ^ is_external_link_storeid(&elem)) { - trace!("Is external id: {:?}", elem); - return Some(elem); - } - } - None - } - } - - /// Helper trait to be implemented on `LinkIter` to select or deselect all external links - /// - /// # See also - /// - /// Also see `OnlyExternalIter` and `NoExternalIter` and the helper traits/functions - /// `OnlyInteralLinks`/`only_internal_links()` and `OnlyExternalLinks`/`only_external_links()`. - pub trait SelectExternal { - fn select_external_links(self, b: bool) -> ExternalFilterIter; - } - - impl SelectExternal for LinkIter { - fn select_external_links(self, b: bool) -> ExternalFilterIter { - ExternalFilterIter(self, b) - } - } - - - pub struct OnlyExternalIter(ExternalFilterIter); - - impl OnlyExternalIter { - pub fn new(li: LinkIter) -> OnlyExternalIter { - OnlyExternalIter(ExternalFilterIter(li, true)) - } - - pub fn urls<'a>(self, store: &'a Store) -> UrlIter<'a> { - UrlIter(self, store) - } - } - - impl Iterator for OnlyExternalIter { - type Item = Link; - - fn next(&mut self) -> Option { - self.0.next() - } - } - - pub struct NoExternalIter(ExternalFilterIter); - - impl NoExternalIter { - pub fn new(li: LinkIter) -> NoExternalIter { - NoExternalIter(ExternalFilterIter(li, false)) - } - } - - impl Iterator for NoExternalIter { - type Item = Link; - - fn next(&mut self) -> Option { - self.0.next() - } - } - - pub trait OnlyExternalLinks : Sized { - fn only_external_links(self) -> OnlyExternalIter ; - - fn no_internal_links(self) -> OnlyExternalIter { - self.only_external_links() - } - } - - impl OnlyExternalLinks for LinkIter { - fn only_external_links(self) -> OnlyExternalIter { - OnlyExternalIter::new(self) - } - } - - pub trait OnlyInternalLinks : Sized { - fn only_internal_links(self) -> NoExternalIter; - - fn no_external_links(self) -> NoExternalIter { - self.only_internal_links() - } - } - - impl OnlyInternalLinks for LinkIter { - fn only_internal_links(self) -> NoExternalIter { - NoExternalIter::new(self) - } - } - - pub struct UrlIter<'a>(OnlyExternalIter, &'a Store); - - impl<'a> Iterator for UrlIter<'a> { - type Item = Result; - - fn next(&mut self) -> Option { - use crate::external::Link; - - loop { - let next = self.0 - .next() - .map(|id| { - debug!("Retrieving entry for id: '{:?}'", id); - self.1 - .retrieve(id.clone()) - .map_dbg_err(|_| format!("Retrieving entry for id: '{:?}' failed", id)) - .map_err(From::from) - .and_then(|f| { - debug!("Store::retrieve({:?}) succeeded", id); - debug!("getting external link from file now"); - f.get_link_uri_from_filelockentry() - .map_dbg_str("Error happened while getting link URI from FLE") - .map_dbg_err(|e| format!("URL -> Err = {:?}", e)) - }) - }); - - match next { - Some(Ok(Some(link))) => return Some(Ok(link)), - Some(Ok(None)) => continue, - Some(Err(e)) => return Some(Err(e)), - None => return None - } - } - } - - } - -} - - -/// Check whether the StoreId starts with `/link/external/` -pub fn is_external_link_storeid + Debug>(id: A) -> bool { - debug!("Checking whether this is a 'links/external/': '{:?}'", id); - id.as_ref().is_in_collection(&["links", "external"]) -} - /// Implement `ExternalLinker` for `Entry`, hiding the fact that there is no such thing as an external /// link in an entry, but internal links to other entries which serve as external links, as one /// entry in the store can only have one external link. -impl ExternalLinker for Entry { +impl UrlLinker for Entry { /// Get the external links from the implementor object fn get_external_links<'a>(&self, store: &'a Store) -> Result> { + use crate::iter::OnlyExternalLinks; + // Iterate through all internal links and filter for FileLockEntries which live in // /link/external/ -> load these files and get the external link from their headers, // put them into the return vector. @@ -473,4 +222,3 @@ mod tests { } } - diff --git a/lib/entry/libimagentryurl/src/util.rs b/lib/entry/libimagentryurl/src/util.rs new file mode 100644 index 00000000..48d02fff --- /dev/null +++ b/lib/entry/libimagentryurl/src/util.rs @@ -0,0 +1,28 @@ +// +// 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 +// + +use std::fmt::Debug; + +use libimagstore::storeid::StoreId; + +/// Check whether the StoreId starts with `/link/external/` +pub fn is_external_link_storeid + Debug>(id: A) -> bool { + debug!("Checking whether this is a 'url/external/': '{:?}'", id); + id.as_ref().is_in_collection(&["url", "external"]) +} From c33c29e8e25812c77010dd140c49b3d48aa675af Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 29 May 2019 18:06:12 +0200 Subject: [PATCH 03/11] Fix import for new libimagentryurl lib Signed-off-by: Matthias Beyer --- bin/core/imag-link/src/main.rs | 2 +- lib/domain/libimagbookmark/src/collection.rs | 4 ++-- lib/entry/libimagentrymarkdown/src/processor.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/core/imag-link/src/main.rs b/bin/core/imag-link/src/main.rs index 3e12f1c0..614a18f9 100644 --- a/bin/core/imag-link/src/main.rs +++ b/bin/core/imag-link/src/main.rs @@ -61,7 +61,7 @@ use std::path::PathBuf; use failure::Error; use failure::err_msg; -use libimagentrylink::external::ExternalLinker; +use libimagentryurl::linker::UrlLinker; use libimagentrylink::internal::InternalLinker; use libimagentrylink::internal::store_check::StoreLinkConsistentExt; use libimagerror::trace::{MapErrTrace, trace_error}; diff --git a/lib/domain/libimagbookmark/src/collection.rs b/lib/domain/libimagbookmark/src/collection.rs index 19f10f64..65890483 100644 --- a/lib/domain/libimagbookmark/src/collection.rs +++ b/lib/domain/libimagbookmark/src/collection.rs @@ -20,7 +20,7 @@ //! BookmarkCollection module //! //! A BookmarkCollection is nothing more than a simple store entry. One can simply call functions -//! from the libimagentrylink::external::ExternalLinker trait on this to generate external links. +//! from the libimagentryurl::linker::UrlLinker trait on this to generate external links. //! //! The BookmarkCollection type offers helper functions to get all links or such things. @@ -34,7 +34,7 @@ use libimagstore::store::Store; use libimagstore::store::Entry; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreId; -use libimagentrylink::external::ExternalLinker; +use libimagentryurl::linker::UrlLinker; use libimagentrylink::external::iter::UrlIter; use libimagentrylink::internal::InternalLinker; use libimagentrylink::internal::Link as StoreLink; diff --git a/lib/entry/libimagentrymarkdown/src/processor.rs b/lib/entry/libimagentrymarkdown/src/processor.rs index 87f03ad7..9562c449 100644 --- a/lib/entry/libimagentrymarkdown/src/processor.rs +++ b/lib/entry/libimagentrymarkdown/src/processor.rs @@ -24,7 +24,7 @@ use failure::ResultExt; use failure::Error; use crate::link::extract_links; -use libimagentrylink::external::ExternalLinker; +use libimagentryurl::linker::UrlLinker; use libimagentrylink::internal::InternalLinker; use libimagentryref::reference::MutRef; use libimagentryref::reference::RefFassade; From 8a5bc09b62ed7a91e5a60e12fa68cba92395d2c8 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 30 May 2019 10:30:24 +0200 Subject: [PATCH 04/11] Fix libimagbookmark for new url library --- lib/domain/libimagbookmark/Cargo.toml | 1 + lib/domain/libimagbookmark/src/collection.rs | 12 ++++++------ lib/domain/libimagbookmark/src/lib.rs | 1 + 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/domain/libimagbookmark/Cargo.toml b/lib/domain/libimagbookmark/Cargo.toml index cd2aaa9e..f351fa5c 100644 --- a/lib/domain/libimagbookmark/Cargo.toml +++ b/lib/domain/libimagbookmark/Cargo.toml @@ -27,4 +27,5 @@ failure = "0.1" libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" } libimagentrylink = { version = "0.10.0", path = "../../../lib/entry/libimagentrylink" } +libimagentryurl = { version = "0.10.0", path = "../../../lib/entry/libimagentryurl" } diff --git a/lib/domain/libimagbookmark/src/collection.rs b/lib/domain/libimagbookmark/src/collection.rs index 65890483..6647a261 100644 --- a/lib/domain/libimagbookmark/src/collection.rs +++ b/lib/domain/libimagbookmark/src/collection.rs @@ -35,7 +35,7 @@ use libimagstore::store::Entry; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreId; use libimagentryurl::linker::UrlLinker; -use libimagentrylink::external::iter::UrlIter; +use libimagentryurl::iter::UrlIter; use libimagentrylink::internal::InternalLinker; use libimagentrylink::internal::Link as StoreLink; @@ -80,7 +80,7 @@ impl<'a> BookmarkCollectionStore<'a> for Store { } -pub trait BookmarkCollection : Sized + InternalLinker + ExternalLinker { +pub trait BookmarkCollection : Sized + InternalLinker + UrlLinker { fn links<'a>(&self, store: &'a Store) -> Result>; fn link_entries(&self) -> Result>; fn add_link(&mut self, store: &Store, l: Link) -> Result>; @@ -95,7 +95,7 @@ impl BookmarkCollection for Entry { } fn link_entries(&self) -> Result> { - use libimagentrylink::external::is_external_link_storeid; + use libimagentryurl::util::is_external_link_storeid; self.get_internal_links().map(|v| v.filter(|id| is_external_link_storeid(id)).collect()) } @@ -120,6 +120,9 @@ pub mod iter { use crate::link::Link; use failure::Fallible as Result; use failure::Error; + use regex::Regex; + + use libimagentryurl::iter::UrlIter; pub struct LinkIter(I) where I: Iterator; @@ -144,9 +147,6 @@ pub mod iter { } } - use libimagentrylink::external::iter::UrlIter; - use regex::Regex; - pub struct LinksMatchingRegexIter<'a>(UrlIter<'a>, Regex); impl<'a> LinksMatchingRegexIter<'a> { diff --git a/lib/domain/libimagbookmark/src/lib.rs b/lib/domain/libimagbookmark/src/lib.rs index 6072070c..c8b2c59c 100644 --- a/lib/domain/libimagbookmark/src/lib.rs +++ b/lib/domain/libimagbookmark/src/lib.rs @@ -44,6 +44,7 @@ extern crate regex; #[macro_use] extern crate libimagstore; extern crate libimagerror; extern crate libimagentrylink; +extern crate libimagentryurl; module_entry_path_mod!("bookmark"); From 8b66672772511f1f3d8c036619fa03069cc2ad2f Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 30 May 2019 10:32:12 +0200 Subject: [PATCH 05/11] Fix libimagentrymarkdown for new url lib --- lib/entry/libimagentrymarkdown/Cargo.toml | 1 + lib/entry/libimagentrymarkdown/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/entry/libimagentrymarkdown/Cargo.toml b/lib/entry/libimagentrymarkdown/Cargo.toml index cf082a03..bcd97a5c 100644 --- a/lib/entry/libimagentrymarkdown/Cargo.toml +++ b/lib/entry/libimagentrymarkdown/Cargo.toml @@ -30,6 +30,7 @@ sha-1 = "0.8" libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" } libimagentrylink = { version = "0.10.0", path = "../../../lib/entry/libimagentrylink/" } +libimagentryurl = { version = "0.10.0", path = "../../../lib/entry/libimagentryurl/" } libimagentryref = { version = "0.10.0", path = "../../../lib/entry/libimagentryref/" } libimagutil = { version = "0.10.0", path = "../../../lib/etc/libimagutil/" } diff --git a/lib/entry/libimagentrymarkdown/src/lib.rs b/lib/entry/libimagentrymarkdown/src/lib.rs index 8eedff8d..0a8f0b9b 100644 --- a/lib/entry/libimagentrymarkdown/src/lib.rs +++ b/lib/entry/libimagentrymarkdown/src/lib.rs @@ -42,6 +42,7 @@ extern crate url; extern crate libimagstore; extern crate libimagerror; extern crate libimagentrylink; +extern crate libimagentryurl; extern crate libimagentryref; extern crate libimagutil; #[macro_use] extern crate failure; From 14ea375ca472dd8941bcfa502198479d080cd2cb Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 30 May 2019 10:32:24 +0200 Subject: [PATCH 06/11] Fix imag-link for new url library --- bin/core/imag-link/Cargo.toml | 1 + bin/core/imag-link/src/main.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/bin/core/imag-link/Cargo.toml b/bin/core/imag-link/Cargo.toml index e2caf2fa..be2fa058 100644 --- a/bin/core/imag-link/Cargo.toml +++ b/bin/core/imag-link/Cargo.toml @@ -31,6 +31,7 @@ libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" } libimagentrylink = { version = "0.10.0", path = "../../../lib/entry/libimagentrylink" } +libimagentryurl = { version = "0.10.0", path = "../../../lib/entry/libimagentryurl" } libimagutil = { version = "0.10.0", path = "../../../lib/etc/libimagutil" } [dependencies.clap] diff --git a/bin/core/imag-link/src/main.rs b/bin/core/imag-link/src/main.rs index 614a18f9..a8408178 100644 --- a/bin/core/imag-link/src/main.rs +++ b/bin/core/imag-link/src/main.rs @@ -44,6 +44,7 @@ extern crate failure; #[cfg(test)] extern crate env_logger; extern crate libimagentrylink; +extern crate libimagentryurl; #[macro_use] extern crate libimagrt; extern crate libimagstore; extern crate libimagerror; From 7f2e4c8442c334142cff7edb80b4d35bbf712113 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 30 May 2019 10:57:22 +0200 Subject: [PATCH 07/11] Adapt tested path --- lib/entry/libimagentrymarkdown/src/processor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/entry/libimagentrymarkdown/src/processor.rs b/lib/entry/libimagentrymarkdown/src/processor.rs index 9562c449..060a95bc 100644 --- a/lib/entry/libimagentrymarkdown/src/processor.rs +++ b/lib/entry/libimagentrymarkdown/src/processor.rs @@ -438,7 +438,7 @@ mod tests { assert!(result.is_ok(), "Should be Ok(()): {:?}", result); // The hash of "http://example.com" processed in the `libimagentrylink` way. - let expected_link = "links/external/9c17e047f58f9220a7008d4f18152fee4d111d14"; + let expected_link = "url/external/9c17e047f58f9220a7008d4f18152fee4d111d14"; { let base_links = base.get_internal_links(); assert!(base_links.is_ok()); From d2a5e8fb59b2f8a780d0ead752c38853ece7380f Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 30 May 2019 11:00:43 +0200 Subject: [PATCH 08/11] Rename functions: *_external_link -> *_url Signed-off-by: Matthias Beyer --- bin/core/imag-link/src/main.rs | 6 ++-- lib/domain/libimagbookmark/src/collection.rs | 8 ++--- lib/domain/libimagwiki/src/entry.rs | 2 +- .../libimagentrymarkdown/src/processor.rs | 32 ++++++++--------- lib/entry/libimagentryurl/src/iter.rs | 14 ++++---- lib/entry/libimagentryurl/src/linker.rs | 36 +++++++++---------- 6 files changed, 49 insertions(+), 49 deletions(-) diff --git a/bin/core/imag-link/src/main.rs b/bin/core/imag-link/src/main.rs index a8408178..226b3a43 100644 --- a/bin/core/imag-link/src/main.rs +++ b/bin/core/imag-link/src/main.rs @@ -158,7 +158,7 @@ fn link_from_to<'a, I>(rt: &'a Runtime, from: &'a str, to: I) }); let iter = from_entry - .add_external_link(rt.store(), url) + .add_url(rt.store(), url) .map_err_trace_exit_unwrap() .into_iter(); @@ -239,7 +239,7 @@ fn remove_linking(rt: &Runtime) { error!("Error parsing URL: {:?}", e); ::std::process::exit(1); }); - from.remove_external_link(rt.store(), url).map_err_trace_exit_unwrap(); + from.remove_url(rt.store(), url).map_err_trace_exit_unwrap(); info!("Ok: {}", id); } else { warn!("Entry not found: {:?}", id); @@ -314,7 +314,7 @@ fn list_linkings(rt: &Runtime) { } if list_externals { - entry.get_external_links(rt.store()) + entry.get_urls(rt.store()) .map_err_trace_exit_unwrap() .enumerate() .for_each(|(i, link)| { diff --git a/lib/domain/libimagbookmark/src/collection.rs b/lib/domain/libimagbookmark/src/collection.rs index 6647a261..ec70a6c6 100644 --- a/lib/domain/libimagbookmark/src/collection.rs +++ b/lib/domain/libimagbookmark/src/collection.rs @@ -91,7 +91,7 @@ pub trait BookmarkCollection : Sized + InternalLinker + UrlLinker { impl BookmarkCollection for Entry { fn links<'a>(&self, store: &'a Store) -> Result> { - self.get_external_links(store) + self.get_urls(store) } fn link_entries(&self) -> Result> { @@ -101,17 +101,17 @@ impl BookmarkCollection for Entry { fn add_link(&mut self, store: &Store, l: Link) -> Result> { use crate::link::IntoUrl; - l.into_url().and_then(|url| self.add_external_link(store, url)) + l.into_url().and_then(|url| self.add_url(store, url)) } fn get_links_matching<'a>(&self, store: &'a Store, r: Regex) -> Result> { use self::iter::IntoLinksMatchingRegexIter; - self.get_external_links(store).map(|iter| iter.matching_regex(r)) + self.get_urls(store).map(|iter| iter.matching_regex(r)) } fn remove_link(&mut self, store: &Store, l: Link) -> Result> { use crate::link::IntoUrl; - l.into_url().and_then(|url| self.remove_external_link(store, url)) + l.into_url().and_then(|url| self.remove_url(store, url)) } } diff --git a/lib/domain/libimagwiki/src/entry.rs b/lib/domain/libimagwiki/src/entry.rs index 2619a943..9ced2299 100644 --- a/lib/domain/libimagwiki/src/entry.rs +++ b/lib/domain/libimagwiki/src/entry.rs @@ -57,7 +57,7 @@ impl WikiEntry for Entry { let processor = LinkProcessor::default() .process_internal_links(true) .create_internal_targets(true) - .process_external_links(true) + .process_urls(true) .process_refs(true); self.autolink_with_processor(store, processor) diff --git a/lib/entry/libimagentrymarkdown/src/processor.rs b/lib/entry/libimagentrymarkdown/src/processor.rs index 060a95bc..f61ea92b 100644 --- a/lib/entry/libimagentrymarkdown/src/processor.rs +++ b/lib/entry/libimagentrymarkdown/src/processor.rs @@ -58,7 +58,7 @@ use url::Url; pub struct LinkProcessor { process_internal_links: bool, create_internal_targets: bool, - process_external_links: bool, + process_urls: bool, process_refs: bool } @@ -86,8 +86,8 @@ impl LinkProcessor { /// Switch external link processing on/off /// /// An external link must start with `https://` or `http://`. - pub fn process_external_links(mut self, b: bool) -> Self { - self.process_external_links = b; + pub fn process_urls(mut self, b: bool) -> Self { + self.process_urls = b; self } @@ -154,11 +154,11 @@ impl LinkProcessor { let _ = entry.add_internal_link(&mut target)?; }, LinkQualification::ExternalLink(url) => { - if !self.process_external_links { + if !self.process_urls { continue } - entry.add_external_link(store, url)?; + entry.add_url(store, url)?; }, LinkQualification::RefLink(url) => { use sha1::{Sha1, Digest}; @@ -273,7 +273,7 @@ impl Default for LinkProcessor { LinkProcessor { process_internal_links: true, create_internal_targets: false, - process_external_links: true, + process_urls: true, process_refs: false } } @@ -330,7 +330,7 @@ mod tests { let processor = LinkProcessor::default() .process_internal_links(true) .create_internal_targets(false) - .process_external_links(false) + .process_urls(false) .process_refs(false); let result = processor.process(&mut base, &store); @@ -370,7 +370,7 @@ mod tests { let processor = LinkProcessor::default() .process_internal_links(true) .create_internal_targets(false) - .process_external_links(false) + .process_urls(false) .process_refs(false); let result = processor.process(&mut base, &store); @@ -391,7 +391,7 @@ mod tests { let processor = LinkProcessor::default() .process_internal_links(true) .create_internal_targets(true) - .process_external_links(false) + .process_urls(false) .process_refs(false); let result = processor.process(&mut base, &store); @@ -418,7 +418,7 @@ mod tests { } #[test] - fn test_process_one_external_link() { + fn test_process_one_url() { setup_logging(); let store = get_store(); @@ -431,7 +431,7 @@ mod tests { let processor = LinkProcessor::default() .process_internal_links(true) .create_internal_targets(true) - .process_external_links(true) + .process_urls(true) .process_refs(false); let result = processor.process(&mut base, &store); @@ -481,7 +481,7 @@ mod tests { let processor = LinkProcessor::default() .process_internal_links(false) .create_internal_targets(false) - .process_external_links(false) + .process_urls(false) .process_refs(true); let result = processor.process(&mut base, &store); @@ -514,7 +514,7 @@ mod tests { let processor = LinkProcessor::default() .process_internal_links(false) .create_internal_targets(false) - .process_external_links(false) + .process_urls(false) .process_refs(true); let result = processor.process(&mut base, &store); @@ -547,7 +547,7 @@ mod tests { let processor = LinkProcessor::default() .process_internal_links(false) .create_internal_targets(false) - .process_external_links(false) + .process_urls(false) .process_refs(false); let result = processor.process(&mut base, &store); @@ -575,7 +575,7 @@ mod tests { let processor = LinkProcessor::default() .process_internal_links(true) .create_internal_targets(true) - .process_external_links(false) + .process_urls(false) .process_refs(false); let result = processor.process(&mut base, &store); @@ -605,7 +605,7 @@ mod tests { let processor = LinkProcessor::default() .process_internal_links(false) .create_internal_targets(false) - .process_external_links(false) + .process_urls(false) .process_refs(false); let result = processor.process(&mut base, &store); diff --git a/lib/entry/libimagentryurl/src/iter.rs b/lib/entry/libimagentryurl/src/iter.rs index f5ef6ed0..ea492ec8 100644 --- a/lib/entry/libimagentryurl/src/iter.rs +++ b/lib/entry/libimagentryurl/src/iter.rs @@ -79,13 +79,13 @@ impl Iterator for ExternalFilterIter { /// # See also /// /// Also see `OnlyExternalIter` and `NoExternalIter` and the helper traits/functions -/// `OnlyInteralLinks`/`only_internal_links()` and `OnlyExternalLinks`/`only_external_links()`. +/// `OnlyInteralLinks`/`only_internal_links()` and `OnlyExternalLinks`/`only_urls()`. pub trait SelectExternal { - fn select_external_links(self, b: bool) -> ExternalFilterIter; + fn select_urls(self, b: bool) -> ExternalFilterIter; } impl SelectExternal for LinkIter { - fn select_external_links(self, b: bool) -> ExternalFilterIter { + fn select_urls(self, b: bool) -> ExternalFilterIter { ExternalFilterIter(self, b) } } @@ -128,15 +128,15 @@ impl Iterator for NoExternalIter { } pub trait OnlyExternalLinks : Sized { - fn only_external_links(self) -> OnlyExternalIter ; + fn only_urls(self) -> OnlyExternalIter ; fn no_internal_links(self) -> OnlyExternalIter { - self.only_external_links() + self.only_urls() } } impl OnlyExternalLinks for LinkIter { - fn only_external_links(self) -> OnlyExternalIter { + fn only_urls(self) -> OnlyExternalIter { OnlyExternalIter::new(self) } } @@ -144,7 +144,7 @@ impl OnlyExternalLinks for LinkIter { pub trait OnlyInternalLinks : Sized { fn only_internal_links(self) -> NoExternalIter; - fn no_external_links(self) -> NoExternalIter { + fn no_urls(self) -> NoExternalIter { self.only_internal_links() } } diff --git a/lib/entry/libimagentryurl/src/linker.rs b/lib/entry/libimagentryurl/src/linker.rs index 8e409743..fdc0b9b9 100644 --- a/lib/entry/libimagentryurl/src/linker.rs +++ b/lib/entry/libimagentryurl/src/linker.rs @@ -39,16 +39,16 @@ use crate::iter::UrlIter; pub trait UrlLinker : InternalLinker { /// Get the external links from the implementor object - fn get_external_links<'a>(&self, store: &'a Store) -> Result>; + fn get_urls<'a>(&self, store: &'a Store) -> Result>; /// Set the external links for the implementor object - fn set_external_links(&mut self, store: &Store, links: Vec) -> Result>; + fn set_urls(&mut self, store: &Store, links: Vec) -> Result>; /// Add an external link to the implementor object - fn add_external_link(&mut self, store: &Store, link: Url) -> Result>; + fn add_url(&mut self, store: &Store, link: Url) -> Result>; /// Remove an external link from the implementor object - fn remove_external_link(&mut self, store: &Store, link: Url) -> Result>; + fn remove_url(&mut self, store: &Store, link: Url) -> Result>; } @@ -58,7 +58,7 @@ pub trait UrlLinker : InternalLinker { impl UrlLinker for Entry { /// Get the external links from the implementor object - fn get_external_links<'a>(&self, store: &'a Store) -> Result> { + fn get_urls<'a>(&self, store: &'a Store) -> Result> { use crate::iter::OnlyExternalLinks; // Iterate through all internal links and filter for FileLockEntries which live in @@ -67,7 +67,7 @@ impl UrlLinker for Entry { self.get_internal_links() .map(|iter| { debug!("Getting external links"); - iter.only_external_links().urls(store) + iter.only_urls().urls(store) }) } @@ -79,7 +79,7 @@ impl UrlLinker for Entry { /// external links than before. /// If there are less external links than before, an empty vec![] is returned. /// - fn set_external_links(&mut self, store: &Store, links: Vec) -> Result> { + fn set_urls(&mut self, store: &Store, links: Vec) -> Result> { // Take all the links, generate a SHA sum out of each one, filter out the already existing // store entries and store the other URIs in the header of one FileLockEntry each, in // the path /link/external/ @@ -146,16 +146,16 @@ impl UrlLinker for Entry { /// /// # Return Value /// - /// (See ExternalLinker::set_external_links()) + /// (See ExternalLinker::set_urls()) /// /// Returns the StoreIds which were newly created for the new external links, if there are more /// external links than before. /// If there are less external links than before, an empty vec![] is returned. /// - fn add_external_link(&mut self, store: &Store, link: Url) -> Result> { + fn add_url(&mut self, store: &Store, link: Url) -> Result> { // get external links, add this one, save them debug!("Getting links"); - self.get_external_links(store) + self.get_urls(store) .and_then(|links| { let mut links = links.collect::>>()?; @@ -163,7 +163,7 @@ impl UrlLinker for Entry { links.push(link); debug!("Setting {} links = {:?}", links.len(), links); - self.set_external_links(store, links) + self.set_urls(store, links) }) } @@ -171,22 +171,22 @@ impl UrlLinker for Entry { /// /// # Return Value /// - /// (See ExternalLinker::set_external_links()) + /// (See ExternalLinker::set_urls()) /// /// Returns the StoreIds which were newly created for the new external links, if there are more /// external links than before. /// If there are less external links than before, an empty vec![] is returned. /// - fn remove_external_link(&mut self, store: &Store, link: Url) -> Result> { + fn remove_url(&mut self, store: &Store, link: Url) -> Result> { // get external links, remove this one, save them - self.get_external_links(store) + self.get_urls(store) .and_then(|links| { debug!("Removing link = '{:?}'", link); let links = links .filter_map(Result::ok) .filter(|l| l.as_str() != link.as_str()) .collect::>(); - self.set_external_links(store, links) + self.set_urls(store, links) }) } @@ -215,10 +215,10 @@ mod tests { let mut e = store.retrieve(PathBuf::from("base-test_simple")).unwrap(); let url = Url::parse("http://google.de").unwrap(); - assert!(e.add_external_link(&store, url.clone()).is_ok()); + assert!(e.add_url(&store, url.clone()).is_ok()); - assert_eq!(1, e.get_external_links(&store).unwrap().count()); - assert_eq!(url, e.get_external_links(&store).unwrap().next().unwrap().unwrap()); + assert_eq!(1, e.get_urls(&store).unwrap().count()); + assert_eq!(url, e.get_urls(&store).unwrap().next().unwrap().unwrap()); } } From d02d53594e8b95786f4cff93aab3c87132889bf3 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 30 May 2019 11:35:42 +0200 Subject: [PATCH 09/11] Fix debug output message --- lib/entry/libimagentryurl/src/linker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/entry/libimagentryurl/src/linker.rs b/lib/entry/libimagentryurl/src/linker.rs index fdc0b9b9..f4095069 100644 --- a/lib/entry/libimagentryurl/src/linker.rs +++ b/lib/entry/libimagentryurl/src/linker.rs @@ -131,7 +131,7 @@ impl UrlLinker for Entry { // then add an internal link to the new file or return an error if this fails let _ = self.add_internal_link(file.deref_mut())?; - debug!("Error adding internal link"); + debug!("Added internal link"); Ok((link_already_exists, file_id)) }) From 901502b67efd885b2deb9ff1346808689e025f4c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 30 May 2019 17:54:48 +0200 Subject: [PATCH 10/11] Split "internal" module into several submodules Signed-off-by: Matthias Beyer --- bin/core/imag-annotate/src/main.rs | 2 +- bin/core/imag-diagnostics/src/main.rs | 2 +- bin/core/imag-link/src/main.rs | 4 +- bin/core/imag-mv/src/main.rs | 2 +- bin/domain/imag-bookmark/src/main.rs | 2 +- bin/domain/imag-wiki/src/main.rs | 2 +- lib/domain/libimagbookmark/src/collection.rs | 4 +- lib/domain/libimaghabit/src/habit.rs | 2 +- lib/domain/libimagwiki/src/wiki.rs | 2 +- .../src/annotateable.rs | 2 +- .../libimagentrycategory/src/category.rs | 2 +- lib/entry/libimagentrycategory/src/entry.rs | 2 +- lib/entry/libimagentrycategory/src/store.rs | 2 +- lib/entry/libimagentrylink/src/iter.rs | 97 +++++ lib/entry/libimagentrylink/src/lib.rs | 5 +- lib/entry/libimagentrylink/src/link.rs | 150 +++++++ .../src/{internal.rs => linker.rs} | 365 +----------------- lib/entry/libimagentrylink/src/storecheck.rs | 173 +++++++++ .../libimagentrymarkdown/src/processor.rs | 4 +- lib/entry/libimagentryurl/src/iter.rs | 4 +- lib/entry/libimagentryurl/src/linker.rs | 2 +- 21 files changed, 447 insertions(+), 383 deletions(-) create mode 100644 lib/entry/libimagentrylink/src/iter.rs create mode 100644 lib/entry/libimagentrylink/src/link.rs rename lib/entry/libimagentrylink/src/{internal.rs => linker.rs} (62%) create mode 100644 lib/entry/libimagentrylink/src/storecheck.rs diff --git a/bin/core/imag-annotate/src/main.rs b/bin/core/imag-annotate/src/main.rs index 5904b345..f86d71fa 100644 --- a/bin/core/imag-annotate/src/main.rs +++ b/bin/core/imag-annotate/src/main.rs @@ -66,7 +66,7 @@ use libimagrt::runtime::Runtime; use libimagrt::setup::generate_runtime_setup; use libimagstore::store::FileLockEntry; use libimagstore::iter::get::StoreIdGetIteratorExtension; -use libimagentrylink::internal::InternalLinker; +use libimagentrylink::linker::InternalLinker; mod ui; diff --git a/bin/core/imag-diagnostics/src/main.rs b/bin/core/imag-diagnostics/src/main.rs index 4414c1b8..5aa6844d 100644 --- a/bin/core/imag-diagnostics/src/main.rs +++ b/bin/core/imag-diagnostics/src/main.rs @@ -55,7 +55,7 @@ use libimagerror::io::ToExitCode; use libimagerror::exit::ExitUnwrap; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreId; -use libimagentrylink::internal::*; +use libimagentrylink::linker::InternalLinker; use toml::Value; use toml_query::read::TomlValueReadExt; diff --git a/bin/core/imag-link/src/main.rs b/bin/core/imag-link/src/main.rs index 226b3a43..df717015 100644 --- a/bin/core/imag-link/src/main.rs +++ b/bin/core/imag-link/src/main.rs @@ -63,8 +63,8 @@ use failure::Error; use failure::err_msg; use libimagentryurl::linker::UrlLinker; -use libimagentrylink::internal::InternalLinker; -use libimagentrylink::internal::store_check::StoreLinkConsistentExt; +use libimagentrylink::linker::InternalLinker; +use libimagentrylink::storecheck::StoreLinkConsistentExt; use libimagerror::trace::{MapErrTrace, trace_error}; use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; diff --git a/bin/core/imag-mv/src/main.rs b/bin/core/imag-mv/src/main.rs index 9f2fde74..9eca7b35 100644 --- a/bin/core/imag-mv/src/main.rs +++ b/bin/core/imag-mv/src/main.rs @@ -56,7 +56,7 @@ use libimagerror::exit::ExitUnwrap; use libimagstore::storeid::StoreId; use libimagstore::store::Store; use libimagstore::store::FileLockEntry; -use libimagentrylink::internal::InternalLinker; +use libimagentrylink::linker::InternalLinker; use libimagstore::iter::get::StoreIdGetIteratorExtension; fn main() { diff --git a/bin/domain/imag-bookmark/src/main.rs b/bin/domain/imag-bookmark/src/main.rs index b2eaa795..f15ceabe 100644 --- a/bin/domain/imag-bookmark/src/main.rs +++ b/bin/domain/imag-bookmark/src/main.rs @@ -61,7 +61,7 @@ use libimagerror::trace::{MapErrTrace, trace_error}; use libimagerror::io::ToExitCode; use libimagerror::exit::ExitUnwrap; use libimagutil::debug_result::DebugResult; -use libimagentrylink::internal::InternalLinker; +use libimagentrylink::linker::InternalLinker; mod ui; diff --git a/bin/domain/imag-wiki/src/main.rs b/bin/domain/imag-wiki/src/main.rs index 1556abbb..765a9e64 100644 --- a/bin/domain/imag-wiki/src/main.rs +++ b/bin/domain/imag-wiki/src/main.rs @@ -252,7 +252,7 @@ fn show(rt: &Runtime, wiki_name: &str) { } fn delete(rt: &Runtime, wiki_name: &str) { - use libimagentrylink::internal::InternalLinker; + use libimagentrylink::linker::InternalLinker; let scmd = rt.cli().subcommand_matches("delete").unwrap(); // safed by clap let name = String::from(scmd.value_of("delete-name").unwrap()); // safe by clap diff --git a/lib/domain/libimagbookmark/src/collection.rs b/lib/domain/libimagbookmark/src/collection.rs index ec70a6c6..3ebf8066 100644 --- a/lib/domain/libimagbookmark/src/collection.rs +++ b/lib/domain/libimagbookmark/src/collection.rs @@ -36,8 +36,8 @@ use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreId; use libimagentryurl::linker::UrlLinker; use libimagentryurl::iter::UrlIter; -use libimagentrylink::internal::InternalLinker; -use libimagentrylink::internal::Link as StoreLink; +use libimagentrylink::linker::InternalLinker; +use libimagentrylink::link::Link as StoreLink; use crate::link::Link; diff --git a/lib/domain/libimaghabit/src/habit.rs b/lib/domain/libimaghabit/src/habit.rs index 7041dff7..bd203189 100644 --- a/lib/domain/libimaghabit/src/habit.rs +++ b/lib/domain/libimaghabit/src/habit.rs @@ -33,7 +33,7 @@ use crate::util::IsHabitCheck; use crate::util::get_string_header_from_entry; use crate::instance::IsHabitInstance; -use libimagentrylink::internal::InternalLinker; +use libimagentrylink::linker::InternalLinker; use libimagstore::store::Store; use libimagstore::store::FileLockEntry; use libimagstore::store::Entry; diff --git a/lib/domain/libimagwiki/src/wiki.rs b/lib/domain/libimagwiki/src/wiki.rs index c61a6962..9cd3d236 100644 --- a/lib/domain/libimagwiki/src/wiki.rs +++ b/lib/domain/libimagwiki/src/wiki.rs @@ -22,7 +22,7 @@ use std::path::PathBuf; use libimagstore::store::Store; use libimagstore::store::FileLockEntry; use libimagstore::iter::Entries; -use libimagentrylink::internal::InternalLinker; +use libimagentrylink::linker::InternalLinker; use failure::Fallible as Result; use failure::Error; diff --git a/lib/entry/libimagentryannotation/src/annotateable.rs b/lib/entry/libimagentryannotation/src/annotateable.rs index 46b8cdbc..f89ca631 100644 --- a/lib/entry/libimagentryannotation/src/annotateable.rs +++ b/lib/entry/libimagentryannotation/src/annotateable.rs @@ -24,7 +24,7 @@ use libimagstore::store::Entry; use libimagstore::store::FileLockEntry; use libimagstore::store::Store; use libimagstore::storeid::StoreIdIterator; -use libimagentrylink::internal::InternalLinker; +use libimagentrylink::linker::InternalLinker; use libimagentryutil::isa::Is; use libimagentryutil::isa::IsKindHeaderPathProvider; diff --git a/lib/entry/libimagentrycategory/src/category.rs b/lib/entry/libimagentrycategory/src/category.rs index fb7268a7..f33a7ed5 100644 --- a/lib/entry/libimagentrycategory/src/category.rs +++ b/lib/entry/libimagentrycategory/src/category.rs @@ -22,7 +22,7 @@ use libimagentryutil::isa::IsKindHeaderPathProvider; use libimagstore::store::Entry; use libimagstore::store::Store; use libimagstore::storeid::StoreIdIterator; -use libimagentrylink::internal::InternalLinker; +use libimagentrylink::linker::InternalLinker; use toml_query::read::TomlValueReadTypeExt; diff --git a/lib/entry/libimagentrycategory/src/entry.rs b/lib/entry/libimagentrycategory/src/entry.rs index 9876add4..a9e39da0 100644 --- a/lib/entry/libimagentrycategory/src/entry.rs +++ b/lib/entry/libimagentrycategory/src/entry.rs @@ -23,7 +23,7 @@ use toml_query::read::TomlValueReadTypeExt; use toml::Value; use libimagstore::store::Entry; -use libimagentrylink::internal::InternalLinker; +use libimagentrylink::linker::InternalLinker; use libimagerror::errors::ErrorMsg as EM; use failure::Fallible as Result; diff --git a/lib/entry/libimagentrycategory/src/store.rs b/lib/entry/libimagentrycategory/src/store.rs index 3ea78648..3f0f7df2 100644 --- a/lib/entry/libimagentrycategory/src/store.rs +++ b/lib/entry/libimagentrycategory/src/store.rs @@ -84,7 +84,7 @@ impl CategoryStore for Store { /// /// Automatically removes all category settings from entries which are linked to this category. fn delete_category(&self, name: &str) -> Result<()> { - use libimagentrylink::internal::InternalLinker; + use libimagentrylink::linker::InternalLinker; use crate::category::Category; trace!("Deleting category: '{}'", name); diff --git a/lib/entry/libimagentrylink/src/iter.rs b/lib/entry/libimagentrylink/src/iter.rs new file mode 100644 index 00000000..5d76d0b6 --- /dev/null +++ b/lib/entry/libimagentrylink/src/iter.rs @@ -0,0 +1,97 @@ +// +// 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 +// + + +use std::vec::IntoIter; + +use failure::Error; +use failure::ResultExt; +use failure::Fallible as Result; +use toml::Value; +use itertools::Itertools; + +use libimagstore::store::Store; +use libimagstore::store::FileLockEntry; +use libimagerror::errors::ErrorMsg as EM; + +use crate::link::Link; + +pub struct LinkIter(IntoIter); + +impl LinkIter { + + pub fn new(v: Vec) -> LinkIter { + LinkIter(v.into_iter()) + } + + pub fn into_getter(self, store: &Store) -> GetIter { + GetIter(self.0, store) + } + +} + +impl Iterator for LinkIter { + type Item = Link; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +pub trait IntoValues { + fn into_values(self) -> Vec>; +} + +impl> IntoValues for I { + fn into_values(self) -> Vec> { + self.map(|s| s.without_base()) + .unique() + .sorted() + .into_iter() // Cannot sort toml::Value, hence uglyness here + .map(|link| link.to_value().context(EM::ConversionError).map_err(Error::from)) + .collect() + } +} + +/// An Iterator that `Store::get()`s the Entries from the store while consumed +pub struct GetIter<'a>(IntoIter, &'a Store); + +impl<'a> GetIter<'a> { + pub fn new(i: IntoIter, store: &'a Store) -> GetIter<'a> { + GetIter(i, store) + } + + pub fn store(&self) -> &Store { + self.1 + } +} + +impl<'a> Iterator for GetIter<'a> { + type Item = Result>; + + fn next(&mut self) -> Option { + self.0.next().and_then(|id| match self.1.get(id) { + Ok(None) => None, + Ok(Some(x)) => Some(Ok(x)), + Err(e) => Some(Err(e).map_err(From::from)), + }) + } + +} + diff --git a/lib/entry/libimagentrylink/src/lib.rs b/lib/entry/libimagentrylink/src/lib.rs index 992d3dd2..84fcba78 100644 --- a/lib/entry/libimagentrylink/src/lib.rs +++ b/lib/entry/libimagentrylink/src/lib.rs @@ -56,5 +56,8 @@ extern crate libimagutil; module_entry_path_mod!("links"); -pub mod internal; +pub mod iter; +pub mod linker; +pub mod link; +pub mod storecheck; diff --git a/lib/entry/libimagentrylink/src/link.rs b/lib/entry/libimagentrylink/src/link.rs new file mode 100644 index 00000000..eb594877 --- /dev/null +++ b/lib/entry/libimagentrylink/src/link.rs @@ -0,0 +1,150 @@ +// +// 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 +// + +use libimagstore::storeid::StoreId; +use libimagstore::storeid::IntoStoreId; +use libimagstore::store::Store; +use libimagerror::errors::ErrorMsg as EM; + +use toml::Value; +use toml::map::Map; +use failure::ResultExt; +use failure::Fallible as Result; +use failure::Error; + +#[derive(Eq, PartialOrd, Ord, Hash, Debug, Clone)] +pub enum Link { + Id { link: StoreId }, + Annotated { link: StoreId, annotation: String }, +} + +impl Link { + + pub fn exists(&self, store: &Store) -> Result { + match *self { + Link::Id { ref link } => store.exists(link.clone()), + Link::Annotated { ref link, .. } => store.exists(link.clone()), + } + .map_err(From::from) + } + + pub fn to_str(&self) -> Result { + match *self { + Link::Id { ref link } => link.to_str(), + Link::Annotated { ref link, .. } => link.to_str(), + } + .map_err(From::from) + } + + + pub(crate) fn eq_store_id(&self, id: &StoreId) -> bool { + match self { + &Link::Id { link: ref s } => s.eq(id), + &Link::Annotated { link: ref s, .. } => s.eq(id), + } + } + + /// Get the StoreId inside the Link, which is always present + pub fn get_store_id(&self) -> &StoreId { + match self { + &Link::Id { link: ref s } => s, + &Link::Annotated { link: ref s, .. } => s, + } + } + + /// Helper wrapper around Link for StoreId + pub(crate) fn without_base(self) -> Link { + match self { + Link::Id { link: s } => Link::Id { link: s }, + Link::Annotated { link: s, annotation: ann } => + Link::Annotated { link: s, annotation: ann }, + } + } + + pub(crate) fn to_value(&self) -> Result { + match self { + &Link::Id { link: ref s } => + s.to_str() + .map(Value::String) + .context(EM::ConversionError) + .map_err(Error::from), + &Link::Annotated { ref link, annotation: ref anno } => { + link.to_str() + .map(Value::String) + .context(EM::ConversionError) + .map_err(Error::from) + .map(|link| { + let mut tab = Map::new(); + + tab.insert("link".to_owned(), link); + tab.insert("annotation".to_owned(), Value::String(anno.clone())); + Value::Table(tab) + }) + } + } + } + +} + +impl ::std::cmp::PartialEq for Link { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (&Link::Id { link: ref a }, &Link::Id { link: ref b }) => a.eq(&b), + (&Link::Annotated { link: ref a, annotation: ref ann1 }, + &Link::Annotated { link: ref b, annotation: ref ann2 }) => + (a, ann1).eq(&(b, ann2)), + _ => false, + } + } +} + +impl From for Link { + + fn from(s: StoreId) -> Link { + Link::Id { link: s } + } +} + +impl Into for Link { + fn into(self) -> StoreId { + match self { + Link::Id { link } => link, + Link::Annotated { link, .. } => link, + } + } +} + +impl IntoStoreId for Link { + fn into_storeid(self) -> Result { + match self { + Link::Id { link } => Ok(link), + Link::Annotated { link, .. } => Ok(link), + } + } +} + +impl AsRef for Link { + fn as_ref(&self) -> &StoreId { + match self { + &Link::Id { ref link } => &link, + &Link::Annotated { ref link, .. } => &link, + } + } +} + diff --git a/lib/entry/libimagentrylink/src/internal.rs b/lib/entry/libimagentrylink/src/linker.rs similarity index 62% rename from lib/entry/libimagentrylink/src/internal.rs rename to lib/entry/libimagentrylink/src/linker.rs index ca24201f..a94a5707 100644 --- a/lib/entry/libimagentrylink/src/internal.rs +++ b/lib/entry/libimagentrylink/src/linker.rs @@ -18,144 +18,23 @@ // use libimagstore::storeid::StoreId; -use libimagstore::storeid::IntoStoreId; use libimagstore::store::Entry; use libimagstore::store::Store; use libimagerror::errors::ErrorMsg as EM; use toml_query::read::TomlValueReadExt; use toml_query::insert::TomlValueInsertExt; -use toml::map::Map; use failure::ResultExt; use failure::Fallible as Result; use failure::Error; use failure::err_msg; -use self::iter::LinkIter; -use self::iter::IntoValues; +use crate::iter::LinkIter; +use crate::iter::IntoValues; +use crate::link::Link; use toml::Value; -#[derive(Eq, PartialOrd, Ord, Hash, Debug, Clone)] -pub enum Link { - Id { link: StoreId }, - Annotated { link: StoreId, annotation: String }, -} - -impl Link { - - pub fn exists(&self, store: &Store) -> Result { - match *self { - Link::Id { ref link } => store.exists(link.clone()), - Link::Annotated { ref link, .. } => store.exists(link.clone()), - } - .map_err(From::from) - } - - pub fn to_str(&self) -> Result { - match *self { - Link::Id { ref link } => link.to_str(), - Link::Annotated { ref link, .. } => link.to_str(), - } - .map_err(From::from) - } - - - fn eq_store_id(&self, id: &StoreId) -> bool { - match self { - &Link::Id { link: ref s } => s.eq(id), - &Link::Annotated { link: ref s, .. } => s.eq(id), - } - } - - /// Get the StoreId inside the Link, which is always present - pub fn get_store_id(&self) -> &StoreId { - match self { - &Link::Id { link: ref s } => s, - &Link::Annotated { link: ref s, .. } => s, - } - } - - /// Helper wrapper around Link for StoreId - fn without_base(self) -> Link { - match self { - Link::Id { link: s } => Link::Id { link: s }, - Link::Annotated { link: s, annotation: ann } => - Link::Annotated { link: s, annotation: ann }, - } - } - - fn to_value(&self) -> Result { - match self { - &Link::Id { link: ref s } => - s.to_str() - .map(Value::String) - .context(EM::ConversionError) - .map_err(Error::from), - &Link::Annotated { ref link, annotation: ref anno } => { - link.to_str() - .map(Value::String) - .context(EM::ConversionError) - .map_err(Error::from) - .map(|link| { - let mut tab = Map::new(); - - tab.insert("link".to_owned(), link); - tab.insert("annotation".to_owned(), Value::String(anno.clone())); - Value::Table(tab) - }) - } - } - } - -} - -impl ::std::cmp::PartialEq for Link { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (&Link::Id { link: ref a }, &Link::Id { link: ref b }) => a.eq(&b), - (&Link::Annotated { link: ref a, annotation: ref ann1 }, - &Link::Annotated { link: ref b, annotation: ref ann2 }) => - (a, ann1).eq(&(b, ann2)), - _ => false, - } - } -} - -impl From for Link { - - fn from(s: StoreId) -> Link { - Link::Id { link: s } - } -} - -impl Into for Link { - fn into(self) -> StoreId { - match self { - Link::Id { link } => link, - Link::Annotated { link, .. } => link, - } - } -} - -impl IntoStoreId for Link { - fn into_storeid(self) -> Result { - match self { - Link::Id { link } => Ok(link), - Link::Annotated { link, .. } => Ok(link), - } - } -} - -impl AsRef for Link { - fn as_ref(&self) -> &StoreId { - match self { - &Link::Id { ref link } => &link, - &Link::Annotated { ref link, .. } => &link, - } - } -} - pub trait InternalLinker { /// Get the internal links from the implementor object @@ -174,85 +53,6 @@ pub trait InternalLinker { fn add_internal_annotated_link(&mut self, link: &mut Entry, annotation: String) -> Result<()>; } -pub mod iter { - use std::vec::IntoIter; - use super::Link; - - use failure::Error; - use failure::Fallible as Result; - use failure::ResultExt; - use toml::Value; - use itertools::Itertools; - - use libimagstore::store::Store; - use libimagstore::store::FileLockEntry; - use libimagerror::errors::ErrorMsg as EM; - - pub struct LinkIter(IntoIter); - - impl LinkIter { - - pub fn new(v: Vec) -> LinkIter { - LinkIter(v.into_iter()) - } - - pub fn into_getter(self, store: &Store) -> GetIter { - GetIter(self.0, store) - } - - } - - impl Iterator for LinkIter { - type Item = Link; - - fn next(&mut self) -> Option { - self.0.next() - } - } - - pub trait IntoValues { - fn into_values(self) -> Vec>; - } - - impl> IntoValues for I { - fn into_values(self) -> Vec> { - self.map(|s| s.without_base()) - .unique() - .sorted() - .into_iter() // Cannot sort toml::Value, hence uglyness here - .map(|link| link.to_value().context(EM::ConversionError).map_err(Error::from)) - .collect() - } - } - - /// An Iterator that `Store::get()`s the Entries from the store while consumed - pub struct GetIter<'a>(IntoIter, &'a Store); - - impl<'a> GetIter<'a> { - pub fn new(i: IntoIter, store: &'a Store) -> GetIter<'a> { - GetIter(i, store) - } - - pub fn store(&self) -> &Store { - self.1 - } - } - - impl<'a> Iterator for GetIter<'a> { - type Item = Result>; - - fn next(&mut self) -> Option { - self.0.next().and_then(|id| match self.1.get(id) { - Ok(None) => None, - Ok(Some(x)) => Some(Ok(x)), - Err(e) => Some(Err(e).map_err(From::from)), - }) - } - - } - -} - impl InternalLinker for Entry { fn get_internal_links(&self) -> Result { @@ -452,164 +252,6 @@ fn process_rw_result(links: Result>) -> Result { Ok(LinkIter::new(links)) } -pub mod store_check { - use libimagstore::store::Store; - - use failure::ResultExt; - use failure::Fallible as Result; - use failure::Error; - use failure::err_msg; - - pub trait StoreLinkConsistentExt { - fn check_link_consistency(&self) -> Result<()>; - } - - impl StoreLinkConsistentExt for Store { - fn check_link_consistency(&self) -> Result<()> { - use std::collections::HashMap; - - use crate::internal::InternalLinker; - - use libimagstore::storeid::StoreId; - use libimagutil::debug_result::DebugResult; - - // Helper data structure to collect incoming and outgoing links for each StoreId - #[derive(Debug, Default)] - struct Linking { - outgoing: Vec, - incoming: Vec, - } - - // Helper function to aggregate the Link network - // - // This function aggregates a HashMap which maps each StoreId object in the store onto - // a Linking object, which contains a list of StoreIds which this entry links to and a - // list of StoreIds which link to the current one. - // - // The lambda returns an error if something fails - let aggregate_link_network = |store: &Store| -> Result> { - store - .entries()? - .into_get_iter() - .fold(Ok(HashMap::new()), |map, element| { - map.and_then(|mut map| { - debug!("Checking element = {:?}", element); - let entry = element?.ok_or_else(|| err_msg("TODO: Not yet handled"))?; - - debug!("Checking entry = {:?}", entry.get_location()); - - let internal_links = entry - .get_internal_links()? - .into_getter(store); // get the FLEs from the Store - - let mut linking = Linking::default(); - for internal_link in internal_links { - debug!("internal link = {:?}", internal_link); - - linking.outgoing.push(internal_link?.get_location().clone()); - linking.incoming.push(entry.get_location().clone()); - } - - map.insert(entry.get_location().clone(), linking); - Ok(map) - }) - }) - }; - - // Helper to check whethre all StoreIds in the network actually exists - // - // Because why not? - let all_collected_storeids_exist = |network: &HashMap| -> Result<()> { - for (id, _) in network.iter() { - if is_match!(self.get(id.clone()), Ok(Some(_))) { - debug!("Exists in store: {:?}", id); - - if !self.exists(id.clone())? { - warn!("Does exist in store but not on FS: {:?}", id); - return Err(err_msg("Link target does not exist")) - } - } else { - warn!("Does not exist in store: {:?}", id); - return Err(err_msg("Link target does not exist")) - } - } - - Ok(()) - }; - - // Helper function to create a SLCECD::OneDirectionalLink error object - let mk_one_directional_link_err = |src: StoreId, target: StoreId| -> Error { - Error::from(format_err!("Dead link: {} -> {}", - src.local_display_string(), - target.local_display_string())) - }; - - // Helper lambda to check whether the _incoming_ links of each entry actually also - // appear in the _outgoing_ list of the linked entry - let incoming_links_exists_as_outgoing_links = - |src: &StoreId, linking: &Linking, network: &HashMap| -> Result<()> { - for link in linking.incoming.iter() { - // Check whether the links which are _incoming_ on _src_ are outgoing - // in each of the links in the incoming list. - let incoming_consistent = network.get(link) - .map(|l| l.outgoing.contains(src)) - .unwrap_or(false); - - if !incoming_consistent { - return Err(mk_one_directional_link_err(src.clone(), link.clone())) - } - } - - Ok(()) - }; - - // Helper lambda to check whether the _outgoing links of each entry actually also - // appear in the _incoming_ list of the linked entry - let outgoing_links_exist_as_incoming_links = - |src: &StoreId, linking: &Linking, network: &HashMap| -> Result<()> { - for link in linking.outgoing.iter() { - // Check whether the links which are _outgoing_ on _src_ are incoming - // in each of the links in the outgoing list. - let outgoing_consistent = network.get(link) - .map(|l| l.incoming.contains(src)) - .unwrap_or(false); - - if !outgoing_consistent { - return Err(mk_one_directional_link_err(link.clone(), src.clone())) - } - } - - Ok(()) - }; - - aggregate_link_network(&self) - .map_dbg_str("Aggregated") - .map_dbg(|nw| { - let mut s = String::new(); - for (k, v) in nw { - s.push_str(&format!("{}\n in: {:?}\n out: {:?}", k, v.incoming, v.outgoing)); - } - s - }) - .and_then(|nw| { - all_collected_storeids_exist(&nw) - .map(|_| nw) - .context(err_msg("Link handling error")) - .map_err(Error::from) - }) - .and_then(|nw| { - for (id, linking) in nw.iter() { - incoming_links_exists_as_outgoing_links(id, linking, &nw)?; - outgoing_links_exist_as_incoming_links(id, linking, &nw)?; - } - Ok(()) - }) - .map(|_| ()) - } - } - -} - #[cfg(test)] mod test { use std::path::PathBuf; @@ -852,4 +494,3 @@ mod test { } } - diff --git a/lib/entry/libimagentrylink/src/storecheck.rs b/lib/entry/libimagentrylink/src/storecheck.rs new file mode 100644 index 00000000..decf4cdd --- /dev/null +++ b/lib/entry/libimagentrylink/src/storecheck.rs @@ -0,0 +1,173 @@ +// +// 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 +// + +use std::collections::HashMap; + +use libimagstore::store::Store; +use libimagstore::storeid::StoreId; +use libimagutil::debug_result::DebugResult; + +use failure::ResultExt; +use failure::Fallible as Result; +use failure::Error; +use failure::err_msg; + +use crate::linker::*; + +pub trait StoreLinkConsistentExt { + fn check_link_consistency(&self) -> Result<()>; +} + +impl StoreLinkConsistentExt for Store { + fn check_link_consistency(&self) -> Result<()> { + // Helper data structure to collect incoming and outgoing links for each StoreId + #[derive(Debug, Default)] + struct Linking { + outgoing: Vec, + incoming: Vec, + } + + // Helper function to aggregate the Link network + // + // This function aggregates a HashMap which maps each StoreId object in the store onto + // a Linking object, which contains a list of StoreIds which this entry links to and a + // list of StoreIds which link to the current one. + // + // The lambda returns an error if something fails + let aggregate_link_network = |store: &Store| -> Result> { + store + .entries()? + .into_get_iter() + .fold(Ok(HashMap::new()), |map, element| { + map.and_then(|mut map| { + debug!("Checking element = {:?}", element); + let entry = element?.ok_or_else(|| err_msg("TODO: Not yet handled"))?; + + debug!("Checking entry = {:?}", entry.get_location()); + + let internal_links = entry + .get_internal_links()? + .into_getter(store); // get the FLEs from the Store + + let mut linking = Linking::default(); + for internal_link in internal_links { + debug!("internal link = {:?}", internal_link); + + linking.outgoing.push(internal_link?.get_location().clone()); + linking.incoming.push(entry.get_location().clone()); + } + + map.insert(entry.get_location().clone(), linking); + Ok(map) + }) + }) + }; + + // Helper to check whethre all StoreIds in the network actually exists + // + // Because why not? + let all_collected_storeids_exist = |network: &HashMap| -> Result<()> { + for (id, _) in network.iter() { + if is_match!(self.get(id.clone()), Ok(Some(_))) { + debug!("Exists in store: {:?}", id); + + if !self.exists(id.clone())? { + warn!("Does exist in store but not on FS: {:?}", id); + return Err(err_msg("Link target does not exist")) + } + } else { + warn!("Does not exist in store: {:?}", id); + return Err(err_msg("Link target does not exist")) + } + } + + Ok(()) + }; + + // Helper function to create a SLCECD::OneDirectionalLink error object + let mk_one_directional_link_err = |src: StoreId, target: StoreId| -> Error { + Error::from(format_err!("Dead link: {} -> {}", + src.local_display_string(), + target.local_display_string())) + }; + + // Helper lambda to check whether the _incoming_ links of each entry actually also + // appear in the _outgoing_ list of the linked entry + let incoming_links_exists_as_outgoing_links = + |src: &StoreId, linking: &Linking, network: &HashMap| -> Result<()> { + for link in linking.incoming.iter() { + // Check whether the links which are _incoming_ on _src_ are outgoing + // in each of the links in the incoming list. + let incoming_consistent = network.get(link) + .map(|l| l.outgoing.contains(src)) + .unwrap_or(false); + + if !incoming_consistent { + return Err(mk_one_directional_link_err(src.clone(), link.clone())) + } + } + + Ok(()) + }; + + // Helper lambda to check whether the _outgoing links of each entry actually also + // appear in the _incoming_ list of the linked entry + let outgoing_links_exist_as_incoming_links = + |src: &StoreId, linking: &Linking, network: &HashMap| -> Result<()> { + for link in linking.outgoing.iter() { + // Check whether the links which are _outgoing_ on _src_ are incoming + // in each of the links in the outgoing list. + let outgoing_consistent = network.get(link) + .map(|l| l.incoming.contains(src)) + .unwrap_or(false); + + if !outgoing_consistent { + return Err(mk_one_directional_link_err(link.clone(), src.clone())) + } + } + + Ok(()) + }; + + aggregate_link_network(&self) + .map_dbg_str("Aggregated") + .map_dbg(|nw| { + let mut s = String::new(); + for (k, v) in nw { + s.push_str(&format!("{}\n in: {:?}\n out: {:?}", k, v.incoming, v.outgoing)); + } + s + }) + .and_then(|nw| { + all_collected_storeids_exist(&nw) + .map(|_| nw) + .context(err_msg("Link handling error")) + .map_err(Error::from) + }) + .and_then(|nw| { + for (id, linking) in nw.iter() { + incoming_links_exists_as_outgoing_links(id, linking, &nw)?; + outgoing_links_exist_as_incoming_links(id, linking, &nw)?; + } + Ok(()) + }) + .map(|_| ()) + } +} + diff --git a/lib/entry/libimagentrymarkdown/src/processor.rs b/lib/entry/libimagentrymarkdown/src/processor.rs index f61ea92b..c2626f4d 100644 --- a/lib/entry/libimagentrymarkdown/src/processor.rs +++ b/lib/entry/libimagentrymarkdown/src/processor.rs @@ -25,7 +25,7 @@ use failure::Error; use crate::link::extract_links; use libimagentryurl::linker::UrlLinker; -use libimagentrylink::internal::InternalLinker; +use libimagentrylink::linker::InternalLinker; use libimagentryref::reference::MutRef; use libimagentryref::reference::RefFassade; use libimagentryref::hasher::sha1::Sha1Hasher; @@ -286,7 +286,7 @@ mod tests { use std::path::PathBuf; use libimagstore::store::Store; - use libimagentrylink::internal::InternalLinker; + use libimagentrylink::linker::InternalLinker; fn setup_logging() { let _ = ::env_logger::try_init(); diff --git a/lib/entry/libimagentryurl/src/iter.rs b/lib/entry/libimagentryurl/src/iter.rs index ea492ec8..cfa0ccf5 100644 --- a/lib/entry/libimagentryurl/src/iter.rs +++ b/lib/entry/libimagentryurl/src/iter.rs @@ -29,8 +29,8 @@ //! Not to confuse with `external::Link` which is a real `FileLockEntry` under the hood. //! -use libimagentrylink::internal::Link; -use libimagentrylink::internal::iter::LinkIter; +use libimagentrylink::link::Link; +use libimagentrylink::iter::LinkIter; use libimagstore::store::Store; use libimagutil::debug_result::DebugResult; diff --git a/lib/entry/libimagentryurl/src/linker.rs b/lib/entry/libimagentryurl/src/linker.rs index f4095069..fe98ade3 100644 --- a/lib/entry/libimagentryurl/src/linker.rs +++ b/lib/entry/libimagentryurl/src/linker.rs @@ -23,7 +23,7 @@ use libimagstore::storeid::StoreId; use libimagstore::store::Store; use libimagstore::store::Entry; use libimagutil::debug_result::DebugResult; -use libimagentrylink::internal::InternalLinker; +use libimagentrylink::linker::InternalLinker; use failure::Fallible as Result; use toml::Value; From 2268fd809181b089b833555db3a5dcbd2b52a6a5 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 31 May 2019 11:47:23 +0200 Subject: [PATCH 11/11] Import toml-query with typed feature Signed-off-by: Matthias Beyer --- lib/core/libimagrt/Cargo.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/core/libimagrt/Cargo.toml b/lib/core/libimagrt/Cargo.toml index f9b83932..318d7f37 100644 --- a/lib/core/libimagrt/Cargo.toml +++ b/lib/core/libimagrt/Cargo.toml @@ -25,7 +25,6 @@ toml = "0.5" xdg-basedir = "1.0" itertools = "0.7" ansi_term = "0.11" -toml-query = "0.9" atty = "0.2" failure = "0.1" failure_derive = "0.1" @@ -52,6 +51,11 @@ version = "^1.0.5" default-features = false features = ["no_logging"] +[dependencies.toml-query] +version = "0.9" +default-features = false +features = [ "typed" ] + [features] default = []