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 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))
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"])
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue