Merge pull request #667 from matthiasbeyer/rewrite-storeid-type

Rewrite storeid type
This commit is contained in:
Matthias Beyer 2016-09-05 16:10:47 +02:00 committed by GitHub
commit 737aab80dc
48 changed files with 482 additions and 470 deletions

View File

@ -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("<<Path Parsing Error>>"))
}
@ -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))))
})

View File

@ -23,3 +23,6 @@ path = "../libimagentrylink"
[dependencies.libimagerror]
path = "../libimagerror"
[dependencies.libimagutil]
path = "../libimagutil"

View File

@ -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<FileLockEntry<'a>> {
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<Vec<FileLockEntry<'a>>> {
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<FileLockEntry<'a>, 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<Option<FileLockEntry<'a>>, 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") {

View File

@ -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();

View File

@ -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);

View File

@ -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,
};

View File

@ -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);

View File

@ -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,
};

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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<Vec<Tag>>, rem: Option<Vec<Tag>>) {
fn alter(rt: &Runtime, id: PathBuf, add: Option<Vec<Tag>>, rem: Option<Vec<Tag>>) {
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<Vec<Tag>>, rem: Option<Vec<Tag>>) {
}
}
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);
},
};

View File

@ -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");

View File

@ -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")

View File

@ -51,8 +51,9 @@ impl<'a> DerefMut for BookmarkCollection<'a> {
impl<'a> BookmarkCollection<'a> {
pub fn new(store: &'a Store, name: &str) -> Result<BookmarkCollection<'a>> {
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<BookmarkCollection<'a>> {
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<Vec<Url>> {

View File

@ -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;

View File

@ -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<T, F>(&self, name: &str, f: F) -> Result<T>
fn read_header_at<T, F>(&self, name: &str, f: F) -> Result<T>
where F: FnOnce(Option<Value>) -> Result<T>
{
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<Counter> {
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<CounterIterator> {
@ -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)
})
}
}

View File

@ -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",

View File

@ -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;

View File

@ -45,8 +45,8 @@ impl<'a> Diary<'a> {
}
pub fn retrieve(&self, id: DiaryId) -> Result<Entry> {
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))))
}

View File

@ -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<StoreId> {
let s : String = self.into();
ModuleEntryPath::new(s).into_storeid()
}

View File

@ -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))
}
}

View File

@ -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;

View File

@ -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"
);
);

View File

@ -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<Url> {
@ -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);

View File

@ -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<StoreId>) -> Vec<Option<Value>> {
fn links_into_values(links: Vec<StoreId>) -> Vec<Result<Value>> {
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<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
})
})
}));
@ -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<Option<Value>>) -> Result<Vec<Link>> {
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<Option<Value>>) -> Result<Vec<Link>> {
return Err(LEK::ExistingLinkTypeWrong.into());
}
let links : Vec<Link> = links.into_iter()
let links : Vec<Link> = 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)

View File

@ -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;

View File

@ -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))))
})
}

View File

@ -26,10 +26,12 @@ impl Lister for PathLister {
fn list<'a, I: Iterator<Item = FileLockEntry<'a>>>(&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 {

View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1,6 @@
use std::result::Result as RResult;
use error::EntrySelectError;
pub type Result<T> = RResult<T, EntrySelectError>;

View File

@ -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<Vec<StoreId>> {
matches.values_of(id_argument_name())
.map(|vals| {
pub fn get_id(matches: &ArgMatches) -> Result<Vec<StoreId>> {
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<Vec<StoreId>> {
pub fn get_or_select_id(matches: &ArgMatches, store_path: &PathBuf) -> Result<Vec<StoreId>> {
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])
},
}
}

View File

@ -1,4 +1,3 @@
pub mod editor;
pub mod plain;
pub mod stdout;
pub mod versions;

View File

@ -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()))
}
}

View File

@ -9,4 +9,5 @@ generate_error_module!(
pub use self::error::NoteError;
pub use self::error::NoteErrorKind;
pub use self::error::MapErrInto;

View File

@ -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;

View File

@ -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<Note> {
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<Option<Note>> {
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<NoteIterator> {

View File

@ -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;

View File

@ -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<Option<Ref<'a>>> {
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<String> {
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;

View File

@ -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()",

View File

@ -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<FileLockEntry<'a>> {
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<FileLockEntry<'a>> {
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<Option<FileLockEntry<'a>>> {
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<StoreIdIterator>
{
// get PathBuf component from storeid, but not version component
fn path_component<S: IntoStoreId>(id: S) -> Result<PathBuf> {
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<String> {
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<StoreIdIterator> {
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<S: IntoStoreId>(&self, id: S) -> Result<Entry> {
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<S: IntoStoreId>(&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<StoreId> {
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();

View File

@ -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<PathBuf>,
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<PathBuf>, id: PathBuf) -> Result<StoreId> {
StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
}
pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
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<String> {
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<PathBuf> 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<PathBuf> 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<PathBuf> for StoreId {
fn from(pb: PathBuf) -> StoreId {
StoreId(pb)
}
}
impl From<String> for StoreId {
fn from(string: String) -> StoreId {
StoreId(string.into())
}
}
impl AsRef<Path> for StoreId {
fn as_ref(&self) -> &Path {
self.0.as_ref()
}
}
impl Borrow<Path> 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<StoreId>;
}
impl IntoStoreId for StoreId {
fn into_storeid(self) -> StoreId {
self
fn into_storeid(self) -> Result<StoreId> {
Ok(self)
}
}
pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
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> {
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");
}
}

View File

@ -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(|_| ())
}

View File

@ -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);
}
}
})

View File

@ -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"
);
);

View File

@ -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;

View File

@ -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<Option<Task<'a>>> {
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<Task<'a>> {
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))
})
})
}
}