Implement link setting

This commit is contained in:
Matthias Beyer 2016-04-09 15:49:50 +02:00
parent 890458ea1e
commit 23049d02c6

View file

@ -13,21 +13,27 @@
use std::convert::Into; use std::convert::Into;
use std::ops::Deref; use std::ops::Deref;
use std::ops::DerefMut;
use std::collections::BTreeMap;
use libimagstore::store::Entry; use libimagstore::store::Entry;
use libimagstore::store::EntryHeader; use libimagstore::store::EntryHeader;
use libimagstore::store::FileLockEntry; use libimagstore::store::FileLockEntry;
use libimagstore::store::Store; use libimagstore::store::Store;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use error::LinkError as LE; use error::LinkError as LE;
use error::LinkErrorKind as LEK; use error::LinkErrorKind as LEK;
use result::Result; use result::Result;
use internal::InternalLinker; use internal::InternalLinker;
use module_path::ModuleEntryPath;
use toml::Value; use toml::Value;
use toml::Table; use toml::Table;
use url::Url; use url::Url;
use sodiumoxide::crypto::hash;
use sodiumoxide::crypto::hash::sha512::Digest;
/// "Link" Type, just an abstraction over FileLockEntry to have some convenience internally. /// "Link" Type, just an abstraction over FileLockEntry to have some convenience internally.
struct Link<'a> { struct Link<'a> {
@ -94,7 +100,7 @@ pub trait ExternalLinker : InternalLinker {
fn get_external_links(&self, store: &Store) -> Result<Vec<Url>>; fn get_external_links(&self, store: &Store) -> Result<Vec<Url>>;
/// Set the external links for the implementor object /// Set the external links for the implementor object
fn set_external_links(&mut self, links: Vec<Url>) -> Result<Vec<Url>>; fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()>;
/// Add an external link to the implementor object /// Add an external link to the implementor object
fn add_external_link(&mut self, link: Url) -> Result<()>; fn add_external_link(&mut self, link: Url) -> Result<()>;
@ -141,11 +147,59 @@ impl ExternalLinker for Entry {
} }
/// Set the external links for the implementor object /// Set the external links for the implementor object
fn set_external_links(&mut self, links: Vec<Url>) -> Result<Vec<Url>> { fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()> {
// Take all the links, generate a SHA sum out of each one, filter out the already existing // 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 // store entries and store the other URIs in the header of one FileLockEntry each, in
// the path /link/external/<SHA of the URL> // the path /link/external/<SHA of the URL>
unimplemented!()
/// Convert a hash::sha512::Digest from sodiumoxide into a StoreId
fn hash_to_storeid(d: Digest) -> StoreId {
let hash = &d[..];
let v = Vec::from(hash);
let s = String::from_utf8(v).unwrap(); // TODO: Uncaught unwrap()
ModuleEntryPath::new(format!("external/{}", s)).into_storeid()
}
for link in links { // for all links
let hash = hash::hash(link.serialize().as_bytes());
let file_id = hash_to_storeid(hash);
let mut file = {
if let Ok(mut file) = store.retrieve(file_id.clone()) { // retrieve the file from the store
file
} else { // or
let res = store.create(file_id) // create it
.and_then(|mut file| {
{
let mut hdr = file.deref_mut().get_header_mut();
// Write the URI into the header
match hdr.set("imag.content", Value::Table(BTreeMap::new())) {
Ok(_) => {
let v = Value::String(link.serialize());
hdr.set("imag.content.uri", v);
Ok(())
},
Err(e) => Err(e),
}
}.map(|_| file)
})
.map_err(|e| LE::new(LEK::StoreWriteError, Some(Box::new(e))));
// And if that fails we can error
if let Err(e) = res {
return Err(e);
}
res.unwrap()
}
};
// then add an internal link to the new file or return an error if this fails
if let Err(e) = self.add_internal_link(file.deref_mut()) {
return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e))));
}
}
Ok(())
} }
/// Add an external link to the implementor object /// Add an external link to the implementor object