diff --git a/imag-diary/src/list.rs b/imag-diary/src/list.rs index 9c0cc3c5..6ec43dcf 100644 --- a/imag-diary/src/list.rs +++ b/imag-diary/src/list.rs @@ -1,4 +1,3 @@ -use std::path::PathBuf; use std::process::exit; use libimagdiary::diary::Diary; @@ -8,7 +7,6 @@ use libimagentrylist::listers::core::CoreLister; use libimagentrylist::lister::Lister; use libimagrt::runtime::Runtime; use libimagstore::store::Entry; -use libimagstore::storeid::StoreId; use libimagerror::trace::trace_error; use util::get_diary_name; @@ -21,11 +19,11 @@ pub fn list(rt: &Runtime) { } let diaryname = diaryname.unwrap(); - fn location_to_listing_string(id: &StoreId, base: &PathBuf) -> String { - id.strip_prefix(base) + fn entry_to_location_listing_string(e: &Entry) -> String { + e.get_location().clone() + .without_base() + .to_str() .map_err(|e| trace_error(&e)) - .ok() - .and_then(|p| p.to_str().map(String::from)) .unwrap_or(String::from("<>")) } @@ -40,9 +38,7 @@ pub fn list(rt: &Runtime) { a.ok() }).map(|e| e.into()); - let base = rt.store().path(); - - CoreLister::new(&move |e: &Entry| location_to_listing_string(e.get_location(), base)) + CoreLister::new(&entry_to_location_listing_string) .list(es) // TODO: Do not ignore non-ok()s .map_err(|e| DE::new(DEK::IOError, Some(Box::new(e)))) }) diff --git a/imag-link/Cargo.toml b/imag-link/Cargo.toml index ed215bc5..96615b6c 100644 --- a/imag-link/Cargo.toml +++ b/imag-link/Cargo.toml @@ -23,3 +23,6 @@ path = "../libimagentrylink" [dependencies.libimagerror] path = "../libimagerror" +[dependencies.libimagutil] +path = "../libimagutil" + diff --git a/imag-link/src/main.rs b/imag-link/src/main.rs index c1448678..fd8d9d5d 100644 --- a/imag-link/src/main.rs +++ b/imag-link/src/main.rs @@ -24,6 +24,7 @@ extern crate libimagentrylink; extern crate libimagrt; extern crate libimagstore; extern crate libimagerror; +extern crate libimagutil; use std::process::exit; use std::ops::Deref; @@ -36,6 +37,7 @@ use libimagstore::store::FileLockEntry; use libimagstore::store::Store; use libimagerror::trace::{trace_error, trace_error_exit}; use libimagentrylink::external::ExternalLinker; +use libimagutil::warn_result::*; use clap::ArgMatches; use url::Url; @@ -74,10 +76,19 @@ fn handle_internal_linking(rt: &Runtime) { for entry in cmd.value_of("list").unwrap().split(',') { debug!("Listing for '{}'", entry); match get_entry_by_name(rt, entry) { - Ok(e) => { + Ok(Some(e)) => { e.get_internal_links() .map(|links| { - for (i, link) in links.iter().map(|l| l.to_str()).filter_map(|x| x).enumerate() { + let i = links + .iter() + .filter_map(|l| { + l.to_str() + .map_warn_err(|e| format!("Failed to convert StoreId to string: {:?}", e)) + .ok() + }) + .enumerate(); + + for (i, link) in i { println!("{: <3}: {}", i, link); } }) @@ -85,6 +96,11 @@ fn handle_internal_linking(rt: &Runtime) { .ok(); }, + Ok(None) => { + warn!("Entry not found: {:?}", entry); + break; + } + Err(e) => { trace_error(&e); break; @@ -148,7 +164,8 @@ fn get_from_entry<'a>(rt: &'a Runtime) -> Option> { debug!("We couldn't get the entry from name: '{:?}'", from_name); trace_error(&e); None }, - Ok(e) => Some(e), + Ok(Some(e)) => Some(e), + Ok(None) => None, } }) @@ -166,17 +183,20 @@ fn get_to_entries<'a>(rt: &'a Runtime) -> Option>> { for entry in values.map(|v| get_entry_by_name(rt, v)) { match entry { Err(e) => trace_error(&e), - Ok(e) => v.push(e), + Ok(Some(e)) => v.push(e), + Ok(None) => warn!("Entry not found: {:?}", v), } } v }) } -fn get_entry_by_name<'a>(rt: &'a Runtime, name: &str) -> Result, StoreError> { - use libimagstore::storeid::build_entry_path; - build_entry_path(rt.store(), name) - .and_then(|path| rt.store().retrieve(path)) +fn get_entry_by_name<'a>(rt: &'a Runtime, name: &str) -> Result>, StoreError> { + use std::path::PathBuf; + use libimagstore::storeid::StoreId; + + StoreId::new(Some(rt.store().path().clone()), PathBuf::from(name)) + .and_then(|id| rt.store().get(id)) } fn handle_external_linking(rt: &Runtime) { @@ -186,6 +206,11 @@ fn handle_external_linking(rt: &Runtime) { if entry.is_err() { trace_error_exit(&entry.unwrap_err(), 1); } + let entry = entry.unwrap(); + if entry.is_none() { + warn!("Entry not found: {:?}", entry_name); + return; + } let mut entry = entry.unwrap(); if scmd.is_present("add") { diff --git a/imag-store/src/create.rs b/imag-store/src/create.rs index 7329df3f..0380ddf5 100644 --- a/imag-store/src/create.rs +++ b/imag-store/src/create.rs @@ -13,8 +13,9 @@ use clap::ArgMatches; use libimagrt::runtime::Runtime; use libimagstore::store::Entry; use libimagstore::store::EntryHeader; -use libimagstore::storeid::build_entry_path; +use libimagstore::storeid::StoreId; use libimagerror::trace::trace_error_exit; +use libimagutil::debug_result::*; use error::StoreError; use error::StoreErrorKind; @@ -36,13 +37,15 @@ pub fn create(rt: &Runtime) { exit(1); } - let path = match build_entry_path(rt.store(), path.unwrap()) { + let store_path = rt.store().path().clone(); + let path = match StoreId::new(Some(store_path), PathBuf::from(path.unwrap())) { Err(e) => trace_error_exit(&e, 1), - Ok(p) => p, + Ok(o) => o, }; debug!("path = {:?}", path); if scmd.subcommand_matches("entry").is_some() { + debug!("Creating entry from CLI specification"); create_from_cli_spec(rt, scmd, &path) .or_else(|_| create_from_source(rt, scmd, &path)) .or_else(|_| create_with_content_and_header(rt, @@ -50,13 +53,17 @@ pub fn create(rt: &Runtime) { String::new(), EntryHeader::new())) } else { + debug!("Creating entry"); create_with_content_and_header(rt, &path, String::new(), EntryHeader::new()) } - .unwrap_or_else(|e| debug!("Error building Entry: {:?}", e)) + .unwrap_or_else(|e| { + error!("Error building Entry"); + trace_error_exit(&e, 1); + }) }); } -fn create_from_cli_spec(rt: &Runtime, matches: &ArgMatches, path: &PathBuf) -> Result<()> { +fn create_from_cli_spec(rt: &Runtime, matches: &ArgMatches, path: &StoreId) -> Result<()> { let content = matches.subcommand_matches("entry") .map_or_else(|| { debug!("Didn't find entry subcommand, getting raw content"); @@ -80,7 +87,7 @@ fn create_from_cli_spec(rt: &Runtime, matches: &ArgMatches, path: &PathBuf) -> R create_with_content_and_header(rt, path, content, header) } -fn create_from_source(rt: &Runtime, matches: &ArgMatches, path: &PathBuf) -> Result<()> { +fn create_from_source(rt: &Runtime, matches: &ArgMatches, path: &StoreId) -> Result<()> { let content = matches .value_of("from-raw") .ok_or(StoreError::new(StoreErrorKind::NoCommandlineCall, None)) @@ -93,9 +100,11 @@ fn create_from_source(rt: &Runtime, matches: &ArgMatches, path: &PathBuf) -> Res debug!("Content with len = {}", content.len()); Entry::from_str(path.clone(), &content[..]) + .map_dbg_err(|e| format!("Error building entry: {:?}", e)) .and_then(|new_e| { let r = rt.store() .create(path.clone()) + .map_dbg_err(|e| format!("Error in Store::create(): {:?}", e)) .map(|mut old_e| { *old_e.deref_mut() = new_e; }); @@ -103,17 +112,19 @@ fn create_from_source(rt: &Runtime, matches: &ArgMatches, path: &PathBuf) -> Res debug!("Entry build"); r }) + .map_dbg_err(|e| format!("Error storing entry: {:?}", e)) .map_err(|serr| StoreError::new(StoreErrorKind::BackendError, Some(Box::new(serr)))) } fn create_with_content_and_header(rt: &Runtime, - path: &PathBuf, + path: &StoreId, content: String, header: EntryHeader) -> Result<()> { - debug!("Creating entry with content"); + debug!("Creating entry with content at {:?}", path); rt.store() - .create(PathBuf::from(path)) + .create(path.clone()) + .map_dbg_err(|e| format!("Error in Store::create(): {:?}", e)) .map(|mut element| { { let mut e_content = element.get_content_mut(); diff --git a/imag-store/src/delete.rs b/imag-store/src/delete.rs index 46626816..537b638d 100644 --- a/imag-store/src/delete.rs +++ b/imag-store/src/delete.rs @@ -1,6 +1,8 @@ -use libimagstore::storeid::build_entry_path; +use std::path::PathBuf; + use libimagrt::runtime::Runtime; use libimagerror::trace::trace_error_exit; +use libimagstore::storeid::StoreId; pub fn delete(rt: &Runtime) { use std::process::exit; @@ -10,7 +12,8 @@ pub fn delete(rt: &Runtime) { .map(|sub| { sub.value_of("id") .map(|id| { - let path = try!(build_entry_path(rt.store(), id) + let path = PathBuf::from(id); + let path = try!(StoreId::new(Some(rt.store().path().clone()), path) .map_err(|e| trace_error_exit(&e, 1))); debug!("Deleting file at {:?}", id); diff --git a/imag-store/src/get.rs b/imag-store/src/get.rs index 3e33ac2b..1302b763 100644 --- a/imag-store/src/get.rs +++ b/imag-store/src/get.rs @@ -1,6 +1,8 @@ -use libimagstore::storeid::build_entry_path; +use std::path::PathBuf; + use libimagrt::runtime::Runtime; use libimagerror::trace::{trace_error, trace_error_exit}; +use libimagstore::storeid::StoreId; use retrieve::print_entry; @@ -10,7 +12,8 @@ pub fn get(rt: &Runtime) { .map(|scmd| { scmd.value_of("id") .map(|id| { - let path = match build_entry_path(rt.store(), id) { + let path = PathBuf::from(id); + let path = match StoreId::new(Some(rt.store().path().clone()), path) { Err(e) => trace_error_exit(&e, 1), Ok(p) => p, }; diff --git a/imag-store/src/retrieve.rs b/imag-store/src/retrieve.rs index f9f45993..39b66741 100644 --- a/imag-store/src/retrieve.rs +++ b/imag-store/src/retrieve.rs @@ -1,8 +1,10 @@ +use std::path::PathBuf; + use clap::ArgMatches; use toml::Value; use libimagstore::store::FileLockEntry; -use libimagstore::storeid::build_entry_path; +use libimagstore::storeid::StoreId; use libimagrt::runtime::Runtime; use libimagerror::trace::{trace_error, trace_error_exit}; @@ -12,7 +14,8 @@ pub fn retrieve(rt: &Runtime) { .map(|scmd| { scmd.value_of("id") .map(|id| { - let path = try!(build_entry_path(rt.store(), id) + let path = PathBuf::from(id); + let path = try!(StoreId::new(Some(rt.store().path().clone()), path) .map_err(|e| trace_error_exit(&e, 1))); debug!("path = {:?}", path); diff --git a/imag-store/src/update.rs b/imag-store/src/update.rs index 9959ec09..87279dc0 100644 --- a/imag-store/src/update.rs +++ b/imag-store/src/update.rs @@ -1,8 +1,9 @@ use std::ops::DerefMut; +use std::path::PathBuf; use libimagrt::runtime::Runtime; -use libimagstore::storeid::build_entry_path; use libimagerror::trace::trace_error_exit; +use libimagstore::storeid::StoreId; use util::build_toml_header; @@ -12,7 +13,8 @@ pub fn update(rt: &Runtime) { .map(|scmd| { scmd.value_of("id") .map(|id| { - let path = match build_entry_path(rt.store(), id) { + let path = PathBuf::from(id); + let path = match StoreId::new(Some(rt.store().path().clone()), path) { Err(e) => trace_error_exit(&e, 1), Ok(p) => p, }; diff --git a/imag-store/tests/001-create_test.sh b/imag-store/tests/001-create_test.sh index 4f767c7d..3d030b34 100644 --- a/imag-store/tests/001-create_test.sh +++ b/imag-store/tests/001-create_test.sh @@ -4,7 +4,7 @@ source $(dirname ${BASH_SOURCE[0]})/../../tests/utils.sh source $(dirname ${BASH_SOURCE[0]})/utils.sh test_call() { - imag-store create -p /test-call~0.2.0 + imag-store create -p test-call if [[ ! $? -eq 0 ]]; then err "Return value should be zero, was non-zero" return 1; @@ -12,7 +12,7 @@ test_call() { } test_call_id() { - imag-store create -i /test-call~0.2.0 + imag-store create -i test-call if [[ ! $? -eq 0 ]]; then err "Return value should be zero, was non-zero" return 1; @@ -28,7 +28,7 @@ test_call_no_id() { } test_mkstore() { - imag-store create -p /test-mkstore~0.2.0 || { err "Calling imag failed"; return 1; } + imag-store create -p test-mkstore || { err "Calling imag failed"; return 1; } if [[ -d ${STORE} ]]; then out "Store exists." else @@ -48,12 +48,12 @@ version = "0.2.0" EOS ) - imag-store create -p /test-std-header~0.2.0 - local result=$(cat ${STORE}/test-std-header~0.2.0) + imag-store create -p test-std-header + local result=$(cat ${STORE}/test-std-header) if [[ "$expected" == "$result" ]]; then out "Expected store entry == result" else - err "${STORE}/test-std-header~0.2.0 differs from expected" + err "${STORE}/test-std-header differs from expected" return 1 fi } @@ -72,8 +72,8 @@ zzz = "z" EOS ) - imag-store create -p /test-std-header-plus-custom~0.2.0 entry -h zzz.zzz=z - local result=$(cat ${STORE}/test-std-header-plus-custom~0.2.0) + imag-store create -p test-std-header-plus-custom entry -h zzz.zzz=z + local result=$(cat ${STORE}/test-std-header-plus-custom) if [[ "$expected" == "$result" ]]; then out "Expected store entry == result" else @@ -99,8 +99,8 @@ zzz = "z" EOS ) - local filename="test-std-header-plus-custom-multiheader~0.2.0" - imag-store create -p /$filename entry -h zzz.zzz=z foo.bar=baz + local filename="test-std-header-plus-custom-multiheader" + imag-store create -p $filename entry -h zzz.zzz=z foo.bar=baz local result=$(cat ${STORE}/$filename) if [[ "$expected" == "$result" ]]; then out "Expected store entry == result" @@ -126,8 +126,8 @@ zzz = "z" EOS ) - local filename="test-std-header-plus-custom-mutliheader-same-section~0.2.0" - imag-store create -p /$filename entry -h zzz.zzz=z zzz.bar=baz + local filename="test-std-header-plus-custom-mutliheader-same-section" + imag-store create -p $filename entry -h zzz.zzz=z zzz.bar=baz local result=$(cat ${STORE}/$filename) if [[ "$expected" == "$result" ]]; then out "Expected store entry == result" @@ -151,8 +151,8 @@ content EOS ) - local name="test-std-header-plus-custom-and-content~0.2.0" - imag-store create -p /$name entry -h zzz.zzz=z -c content + local name="test-std-header-plus-custom-and-content" + imag-store create -p $name entry -h zzz.zzz=z -c content local result=$(cat ${STORE}/$name) if [[ "$expected" == "$result" ]]; then out "Expected store entry == result" diff --git a/imag-store/tests/002-retrieve_test.sh b/imag-store/tests/002-retrieve_test.sh index 01fcfd3e..1e6e7203 100644 --- a/imag-store/tests/002-retrieve_test.sh +++ b/imag-store/tests/002-retrieve_test.sh @@ -18,9 +18,9 @@ retrieve() { } test_retrieve_nothing() { - local id="test-retrieve_nothing~0.2.0" + local id="test-retrieve_nothing" - imag-store create -p /${id} || { err "create failed"; return 1; } + imag-store create -p ${id} || { err "create failed"; return 1; } out "Going to test the retrieve functionality now" local zero_out="$(retrieve --id /${id})" @@ -33,9 +33,9 @@ test_retrieve_nothing() { } test_retrieve_content() { - local id="test-retrieve_simple~0.2.0" + local id="test-retrieve_simple" - imag-store create -p /${id} || { err "create failed"; return 1; } + imag-store create -p ${id} || { err "create failed"; return 1; } out "Going to test the retrieve functionality now" @@ -49,12 +49,12 @@ test_retrieve_content() { } test_retrieve_header() { - local id="test-retrieve_simple~0.2.0" + local id="test-retrieve_simple" - imag-store create -p /${id} || { err "create failed"; return 1; } + imag-store create -p ${id} || { err "create failed"; return 1; } out "Going to test the retrieve functionality now" - local header_out="$(retrieve --id /${id} --header)" + local header_out="$(retrieve --id ${id} --header)" out "Retrieving for header_out finished" if [[ ! "$header_out" != "$(std_header)" ]]; then @@ -64,12 +64,12 @@ test_retrieve_header() { } test_retrieve_raw() { - local id="test-retrieve_simple~0.2.0" + local id="test-retrieve_simple" - imag-store create -p /${id} || { err "create failed"; return 1; } + imag-store create -p ${id} || { err "create failed"; return 1; } out "Going to test the retrieve functionality now" - local both_out="$(retrieve --id /${id} --raw)" + local both_out="$(retrieve --id ${id} --raw)" out "Retrieving for both_out finished" if [[ "$both_out" != "$(std_header)" ]]; then diff --git a/imag-store/tests/003-delete_test.sh b/imag-store/tests/003-delete_test.sh index a0eb97a2..a3d890e5 100644 --- a/imag-store/tests/003-delete_test.sh +++ b/imag-store/tests/003-delete_test.sh @@ -12,10 +12,10 @@ delete() { } test_delete_simple() { - local name="test~0.2.0" + local name="test" - create -p /$name - delete --id /$name + create -p $name + delete --id $name local n=$($(find ${STORE}/ -type f | wc -l)) if [[ $n -eq 0 ]]; then diff --git a/imag-tag/src/main.rs b/imag-tag/src/main.rs index b01a74f0..f7c91dd0 100644 --- a/imag-tag/src/main.rs +++ b/imag-tag/src/main.rs @@ -10,14 +10,15 @@ extern crate libimagentrytag; extern crate libimagerror; use std::process::exit; +use std::path::PathBuf; use libimagrt::runtime::Runtime; use libimagrt::setup::generate_runtime_setup; use libimagentrytag::tagable::Tagable; use libimagentrytag::tag::Tag; -use libimagstore::storeid::build_entry_path; use libimagerror::trace::{trace_error, trace_error_exit}; use libimagentrytag::ui::{get_add_tags, get_remove_tags}; +use libimagstore::storeid::StoreId; mod ui; @@ -34,11 +35,13 @@ fn main() { .subcommand_name() .map_or_else( || { + let id = PathBuf::from(id); let add = get_add_tags(rt.cli()); let rem = get_remove_tags(rt.cli()); alter(&rt, id, add, rem); }, |name| { + let id = PathBuf::from(id); debug!("Call: {}", name); match name { "list" => list(id, &rt), @@ -50,9 +53,9 @@ fn main() { }); } -fn alter(rt: &Runtime, id: &str, add: Option>, rem: Option>) { +fn alter(rt: &Runtime, id: PathBuf, add: Option>, rem: Option>) { let path = { - match build_entry_path(rt.store(), id) { + match StoreId::new(Some(rt.store().path().clone()), id) { Err(e) => trace_error_exit(&e, 1), Ok(s) => s, } @@ -91,12 +94,10 @@ fn alter(rt: &Runtime, id: &str, add: Option>, rem: Option>) { } } -fn list(id: &str, rt: &Runtime) { - let path = { - match build_entry_path(rt.store(), id) { - Err(e) => trace_error_exit(&e, 1), - Ok(s) => s, - } +fn list(id: PathBuf, rt: &Runtime) { + let path = match StoreId::new(Some(rt.store().path().clone()), id) { + Err(e) => trace_error_exit(&e, 1), + Ok(s) => s, }; debug!("path = {:?}", path); @@ -108,8 +109,7 @@ fn list(id: &str, rt: &Runtime) { }, Err(e) => { - debug!("Could not get '{:?}' => {:?}", id, path); - warn!("Could not get entry '{}'", id); + warn!("Could not get entry '{:?}'", path); trace_error_exit(&e, 1); }, }; diff --git a/imag-view/src/main.rs b/imag-view/src/main.rs index 907758ae..ae9d5d29 100644 --- a/imag-view/src/main.rs +++ b/imag-view/src/main.rs @@ -30,7 +30,6 @@ use std::path::PathBuf; use libimagrt::setup::generate_runtime_setup; use libimagerror::trace::trace_error_exit; use libimagentryview::builtin::stdout::StdoutViewer; -use libimagentryview::builtin::versions::VersionsViewer; use libimagentryview::viewer::Viewer; mod ui; @@ -68,9 +67,7 @@ fn main() { } }; - let res = if rt.cli().is_present("versions") { - VersionsViewer::new(rt.store()).view_entry(&entry) - } else { + let res = { if scmd.is_present("view-in-stdout") { } else if scmd.is_present("view-in-ui") { warn!("Viewing in UI is currently not supported, switch to stdout"); diff --git a/imag-view/src/ui.rs b/imag-view/src/ui.rs index 3d6592ad..b1081e86 100644 --- a/imag-view/src/ui.rs +++ b/imag-view/src/ui.rs @@ -10,12 +10,6 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .help("View this entry at this store path") .value_name("ID")) - .arg(Arg::with_name("versions") - .long("versions") - .takes_value(false) - .required(false) - .help("Only print available versions for this file")) - .arg(Arg::with_name("view-header") .long("header") .short("h") diff --git a/libimagbookmark/src/collection.rs b/libimagbookmark/src/collection.rs index b7fc4459..b2cde9ef 100644 --- a/libimagbookmark/src/collection.rs +++ b/libimagbookmark/src/collection.rs @@ -51,8 +51,9 @@ impl<'a> DerefMut for BookmarkCollection<'a> { impl<'a> BookmarkCollection<'a> { pub fn new(store: &'a Store, name: &str) -> Result> { - let id = ModuleEntryPath::new(name).into_storeid(); - store.create(id) + ModuleEntryPath::new(name) + .into_storeid() + .and_then(|id| store.create(id)) .map(|fle| { BookmarkCollection { fle: fle, @@ -63,8 +64,9 @@ impl<'a> BookmarkCollection<'a> { } pub fn get(store: &'a Store, name: &str) -> Result> { - let id = ModuleEntryPath::new(name).into_storeid(); - store.get(id) + ModuleEntryPath::new(name) + .into_storeid() + .and_then(|id| store.get(id)) .map_err_into(BEK::StoreReadError) .and_then(|fle| { match fle { @@ -78,7 +80,10 @@ impl<'a> BookmarkCollection<'a> { } pub fn delete(store: &Store, name: &str) -> Result<()> { - store.delete(ModuleEntryPath::new(name).into_storeid()).map_err_into(BEK::StoreReadError) + ModuleEntryPath::new(name) + .into_storeid() + .and_then(|id| store.delete(id)) + .map_err_into(BEK::StoreReadError) } pub fn links(&self) -> Result> { diff --git a/libimagbookmark/src/lib.rs b/libimagbookmark/src/lib.rs index 5b0a82ef..bc98b061 100644 --- a/libimagbookmark/src/lib.rs +++ b/libimagbookmark/src/lib.rs @@ -21,7 +21,7 @@ extern crate regex; #[macro_use] extern crate libimagerror; extern crate libimagentrylink; -module_entry_path_mod!("bookmark", "0.1.0"); +module_entry_path_mod!("bookmark"); pub mod collection; pub mod error; diff --git a/libimagcounter/src/counter.rs b/libimagcounter/src/counter.rs index 8aa7e4bb..e6a6e309 100644 --- a/libimagcounter/src/counter.rs +++ b/libimagcounter/src/counter.rs @@ -48,8 +48,10 @@ impl<'a> Counter<'a> { debug!("Creating new counter: '{}' with value: {}", name, init); let fle = { - let mut lockentry = try!(store.create(ModuleEntryPath::new(name.clone()).into_storeid()) - .map_err_into(CEK::StoreWriteError)); + let id = try!(ModuleEntryPath::new(name.clone()) + .into_storeid() + .map_err_into(CEK::StoreWriteError)); + let mut lockentry = try!(store.create(id).map_err_into(CEK::StoreWriteError)); { let mut entry = lockentry.deref_mut(); @@ -153,7 +155,7 @@ impl<'a> Counter<'a> { }) } - fn read_header_at(&self, name: &str, f: F) -> Result + fn read_header_at(&self, name: &str, f: F) -> Result where F: FnOnce(Option) -> Result { self.fle.get_header().read(name).map_err_into(CEK::StoreWriteError).and_then(f) @@ -161,14 +163,18 @@ impl<'a> Counter<'a> { pub fn load(name: CounterName, store: &Store) -> Result { debug!("Loading counter: '{}'", name); - let id = ModuleEntryPath::new(name).into_storeid(); + let id = try!(ModuleEntryPath::new(name) + .into_storeid() + .map_err_into(CEK::StoreWriteError)); Counter::from_storeid(store, id) } pub fn delete(name: CounterName, store: &Store) -> Result<()> { debug!("Deleting counter: '{}'", name); - store.delete(ModuleEntryPath::new(name).into_storeid()) - .map_err_into(CEK::StoreWriteError) + let id = try!(ModuleEntryPath::new(name) + .into_storeid() + .map_err_into(CEK::StoreWriteError)); + store.delete(id).map_err_into(CEK::StoreWriteError) } pub fn all_counters(store: &Store) -> Result { @@ -195,7 +201,7 @@ impl<'a> FromStoreId for Counter<'a> { .map_err_into(CEK::StoreReadError) .and_then(|u| { counter.unit = u; - Ok(counter) + Ok(counter) }) } } diff --git a/libimagcounter/src/error.rs b/libimagcounter/src/error.rs index e8016fb6..e151c407 100644 --- a/libimagcounter/src/error.rs +++ b/libimagcounter/src/error.rs @@ -1,5 +1,6 @@ generate_error_module!( generate_error_types!(CounterError, CounterErrorKind, + StoreIdError => "StoreId error", StoreReadError => "Store read error", StoreWriteError => "Store write error", HeaderTypeError => "Header type error", diff --git a/libimagcounter/src/lib.rs b/libimagcounter/src/lib.rs index 957ac9f9..75340ad6 100644 --- a/libimagcounter/src/lib.rs +++ b/libimagcounter/src/lib.rs @@ -19,7 +19,7 @@ extern crate toml; #[macro_use] extern crate libimagstore; #[macro_use] extern crate libimagerror; -module_entry_path_mod!("counter", "0.2.0"); +module_entry_path_mod!("counter"); pub mod counter; pub mod error; diff --git a/libimagdiary/src/diary.rs b/libimagdiary/src/diary.rs index 40eaca88..de8571f9 100644 --- a/libimagdiary/src/diary.rs +++ b/libimagdiary/src/diary.rs @@ -45,8 +45,8 @@ impl<'a> Diary<'a> { } pub fn retrieve(&self, id: DiaryId) -> Result { - self.store - .retrieve(id.into_storeid()) + id.into_storeid() + .and_then(|id| self.store.retrieve(id)) .map(|fle| Entry::new(fle)) .map_err(|e| DE::new(DEK::StoreWriteError, Some(Box::new(e)))) } diff --git a/libimagdiary/src/diaryid.rs b/libimagdiary/src/diaryid.rs index 2cbdce56..74c78309 100644 --- a/libimagdiary/src/diaryid.rs +++ b/libimagdiary/src/diaryid.rs @@ -9,6 +9,7 @@ use chrono::Timelike; use libimagstore::storeid::StoreId; use libimagstore::storeid::IntoStoreId; +use libimagstore::store::Result as StoreResult; use module_path::ModuleEntryPath; @@ -118,7 +119,7 @@ impl Default for DiaryId { impl IntoStoreId for DiaryId { - fn into_storeid(self) -> StoreId { + fn into_storeid(self) -> StoreResult { let s : String = self.into(); ModuleEntryPath::new(s).into_storeid() } diff --git a/libimagdiary/src/is_in_diary.rs b/libimagdiary/src/is_in_diary.rs index 0d0cfccb..2b9d3fc7 100644 --- a/libimagdiary/src/is_in_diary.rs +++ b/libimagdiary/src/is_in_diary.rs @@ -1,6 +1,5 @@ -use std::path::PathBuf; - use libimagstore::store::Entry; +use libimagstore::storeid::StoreId; pub trait IsInDiary { @@ -11,15 +10,15 @@ pub trait IsInDiary { impl IsInDiary for Entry { fn is_in_diary(&self, name: &str) -> bool { - self.get_location().is_in_diary(name) + self.get_location().clone().is_in_diary(name) } } -impl IsInDiary for PathBuf { +impl IsInDiary for StoreId { fn is_in_diary(&self, name: &str) -> bool { - self.to_str().map(|s| s.contains(name)).unwrap_or(false) + self.local().starts_with(format!("diary/{}", name)) } } diff --git a/libimagdiary/src/lib.rs b/libimagdiary/src/lib.rs index 1e68ee2e..5af7eb50 100644 --- a/libimagdiary/src/lib.rs +++ b/libimagdiary/src/lib.rs @@ -28,7 +28,7 @@ extern crate itertools; extern crate libimagentryedit; extern crate libimagrt; -module_entry_path_mod!("diary", "0.2.0"); +module_entry_path_mod!("diary"); pub mod config; pub mod error; diff --git a/libimagentrylink/src/error.rs b/libimagentrylink/src/error.rs index e975ac4a..9c756c3b 100644 --- a/libimagentrylink/src/error.rs +++ b/libimagentrylink/src/error.rs @@ -7,7 +7,8 @@ generate_error_module!( InternalConversionError => "Error while converting values internally", InvalidUri => "URI is not valid", StoreReadError => "Store read error", - StoreWriteError => "Store write error" + StoreWriteError => "Store write error", + StoreIdError => "StoreId handling error" ); ); diff --git a/libimagentrylink/src/external.rs b/libimagentrylink/src/external.rs index a92b8af1..a6c2faef 100644 --- a/libimagentrylink/src/external.rs +++ b/libimagentrylink/src/external.rs @@ -91,8 +91,8 @@ pub trait ExternalLinker : InternalLinker { /// Check whether the StoreId starts with `/link/external/` pub fn is_external_link_storeid(id: &StoreId) -> bool { - debug!("Checking whether this is a /link/external/*: '{:?}'", id); - id.parent().map(|par| par.ends_with("/link/external")).unwrap_or(false) + debug!("Checking whether this is a link/external/*: '{:?}'", id); + id.local().starts_with("link/external") } fn get_external_link_from_file(entry: &FileLockEntry) -> Result { @@ -144,7 +144,13 @@ impl ExternalLinker for Entry { s.input_str(&link.as_str()[..]); s.result_str() }; - let file_id = ModuleEntryPath::new(format!("external/{}", hash)).into_storeid(); + let file_id = try!( + ModuleEntryPath::new(format!("external/{}", hash)).into_storeid() + .map_err_into(LEK::StoreWriteError) + .map_dbg_err(|_| { + format!("Failed to build StoreId for this hash '{:?}'", hash) + }) + ); debug!("Link = '{:?}'", link); debug!("Hash = '{:?}'", hash); diff --git a/libimagentrylink/src/internal.rs b/libimagentrylink/src/internal.rs index 6032fe0b..e6dddb6f 100644 --- a/libimagentrylink/src/internal.rs +++ b/libimagentrylink/src/internal.rs @@ -7,6 +7,7 @@ use libimagstore::store::Result as StoreResult; use libimagerror::into::IntoError; use error::LinkErrorKind as LEK; +use error::MapErrInto; use result::Result; use toml::Value; @@ -53,13 +54,11 @@ impl InternalLinker for Entry { .into_iter() .fold(Ok(vec![]), |acc, elem| { acc.and_then(move |mut v| { - match elem { - None => Err(LEK::InternalConversionError.into()), - Some(e) => { + elem.map_err_into(LEK::InternalConversionError) + .map(|e| { v.push(e); - Ok(v) - }, - } + v + }) }) })); process_rw_result(self.get_header_mut().set("imag.links", Value::Array(new_links))) @@ -98,17 +97,17 @@ impl InternalLinker for Entry { } -fn links_into_values(links: Vec) -> Vec> { +fn links_into_values(links: Vec) -> Vec> { links .into_iter() - .map(|s| s.to_str().map(String::from)) .unique() + .map(|s| s.without_base().to_str().map_err_into(LEK::InternalConversionError)) .map(|elem| elem.map(Value::String)) .sorted_by(|a, b| { match (a, b) { - (&Some(Value::String(ref a)), &Some(Value::String(ref b))) => Ord::cmp(a, b), - (&None, _) | (_, &None) => Ordering::Equal, - _ => unreachable!() + (&Ok(Value::String(ref a)), &Ok(Value::String(ref b))) => Ord::cmp(a, b), + (&Err(_), _) | (_, &Err(_)) => Ordering::Equal, + _ => unreachable!() } }) } @@ -118,13 +117,11 @@ fn rewrite_links(header: &mut EntryHeader, links: Vec) -> Result<()> { .into_iter() .fold(Ok(vec![]), |acc, elem| { acc.and_then(move |mut v| { - match elem { - None => Err(LEK::InternalConversionError.into()), - Some(e) => { + elem.map_err_into(LEK::InternalConversionError) + .map(|e| { v.push(e); - Ok(v) - }, - } + v + }) }) })); @@ -142,13 +139,11 @@ fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> { .into_iter() .fold(Ok(vec![]), |acc, elem| { acc.and_then(move |mut v| { - match elem { - None => Err(LEK::InternalConversionError.into()), - Some(e) => { + elem.map_err_into(LEK::InternalConversionError) + .map(|e| { v.push(e); - Ok(v) - }, - } + v + }) }) })); process_rw_result(target.get_header_mut().set("imag.links", Value::Array(links))) @@ -157,6 +152,8 @@ fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> { } fn process_rw_result(links: StoreResult>) -> Result> { + use std::path::PathBuf; + let links = match links { Err(e) => { debug!("RW action on store failed. Generating LinkError"); @@ -179,14 +176,15 @@ fn process_rw_result(links: StoreResult>) -> Result> { return Err(LEK::ExistingLinkTypeWrong.into()); } - let links : Vec = links.into_iter() + let links : Vec = try!(links.into_iter() .map(|link| { match link { - Value::String(s) => StoreId::from(s), + Value::String(s) => StoreId::new_baseless(PathBuf::from(s)) + .map_err_into(LEK::StoreIdError), _ => unreachable!(), } }) - .collect(); + .collect()); debug!("Ok, the RW action was successful, returning link vector now!"); Ok(links) diff --git a/libimagentrylink/src/lib.rs b/libimagentrylink/src/lib.rs index 1774c8a6..804916fc 100644 --- a/libimagentrylink/src/lib.rs +++ b/libimagentrylink/src/lib.rs @@ -23,7 +23,7 @@ extern crate crypto; #[macro_use] extern crate libimagerror; #[macro_use] extern crate libimagutil; -module_entry_path_mod!("links", "0.2.0"); +module_entry_path_mod!("links"); pub mod error; pub mod external; diff --git a/libimagentrylist/src/listers/line.rs b/libimagentrylist/src/listers/line.rs index a5af428b..536d2039 100644 --- a/libimagentrylist/src/listers/line.rs +++ b/libimagentrylist/src/listers/line.rs @@ -28,8 +28,8 @@ impl<'a> Lister for LineLister<'a> { use error::ListErrorKind as LEK; entries.fold_defresult(|entry| { - write!(stdout(), "{:?}\n", entry.get_location().to_str().unwrap_or(self.unknown_output)) - .map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e)))) + let s = entry.get_location().to_str().unwrap_or(String::from(self.unknown_output)); + write!(stdout(), "{:?}\n", s).map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e)))) }) } diff --git a/libimagentrylist/src/listers/path.rs b/libimagentrylist/src/listers/path.rs index 503b2478..8b982315 100644 --- a/libimagentrylist/src/listers/path.rs +++ b/libimagentrylist/src/listers/path.rs @@ -26,10 +26,12 @@ impl Lister for PathLister { fn list<'a, I: Iterator>>(&self, entries: I) -> Result<()> { use error::ListError as LE; use error::ListErrorKind as LEK; + use std::path::PathBuf; entries.fold_defresult(|entry| { Ok(entry.get_location().clone()) .and_then(|pb| { + let pb : PathBuf = pb.into(); if self.absolute { pb.canonicalize().map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e)))) } else { diff --git a/libimagentryselect/src/error.rs b/libimagentryselect/src/error.rs new file mode 100644 index 00000000..767779e6 --- /dev/null +++ b/libimagentryselect/src/error.rs @@ -0,0 +1,13 @@ +generate_error_module!( + generate_error_types!(EntrySelectError, EntrySelectErrorKind, + CLIError => "Error on commandline", + IdMissingError => "Commandline: ID missing", + StoreIdParsingError => "Error while parsing StoreId", + IdSelectingError => "Error while selecting id" + ); +); + +pub use self::error::EntrySelectError; +pub use self::error::EntrySelectErrorKind; +pub use self::error::MapErrInto; + diff --git a/libimagentryselect/src/lib.rs b/libimagentryselect/src/lib.rs index 11cb6f1a..8f5bcbd3 100644 --- a/libimagentryselect/src/lib.rs +++ b/libimagentryselect/src/lib.rs @@ -17,7 +17,10 @@ extern crate log; extern crate interactor; extern crate libimagstore; +#[macro_use] extern crate libimagerror; +pub mod error; +pub mod result; pub mod ui; diff --git a/libimagentryselect/src/result.rs b/libimagentryselect/src/result.rs new file mode 100644 index 00000000..db949cf6 --- /dev/null +++ b/libimagentryselect/src/result.rs @@ -0,0 +1,6 @@ +use std::result::Result as RResult; + +use error::EntrySelectError; + +pub type Result = RResult; + diff --git a/libimagentryselect/src/ui.rs b/libimagentryselect/src/ui.rs index c8c524d5..e3e41b8a 100644 --- a/libimagentryselect/src/ui.rs +++ b/libimagentryselect/src/ui.rs @@ -3,7 +3,11 @@ use std::path::PathBuf; use clap::{Arg, ArgMatches}; use libimagstore::storeid::StoreId; -use libimagerror::trace::trace_error; +use libimagerror::into::IntoError; + +use result::Result; +use error::MapErrInto; +use error::EntrySelectErrorKind as ESEK; pub fn id_argument<'a, 'b>() -> Arg<'a, 'b> { Arg::with_name(id_argument_name()) @@ -26,28 +30,35 @@ pub fn id_argument_long() -> &'static str { "id" } -pub fn get_id(matches: &ArgMatches) -> Option> { - matches.values_of(id_argument_name()) - .map(|vals| { +pub fn get_id(matches: &ArgMatches) -> Result> { + matches + .values_of(id_argument_name()) + .ok_or(ESEK::IdMissingError.into_error()) + .map_err_into(ESEK::CLIError) + .and_then(|vals| { vals.into_iter() - .map(String::from) - .map(StoreId::from) - .collect() + .fold(Ok(vec![]), |acc, elem| { + acc.and_then(|mut v| { + let elem = StoreId::new_baseless(PathBuf::from(String::from(elem))); + let elem = try!(elem.map_err_into(ESEK::StoreIdParsingError)); + v.push(elem); + Ok(v) + }) + }) }) } -pub fn get_or_select_id(matches: &ArgMatches, store_path: &PathBuf) -> Option> { +pub fn get_or_select_id(matches: &ArgMatches, store_path: &PathBuf) -> Result> { use interactor::{pick_file, default_menu_cmd}; - get_id(matches).or_else(|| { - match pick_file(default_menu_cmd, store_path.clone()) { - Err(e) => { - trace_error(&e); - None - }, - - Ok(p) => Some(vec![StoreId::from(p)]), - } - }) + match get_id(matches).map_err_into(ESEK::IdSelectingError) { + Ok(v) => Ok(v), + Err(_) => { + let path = store_path.clone(); + let p = try!(pick_file(default_menu_cmd, path).map_err_into(ESEK::IdSelectingError)); + let id = try!(StoreId::new_baseless(p).map_err_into(ESEK::StoreIdParsingError)); + Ok(vec![id]) + }, + } } diff --git a/libimagentryview/src/builtin/mod.rs b/libimagentryview/src/builtin/mod.rs index ec41fd0f..657f5e80 100644 --- a/libimagentryview/src/builtin/mod.rs +++ b/libimagentryview/src/builtin/mod.rs @@ -1,4 +1,3 @@ pub mod editor; pub mod plain; pub mod stdout; -pub mod versions; diff --git a/libimagentryview/src/builtin/versions.rs b/libimagentryview/src/builtin/versions.rs deleted file mode 100644 index 11439c36..00000000 --- a/libimagentryview/src/builtin/versions.rs +++ /dev/null @@ -1,54 +0,0 @@ -use libimagstore::store::Entry; -use libimagstore::store::Store; -use libimagerror::into::IntoError; - -use viewer::Viewer; -use result::Result; -use error::ViewErrorKind as VEK; - -pub struct VersionsViewer<'a> { - store: &'a Store, -} - -impl<'a> VersionsViewer<'a> { - - pub fn new(store: &'a Store) -> VersionsViewer<'a> { - VersionsViewer { - store: store, - } - } - -} - -impl<'a> Viewer for VersionsViewer<'a> { - - fn view_entry(&self, entr: &Entry) -> Result<()> { - use glob::glob; - - entr.get_location() - .clone() - .storified(self.store) - .to_str() - .and_then(|s| s.split("~").next()) - .map(|component| { - glob(&format!("{}~*", component)[..]) - .map_err(|_| VEK::PatternError.into_error()) - .and_then(|paths| { - for entry in paths { - let p = match entry { - Err(_) => return Err(VEK::GlobError.into_error()), - Ok(p) => p, - }; - let p = p.file_name() - .and_then(|s| s.to_str()) - .unwrap(); // TODO - println!("{}", p); - }; - Ok(()) - }) - }) - .unwrap_or(Err(VEK::PatternBuildingError.into_error())) - } - -} - diff --git a/libimagnotes/src/error.rs b/libimagnotes/src/error.rs index bbb02d0c..bebed316 100644 --- a/libimagnotes/src/error.rs +++ b/libimagnotes/src/error.rs @@ -9,4 +9,5 @@ generate_error_module!( pub use self::error::NoteError; pub use self::error::NoteErrorKind; +pub use self::error::MapErrInto; diff --git a/libimagnotes/src/lib.rs b/libimagnotes/src/lib.rs index a275848e..7abc5eb3 100644 --- a/libimagnotes/src/lib.rs +++ b/libimagnotes/src/lib.rs @@ -24,7 +24,7 @@ extern crate libimagrt; extern crate libimagentryedit; extern crate libimagentrytag; -module_entry_path_mod!("notes", "0.2.0"); +module_entry_path_mod!("notes"); pub mod error; pub mod note; diff --git a/libimagnotes/src/note.rs b/libimagnotes/src/note.rs index 48f25bf0..768b5607 100644 --- a/libimagnotes/src/note.rs +++ b/libimagnotes/src/note.rs @@ -19,6 +19,7 @@ use module_path::ModuleEntryPath; use result::Result; use error::NoteError as NE; use error::NoteErrorKind as NEK; +use error::MapErrInto; #[derive(Debug)] pub struct Note<'a> { @@ -32,11 +33,10 @@ impl<'a> Note<'a> { debug!("Creating new Note: '{}'", name); let fle = { - let lockentry = store.create(ModuleEntryPath::new(name.clone()).into_storeid()); - if lockentry.is_err() { - return Err(NE::new(NEK::StoreWriteError, Some(Box::new(lockentry.unwrap_err())))); - } - let mut lockentry = lockentry.unwrap(); + let mut lockentry = try!(ModuleEntryPath::new(name.clone()) + .into_storeid() + .and_then(|id| store.create(id)) + .map_err_into(NEK::StoreWriteError)); { let mut entry = lockentry.deref_mut(); @@ -93,24 +93,26 @@ impl<'a> Note<'a> { } pub fn delete(store: &Store, name: String) -> Result<()> { - store.delete(ModuleEntryPath::new(name).into_storeid()) - .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e)))) + ModuleEntryPath::new(name) + .into_storeid() + .and_then(|id| store.delete(id)) + .map_err_into(NEK::StoreWriteError) } pub fn retrieve(store: &Store, name: String) -> Result { - store.retrieve(ModuleEntryPath::new(name).into_storeid()) - .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e)))) + ModuleEntryPath::new(name) + .into_storeid() + .and_then(|id| store.retrieve(id)) + .map_err_into(NEK::StoreWriteError) .map(|entry| Note { entry: entry }) } pub fn get(store: &Store, name: String) -> Result> { - use libimagerror::into::IntoError; - - match store.get(ModuleEntryPath::new(name).into_storeid()) { - Ok(Some(entry)) => Ok(Some(Note { entry: entry })), - Ok(None) => Ok(None), - Err(e) => Err(NEK::StoreWriteError.into_error_with_cause(Box::new(e))), - } + ModuleEntryPath::new(name) + .into_storeid() + .and_then(|id| store.get(id)) + .map_err_into(NEK::StoreWriteError) + .map(|o| o.map(|entry| Note { entry: entry })) } pub fn all_notes(store: &Store) -> Result { diff --git a/libimagref/src/lib.rs b/libimagref/src/lib.rs index bcdaf36d..fb4814c9 100644 --- a/libimagref/src/lib.rs +++ b/libimagref/src/lib.rs @@ -25,7 +25,7 @@ extern crate walkdir; #[macro_use] extern crate libimagutil; extern crate libimagentrylist; -module_entry_path_mod!("ref", "0.2.0"); +module_entry_path_mod!("ref"); pub mod error; pub mod flags; diff --git a/libimagref/src/reference.rs b/libimagref/src/reference.rs index 577311a8..fabb26a5 100644 --- a/libimagref/src/reference.rs +++ b/libimagref/src/reference.rs @@ -19,6 +19,7 @@ use libimagerror::into::IntoError; use toml::Value; use error::RefErrorKind as REK; +use error::MapErrInto; use flags::RefFlags; use result::Result; use hasher::*; @@ -47,8 +48,9 @@ impl<'a> Ref<'a> { /// /// Returns None if the hash cannot be found. pub fn get_by_hash(store: &'a Store, hash: String) -> Result>> { - store - .get(ModuleEntryPath::new(hash).into_storeid()) + ModuleEntryPath::new(hash) + .into_storeid() + .and_then(|id| store.get(id)) .map(|opt_fle| opt_fle.map(|fle| Ref(fle))) .map_err(Box::new) .map_err(|e| REK::StoreReadError.into_error_with_cause(e)) @@ -58,8 +60,9 @@ impl<'a> Ref<'a> { /// /// If the returned Result contains an error, the ref might not be deleted. pub fn delete_by_hash(store: &'a Store, hash: String) -> Result<()> { - store - .delete(ModuleEntryPath::new(hash).into_storeid()) + ModuleEntryPath::new(hash) + .into_storeid() + .and_then(|id| store.delete(id)) .map_err(Box::new) .map_err(|e| REK::StoreWriteError.into_error_with_cause(e)) } @@ -223,10 +226,8 @@ impl<'a> Ref<'a> { /// Get the hash from the path of the ref pub fn get_path_hash(&self) -> Option { - self.0 - .get_location() - .as_path() - .file_name() + let pb : PathBuf = self.0.get_location().clone().into(); + pb.file_name() .and_then(|osstr| osstr.to_str()) .and_then(|s| s.split("~").next()) .map(String::from) @@ -398,13 +399,9 @@ impl<'a> Ref<'a> { // manually here. If you can come up with a better version of this, feel free to // take this note as a todo. for r in possible_refs { - let contains_hash = match r.to_str() { - None => { // couldn't parse StoreId -> PathBuf -> &str - // TODO: How to report this? - return Err(REK::TypeConversionError.into_error()); - }, - Some(s) => s.contains(&hash[..]), - }; + let contains_hash = try!(r.to_str() + .map_err_into(REK::TypeConversionError) + .map(|s| s.contains(&hash[..]))); if !contains_hash { continue; diff --git a/libimagstore/src/error.rs b/libimagstore/src/error.rs index f6067ccb..2eef6d53 100644 --- a/libimagstore/src/error.rs +++ b/libimagstore/src/error.rs @@ -42,6 +42,7 @@ generate_custom_error_types!(StoreError, StoreErrorKind, CustomErrorData, StorePathError => "Store Path error", EntryRenameError => "Entry rename error", StoreIdHandlingError => "StoreId handling error", + StoreIdLocalPartAbsoluteError => "StoreId 'id' part is absolute (starts with '/') which is not allowed", CreateCallError => "Error when calling create()", RetrieveCallError => "Error when calling retrieve()", diff --git a/libimagstore/src/store.rs b/libimagstore/src/store.rs index 3f344f5c..0a510ab9 100644 --- a/libimagstore/src/store.rs +++ b/libimagstore/src/store.rs @@ -36,6 +36,7 @@ use hook::position::HookPosition; use hook::Hook; use libimagerror::into::IntoError; +use libimagerror::trace::trace_error; use libimagutil::iter::FoldResult; use self::glob_store_iter::*; @@ -65,14 +66,17 @@ pub enum StoreObject { } pub struct Walk { + store_path: PathBuf, dirwalker: WalkDirIter, } impl Walk { fn new(mut store_path: PathBuf, mod_name: &str) -> Walk { + let pb = store_path.clone(); store_path.push(mod_name); Walk { + store_path: pb, dirwalker: WalkDir::new(store_path).into_iter(), } } @@ -95,7 +99,15 @@ impl Iterator for Walk { Ok(next) => if next.file_type().is_dir() { return Some(StoreObject::Collection(next.path().to_path_buf())) } else if next.file_type().is_file() { - return Some(StoreObject::Id(next.path().to_path_buf().into())) + let n = next.path().to_path_buf(); + let sid = match StoreId::new(Some(self.store_path.clone()), n) { + Err(e) => { + trace_error(&e); + continue; + }, + Ok(o) => o, + }; + return Some(StoreObject::Id(sid)) }, Err(e) => { warn!("Error in Walker"); @@ -376,7 +388,7 @@ impl Store { /// Creates the Entry at the given location (inside the entry) pub fn create<'a, S: IntoStoreId>(&'a self, id: S) -> Result> { - let id = id.into_storeid().storified(self); + let id = try!(id.into_storeid()).with_base(self.path().clone()); if let Err(e) = self.execute_hooks_for_id(self.pre_create_aspects.clone(), &id) { return Err(e) .map_err_into(SEK::PreHookExecuteError) @@ -414,7 +426,7 @@ impl Store { /// Implicitely creates a entry in the store if there is no entry with the id `id`. For a /// non-implicitely-create look at `Store::get`. pub fn retrieve<'a, S: IntoStoreId>(&'a self, id: S) -> Result> { - let id = id.into_storeid().storified(self); + let id = try!(id.into_storeid()).with_base(self.path().clone()); if let Err(e) = self.execute_hooks_for_id(self.pre_retrieve_aspects.clone(), &id) { return Err(e) .map_err_into(SEK::PreHookExecuteError) @@ -447,57 +459,14 @@ impl Store { /// /// This executes the {pre,post}_retrieve_aspects hooks. pub fn get<'a, S: IntoStoreId + Clone>(&'a self, id: S) -> Result>> { - if !id.clone().into_storeid().storified(self).exists() { - debug!("Does not exist: {:?}", id.clone().into_storeid()); + let id_copy = try!(id.clone().into_storeid()).with_base(self.path().clone()); + if !id_copy.exists() { + debug!("Does not exist: {:?}", id_copy); return Ok(None); } self.retrieve(id).map(Some).map_err_into(SEK::GetCallError) } - /// Same as `Store::get()` but also tries older versions of the entry, returning an iterator - /// over all versions of the entry. - pub fn get_all_versions<'a, S: IntoStoreId>(&'a self, id: S) -> Result - { - // get PathBuf component from storeid, but not version component - fn path_component(id: S) -> Result { - let p : PathBuf = id.into_storeid().into(); - match p.to_str() { - Some(s) => { - let mut split = s.split("~"); - let path_element = match split.next() { - Some(s) => s, - None => return Err(SE::new(SEK::StorePathError, None)) - .map_err_into(SEK::GetAllVersionsCallError), - }; - - Ok(PathBuf::from(path_element)) - }, - - None => Err(SE::new(SEK::StorePathError, None)) - .map_err_into(SEK::GetAllVersionsCallError), - } - } - - fn build_glob_pattern(mut pb: PathBuf) -> Option { - pb.push("~*.*.*"); - pb.to_str().map(String::from) - } - - match path_component(id).map(build_glob_pattern) { - Err(e) => Err(SEK::StorePathError.into_error_with_cause(Box::new(e))) - .map_err_into(SEK::GetAllVersionsCallError), - Ok(None) => Err(SE::new(SEK::StorePathError, None)) - .map_err_into(SEK::GetAllVersionsCallError), - Ok(Some(pattern)) => { - glob(&pattern[..]) - .map(|paths| GlobStoreIdIterator::new(paths).into()) - .map_err_into(SEK::GlobError) - .map_err_into(SEK::GetAllVersionsCallError) - } - } - - } - /// Iterate over all StoreIds for one module name pub fn retrieve_for_module(&self, mod_name: &str) -> Result { let mut path = self.path().clone(); @@ -510,7 +479,7 @@ impl Store { debug!("glob()ing with '{}'", path); glob(&path[..]).map_err_into(SEK::GlobError) }) - .map(|paths| GlobStoreIdIterator::new(paths).into()) + .map(|paths| GlobStoreIdIterator::new(paths, self.path().clone()).into()) .map_err_into(SEK::GlobError) .map_err_into(SEK::RetrieveForModuleCallError) } @@ -567,7 +536,7 @@ impl Store { /// Retrieve a copy of a given entry, this cannot be used to mutate /// the one on disk pub fn retrieve_copy(&self, id: S) -> Result { - let id = id.into_storeid().storified(self); + let id = try!(id.into_storeid()).with_base(self.path().clone()); let entries = match self.entries.write() { Err(_) => { return Err(SE::new(SEK::LockPoisoned, None)) @@ -586,7 +555,7 @@ impl Store { /// Delete an entry pub fn delete(&self, id: S) -> Result<()> { - let id = id.into_storeid().storified(self); + let id = try!(id.into_storeid()).with_base(self.path().clone()); if let Err(e) = self.execute_hooks_for_id(self.pre_delete_aspects.clone(), &id) { return Err(e) .map_err_into(SEK::PreHookExecuteError) @@ -609,7 +578,7 @@ impl Store { // remove the entry first, then the file entries.remove(&id); - if let Err(e) = FileAbstraction::remove_file(&id) { + if let Err(e) = FileAbstraction::remove_file(&id.clone().into()) { return Err(SEK::FileError.into_error_with_cause(Box::new(e))) .map_err_into(SEK::DeleteCallError); } @@ -637,7 +606,7 @@ impl Store { fn save_to_other_location(&self, entry: &FileLockEntry, new_id: StoreId, remove_old: bool) -> Result<()> { - let new_id = new_id.storified(self); + let new_id = new_id.with_base(self.path().clone()); let hsmap = self.entries.write(); if hsmap.is_err() { return Err(SE::new(SEK::LockPoisoned, None)).map_err_into(SEK::MoveCallError) @@ -666,8 +635,8 @@ impl Store { /// Move an entry without loading pub fn move_by_id(&self, old_id: StoreId, new_id: StoreId) -> Result<()> { - let new_id = new_id.storified(self); - let old_id = old_id.storified(self); + let new_id = new_id.with_base(self.path().clone()); + let old_id = old_id.with_base(self.path().clone()); if let Err(e) = self.execute_hooks_for_id(self.pre_move_aspects.clone(), &old_id) { return Err(e) @@ -677,15 +646,17 @@ impl Store { } { - let hsmap = self.entries.write(); - if hsmap.is_err() { - return Err(SE::new(SEK::LockPoisoned, None)) - } - let hsmap = hsmap.unwrap(); + let hsmap = match self.entries.write() { + Err(_) => return Err(SE::new(SEK::LockPoisoned, None)), + Ok(m) => m, + }; + if hsmap.contains_key(&old_id) { return Err(SE::new(SEK::EntryAlreadyBorrowed, None)); } else { - match FileAbstraction::rename(&old_id.clone(), &new_id) { + let old_id_pb = old_id.clone().into(); + let new_id_pb = new_id.clone().into(); + match FileAbstraction::rename(&old_id_pb, &new_id_pb) { Err(e) => return Err(SEK::EntryRenameError.into_error_with_cause(Box::new(e))), Ok(_) => { debug!("Rename worked"); @@ -831,11 +802,19 @@ impl Drop for Store { * TODO: Unlock them */ fn drop(&mut self) { - let store_id = StoreId::from(self.location.clone()); - if let Err(e) = self.execute_hooks_for_id(self.store_unload_aspects.clone(), &store_id) { - debug!("Store-load hooks execution failed. Cannot create store object."); - warn!("Store Unload Hook error: {:?}", e); - } + match StoreId::new(Some(self.location.clone()), PathBuf::from(".")) { + Err(e) => { + trace_error(&e); + warn!("Cannot construct StoreId for Store to execute hooks!"); + warn!("Will close Store without executing hooks!"); + }, + Ok(store_id) => { + if let Err(e) = self.execute_hooks_for_id(self.store_unload_aspects.clone(), &store_id) { + debug!("Store-load hooks execution failed. Cannot create store object."); + warn!("Store Unload Hook error: {:?}", e); + } + }, + }; debug!("Dropping store"); } @@ -1449,7 +1428,7 @@ impl Entry { debug!("Header and content found. Yay! Building Entry object now"); Ok(Entry { - location: loc.into_storeid(), + location: try!(loc.into_storeid()), header: try!(EntryHeader::parse(header)), content: content.into(), }) @@ -1490,11 +1469,18 @@ impl Entry { mod glob_store_iter { use std::fmt::{Debug, Formatter}; use std::fmt::Error as FmtError; + use std::path::PathBuf; use glob::Paths; use storeid::StoreId; use storeid::StoreIdIterator; + use error::StoreErrorKind as SEK; + use error::MapErrInto; + + use libimagerror::trace::trace_error; + pub struct GlobStoreIdIterator { + store_path: PathBuf, paths: Paths, } @@ -1516,8 +1502,9 @@ mod glob_store_iter { impl GlobStoreIdIterator { - pub fn new(paths: Paths) -> GlobStoreIdIterator { + pub fn new(paths: Paths, store_path: PathBuf) -> GlobStoreIdIterator { GlobStoreIdIterator { + store_path: store_path, paths: paths, } } @@ -1528,15 +1515,16 @@ mod glob_store_iter { type Item = StoreId; fn next(&mut self) -> Option { - self.paths.next().and_then(|o| { - match o { - Ok(o) => Some(o), - Err(e) => { - debug!("GlobStoreIdIterator error: {:?}", e); - None - }, - } - }).map(|p| StoreId::from(p)) + self.paths + .next() + .and_then(|o| { + o.map_err_into(SEK::StoreIdHandlingError) + .and_then(|p| StoreId::new(Some(self.store_path.clone()), p)) + .map_err(|e| { + debug!("GlobStoreIdIterator error: {:?}", e); + trace_error(&e); + }).ok() + }) } } @@ -1551,6 +1539,7 @@ mod test { use std::collections::BTreeMap; use super::EntryHeader; use super::Token; + use storeid::StoreId; use toml::Value; @@ -1681,7 +1670,7 @@ Hai"; use super::Entry; use std::path::PathBuf; println!("{}", TEST_ENTRY); - let entry = Entry::from_str(PathBuf::from("/test/foo~1.3"), + let entry = Entry::from_str(StoreId::new_baseless(PathBuf::from("test/foo~1.3")).unwrap(), TEST_ENTRY).unwrap(); assert_eq!(entry.content, "Hai"); @@ -1692,7 +1681,7 @@ Hai"; use super::Entry; use std::path::PathBuf; println!("{}", TEST_ENTRY); - let entry = Entry::from_str(PathBuf::from("/test/foo~1.3"), + let entry = Entry::from_str(StoreId::new_baseless(PathBuf::from("test/foo~1.3")).unwrap(), TEST_ENTRY).unwrap(); let string = entry.to_str(); diff --git a/libimagstore/src/storeid.rs b/libimagstore/src/storeid.rs index 25e550ec..4bb26bf6 100644 --- a/libimagstore/src/storeid.rs +++ b/libimagstore/src/storeid.rs @@ -1,12 +1,11 @@ use std::path::PathBuf; -use std::path::Path; -use std::borrow::Borrow; -use std::ops::Deref; -use semver::Version; use std::fmt::{Display, Debug, Formatter}; use std::fmt::Error as FmtError; use std::result::Result as RResult; +use std::path::Components; + +use libimagerror::into::IntoError; use error::StoreErrorKind as SEK; use store::Result; @@ -14,29 +13,92 @@ use store::Store; /// The Index into the Store #[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)] -pub struct StoreId(PathBuf); +pub struct StoreId { + base: Option, + id: PathBuf, +} impl StoreId { - pub fn storified(self, store: &Store) -> StoreId { - if self.starts_with(store.path()) { - debug!("Not storifying {:?}, because it is already.", self); - self + pub fn new(base: Option, id: PathBuf) -> Result { + StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid }) + } + + pub fn new_baseless(id: PathBuf) -> Result { + if id.is_absolute() { + Err(SEK::StoreIdLocalPartAbsoluteError.into_error()) } else { - debug!("Create new store id out of: {:?} and {:?}", store.path(), self); - let mut new_id = store.path().clone(); - new_id.push(self); - debug!("Created: '{:?}'", new_id); - StoreId::from(new_id) + Ok(StoreId { + base: None, + id: id + }) } } + pub fn without_base(mut self) -> StoreId { + self.base = None; + self + } + + pub fn with_base(mut self, base: PathBuf) -> Self { + self.base = Some(base); + self + } + + pub fn storified(self, store: &Store) -> StoreId { + StoreId { + base: Some(store.path().clone()), + id: self.id + } + } + + pub fn exists(&self) -> bool { + let pb : PathBuf = self.clone().into(); + pb.exists() + } + + pub fn is_file(&self) -> bool { + true + } + + pub fn is_dir(&self) -> bool { + false + } + + pub fn to_str(&self) -> Result { + if self.base.is_some() { + let mut base = self.base.as_ref().cloned().unwrap(); + base.push(self.id.clone()); + base + } else { + self.id.clone() + } + .to_str() + .map(String::from) + .ok_or(SEK::StoreIdHandlingError.into_error()) + } + + /// Returns the components of the `id` part of the StoreId object. + /// + /// Can be used to check whether a StoreId points to an entry in a specific collection of + /// StoreIds. + pub fn components(&self) -> Components { + self.id.components() + } + + /// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry". + pub fn local(&self) -> &PathBuf { + &self.id + } + } impl Into for StoreId { fn into(self) -> PathBuf { - self.0 + let mut base = self.base.unwrap_or(PathBuf::from("/")); + base.push(self.id); + base } } @@ -44,97 +106,35 @@ impl Into for StoreId { impl Display for StoreId { fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> { - match self.0.to_str() { + match self.id.to_str() { Some(s) => write!(fmt, "{}", s), - None => write!(fmt, "{}", self.0.to_string_lossy()), + None => write!(fmt, "{}", self.id.to_string_lossy()), } } } -impl Deref for StoreId { - type Target = PathBuf; - - fn deref(&self) -> &PathBuf { - &self.0 - } - -} - -impl From for StoreId { - - fn from(pb: PathBuf) -> StoreId { - StoreId(pb) - } - -} - -impl From for StoreId { - - fn from(string: String) -> StoreId { - StoreId(string.into()) - } - -} - -impl AsRef for StoreId { - - fn as_ref(&self) -> &Path { - self.0.as_ref() - } - -} - -impl Borrow for StoreId { - - fn borrow(&self) -> &Path { - self.0.borrow() - } - -} - /// This Trait allows you to convert various representations to a single one /// suitable for usage in the Store pub trait IntoStoreId { - fn into_storeid(self) -> StoreId; -} - -impl IntoStoreId for PathBuf { - fn into_storeid(self) -> StoreId { - StoreId(self) - } + fn into_storeid(self) -> Result; } impl IntoStoreId for StoreId { - fn into_storeid(self) -> StoreId { - self + fn into_storeid(self) -> Result { + Ok(self) } } -pub fn build_entry_path(store: &Store, path_elem: &str) -> Result { - debug!("Checking path element for version"); - if path_elem.split('~').last().map_or(false, |v| Version::parse(v).is_err()) { - debug!("Version cannot be parsed from {:?}", path_elem); - debug!("Path does not contain version!"); - return Err(SEK::StorePathLacksVersion.into()); +impl IntoStoreId for PathBuf { + fn into_storeid(self) -> Result { + StoreId::new_baseless(self) } - debug!("Version checking succeeded"); - - debug!("Building path from {:?}", path_elem); - let mut path = store.path().clone(); - - if path_elem.starts_with('/') { - path.push(&path_elem[1..]); - } else { - path.push(path_elem); - } - - Ok(path) } #[macro_export] macro_rules! module_entry_path_mod { - ($name:expr, $version:expr) => ( + ($name:expr) => ( #[deny(missing_docs, missing_copy_implementations, trivial_casts, trivial_numeric_casts, @@ -144,12 +144,12 @@ macro_rules! module_entry_path_mod { unused_imports)] /// A helper module to create valid module entry paths pub mod module_path { - use semver::Version; use std::convert::AsRef; use std::path::Path; use std::path::PathBuf; use $crate::storeid::StoreId; + use $crate::store::Result; /// A Struct giving you the ability to choose store entries assigned /// to it. @@ -163,19 +163,16 @@ macro_rules! module_entry_path_mod { let mut path = PathBuf::new(); path.push(format!("{}", $name)); path.push(pa.as_ref().clone()); - let version = Version::parse($version).unwrap(); let name = pa.as_ref().file_name().unwrap() .to_str().unwrap(); - path.set_file_name(format!("{}~{}", - name, - version)); + path.set_file_name(name); ModuleEntryPath(path) } } impl $crate::storeid::IntoStoreId for ModuleEntryPath { - fn into_storeid(self) -> $crate::storeid::StoreId { - StoreId::from(self.0) + fn into_storeid(self) -> Result<$crate::storeid::StoreId> { + StoreId::new(None, self.0) } } } @@ -218,13 +215,13 @@ mod test { use storeid::IntoStoreId; - module_entry_path_mod!("test", "0.2.0-alpha+leet1337"); + module_entry_path_mod!("test"); #[test] fn correct_path() { let p = module_path::ModuleEntryPath::new("test"); - assert_eq!(p.into_storeid().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337"); + assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test"); } } diff --git a/libimagstorestdhook/src/flock.rs b/libimagstorestdhook/src/flock.rs index 2386180a..24673f0e 100644 --- a/libimagstorestdhook/src/flock.rs +++ b/libimagstorestdhook/src/flock.rs @@ -18,27 +18,23 @@ use libimagstore::store::FileLockEntry; use libimagstore::store::Entry; trait EntryFlock { - fn lock(&self, store_location: &PathBuf) -> IoResult<()>; - fn unlock(&self, store_location: &PathBuf) -> IoResult<()>; + fn lock(&self) -> IoResult<()>; + fn unlock(&self) -> IoResult<()>; } impl EntryFlock for Entry { - fn lock(&self, store_location: &PathBuf) -> IoResult<()> { + fn lock(&self) -> IoResult<()> { use std::fs::File; - let mut location = store_location.clone(); - location.push(self.get_location()); - + let location : PathBuf = self.get_location().clone().into(); File::open(location).and_then(|file| file.lock_exclusive()) } - fn unlock(&self, store_location: &PathBuf) -> IoResult<()> { + fn unlock(&self) -> IoResult<()> { use std::fs::File; - let mut location = store_location.clone(); - location.push(self.get_location()); - + let location : PathBuf = self.get_location().clone().into(); File::open(location).and_then(|file| file.unlock()) } @@ -60,15 +56,13 @@ fn action_to_str(a: &Action) -> &'static str { #[derive(Debug, Clone)] pub struct FlockUpdateHook { action: Action, - store_location: PathBuf, } impl FlockUpdateHook { - pub fn new(action: Action, store_location: PathBuf) -> FlockUpdateHook { + pub fn new(action: Action) -> FlockUpdateHook { FlockUpdateHook { action: action, - store_location: store_location, } } @@ -107,7 +101,7 @@ impl MutableHookDataAccessor for FlockUpdateHook { fn access_mut(&self, fle: &mut FileLockEntry) -> HookResult<()> { debug!("[FLOCK HOOK][{}] {:?}", action_to_str(&self.action), fle.get_location()); - fle.lock(&self.store_location) + fle.lock() .map_err(|e| HookError::new(HookErrorKind::HookExecutionError, Some(Box::new(e)))) .map(|_| ()) } @@ -118,7 +112,7 @@ impl NonMutableHookDataAccessor for FlockUpdateHook { fn access(&self, fle: &FileLockEntry) -> HookResult<()> { debug!("[FLOCK HOOK][{}] {:?}", action_to_str(&self.action), fle.get_location()); - fle.unlock(&self.store_location) + fle.unlock() .map_err(|e| HookError::new(HookErrorKind::HookExecutionError, Some(Box::new(e)))) .map(|_| ()) } diff --git a/libimagstorestdhook/src/linkverify.rs b/libimagstorestdhook/src/linkverify.rs index e97981b7..85551999 100644 --- a/libimagstorestdhook/src/linkverify.rs +++ b/libimagstorestdhook/src/linkverify.rs @@ -53,12 +53,10 @@ impl NonMutableHookDataAccessor for LinkedEntriesExistHook { let _ = fle.get_internal_links() .map(|links| { for link in links { - let mut path = self.store_location.clone(); - path.push(link); - if !path.exists() { - warn!("File link does not exist: {:?} -> {:?}", fle.get_location(), path); - } else if !path.is_file() { - warn!("File link is not a file: {:?} -> {:?}", fle.get_location(), path); + if !link.exists() { + warn!("File link does not exist: {:?} -> {:?}", fle.get_location(), link); + } else if !link.is_file() { + warn!("File link is not a file: {:?} -> {:?}", fle.get_location(), link); } } }) diff --git a/libimagtodo/src/error.rs b/libimagtodo/src/error.rs index 8aa42410..ebcebf3e 100644 --- a/libimagtodo/src/error.rs +++ b/libimagtodo/src/error.rs @@ -2,6 +2,7 @@ generate_error_module!( generate_error_types!(TodoError, TodoErrorKind, ConversionError => "Conversion Error", StoreError => "Store Error", + StoreIdError => "Store Id handling error", ImportError => "Error importing" ); ); diff --git a/libimagtodo/src/lib.rs b/libimagtodo/src/lib.rs index 4362446d..3376ac62 100644 --- a/libimagtodo/src/lib.rs +++ b/libimagtodo/src/lib.rs @@ -22,7 +22,7 @@ extern crate serde_json; #[macro_use] extern crate libimagerror; extern crate task_hookrs; -module_entry_path_mod!("todo", "0.1.0"); +module_entry_path_mod!("todo"); pub mod error; pub mod result; diff --git a/libimagtodo/src/task.rs b/libimagtodo/src/task.rs index 1b44259b..6b3dc990 100644 --- a/libimagtodo/src/task.rs +++ b/libimagtodo/src/task.rs @@ -73,9 +73,9 @@ impl<'a> Task<'a> { /// /// If there is no task with this UUID, this returns `Ok(None)`. pub fn get_from_uuid(store: &'a Store, uuid: Uuid) -> Result>> { - let store_id = ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid(); - - store.get(store_id) + ModuleEntryPath::new(format!("taskwarrior/{}", uuid)) + .into_storeid() + .and_then(|store_id| store.get(store_id)) .map(|o| o.map(Task::new)) .map_err_into(TodoErrorKind::StoreError) } @@ -138,7 +138,9 @@ impl<'a> Task<'a> { } pub fn delete_by_uuid(store: &Store, uuid: Uuid) -> Result<()> { - store.delete(ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid()) + ModuleEntryPath::new(format!("taskwarrior/{}", uuid)) + .into_storeid() + .and_then(|id| store.delete(id)) .map_err(|e| TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))) } @@ -196,34 +198,30 @@ impl<'a> IntoTask<'a> for TTask { fn into_task(self, store : &'a Store) -> Result> { let uuid = self.uuid(); - let store_id = ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid(); - - match store.retrieve(store_id) { - Err(e) => return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))), - Ok(mut fle) => { - { - let mut header = fle.get_header_mut(); - match header.read("todo") { - Ok(None) => { - if let Err(e) = header.set("todo", Value::Table(BTreeMap::new())) { - return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))) + ModuleEntryPath::new(format!("taskwarrior/{}", uuid)) + .into_storeid() + .map_err_into(TodoErrorKind::StoreIdError) + .and_then(|id| { + store.retrieve(id) + .map_err_into(TodoErrorKind::StoreError) + .and_then(|mut fle| { + { + let mut hdr = fle.get_header_mut(); + let read = hdr.read("todo").map_err_into(TodoErrorKind::StoreError); + if try!(read).is_none() { + try!(hdr + .set("todo", Value::Table(BTreeMap::new())) + .map_err_into(TodoErrorKind::StoreError)); } - } - Ok(Some(_)) => { } - Err(e) => { - return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))) - } - } - if let Err(e) = header.set("todo.uuid", Value::String(format!("{}",uuid))) { - return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))) - } - } + try!(hdr.set("todo.uuid", Value::String(format!("{}",uuid))) + .map_err_into(TodoErrorKind::StoreError)); + } - // If none of the errors above have returned the function, everything is fine - Ok(Task::new(fle)) - } - } + // If none of the errors above have returned the function, everything is fine + Ok(Task::new(fle)) + }) + }) } }