Refactor: Remove notion of "external link"s
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
parent
59ddb70345
commit
cdc90f7be7
4 changed files with 54 additions and 72 deletions
|
@ -37,7 +37,7 @@ use libimagutil::debug_result::DebugResult;
|
|||
use failure::Fallible as Result;
|
||||
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
|
||||
/// (here as "pred"):
|
||||
|
@ -55,9 +55,9 @@ use url::Url;
|
|||
/// false... and so on.
|
||||
///
|
||||
/// 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;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
@ -78,24 +78,24 @@ impl Iterator for ExternalFilterIter {
|
|||
///
|
||||
/// # See also
|
||||
///
|
||||
/// Also see `OnlyExternalIter` and `NoExternalIter` and the helper traits/functions
|
||||
/// `OnlyInteralLinks`/`only_links()` and `OnlyExternalLinks`/`only_urls()`.
|
||||
pub trait SelectExternal {
|
||||
fn select_urls(self, b: bool) -> ExternalFilterIter;
|
||||
/// Also see `OnlyUrlIter` and `NoUrlIter` and the helper traits/functions
|
||||
/// `OnlyInteralLinks`/`only_links()` and `OnlyUrlLinks`/`only_urls()`.
|
||||
pub trait SelectUrl {
|
||||
fn select_urls(self, b: bool) -> UrlFilterIter;
|
||||
}
|
||||
|
||||
impl SelectExternal for LinkIter {
|
||||
fn select_urls(self, b: bool) -> ExternalFilterIter {
|
||||
ExternalFilterIter(self, b)
|
||||
impl SelectUrl for LinkIter {
|
||||
fn select_urls(self, b: bool) -> UrlFilterIter {
|
||||
UrlFilterIter(self, b)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct OnlyExternalIter(ExternalFilterIter);
|
||||
pub struct OnlyUrlIter(UrlFilterIter);
|
||||
|
||||
impl OnlyExternalIter {
|
||||
pub fn new(li: LinkIter) -> OnlyExternalIter {
|
||||
OnlyExternalIter(ExternalFilterIter(li, true))
|
||||
impl OnlyUrlIter {
|
||||
pub fn new(li: LinkIter) -> OnlyUrlIter {
|
||||
OnlyUrlIter(UrlFilterIter(li, true))
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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 {
|
||||
pub fn new(li: LinkIter) -> NoExternalIter {
|
||||
NoExternalIter(ExternalFilterIter(li, false))
|
||||
impl NoUrlIter {
|
||||
pub fn new(li: LinkIter) -> NoUrlIter {
|
||||
NoUrlIter(UrlFilterIter(li, false))
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for NoExternalIter {
|
||||
impl Iterator for NoUrlIter {
|
||||
type Item = Link;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
@ -127,35 +127,35 @@ impl Iterator for NoExternalIter {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait OnlyExternalLinks : Sized {
|
||||
fn only_urls(self) -> OnlyExternalIter ;
|
||||
pub trait OnlyUrlLinks : Sized {
|
||||
fn only_urls(self) -> OnlyUrlIter ;
|
||||
|
||||
fn no_links(self) -> OnlyExternalIter {
|
||||
fn no_links(self) -> OnlyUrlIter {
|
||||
self.only_urls()
|
||||
}
|
||||
}
|
||||
|
||||
impl OnlyExternalLinks for LinkIter {
|
||||
fn only_urls(self) -> OnlyExternalIter {
|
||||
OnlyExternalIter::new(self)
|
||||
impl OnlyUrlLinks for LinkIter {
|
||||
fn only_urls(self) -> OnlyUrlIter {
|
||||
OnlyUrlIter::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
impl OnlyInternalLinks for LinkIter {
|
||||
fn only_links(self) -> NoExternalIter {
|
||||
NoExternalIter::new(self)
|
||||
fn only_links(self) -> NoUrlIter {
|
||||
NoUrlIter::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UrlIter<'a>(OnlyExternalIter, &'a Store);
|
||||
pub struct UrlIter<'a>(OnlyUrlIter, &'a Store);
|
||||
|
||||
impl<'a> Iterator for UrlIter<'a> {
|
||||
type Item = Result<Url>;
|
||||
|
@ -174,7 +174,7 @@ impl<'a> Iterator for UrlIter<'a> {
|
|||
.map_err(From::from)
|
||||
.and_then(|f| {
|
||||
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()
|
||||
.map_dbg_str("Error happened while getting link URI from FLE")
|
||||
.map_dbg_err(|e| format!("URL -> Err = {:?}", e))
|
||||
|
|
|
@ -40,8 +40,8 @@ impl Link for Entry {
|
|||
|
||||
fn get_link_uri_from_filelockentry(&self) -> Result<Option<Url>> {
|
||||
self.get_header()
|
||||
.read_string("links.external.content.url")
|
||||
.context(format_err!("Error reading header 'links.external.content.url' from '{}'", self.get_location()))
|
||||
.read_string("url.uri")
|
||||
.context(format_err!("Error reading header 'url.uri' from '{}'", self.get_location()))
|
||||
.context(EM::EntryHeaderReadError)
|
||||
.map_err(Error::from)
|
||||
.and_then(|opt| match opt {
|
||||
|
@ -61,7 +61,7 @@ impl Link for Entry {
|
|||
}
|
||||
|
||||
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),
|
||||
Some(ref s) => Url::parse(&s[..])
|
||||
.context(format_err!("Failed to parse URL: '{}'", s))
|
||||
|
|
|
@ -38,56 +38,48 @@ use crate::iter::UrlIter;
|
|||
|
||||
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>>;
|
||||
|
||||
/// 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>>;
|
||||
|
||||
/// 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>>;
|
||||
|
||||
/// 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>>;
|
||||
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
|
||||
/// Get the external links from the implementor object
|
||||
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
|
||||
// /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.
|
||||
self.links()
|
||||
.map(|iter| {
|
||||
debug!("Getting external links");
|
||||
debug!("Getting urls");
|
||||
iter.only_urls().urls(store)
|
||||
})
|
||||
}
|
||||
|
||||
/// Set the external links for the implementor object
|
||||
/// Set the url links for the implementor object
|
||||
///
|
||||
/// # Return Value
|
||||
///
|
||||
/// 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.
|
||||
/// Returns the StoreIds which were newly created for the new urls, if there are more
|
||||
/// urls than before.
|
||||
/// 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>> {
|
||||
// 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);
|
||||
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!("external/{}", hash))
|
||||
let file_id = crate::module_path::new_id(format!("links/{}", hash))
|
||||
.map_dbg_err(|_| {
|
||||
format!("Failed to build StoreId for this hash '{:?}'", hash)
|
||||
})?;
|
||||
|
@ -142,18 +134,13 @@ impl UrlLinker for Entry {
|
|||
.collect()
|
||||
}
|
||||
|
||||
/// Add an external link to the implementor object
|
||||
/// Add an url to the implementor object
|
||||
///
|
||||
/// # Return Value
|
||||
///
|
||||
/// (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.
|
||||
/// (See UrlLinker::set_urls())
|
||||
///
|
||||
fn add_url(&mut self, store: &Store, link: Url) -> Result<Vec<StoreId>> {
|
||||
// get external links, add this one, save them
|
||||
debug!("Getting links");
|
||||
self.get_urls(store)
|
||||
.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
|
||||
///
|
||||
/// (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.
|
||||
/// (See UrlLinker::set_urls())
|
||||
///
|
||||
fn remove_url(&mut self, store: &Store, link: Url) -> Result<Vec<StoreId>> {
|
||||
// get external links, remove this one, save them
|
||||
self.get_urls(store)
|
||||
.and_then(|links| {
|
||||
debug!("Removing link = '{:?}'", link);
|
||||
|
|
|
@ -21,8 +21,8 @@ use std::fmt::Debug;
|
|||
|
||||
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 {
|
||||
debug!("Checking whether this is a 'url/external/': '{:?}'", id);
|
||||
id.as_ref().is_in_collection(&["url", "external"])
|
||||
debug!("Checking whether this is a 'url/': '{:?}'", id);
|
||||
id.as_ref().is_in_collection(&["url"])
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue