Refactor: Remove notion of "external link"s

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
Matthias Beyer 2019-06-23 13:11:23 +02:00
parent 59ddb70345
commit cdc90f7be7
4 changed files with 54 additions and 72 deletions

View file

@ -37,7 +37,7 @@ use libimagutil::debug_result::DebugResult;
use failure::Fallible as Result; use failure::Fallible as Result;
use url::Url; use url::Url;
/// Helper for building `OnlyExternalIter` and `NoExternalIter` /// Helper for building `OnlyUrlIter` and `NoUrlIter`
/// ///
/// The boolean value defines, how to interpret the `is_external_link_storeid()` return value /// The boolean value defines, how to interpret the `is_external_link_storeid()` return value
/// (here as "pred"): /// (here as "pred"):
@ -55,9 +55,9 @@ use url::Url;
/// false... and so on. /// false... and so on.
/// ///
/// As we can see, the operator between these two operants is `!(a ^ b)`. /// As we can see, the operator between these two operants is `!(a ^ b)`.
pub struct ExternalFilterIter(LinkIter, bool); pub struct UrlFilterIter(LinkIter, bool);
impl Iterator for ExternalFilterIter { impl Iterator for UrlFilterIter {
type Item = Link; type Item = Link;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -78,24 +78,24 @@ impl Iterator for ExternalFilterIter {
/// ///
/// # See also /// # See also
/// ///
/// Also see `OnlyExternalIter` and `NoExternalIter` and the helper traits/functions /// Also see `OnlyUrlIter` and `NoUrlIter` and the helper traits/functions
/// `OnlyInteralLinks`/`only_links()` and `OnlyExternalLinks`/`only_urls()`. /// `OnlyInteralLinks`/`only_links()` and `OnlyUrlLinks`/`only_urls()`.
pub trait SelectExternal { pub trait SelectUrl {
fn select_urls(self, b: bool) -> ExternalFilterIter; fn select_urls(self, b: bool) -> UrlFilterIter;
} }
impl SelectExternal for LinkIter { impl SelectUrl for LinkIter {
fn select_urls(self, b: bool) -> ExternalFilterIter { fn select_urls(self, b: bool) -> UrlFilterIter {
ExternalFilterIter(self, b) UrlFilterIter(self, b)
} }
} }
pub struct OnlyExternalIter(ExternalFilterIter); pub struct OnlyUrlIter(UrlFilterIter);
impl OnlyExternalIter { impl OnlyUrlIter {
pub fn new(li: LinkIter) -> OnlyExternalIter { pub fn new(li: LinkIter) -> OnlyUrlIter {
OnlyExternalIter(ExternalFilterIter(li, true)) OnlyUrlIter(UrlFilterIter(li, true))
} }
pub fn urls<'a>(self, store: &'a Store) -> UrlIter<'a> { pub fn urls<'a>(self, store: &'a Store) -> UrlIter<'a> {
@ -103,7 +103,7 @@ impl OnlyExternalIter {
} }
} }
impl Iterator for OnlyExternalIter { impl Iterator for OnlyUrlIter {
type Item = Link; type Item = Link;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -111,15 +111,15 @@ impl Iterator for OnlyExternalIter {
} }
} }
pub struct NoExternalIter(ExternalFilterIter); pub struct NoUrlIter(UrlFilterIter);
impl NoExternalIter { impl NoUrlIter {
pub fn new(li: LinkIter) -> NoExternalIter { pub fn new(li: LinkIter) -> NoUrlIter {
NoExternalIter(ExternalFilterIter(li, false)) NoUrlIter(UrlFilterIter(li, false))
} }
} }
impl Iterator for NoExternalIter { impl Iterator for NoUrlIter {
type Item = Link; type Item = Link;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -127,35 +127,35 @@ impl Iterator for NoExternalIter {
} }
} }
pub trait OnlyExternalLinks : Sized { pub trait OnlyUrlLinks : Sized {
fn only_urls(self) -> OnlyExternalIter ; fn only_urls(self) -> OnlyUrlIter ;
fn no_links(self) -> OnlyExternalIter { fn no_links(self) -> OnlyUrlIter {
self.only_urls() self.only_urls()
} }
} }
impl OnlyExternalLinks for LinkIter { impl OnlyUrlLinks for LinkIter {
fn only_urls(self) -> OnlyExternalIter { fn only_urls(self) -> OnlyUrlIter {
OnlyExternalIter::new(self) OnlyUrlIter::new(self)
} }
} }
pub trait OnlyInternalLinks : Sized { pub trait OnlyInternalLinks : Sized {
fn only_links(self) -> NoExternalIter; fn only_links(self) -> NoUrlIter;
fn no_urls(self) -> NoExternalIter { fn no_urls(self) -> NoUrlIter {
self.only_links() self.only_links()
} }
} }
impl OnlyInternalLinks for LinkIter { impl OnlyInternalLinks for LinkIter {
fn only_links(self) -> NoExternalIter { fn only_links(self) -> NoUrlIter {
NoExternalIter::new(self) NoUrlIter::new(self)
} }
} }
pub struct UrlIter<'a>(OnlyExternalIter, &'a Store); pub struct UrlIter<'a>(OnlyUrlIter, &'a Store);
impl<'a> Iterator for UrlIter<'a> { impl<'a> Iterator for UrlIter<'a> {
type Item = Result<Url>; type Item = Result<Url>;
@ -174,7 +174,7 @@ impl<'a> Iterator for UrlIter<'a> {
.map_err(From::from) .map_err(From::from)
.and_then(|f| { .and_then(|f| {
debug!("Store::retrieve({:?}) succeeded", id); debug!("Store::retrieve({:?}) succeeded", id);
debug!("getting external link from file now"); debug!("getting uri link from file now");
f.get_link_uri_from_filelockentry() f.get_link_uri_from_filelockentry()
.map_dbg_str("Error happened while getting link URI from FLE") .map_dbg_str("Error happened while getting link URI from FLE")
.map_dbg_err(|e| format!("URL -> Err = {:?}", e)) .map_dbg_err(|e| format!("URL -> Err = {:?}", e))

View file

@ -40,8 +40,8 @@ impl Link for Entry {
fn get_link_uri_from_filelockentry(&self) -> Result<Option<Url>> { fn get_link_uri_from_filelockentry(&self) -> Result<Option<Url>> {
self.get_header() self.get_header()
.read_string("links.external.content.url") .read_string("url.uri")
.context(format_err!("Error reading header 'links.external.content.url' from '{}'", self.get_location())) .context(format_err!("Error reading header 'url.uri' from '{}'", self.get_location()))
.context(EM::EntryHeaderReadError) .context(EM::EntryHeaderReadError)
.map_err(Error::from) .map_err(Error::from)
.and_then(|opt| match opt { .and_then(|opt| match opt {
@ -61,7 +61,7 @@ impl Link for Entry {
} }
fn get_url(&self) -> Result<Option<Url>> { fn get_url(&self) -> Result<Option<Url>> {
match self.get_header().read_string("links.external.url")? { match self.get_header().read_string("url.uri")? {
None => Ok(None), None => Ok(None),
Some(ref s) => Url::parse(&s[..]) Some(ref s) => Url::parse(&s[..])
.context(format_err!("Failed to parse URL: '{}'", s)) .context(format_err!("Failed to parse URL: '{}'", s))

View file

@ -38,56 +38,48 @@ use crate::iter::UrlIter;
pub trait UrlLinker : Linkable { pub trait UrlLinker : Linkable {
/// Get the external links from the implementor object /// Get the urls from the implementor object
fn get_urls<'a>(&self, store: &'a Store) -> Result<UrlIter<'a>>; fn get_urls<'a>(&self, store: &'a Store) -> Result<UrlIter<'a>>;
/// Set the external links for the implementor object /// Set the urls for the implementor object
fn set_urls(&mut self, store: &Store, links: Vec<Url>) -> Result<Vec<StoreId>>; fn set_urls(&mut self, store: &Store, links: Vec<Url>) -> Result<Vec<StoreId>>;
/// Add an external link to the implementor object /// Add an url to the implementor object
fn add_url(&mut self, store: &Store, link: Url) -> Result<Vec<StoreId>>; fn add_url(&mut self, store: &Store, link: Url) -> Result<Vec<StoreId>>;
/// Remove an external link from the implementor object /// Remove an url from the implementor object
fn remove_url(&mut self, store: &Store, link: Url) -> Result<Vec<StoreId>>; fn remove_url(&mut self, store: &Store, link: Url) -> Result<Vec<StoreId>>;
} }
/// 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 UrlLinker for Entry { impl UrlLinker for Entry {
/// Get the external links from the implementor object
fn get_urls<'a>(&self, store: &'a Store) -> Result<UrlIter<'a>> { fn get_urls<'a>(&self, store: &'a Store) -> Result<UrlIter<'a>> {
use crate::iter::OnlyExternalLinks; use crate::iter::OnlyUrlLinks;
// Iterate through all internal links and filter for FileLockEntries which live in // Iterate through all internal links and filter for FileLockEntries which live in
// /link/external/<SHA> -> load these files and get the external link from their headers, // /links/<SHA> -> load these files and get the url from their headers,
// put them into the return vector. // put them into the return vector.
self.links() self.links()
.map(|iter| { .map(|iter| {
debug!("Getting external links"); debug!("Getting urls");
iter.only_urls().urls(store) iter.only_urls().urls(store)
}) })
} }
/// Set the external links for the implementor object /// Set the url links for the implementor object
/// ///
/// # Return Value /// # Return Value
/// ///
/// Returns the StoreIds which were newly created for the new external links, if there are more /// Returns the StoreIds which were newly created for the new urls, if there are more
/// external links than before. /// urls than before.
/// If there are less external links than before, an empty vec![] is returned. /// If there are less urls than before, an empty vec![] is returned.
/// ///
fn set_urls(&mut self, store: &Store, links: Vec<Url>) -> Result<Vec<StoreId>> { fn set_urls(&mut self, store: &Store, links: Vec<Url>) -> Result<Vec<StoreId>> {
// 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/<SHA of the URL>
debug!("Iterating {} links = {:?}", links.len(), links); debug!("Iterating {} links = {:?}", links.len(), links);
links.into_iter().map(|link| { links.into_iter().map(|link| {
let hash = hex::encode(Sha1::digest(&link.as_str().as_bytes())); let hash = hex::encode(Sha1::digest(&link.as_str().as_bytes()));
let file_id = crate::module_path::new_id(format!("external/{}", hash)) let file_id = crate::module_path::new_id(format!("links/{}", hash))
.map_dbg_err(|_| { .map_dbg_err(|_| {
format!("Failed to build StoreId for this hash '{:?}'", hash) format!("Failed to build StoreId for this hash '{:?}'", hash)
})?; })?;
@ -142,18 +134,13 @@ impl UrlLinker for Entry {
.collect() .collect()
} }
/// Add an external link to the implementor object /// Add an url to the implementor object
/// ///
/// # Return Value /// # Return Value
/// ///
/// (See ExternalLinker::set_urls()) /// (See UrlLinker::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_url(&mut self, store: &Store, link: Url) -> Result<Vec<StoreId>> { fn add_url(&mut self, store: &Store, link: Url) -> Result<Vec<StoreId>> {
// get external links, add this one, save them
debug!("Getting links"); debug!("Getting links");
self.get_urls(store) self.get_urls(store)
.and_then(|links| { .and_then(|links| {
@ -167,18 +154,13 @@ impl UrlLinker for Entry {
}) })
} }
/// Remove an external link from the implementor object /// Remove an url from the implementor object
/// ///
/// # Return Value /// # Return Value
/// ///
/// (See ExternalLinker::set_urls()) /// (See UrlLinker::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_url(&mut self, store: &Store, link: Url) -> Result<Vec<StoreId>> { fn remove_url(&mut self, store: &Store, link: Url) -> Result<Vec<StoreId>> {
// get external links, remove this one, save them
self.get_urls(store) self.get_urls(store)
.and_then(|links| { .and_then(|links| {
debug!("Removing link = '{:?}'", link); debug!("Removing link = '{:?}'", link);

View file

@ -21,8 +21,8 @@ use std::fmt::Debug;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
/// Check whether the StoreId starts with `/link/external/` /// Check whether the StoreId starts with `/url/`
pub fn is_external_link_storeid<A: AsRef<StoreId> + Debug>(id: A) -> bool { pub fn is_external_link_storeid<A: AsRef<StoreId> + Debug>(id: A) -> bool {
debug!("Checking whether this is a 'url/external/': '{:?}'", id); debug!("Checking whether this is a 'url/': '{:?}'", id);
id.as_ref().is_in_collection(&["url", "external"]) id.as_ref().is_in_collection(&["url"])
} }