From ad3c2c6249b562a7e5dd94318eb8ac2287d6bac2 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 23 Jun 2019 21:07:13 +0200 Subject: [PATCH] Rewrite UrlLinker Signed-off-by: Matthias Beyer --- lib/entry/libimagentryurl/src/linker.rs | 113 +++++++++++------------- 1 file changed, 51 insertions(+), 62 deletions(-) diff --git a/lib/entry/libimagentryurl/src/linker.rs b/lib/entry/libimagentryurl/src/linker.rs index c6aeb600..da3aa5f7 100644 --- a/lib/entry/libimagentryurl/src/linker.rs +++ b/lib/entry/libimagentryurl/src/linker.rs @@ -17,8 +17,6 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use std::ops::DerefMut; - use libimagstore::storeid::StoreId; use libimagstore::store::Store; use libimagstore::store::Entry; @@ -26,39 +24,47 @@ use libimagutil::debug_result::DebugResult; use libimagentrylink::linkable::Linkable; use failure::Fallible as Result; -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; +use crate::link::Link; use crate::iter::UrlIter; pub trait UrlLinker : Linkable { - /// Get the urls from the implementor object fn get_urls<'a>(&self, store: &'a Store) -> Result>; - /// Set the urls for the implementor object fn set_urls(&mut self, store: &Store, links: Vec) -> Result>; - /// Add an url to the implementor object fn add_url(&mut self, store: &Store, link: Url) -> Result>; - /// Remove an url from the implementor object fn remove_url(&mut self, store: &Store, link: Url) -> Result>; } impl UrlLinker for Entry { + /// Get URLs from the Entry + /// + /// + /// # Notice + /// + /// (Also see documentation of `UrlLinker::set_urls()`) + /// + /// This fetches all Links (as in `libimagentrylink` for the Entry and filters them by entries + /// which contain an URL. + /// + /// + /// # Return Value + /// + /// Iterator over URLs + /// fn get_urls<'a>(&self, store: &'a Store) -> Result> { use crate::iter::OnlyUrlLinks; // Iterate through all internal links and filter for FileLockEntries which live in - // /links/ -> load these files and get the url from their headers, + // /url/ -> load these files and get the url from their headers, // put them into the return vector. self.links() .map(|iter| { @@ -67,7 +73,14 @@ impl UrlLinker for Entry { }) } - /// Set the url links for the implementor object + /// Set URLs for the Entry + /// + /// # Notice + /// + /// This does not actually add each URL in this entry, but retrieves (as in + /// `Store::retrieve()`) one entry for each URL and links (as in `libimagentrylink`) this entry + /// to the retrieved ones. + /// /// /// # Return Value /// @@ -79,16 +92,14 @@ impl UrlLinker for Entry { debug!("Iterating {} links = {:?}", links.len(), links); links.into_iter().map(|link| { let hash = hex::encode(Sha1::digest(&link.as_str().as_bytes())); - let file_id = crate::module_path::new_id(format!("links/{}", hash)) - .map_dbg_err(|_| { - format!("Failed to build StoreId for this hash '{:?}'", hash) - })?; + let file_id = crate::module_path::new_id(hash.clone()) + .map_dbg_err(|_| format!("Failed to build StoreId for this hash '{:?}'", hash))?; debug!("Link = '{:?}'", link); debug!("Hash = '{:?}'", hash); debug!("StoreId = '{:?}'", file_id); - let link_already_exists = store.get(file_id.clone())?.is_some(); + let link_already_exists = store.exists(file_id.clone())?; // retrieve the file from the store, which implicitely creates the entry if it does not // exist @@ -99,31 +110,11 @@ impl UrlLinker for Entry { })?; debug!("Generating header content!"); - { - let hdr = file.deref_mut().get_header_mut(); - - let mut table = match hdr.read("links.external.content")? { - Some(&Value::Table(ref table)) => table.clone(), - Some(_) => { - warn!("There is a value at 'links.external.content' which is not a table."); - warn!("Going to override this value"); - Map::new() - }, - None => Map::new(), - }; - - let v = Value::String(link.into_string()); - - debug!("setting URL = '{:?}", v); - table.insert(String::from("url"), v); - - let _ = hdr.insert("links.external.content", Value::Table(table))?; - debug!("Setting URL worked"); - } + file.set_url(link)?; // then add an internal link to the new file or return an error if this fails - let _ = self.add_link(file.deref_mut())?; - debug!("Added internal link"); + let _ = self.add_link(&mut file)?; + debug!("Added linking: {:?} <-> {:?}", self.get_location(), file.get_location()); Ok((link_already_exists, file_id)) }) @@ -134,42 +125,40 @@ impl UrlLinker for Entry { .collect() } - /// Add an url to the implementor object + /// Add an URL to the entry + /// + /// + /// # Notice + /// + /// (Also see documentation of `UrlLinker::set_urls()`) + /// /// /// # Return Value /// /// (See UrlLinker::set_urls()) /// fn add_url(&mut self, store: &Store, link: Url) -> Result> { - debug!("Getting links"); - self.get_urls(store) - .and_then(|links| { - let mut links = links.collect::>>()?; - - debug!("Adding link = '{:?}' to links = {:?}", link, links); - links.push(link); - - debug!("Setting {} links = {:?}", links.len(), links); - self.set_urls(store, links) - }) + let mut links = self.get_urls(store)?.collect::>>()?; + links.push(link); + self.set_urls(store, links) } - /// Remove an url from the implementor object + /// Remove an URL from the entry + /// + /// + /// # Notice + /// + /// (Also see documentation of `UrlLinker::set_urls()`) + /// /// /// # Return Value /// /// (See UrlLinker::set_urls()) /// fn remove_url(&mut self, store: &Store, link: Url) -> Result> { - 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_urls(store, links) - }) + let mut links = self.get_urls(store)?.collect::>>()?; + links.retain(|l| *l != link); + self.set_urls(store, links) } }