summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2018-12-03 00:23:17 +0100
committerMatthias Beyer <mail@beyermatthias.de>2019-02-17 11:09:48 +0100
commitac5a3c02987d318a126b4f0823ea42fc27a9c875 (patch)
treefa5d0c3f068341beba9cb121929fef7022ace57c
parentd8ad741fc22a93bc70dd720720bc1198d8d33af7 (diff)
Reimplement LinkProcessor::process() for new libimagentryref API
The documentation of the function kind of explains why this change is necessary. It might get changed in the future so that the user has more flexibility. Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r--lib/entry/libimagentrymarkdown/Cargo.toml1
-rw-r--r--lib/entry/libimagentrymarkdown/src/lib.rs1
-rw-r--r--lib/entry/libimagentrymarkdown/src/processor.rs105
3 files changed, 81 insertions, 26 deletions
diff --git a/lib/entry/libimagentrymarkdown/Cargo.toml b/lib/entry/libimagentrymarkdown/Cargo.toml
index 8248412a..cf082a03 100644
--- a/lib/entry/libimagentrymarkdown/Cargo.toml
+++ b/lib/entry/libimagentrymarkdown/Cargo.toml
@@ -25,6 +25,7 @@ hoedown = "6.0.0"
url = "1.5"
env_logger = "0.5"
failure = "0.1"
+sha-1 = "0.8"
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" }
diff --git a/lib/entry/libimagentrymarkdown/src/lib.rs b/lib/entry/libimagentrymarkdown/src/lib.rs
index a108fdfd..8eedff8d 100644
--- a/lib/entry/libimagentrymarkdown/src/lib.rs
+++ b/lib/entry/libimagentrymarkdown/src/lib.rs
@@ -46,6 +46,7 @@ extern crate libimagentryref;
extern crate libimagutil;
#[macro_use] extern crate failure;
#[macro_use] extern crate log;
+extern crate sha1;
#[cfg(test)]
extern crate env_logger;
diff --git a/lib/entry/libimagentrymarkdown/src/processor.rs b/lib/entry/libimagentrymarkdown/src/processor.rs
index 6be62a91..6476040b 100644
--- a/lib/entry/libimagentrymarkdown/src/processor.rs
+++ b/lib/entry/libimagentrymarkdown/src/processor.rs
@@ -17,7 +17,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
-use std::path::Path;
+use std::collections::BTreeMap;
use failure::Fallible as Result;
use failure::ResultExt;
@@ -26,34 +26,18 @@ use link::extract_links;
use libimagentrylink::external::ExternalLinker;
use libimagentrylink::internal::InternalLinker;
-use libimagentryref::refstore::RefStore;
-use libimagentryref::refstore::UniqueRefPathGenerator;
-use libimagentryref::generators::sha512::Sha512;
+use libimagentryref::reference::MutRef;
+use libimagentryref::reference::RefFassade;
+use libimagentryref::hasher::sha1::Sha1Hasher;
use libimagstore::store::Entry;
use libimagstore::store::Store;
use libimagstore::storeid::StoreId;
+use libimagerror::errors::ErrorMsg;
use std::path::PathBuf;
use url::Url;
-
-pub struct UniqueMarkdownRefGenerator;
-
-impl UniqueRefPathGenerator for UniqueMarkdownRefGenerator {
- fn collection() -> &'static str {
- "ref" // we can only use this collection, as we don't know about context
- }
-
- fn unique_hash<A: AsRef<Path>>(path: A) -> Result<String> {
- Sha512::unique_hash(path).map_err(Error::from)
- }
-
- fn postprocess_storeid(sid: StoreId) -> Result<StoreId> {
- Ok(sid) // don't do anything
- }
-}
-
/// A link Processor which collects the links from a Markdown and passes them on to
/// `libimagentrylink` functionality
///
@@ -117,11 +101,37 @@ impl LinkProcessor {
/// Process an Entry for its links
///
+ ///
+ /// # Notice
+ ///
+ /// Whenever a "ref" is created, that means when a URL points to a filesystem path (normally
+ /// when using `file:///home/user/foobar.file` for example), the _current_ implementation uses
+ /// libimagentryref to create make the entry into a ref.
+ ///
+ /// The configuration of the `libimagentryref::reference::Reference::make_ref()` call is as
+ /// follows:
+ ///
+ /// * Name of the collection: "root"
+ /// * Configuration: `{"root": "/"}`
+ ///
+ /// This implementation might change in the future, so that the configuration and the name of
+ /// the collection can be passed to the function, or in a way that the user is asked what to do
+ /// during the runtime of this function.
+ ///
+ ///
/// # Warning
///
/// When `LinkProcessor::create_internal_targets()` was called to set the setting to true, this
/// function returns all errors returned by the Store.
///
+ /// That means:
+ ///
+ /// * For an internal link, the linked target is created if create_internal_targets() is true,
+ /// else error
+ /// * For an external link, if create_internal_targets() is true, libimagentrylink creates the
+ /// external link entry, else the link is ignored
+ /// * all other cases do not create elements in the store
+ ///
pub fn process<'a>(&self, entry: &mut Entry, store: &'a Store) -> Result<()> {
let text = entry.to_str()?;
trace!("Processing: {:?}", entry.get_location());
@@ -151,18 +161,58 @@ impl LinkProcessor {
entry.add_external_link(store, url)?;
},
LinkQualification::RefLink(url) => {
+ use sha1::{Sha1, Digest};
+
if !self.process_refs {
+ trace!("Not processing refs... continue...");
continue
}
+ // because we can make one entry only into _one_ ref, but a markdown document
+ // might contain several "ref" links, we create a new entry for the ref we're
+ // about to create
+ //
+ // We generate the StoreId with the SHA1 hash of the path, which is the best
+ // option we have
+ // right now
+ //
+ // TODO: Does this make sense? Can we improve this?
+ let path = url.host_str().unwrap_or_else(|| url.path());
+ let path = PathBuf::from(path);
+ let ref_entry_id = {
+ let digest = Sha1::digest(path.to_str().ok_or(ErrorMsg::UTF8Error)?.as_bytes());
+ StoreId::new(PathBuf::from(format!("ref/{:x}", digest)))? // TODO: Ugh...
+ };
+ let mut ref_entry = store.retrieve(ref_entry_id)?;
+
+ let ref_collection_name = "root";
+
+ // TODO: Maybe this can be a const?
+ // TODO: Maybe we need this ot be overrideable? Not sure.
+ let ref_collection_config = {
+ let mut map = BTreeMap::new();
+ map.insert(String::from("root"), PathBuf::from("/"));
+ ::libimagentryref::reference::Config::new(map)
+ };
+
trace!("URL = {:?}", url);
trace!("URL.path() = {:?}", url.path());
trace!("URL.host_str() = {:?}", url.host_str());
- let path = url.host_str().unwrap_or_else(|| url.path());
- let path = PathBuf::from(path);
- let mut target = store.create_ref::<UniqueMarkdownRefGenerator, PathBuf>(path)?;
- entry.add_internal_link(&mut target)?;
+ trace!("Processing ref: {:?} -> {path}, collection: {ref_collection_name}, cfg: {cfg:?}",
+ path = path.display(),
+ ref_collection_name = ref_collection_name,
+ cfg = ref_collection_config);
+
+ ref_entry.as_ref_with_hasher_mut::<Sha1Hasher>()
+ .make_ref(path,
+ ref_collection_name,
+ &ref_collection_config,
+ false)?;
+
+ trace!("Ready processing, linking new ref entry...");
+
+ let _ = entry.add_internal_link(&mut ref_entry)?;
},
LinkQualification::Undecidable(e) => {
// error
@@ -188,9 +238,11 @@ enum LinkQualification {
impl LinkQualification {
fn qualify(text: &str) -> LinkQualification {
+ trace!("Qualifying: {}", text);
match Url::parse(text) {
Ok(url) => {
if url.scheme() == "file" {
+ trace!("Qualifying = RefLink");
return LinkQualification::RefLink(url)
}
@@ -205,6 +257,7 @@ impl LinkQualification {
Err(e) => {
match e {
::url::ParseError::RelativeUrlWithoutBase => {
+ trace!("Qualifying = InternalLink");
LinkQualification::InternalLink
},
@@ -438,7 +491,7 @@ mod tests {
assert!(entries.is_ok());
let entries : Vec<_> = entries.unwrap().into_storeid_iter().collect();
- assert_eq!(2, entries.len(), "Expected 2 links, got: {:?}", entries);
+ assert_eq!(2, entries.len(), "Expected 1 entries, got: {:?}", entries);
debug!("{:?}", entries);
}