From f321aa82a1dd69940a539deadf0f4ef3ed2a05ae Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 26 Apr 2018 11:20:09 +0200 Subject: [PATCH 1/7] Make sure category is linked when setting it --- lib/entry/libimagentrycategory/src/category.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/entry/libimagentrycategory/src/category.rs b/lib/entry/libimagentrycategory/src/category.rs index cd0e09ac..a9abe76c 100644 --- a/lib/entry/libimagentrycategory/src/category.rs +++ b/lib/entry/libimagentrycategory/src/category.rs @@ -72,12 +72,15 @@ impl EntryCategory for Entry { /// /// This function should be used by default over EntryCategory::set_category()! fn set_category_checked(&mut self, register: &CategoryRegister, s: Category) -> Result<()> { - register.category_exists(&s.0) - .and_then(|bl| if bl { - self.set_category(s) - } else { - Err(CE::from_kind(CEK::CategoryDoesNotExist)) - }) + let c_str = s.clone().into(); + let mut category = register + .get_category_by_name(&c_str)? + .ok_or_else(|| CE::from_kind(CEK::CategoryDoesNotExist))?; + + let _ = self.set_category(s)?; + let _ = self.add_internal_link(&mut category)?; + + Ok(()) } fn get_category(&self) -> Result> { From c26f1aae2ad3a52596e129d048315ecc3b5364d7 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 26 Apr 2018 11:20:40 +0200 Subject: [PATCH 2/7] This module should be named "entry" --- lib/entry/libimagentrycategory/src/{category.rs => entry.rs} | 0 lib/entry/libimagentrycategory/src/lib.rs | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename lib/entry/libimagentrycategory/src/{category.rs => entry.rs} (100%) diff --git a/lib/entry/libimagentrycategory/src/category.rs b/lib/entry/libimagentrycategory/src/entry.rs similarity index 100% rename from lib/entry/libimagentrycategory/src/category.rs rename to lib/entry/libimagentrycategory/src/entry.rs diff --git a/lib/entry/libimagentrycategory/src/lib.rs b/lib/entry/libimagentrycategory/src/lib.rs index 18eb6901..a183f1f7 100644 --- a/lib/entry/libimagentrycategory/src/lib.rs +++ b/lib/entry/libimagentrycategory/src/lib.rs @@ -47,7 +47,7 @@ extern crate libimagerror; #[macro_use] extern crate libimagstore; -pub mod category; +pub mod entry; pub mod error; pub mod register; From 5f305ef7a77ab9f1f2e6348ca79fa4f55d48ccaf Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 26 Apr 2018 11:29:09 +0200 Subject: [PATCH 3/7] Add module for category handling --- .../libimagentrycategory/src/category.rs | 47 +++++++++++++++++++ lib/entry/libimagentrycategory/src/lib.rs | 1 + 2 files changed, 48 insertions(+) create mode 100644 lib/entry/libimagentrycategory/src/category.rs diff --git a/lib/entry/libimagentrycategory/src/category.rs b/lib/entry/libimagentrycategory/src/category.rs new file mode 100644 index 00000000..9fdb397b --- /dev/null +++ b/lib/entry/libimagentrycategory/src/category.rs @@ -0,0 +1,47 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2018 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +use libimagentryutil::isa::Is; +use libimagentryutil::isa::IsKindHeaderPathProvider; + +use error::CategoryError as CE; +use store::CATEGORY_REGISTER_NAME_FIELD_PATH; + +provide_kindflag_path!(pub IsCategory, "category.is_category"); + +pub trait Category { + fn is_category(&self) -> Result; + fn get_name(&self) -> Result; + fn get_entries(&self, store: &Store) -> Result; +} + +impl Category for Entry { + fn is_category(&self) -> Result { + self.is::().map_err(CE::from) + } + + fn get_name(&self) -> Result { + self.get_header().read_string(CATEGORY_REGISTER_NAME_FIELD_PATH).map_err(CE::from) + } + + fn get_entries(&self, store: &Store) -> Result { + unimplemented!() + } +} + diff --git a/lib/entry/libimagentrycategory/src/lib.rs b/lib/entry/libimagentrycategory/src/lib.rs index a183f1f7..822489b5 100644 --- a/lib/entry/libimagentrycategory/src/lib.rs +++ b/lib/entry/libimagentrycategory/src/lib.rs @@ -47,6 +47,7 @@ extern crate libimagerror; #[macro_use] extern crate libimagstore; +pub mod category; pub mod entry; pub mod error; pub mod register; From ab15d89e648901c23fdaf2a0a6f8d3657eb9a82d Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 26 Apr 2018 11:29:23 +0200 Subject: [PATCH 4/7] Rewrite CategoryRegister as CategoryStore --- lib/entry/libimagentrycategory/src/lib.rs | 2 +- .../src/{register.rs => store.rs} | 38 ++++++------------- 2 files changed, 12 insertions(+), 28 deletions(-) rename lib/entry/libimagentrycategory/src/{register.rs => store.rs} (87%) diff --git a/lib/entry/libimagentrycategory/src/lib.rs b/lib/entry/libimagentrycategory/src/lib.rs index 822489b5..58c72d39 100644 --- a/lib/entry/libimagentrycategory/src/lib.rs +++ b/lib/entry/libimagentrycategory/src/lib.rs @@ -50,7 +50,7 @@ extern crate libimagstore; pub mod category; pub mod entry; pub mod error; -pub mod register; +pub mod store; module_entry_path_mod!("category"); diff --git a/lib/entry/libimagentrycategory/src/register.rs b/lib/entry/libimagentrycategory/src/store.rs similarity index 87% rename from lib/entry/libimagentrycategory/src/register.rs rename to lib/entry/libimagentrycategory/src/store.rs index aa75ab4f..6d41a134 100644 --- a/lib/entry/libimagentrycategory/src/register.rs +++ b/lib/entry/libimagentrycategory/src/store.rs @@ -39,7 +39,7 @@ pub const CATEGORY_REGISTER_NAME_FIELD_PATH : &'static str = "category.register. /// Extension on the Store to make it a register for categories /// /// The register writes files to the -pub trait CategoryRegister { +pub trait CategoryStore { fn category_exists(&self, name: &str) -> Result; @@ -53,7 +53,7 @@ pub trait CategoryRegister { } -impl CategoryRegister for Store { +impl CategoryStore for Store { /// Check whether a category exists fn category_exists(&self, name: &str) -> Result { @@ -64,39 +64,23 @@ impl CategoryRegister for Store { /// Create a category /// /// Fails if the category already exists (returns false then) - fn create_category(&self, name: &str) -> Result { - use libimagstore::error::StoreErrorKind as SEK; + fn create_category(&self, name: &str) -> Result> { + let sid = mk_category_storeid(self.path().clone(), name)?; + let mut entry = self.create(sid)?; - let sid = mk_category_storeid(self.path().clone(), name)?; + entry.set_isflag::()?; + let _ = entry + .get_header_mut() + .insert(CATEGORY_REGISTER_NAME_FIELD_PATH, Value::String(String::from(name)))?; - match self.create(sid) { - Ok(mut entry) => { - let val = Value::String(String::from(name)); - entry.get_header_mut() - .insert(CATEGORY_REGISTER_NAME_FIELD_PATH, val) - .map(|opt| if opt.is_none() { - debug!("Setting category header worked") - } else { - warn!("Setting category header replaced existing value: {:?}", opt); - }) - .map(|_| true) - .chain_err(|| CEK::HeaderWriteError) - .chain_err(|| CEK::StoreWriteError) - } - Err(store_error) => if is_match!(store_error.kind(), &SEK::EntryAlreadyExists(_)) { - Ok(false) - } else { - Err(store_error).chain_err(|| CEK::StoreWriteError) - } - } + Ok(entry) } /// Delete a category fn delete_category(&self, name: &str) -> Result<()> { let sid = mk_category_storeid(self.path().clone(), name)?; - - self.delete(sid).chain_err(|| CEK::StoreWriteError) + self.delete(sid).map_err(CE::from) } /// Get all category names From 9fc9e7fe17640799f8cdbf24dd2eb6a8f5834450 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 26 Apr 2018 11:31:01 +0200 Subject: [PATCH 5/7] Outsource iterator in iter module --- lib/entry/libimagentrycategory/src/iter.rs | 77 +++++++++++++++++++++ lib/entry/libimagentrycategory/src/lib.rs | 1 + lib/entry/libimagentrycategory/src/store.rs | 51 +------------- 3 files changed, 79 insertions(+), 50 deletions(-) create mode 100644 lib/entry/libimagentrycategory/src/iter.rs diff --git a/lib/entry/libimagentrycategory/src/iter.rs b/lib/entry/libimagentrycategory/src/iter.rs new file mode 100644 index 00000000..7896bcbd --- /dev/null +++ b/lib/entry/libimagentrycategory/src/iter.rs @@ -0,0 +1,77 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2018 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +use libimagstore::storeid::StoreIdIterator; +use libimagstore::store::Store; + +use error::Result; +use error::CategoryError as CE; +use error::CategoryErrorKind as CEK; +use store::CATEGORY_REGISTER_NAME_FIELD_PATH; + +/// Iterator for Category names +/// +/// Iterates over Result +/// +/// # Return values +/// +/// In each iteration, a Option> is returned. Error kinds are as follows: +/// +/// * CategoryErrorKind::StoreReadError if a name could not be fetched from the store +/// * CategoryErrorKind::HeaderReadError if the header of the fetched item couldn't be read +/// * CategoryErrorKind::TypeError if the name could not be fetched because it is not a String +/// +pub struct CategoryNameIter<'a>(&'a Store, StoreIdIterator); + +impl<'a> CategoryNameIter<'a> { + + fn new(store: &'a Store, sidit: StoreIdIterator) -> CategoryNameIter<'a> { + CategoryNameIter(store, sidit) + } + +} + +impl<'a> Iterator for CategoryNameIter<'a> { + type Item = Result; + + fn next(&mut self) -> Option { + // TODO: Optimize me with lazy_static + let query = CATEGORY_REGISTER_NAME_FIELD_PATH; + + while let Some(sid) = self.1.next() { + if sid.is_in_collection(&["category"]) { + let func = |store: &Store| { // hack for returning Some(Result<_, _>) + store + .get(sid)? + .ok_or_else(|| CE::from_kind(CEK::StoreReadError))? + .get_header() + .read_string(query) + .chain_err(|| CEK::HeaderReadError)? + .map(Category::from) + .ok_or_else(|| CE::from_kind(CEK::StoreReadError)) + }; + + return Some(func(&self.0)) + } // else continue + } + + None + } +} + diff --git a/lib/entry/libimagentrycategory/src/lib.rs b/lib/entry/libimagentrycategory/src/lib.rs index 58c72d39..66f0a9c8 100644 --- a/lib/entry/libimagentrycategory/src/lib.rs +++ b/lib/entry/libimagentrycategory/src/lib.rs @@ -51,6 +51,7 @@ pub mod category; pub mod entry; pub mod error; pub mod store; +pub mod iter; module_entry_path_mod!("category"); diff --git a/lib/entry/libimagentrycategory/src/store.rs b/lib/entry/libimagentrycategory/src/store.rs index 6d41a134..4c2e26cf 100644 --- a/lib/entry/libimagentrycategory/src/store.rs +++ b/lib/entry/libimagentrycategory/src/store.rs @@ -33,6 +33,7 @@ use error::CategoryErrorKind as CEK; use error::CategoryError as CE; use error::ResultExt; use error::Result; +use iter::CategoryNameIter; pub const CATEGORY_REGISTER_NAME_FIELD_PATH : &'static str = "category.register.name"; @@ -221,53 +222,3 @@ fn represents_category(store: &Store, sid: StoreId, name: &str) -> Result }) } -/// Iterator for Category names -/// -/// Iterates over Result -/// -/// # Return values -/// -/// In each iteration, a Option> is returned. Error kinds are as follows: -/// -/// * CategoryErrorKind::StoreReadError if a name could not be fetched from the store -/// * CategoryErrorKind::HeaderReadError if the header of the fetched item couldn't be read -/// * CategoryErrorKind::TypeError if the name could not be fetched because it is not a String -/// -pub struct CategoryNameIter<'a>(&'a Store, StoreIdIterator); - -impl<'a> CategoryNameIter<'a> { - - fn new(store: &'a Store, sidit: StoreIdIterator) -> CategoryNameIter<'a> { - CategoryNameIter(store, sidit) - } - -} - -impl<'a> Iterator for CategoryNameIter<'a> { - type Item = Result; - - fn next(&mut self) -> Option { - // TODO: Optimize me with lazy_static - let query = CATEGORY_REGISTER_NAME_FIELD_PATH; - - while let Some(sid) = self.1.next() { - if sid.is_in_collection(&["category"]) { - let func = |store: &Store| { // hack for returning Some(Result<_, _>) - store - .get(sid)? - .ok_or_else(|| CE::from_kind(CEK::StoreReadError))? - .get_header() - .read_string(query) - .chain_err(|| CEK::HeaderReadError)? - .map(Category::from) - .ok_or_else(|| CE::from_kind(CEK::StoreReadError)) - }; - - return Some(func(&self.0)) - } // else continue - } - - None - } -} - From f0969db47cef7253d3fcd83c210f0b1687c4a633 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 26 Apr 2018 12:04:18 +0200 Subject: [PATCH 6/7] Rewrite This patch rewrites the whole libimagcategory and brings it to a nice standard (the code before was rather messy). Now, categories are represented by an entry in the store and all entries which have this category are linked to that entry. --- lib/entry/libimagentrycategory/Cargo.toml | 14 +++--- .../libimagentrycategory/src/category.rs | 29 +++++++++--- lib/entry/libimagentrycategory/src/entry.rs | 47 +++++++------------ lib/entry/libimagentrycategory/src/error.rs | 7 +++ lib/entry/libimagentrycategory/src/iter.rs | 45 ++++++++++++++++-- lib/entry/libimagentrycategory/src/lib.rs | 8 ++-- lib/entry/libimagentrycategory/src/store.rs | 14 ++++-- 7 files changed, 110 insertions(+), 54 deletions(-) diff --git a/lib/entry/libimagentrycategory/Cargo.toml b/lib/entry/libimagentrycategory/Cargo.toml index 472d1b1e..70c6ee02 100644 --- a/lib/entry/libimagentrycategory/Cargo.toml +++ b/lib/entry/libimagentrycategory/Cargo.toml @@ -20,14 +20,16 @@ is-it-maintained-open-issues = { repository = "matthiasbeyer/imag" } maintenance = { status = "actively-developed" } [dependencies] -log = "0.4.0" -toml = "0.4" -toml-query = "0.6" -is-match = "0.1" +log = "0.4.0" +toml = "0.4" +toml-query = "0.6" error-chain = "0.11" -libimagerror = { version = "0.8.0", path = "../../../lib/core/libimagerror" } -libimagstore = { version = "0.8.0", path = "../../../lib/core/libimagstore" } +libimagerror = { version = "0.8.0", path = "../../../lib/core/libimagerror" } +libimagstore = { version = "0.8.0", path = "../../../lib/core/libimagstore" } +libimagutil = { version = "0.8.0", path = "../../../lib/etc/libimagutil" } +libimagentryutil = { version = "0.8.0", path = "../../../lib/entry/libimagentryutil" } +libimagentrylink = { version = "0.8.0", path = "../../../lib/entry/libimagentrylink" } [dev-dependencies] env_logger = "0.5" diff --git a/lib/entry/libimagentrycategory/src/category.rs b/lib/entry/libimagentrycategory/src/category.rs index 9fdb397b..fab8715f 100644 --- a/lib/entry/libimagentrycategory/src/category.rs +++ b/lib/entry/libimagentrycategory/src/category.rs @@ -19,16 +19,25 @@ use libimagentryutil::isa::Is; use libimagentryutil::isa::IsKindHeaderPathProvider; +use libimagstore::store::Entry; +use libimagstore::store::Store; +use libimagstore::storeid::StoreIdIterator; +use libimagentrylink::internal::InternalLinker; +use toml_query::read::TomlValueReadTypeExt; + +use error::Result; use error::CategoryError as CE; +use error::CategoryErrorKind as CEK; use store::CATEGORY_REGISTER_NAME_FIELD_PATH; +use iter::CategoryEntryIterator; provide_kindflag_path!(pub IsCategory, "category.is_category"); pub trait Category { - fn is_category(&self) -> Result; - fn get_name(&self) -> Result; - fn get_entries(&self, store: &Store) -> Result; + fn is_category(&self) -> Result; + fn get_name(&self) -> Result; + fn get_entries<'a>(&self, store: &'a Store) -> Result>; } impl Category for Entry { @@ -37,11 +46,19 @@ impl Category for Entry { } fn get_name(&self) -> Result { - self.get_header().read_string(CATEGORY_REGISTER_NAME_FIELD_PATH).map_err(CE::from) + trace!("Getting category name of '{:?}'", self.get_location()); + self.get_header() + .read_string(CATEGORY_REGISTER_NAME_FIELD_PATH) + .map_err(CE::from)? + .ok_or_else(|| CE::from_kind(CEK::CategoryNameMissing)) } - fn get_entries(&self, store: &Store) -> Result { - unimplemented!() + fn get_entries<'a>(&self, store: &'a Store) -> Result> { + trace!("Getting linked entries for category '{:?}'", self.get_location()); + let sit = self.get_internal_links()?.map(|l| l.get_store_id().clone()); + let sit = StoreIdIterator::new(Box::new(sit)); + let name = self.get_name()?; + Ok(CategoryEntryIterator::new(store, sit, name)) } } diff --git a/lib/entry/libimagentrycategory/src/entry.rs b/lib/entry/libimagentrycategory/src/entry.rs index a9abe76c..c6f82e04 100644 --- a/lib/entry/libimagentrycategory/src/entry.rs +++ b/lib/entry/libimagentrycategory/src/entry.rs @@ -23,37 +23,21 @@ use toml_query::read::TomlValueReadTypeExt; use toml::Value; use libimagstore::store::Entry; +use libimagentrylink::internal::InternalLinker; use error::CategoryErrorKind as CEK; use error::CategoryError as CE; use error::ResultExt; use error::Result; -use register::CategoryRegister; - -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] -pub struct Category(String); - -impl From for Category { - - fn from(s: String) -> Category { - Category(s) - } - -} - -impl Into for Category { - fn into(self) -> String { - self.0 - } -} +use store::CategoryStore; pub trait EntryCategory { - fn set_category(&mut self, s: Category) -> Result<()>; + fn set_category(&mut self, s: &str) -> Result<()>; - fn set_category_checked(&mut self, register: &CategoryRegister, s: Category) -> Result<()>; + fn set_category_checked(&mut self, register: &CategoryStore, s: &str) -> Result<()>; - fn get_category(&self) -> Result>; + fn get_category(&self) -> Result; fn has_category(&self) -> Result; @@ -61,9 +45,10 @@ pub trait EntryCategory { impl EntryCategory for Entry { - fn set_category(&mut self, s: Category) -> Result<()> { + fn set_category(&mut self, s: &str) -> Result<()> { + trace!("Setting category '{}' UNCHECKED", s); self.get_header_mut() - .insert(&String::from("category.value"), Value::String(s.into())) + .insert(&String::from("category.value"), Value::String(s.to_string())) .chain_err(|| CEK::HeaderWriteError) .map(|_| ()) } @@ -71,10 +56,10 @@ impl EntryCategory for Entry { /// Check whether a category exists before setting it. /// /// This function should be used by default over EntryCategory::set_category()! - fn set_category_checked(&mut self, register: &CategoryRegister, s: Category) -> Result<()> { - let c_str = s.clone().into(); + fn set_category_checked(&mut self, register: &CategoryStore, s: &str) -> Result<()> { + trace!("Setting category '{}' checked", s); let mut category = register - .get_category_by_name(&c_str)? + .get_category_by_name(s)? .ok_or_else(|| CE::from_kind(CEK::CategoryDoesNotExist))?; let _ = self.set_category(s)?; @@ -83,15 +68,15 @@ impl EntryCategory for Entry { Ok(()) } - fn get_category(&self) -> Result> { + fn get_category(&self) -> Result { + trace!("Getting category from '{}'", self.get_location()); self.get_header() - .read_string("category.value") - .chain_err(|| CEK::HeaderReadError) - .and_then(|o| o.map(Category::from).ok_or(CE::from_kind(CEK::TypeError))) - .map(Some) + .read_string("category.value")? + .ok_or_else(|| CE::from_kind(CEK::CategoryNameMissing)) } fn has_category(&self) -> Result { + trace!("Has category? '{}'", self.get_location()); self.get_header().read("category.value") .chain_err(|| CEK::HeaderReadError) .map(|x| x.is_some()) diff --git a/lib/entry/libimagentrycategory/src/error.rs b/lib/entry/libimagentrycategory/src/error.rs index 9cf446e6..f9b90ff3 100644 --- a/lib/entry/libimagentrycategory/src/error.rs +++ b/lib/entry/libimagentrycategory/src/error.rs @@ -24,6 +24,8 @@ error_chain! { links { StoreError(::libimagstore::error::StoreError, ::libimagstore::error::StoreErrorKind); + LinkError(::libimagentrylink::error::LinkError, ::libimagentrylink::error::LinkErrorKind); + EntryUtilError(::libimagentryutil::error::EntryUtilError, ::libimagentryutil::error::EntryUtilErrorKind); } foreign_links { @@ -65,6 +67,11 @@ error_chain! { description("Type Error") display("Type Error") } + + CategoryNameMissing { + description("Category name is missing") + display("Category name is missing") + } } } diff --git a/lib/entry/libimagentrycategory/src/iter.rs b/lib/entry/libimagentrycategory/src/iter.rs index 7896bcbd..a835b82a 100644 --- a/lib/entry/libimagentrycategory/src/iter.rs +++ b/lib/entry/libimagentrycategory/src/iter.rs @@ -19,11 +19,16 @@ use libimagstore::storeid::StoreIdIterator; use libimagstore::store::Store; +use libimagstore::store::FileLockEntry; + +use toml_query::read::TomlValueReadTypeExt; use error::Result; use error::CategoryError as CE; use error::CategoryErrorKind as CEK; use store::CATEGORY_REGISTER_NAME_FIELD_PATH; +use entry::EntryCategory; +use error::ResultExt; /// Iterator for Category names /// @@ -41,14 +46,14 @@ pub struct CategoryNameIter<'a>(&'a Store, StoreIdIterator); impl<'a> CategoryNameIter<'a> { - fn new(store: &'a Store, sidit: StoreIdIterator) -> CategoryNameIter<'a> { + pub(crate) fn new(store: &'a Store, sidit: StoreIdIterator) -> CategoryNameIter<'a> { CategoryNameIter(store, sidit) } } impl<'a> Iterator for CategoryNameIter<'a> { - type Item = Result; + type Item = Result; fn next(&mut self) -> Option { // TODO: Optimize me with lazy_static @@ -63,7 +68,6 @@ impl<'a> Iterator for CategoryNameIter<'a> { .get_header() .read_string(query) .chain_err(|| CEK::HeaderReadError)? - .map(Category::from) .ok_or_else(|| CE::from_kind(CEK::StoreReadError)) }; @@ -75,3 +79,38 @@ impl<'a> Iterator for CategoryNameIter<'a> { } } +pub struct CategoryEntryIterator<'a>(&'a Store, StoreIdIterator, String); + +impl<'a> CategoryEntryIterator<'a> { + pub(crate) fn new(store: &'a Store, sit: StoreIdIterator, name: String) -> Self { + CategoryEntryIterator(store, sit, name) + } +} + +impl<'a> Iterator for CategoryEntryIterator<'a> { + type Item = Result>; + + fn next(&mut self) -> Option { + while let Some(next) = self.1.next() { + let getter = |next| -> Result<(String, FileLockEntry<'a>)> { + let entry = self.0 + .get(next)? + .ok_or_else(|| CE::from_kind(CEK::StoreReadError))?; + Ok((entry.get_category()?, entry)) + }; + + match getter(next) { + Err(e) => return Some(Err(e)), + Ok((c, e)) => { + if c == self.2 { + return Some(Ok(e)) + // } else { + // continue + } + } + } + } + + None + } +} diff --git a/lib/entry/libimagentrycategory/src/lib.rs b/lib/entry/libimagentrycategory/src/lib.rs index 66f0a9c8..0f0e1189 100644 --- a/lib/entry/libimagentrycategory/src/lib.rs +++ b/lib/entry/libimagentrycategory/src/lib.rs @@ -38,14 +38,14 @@ extern crate toml_query; extern crate toml; #[macro_use] -extern crate is_match; -#[macro_use] extern crate log; #[macro_use] extern crate error_chain; extern crate libimagerror; -#[macro_use] -extern crate libimagstore; +#[macro_use] extern crate libimagstore; +extern crate libimagutil; +#[macro_use] extern crate libimagentryutil; +extern crate libimagentrylink; pub mod category; pub mod entry; diff --git a/lib/entry/libimagentrycategory/src/store.rs b/lib/entry/libimagentrycategory/src/store.rs index 4c2e26cf..5fc87347 100644 --- a/lib/entry/libimagentrycategory/src/store.rs +++ b/lib/entry/libimagentrycategory/src/store.rs @@ -26,14 +26,14 @@ use toml::Value; use libimagstore::store::Store; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreId; -use libimagstore::storeid::StoreIdIterator; +use libimagentryutil::isa::Is; -use category::Category; use error::CategoryErrorKind as CEK; use error::CategoryError as CE; use error::ResultExt; use error::Result; use iter::CategoryNameIter; +use category::IsCategory; pub const CATEGORY_REGISTER_NAME_FIELD_PATH : &'static str = "category.register.name"; @@ -44,7 +44,7 @@ pub trait CategoryStore { fn category_exists(&self, name: &str) -> Result; - fn create_category(&self, name: &str) -> Result; + fn create_category<'a>(&'a self, name: &str) -> Result>; fn delete_category(&self, name: &str) -> Result<()>; @@ -58,6 +58,7 @@ impl CategoryStore for Store { /// Check whether a category exists fn category_exists(&self, name: &str) -> Result { + trace!("Category exists? '{}'", name); let sid = mk_category_storeid(self.path().clone(), name)?; represents_category(self, sid, name) } @@ -65,7 +66,8 @@ impl CategoryStore for Store { /// Create a category /// /// Fails if the category already exists (returns false then) - fn create_category(&self, name: &str) -> Result> { + fn create_category<'a>(&'a self, name: &str) -> Result> { + trace!("Creating category: '{}'", name); let sid = mk_category_storeid(self.path().clone(), name)?; let mut entry = self.create(sid)?; @@ -75,17 +77,20 @@ impl CategoryStore for Store { .get_header_mut() .insert(CATEGORY_REGISTER_NAME_FIELD_PATH, Value::String(String::from(name)))?; + trace!("Creating category worked: '{}'", name); Ok(entry) } /// Delete a category fn delete_category(&self, name: &str) -> Result<()> { + trace!("Deleting category: '{}'", name); let sid = mk_category_storeid(self.path().clone(), name)?; self.delete(sid).map_err(CE::from) } /// Get all category names fn all_category_names(&self) -> Result { + trace!("Getting all category names"); Ok(CategoryNameIter::new(self, self.entries()?.without_store())) } @@ -94,6 +99,7 @@ impl CategoryStore for Store { /// Returns the FileLockEntry which represents the category, so one can link to it and use it /// like a normal file in the store (which is exactly what it is). fn get_category_by_name(&self, name: &str) -> Result> { + trace!("Getting category by name: '{}'", name); let sid = mk_category_storeid(self.path().clone(), name)?; self.get(sid) From 82867f3ff6b95d0372e586cc5b36861f7679c54c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 26 Apr 2018 14:19:08 +0200 Subject: [PATCH 7/7] Fix tests for new interface --- lib/entry/libimagentrycategory/src/store.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/lib/entry/libimagentrycategory/src/store.rs b/lib/entry/libimagentrycategory/src/store.rs index 5fc87347..e1fb929a 100644 --- a/lib/entry/libimagentrycategory/src/store.rs +++ b/lib/entry/libimagentrycategory/src/store.rs @@ -139,8 +139,6 @@ mod tests { let res = store.create_category(category_name); assert!(res.is_ok(), format!("Expected Ok(_), got: {:?}", res)); - let res = res.unwrap(); - assert!(res); } #[test] @@ -148,11 +146,10 @@ mod tests { let category_name = "examplecategory"; let store = get_store(); - let res = store.create_category(category_name); - - assert!(res.is_ok(), format!("Expected Ok(_), got: {:?}", res)); - let res = res.unwrap(); - assert!(res); + { + let res = store.create_category(category_name); + assert!(res.is_ok(), format!("Expected Ok(_), got: {:?}", res)); + } let category = store.get(PathBuf::from(format!("category/{}", category_name))); @@ -167,11 +164,11 @@ mod tests { let _ = env_logger::try_init(); let category_name = "examplecategory"; let store = get_store(); - let res = store.create_category(category_name); - assert!(res.is_ok(), format!("Expected Ok(_), got: {:?}", res)); - let res = res.unwrap(); - assert!(res); + { + let res = store.create_category(category_name); + assert!(res.is_ok(), format!("Expected Ok(_), got: {:?}", res)); + } let id = PathBuf::from(format!("category/{}", category_name)); println!("Trying: {:?}", id);