Merge branch 'libimagentryref-partial' into master

This commit is contained in:
Matthias Beyer 2019-04-22 14:26:35 +02:00
commit a410486016
2 changed files with 50 additions and 42 deletions

View file

@ -34,9 +34,11 @@ libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }
libimagentryutil = { version = "0.10.0", path = "../../../lib/entry/libimagentryutil" } libimagentryutil = { version = "0.10.0", path = "../../../lib/entry/libimagentryutil" }
[dependencies.toml-query] [dependencies.toml-query]
version = "0.8" #version = "0.8"
default-features = false default-features = false
features = ["typed"] features = ["typed"]
git = "https://github.com/matthiasbeyer/toml-query"
branch = "master"
[dev-dependencies] [dev-dependencies]
env_logger = "0.5" env_logger = "0.5"

View file

@ -28,6 +28,7 @@ use libimagerror::errors::ErrorMsg as EM;
use toml::Value; use toml::Value;
use toml_query::read::TomlValueReadExt; use toml_query::read::TomlValueReadExt;
use toml_query::read::Partial;
use toml_query::delete::TomlValueDeleteExt; use toml_query::delete::TomlValueDeleteExt;
use toml_query::insert::TomlValueInsertExt; use toml_query::insert::TomlValueInsertExt;
use failure::Fallible as Result; use failure::Fallible as Result;
@ -37,13 +38,13 @@ use failure::ResultExt;
use hasher::Hasher; use hasher::Hasher;
/// A configuration of "collection name" -> "collection path" mappings /// A configuration of "basepath name" -> "basepath path" mappings
/// ///
/// Should be deserializeable from the configuration file right away, because we expect a /// Should be deserializeable from the configuration file right away, because we expect a
/// configuration like this in the config file: /// configuration like this in the config file:
/// ///
/// ```toml /// ```toml
/// [ref.collections] /// [ref.basepathes]
/// music = "/home/alice/music" /// music = "/home/alice/music"
/// documents = "/home/alice/doc" /// documents = "/home/alice/doc"
/// ``` /// ```
@ -66,6 +67,11 @@ impl Deref for Config {
} }
} }
impl<'a> Partial<'a> for Config {
const LOCATION: &'static str = "ref.basepathes";
type Output = Self;
}
provide_kindflag_path!(pub IsRef, "ref.is_ref"); provide_kindflag_path!(pub IsRef, "ref.is_ref");
/// Fassade module /// Fassade module
@ -182,12 +188,12 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> {
.map(PathBuf::from) .map(PathBuf::from)
.ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.relpath")))?; .ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.relpath")))?;
let collection_name = self.0 let basepath_name = self.0
.get_header() .get_header()
.read_string("ref.collection")? .read_string("ref.basepath")?
.ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.collection")))?; .ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.basepath")))?;
get_file_path(config, &collection_name, relpath) get_file_path(config, &basepath_name, relpath)
} }
/// Get the relative path, relative to the configured basepath /// Get the relative path, relative to the configured basepath
@ -211,10 +217,10 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> {
.read("ref")? .read("ref")?
.ok_or_else(|| err_msg("Header missing at 'ref'"))?; .ok_or_else(|| err_msg("Header missing at 'ref'"))?;
let collection_name = ref_header let basepath_name = ref_header
.read("collection") .read("basepath")
.map_err(Error::from)? .map_err(Error::from)?
.ok_or_else(|| err_msg("Header missing at 'ref.collection'"))? .ok_or_else(|| err_msg("Header missing at 'ref.basepath'"))?
.as_str() .as_str()
.ok_or_else(|| Error::from(EM::EntryHeaderTypeError2("ref.hash.<hash>", "string")))?; .ok_or_else(|| Error::from(EM::EntryHeaderTypeError2("ref.hash.<hash>", "string")))?;
@ -227,7 +233,7 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> {
.ok_or_else(|| Error::from(EM::EntryHeaderTypeError2("ref.hash.<hash>", "string")))?; .ok_or_else(|| Error::from(EM::EntryHeaderTypeError2("ref.hash.<hash>", "string")))?;
let file_path = get_file_path(config, collection_name.as_ref(), &path)?; let file_path = get_file_path(config, basepath_name.as_ref(), &path)?;
ref_header ref_header
.read(H::NAME) .read(H::NAME)
@ -249,7 +255,7 @@ pub trait MutRef {
/// Make a ref out of a normal (non-ref) entry. /// Make a ref out of a normal (non-ref) entry.
/// ///
/// If the entry is already a ref, this fails if `force` is false /// If the entry is already a ref, this fails if `force` is false
fn make_ref<P, Coll>(&mut self, path: P, collection_name: Coll, config: &Config, force: bool) fn make_ref<P, Coll>(&mut self, path: P, basepath_name: Coll, config: &Config, force: bool)
-> Result<()> -> Result<()>
where P: AsRef<Path>, where P: AsRef<Path>,
Coll: AsRef<str>; Coll: AsRef<str>;
@ -278,7 +284,7 @@ impl<'a, H> MutRef for MutRefWithHasher<'a, H>
} }
let _ = header.delete("ref.hash").context("Removing ref.hash")?; let _ = header.delete("ref.hash").context("Removing ref.hash")?;
let _ = header.delete("ref.collection").context("Removing ref.collection")?; let _ = header.delete("ref.basepath").context("Removing ref.basepath")?;
} }
debug!("Removing 'ref' header marker"); debug!("Removing 'ref' header marker");
@ -301,13 +307,13 @@ impl<'a, H> MutRef for MutRefWithHasher<'a, H>
/// ///
/// If the entry is already a ref, this fails if `force` is false /// If the entry is already a ref, this fails if `force` is false
/// ///
fn make_ref<P, Coll>(&mut self, path: P, collection_name: Coll, config: &Config, force: bool) fn make_ref<P, Coll>(&mut self, path: P, basepath_name: Coll, config: &Config, force: bool)
-> Result<()> -> Result<()>
where P: AsRef<Path>, where P: AsRef<Path>,
Coll: AsRef<str> Coll: AsRef<str>
{ {
trace!("Making ref out of {:?}", self.0); trace!("Making ref out of {:?}", self.0);
trace!("Making ref with collection name {:?}", collection_name.as_ref()); trace!("Making ref with basepath name {:?}", basepath_name.as_ref());
trace!("Making ref with config {:?}", config); trace!("Making ref with config {:?}", config);
trace!("Making ref forced = {}", force); trace!("Making ref forced = {}", force);
@ -316,7 +322,7 @@ impl<'a, H> MutRef for MutRefWithHasher<'a, H>
let _ = Err(err_msg("Entry is already a reference")).context("Making ref out of entry")?; let _ = Err(err_msg("Entry is already a reference")).context("Making ref out of entry")?;
} }
let file_path = get_file_path(config, collection_name.as_ref(), &path)?; let file_path = get_file_path(config, basepath_name.as_ref(), &path)?;
if !file_path.exists() { if !file_path.exists() {
let msg = format_err!("File '{:?}' does not exist", file_path); let msg = format_err!("File '{:?}' does not exist", file_path);
@ -329,13 +335,13 @@ impl<'a, H> MutRef for MutRefWithHasher<'a, H>
trace!("hash = {}", hash); trace!("hash = {}", hash);
// stripping the prefix of "path" // stripping the prefix of "path"
let prefix = get_basepath(collection_name.as_ref(), config)?; let prefix = get_basepath(basepath_name.as_ref(), config)?;
trace!("Stripping = {}", prefix.display()); trace!("Stripping = {}", prefix.display());
let relpath = path.as_ref().strip_prefix(prefix)?; let relpath = path.as_ref().strip_prefix(prefix)?;
trace!("Using relpath = {} to make header section", relpath.display()); trace!("Using relpath = {} to make header section", relpath.display());
make_header_section(hash, H::NAME, relpath, collection_name) make_header_section(hash, H::NAME, relpath, basepath_name)
}) })
.and_then(|h| self.0.get_header_mut().insert("ref", h).map_err(Error::from)) .and_then(|h| self.0.get_header_mut().insert("ref", h).map_err(Error::from))
.and_then(|_| self.0.set_isflag::<IsRef>()) .and_then(|_| self.0.set_isflag::<IsRef>())
@ -355,8 +361,8 @@ impl<'a, H> MutRef for MutRefWithHasher<'a, H>
/// ///
/// # Warning /// # Warning
/// ///
/// The `relpath` _must_ be relative to the configured path for that collection. /// The `relpath` _must_ be relative to the configured path for that basepath.
pub(crate) fn make_header_section<P, C, H>(hash: String, hashname: H, relpath: P, collection: C) pub(crate) fn make_header_section<P, C, H>(hash: String, hashname: H, relpath: P, basepath: C)
-> Result<Value> -> Result<Value>
where P: AsRef<Path>, where P: AsRef<Path>,
C: AsRef<str>, C: AsRef<str>,
@ -382,26 +388,26 @@ pub(crate) fn make_header_section<P, C, H>(hash: String, hashname: H, relpath: P
let _ = header_section.insert("hash", hash_table)?; let _ = header_section.insert("hash", hash_table)?;
} }
let _ = header_section.insert("collection", Value::String(String::from(collection.as_ref()))); let _ = header_section.insert("basepath", Value::String(String::from(basepath.as_ref())));
Ok(header_section) Ok(header_section)
} }
fn get_basepath<'a, Coll: AsRef<str>>(collection_name: Coll, config: &'a Config) -> Result<&'a PathBuf> { fn get_basepath<'a, Coll: AsRef<str>>(basepath_name: Coll, config: &'a Config) -> Result<&'a PathBuf> {
config.get(collection_name.as_ref()) config.get(basepath_name.as_ref())
.ok_or_else(|| format_err!("Collection {} seems not to exist in config", .ok_or_else(|| format_err!("basepath {} seems not to exist in config",
collection_name.as_ref())) basepath_name.as_ref()))
.map_err(Error::from) .map_err(Error::from)
} }
fn get_file_path<P>(config: &Config, collection_name: &str, path: P) -> Result<PathBuf> fn get_file_path<P>(config: &Config, basepath_name: &str, path: P) -> Result<PathBuf>
where P: AsRef<Path> where P: AsRef<Path>
{ {
config config
.get(collection_name) .get(basepath_name)
.map(PathBuf::clone) .map(PathBuf::clone)
.ok_or_else(|| { .ok_or_else(|| {
format_err!("Configuration missing for collection: '{}'", collection_name) format_err!("Configuration missing for basepath: '{}'", basepath_name)
}) })
.context("Making ref out of entry") .context("Making ref out of entry")
.map_err(Error::from) .map_err(Error::from)
@ -459,14 +465,14 @@ mod test {
let store = get_store(); let store = get_store();
let mut entry = store.retrieve(PathBuf::from("test_makeref")).unwrap(); let mut entry = store.retrieve(PathBuf::from("test_makeref")).unwrap();
let file = PathBuf::from("/tmp"); // has to exist let file = PathBuf::from("/tmp"); // has to exist
let collection_name = "some_collection"; let basepath_name = "some_basepath";
let config = Config({ let config = Config({
let mut c = BTreeMap::new(); let mut c = BTreeMap::new();
c.insert(String::from("some_collection"), PathBuf::from("/")); c.insert(String::from("some_basepath"), PathBuf::from("/"));
c c
}); });
let r = entry.as_ref_with_hasher_mut::<TestHasher>().make_ref(file, collection_name, &config, false); let r = entry.as_ref_with_hasher_mut::<TestHasher>().make_ref(file, basepath_name, &config, false);
assert!(r.is_ok()); assert!(r.is_ok());
} }
@ -476,14 +482,14 @@ mod test {
let store = get_store(); let store = get_store();
let mut entry = store.retrieve(PathBuf::from("test_makeref_isref")).unwrap(); let mut entry = store.retrieve(PathBuf::from("test_makeref_isref")).unwrap();
let file = PathBuf::from("/tmp"); // has to exists let file = PathBuf::from("/tmp"); // has to exists
let collection_name = "some_collection"; let basepath_name = "some_basepath";
let config = Config({ let config = Config({
let mut c = BTreeMap::new(); let mut c = BTreeMap::new();
c.insert(String::from("some_collection"), PathBuf::from("/")); c.insert(String::from("some_basepath"), PathBuf::from("/"));
c c
}); });
let res = entry.as_ref_with_hasher_mut::<TestHasher>().make_ref(file, collection_name, &config, false); let res = entry.as_ref_with_hasher_mut::<TestHasher>().make_ref(file, basepath_name, &config, false);
assert!(res.is_ok(), "Expected to be ok: {:?}", res); assert!(res.is_ok(), "Expected to be ok: {:?}", res);
assert!(entry.as_ref_with_hasher::<TestHasher>().is_ref().unwrap()); assert!(entry.as_ref_with_hasher::<TestHasher>().is_ref().unwrap());
@ -495,14 +501,14 @@ mod test {
let store = get_store(); let store = get_store();
let mut entry = store.retrieve(PathBuf::from("test_makeref_is_ref_with_testhash")).unwrap(); let mut entry = store.retrieve(PathBuf::from("test_makeref_is_ref_with_testhash")).unwrap();
let file = PathBuf::from("/tmp"); // has to exist let file = PathBuf::from("/tmp"); // has to exist
let collection_name = "some_collection"; let basepath_name = "some_basepath";
let config = Config({ let config = Config({
let mut c = BTreeMap::new(); let mut c = BTreeMap::new();
c.insert(String::from("some_collection"), PathBuf::from("/")); c.insert(String::from("some_basepath"), PathBuf::from("/"));
c c
}); });
assert!(entry.as_ref_with_hasher_mut::<TestHasher>().make_ref(file, collection_name, &config, false).is_ok()); assert!(entry.as_ref_with_hasher_mut::<TestHasher>().make_ref(file, basepath_name, &config, false).is_ok());
let check_isstr = |entry: &Entry, location, shouldbe| { let check_isstr = |entry: &Entry, location, shouldbe| {
let var = entry.get_header().read(location); let var = entry.get_header().read(location);
@ -519,7 +525,7 @@ mod test {
check_isstr(&entry, "ref.relpath", "tmp"); check_isstr(&entry, "ref.relpath", "tmp");
check_isstr(&entry, "ref.hash.Testhasher", "/tmp"); // TestHasher hashes by returning the path itself check_isstr(&entry, "ref.hash.Testhasher", "/tmp"); // TestHasher hashes by returning the path itself
check_isstr(&entry, "ref.collection", "some_collection"); check_isstr(&entry, "ref.basepath", "some_basepath");
} }
#[test] #[test]
@ -528,14 +534,14 @@ mod test {
let store = get_store(); let store = get_store();
let mut entry = store.retrieve(PathBuf::from("test_makeref_remref")).unwrap(); let mut entry = store.retrieve(PathBuf::from("test_makeref_remref")).unwrap();
let file = PathBuf::from("/"); // has to exist let file = PathBuf::from("/"); // has to exist
let collection_name = "some_collection"; let basepath_name = "some_basepath";
let config = Config({ let config = Config({
let mut c = BTreeMap::new(); let mut c = BTreeMap::new();
c.insert(String::from("some_collection"), PathBuf::from("/")); c.insert(String::from("some_basepath"), PathBuf::from("/"));
c c
}); });
assert!(entry.as_ref_with_hasher_mut::<TestHasher>().make_ref(file, collection_name, &config, false).is_ok()); assert!(entry.as_ref_with_hasher_mut::<TestHasher>().make_ref(file, basepath_name, &config, false).is_ok());
assert!(entry.as_ref_with_hasher::<TestHasher>().is_ref().unwrap()); assert!(entry.as_ref_with_hasher::<TestHasher>().is_ref().unwrap());
let res = entry.as_ref_with_hasher_mut::<TestHasher>().remove_ref(); let res = entry.as_ref_with_hasher_mut::<TestHasher>().remove_ref();
assert!(res.is_ok(), "Expected to be ok: {:?}", res); assert!(res.is_ok(), "Expected to be ok: {:?}", res);