summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-09-04 21:59:54 +0200
committerGitHub <noreply@github.com>2017-09-04 21:59:54 +0200
commit6d1dab31179eb4414b45d9a94f453833ddc558ce (patch)
tree8bca1ca131e17a647a98d083087e0a42124067eb /lib
parentf025416cf7d96b5f2a41d545c75255cab9fe2d06 (diff)
parent6583ba04a2151d940d99d4277713df4f50bf9eac (diff)
Merge pull request #1029 from matthiasbeyer/all-extensions-as-traits
All extensions as traits
Diffstat (limited to 'lib')
-rw-r--r--lib/domain/libimagdiary/src/diary.rs149
-rw-r--r--lib/domain/libimagdiary/src/entry.rs64
-rw-r--r--lib/domain/libimagdiary/src/error.rs3
-rw-r--r--lib/domain/libimagdiary/src/is_in_diary.rs10
-rw-r--r--lib/domain/libimagdiary/src/iter.rs53
-rw-r--r--lib/domain/libimagdiary/src/viewer.rs12
-rw-r--r--lib/domain/libimagmail/src/iter.rs15
-rw-r--r--lib/domain/libimagmail/src/mail.rs17
-rw-r--r--lib/domain/libimagtodo/src/error.rs5
-rw-r--r--lib/domain/libimagtodo/src/lib.rs1
-rw-r--r--lib/domain/libimagtodo/src/task.rs276
-rw-r--r--lib/domain/libimagtodo/src/taskstore.rs205
-rw-r--r--lib/entry/libimagentrylink/src/external.rs85
-rw-r--r--lib/entry/libimagentryref/Cargo.toml2
-rw-r--r--lib/entry/libimagentryref/src/hashers/nbytes.rs11
-rw-r--r--lib/entry/libimagentryref/src/lib.rs2
-rw-r--r--lib/entry/libimagentryref/src/lister.rs116
-rw-r--r--lib/entry/libimagentryref/src/reference.rs461
-rw-r--r--lib/entry/libimagentryref/src/refstore.rs269
-rw-r--r--lib/entry/libimagentryref/src/util.rs56
20 files changed, 922 insertions, 890 deletions
diff --git a/lib/domain/libimagdiary/src/diary.rs b/lib/domain/libimagdiary/src/diary.rs
index 431b6320..c67467cc 100644
--- a/lib/domain/libimagdiary/src/diary.rs
+++ b/lib/domain/libimagdiary/src/diary.rs
@@ -19,110 +19,117 @@
use std::cmp::Ordering;
+use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
-use libimagstore::storeid::IntoStoreId;
use libimagerror::trace::trace_error;
use chrono::offset::Local;
use chrono::Datelike;
use itertools::Itertools;
use chrono::naive::NaiveDateTime;
+use chrono::Timelike;
-use entry::Entry;
+use entry::DiaryEntry;
use diaryid::DiaryId;
-use error::DiaryError as DE;
use error::DiaryErrorKind as DEK;
+use error::MapErrInto;
use result::Result;
use iter::DiaryEntryIterator;
-use is_in_diary::IsInDiary;
+use iter::DiaryNameIterator;
-#[derive(Debug)]
-pub struct Diary<'a> {
- store: &'a Store,
- name: &'a str,
-}
+pub trait Diary {
-impl<'a> Diary<'a> {
+ // create or get a new entry for today
+ fn new_entry_today(&self, diary_name: &str) -> Result<FileLockEntry>;
- pub fn open(store: &'a Store, name: &'a str) -> Diary<'a> {
- Diary {
- store: store,
- name: name,
- }
- }
+ // create or get a new entry for now
+ fn new_entry_now(&self, diary_name: &str) -> Result<FileLockEntry>;
+
+ // Get an iterator for iterating over all entries of a Diary
+ fn entries(&self, diary_name: &str) -> Result<DiaryEntryIterator>;
+
+ fn get_youngest_entry_id(&self, diary_name: &str) -> Option<Result<DiaryId>>;
+
+ /// Get all diary names
+ fn diary_names(&self) -> Result<DiaryNameIterator>;
+
+}
+
+impl Diary for Store {
// create or get a new entry for today
- pub fn new_entry_today(&self) -> Result<Entry> {
+ fn new_entry_today(&self, diary_name: &str) -> Result<FileLockEntry> {
let dt = Local::now();
let ndt = dt.naive_local();
- let id = DiaryId::new(String::from(self.name), ndt.year(), ndt.month(), ndt.day(), 0, 0);
- self.new_entry_by_id(id)
- }
+ let id = DiaryId::new(String::from(diary_name), ndt.year(), ndt.month(), ndt.day(), 0, 0);
- pub fn new_entry_by_id(&self, id: DiaryId) -> Result<Entry> {
- self.retrieve(id.with_diary_name(String::from(self.name)))
+ self.retrieve(id).map_err_into(DEK::StoreReadError)
}
- pub fn retrieve(&self, id: DiaryId) -> Result<Entry> {
- 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))))
+ // create or get a new entry for today
+ fn new_entry_now(&self, diary_name: &str) -> Result<FileLockEntry> {
+ let dt = Local::now();
+ let ndt = dt.naive_local();
+ let id = DiaryId::new(String::from(diary_name),
+ ndt.year(),
+ ndt.month(),
+ ndt.day(),
+ ndt.minute(),
+ ndt.second());
+
+ self.retrieve(id).map_err_into(DEK::StoreReadError)
}
// Get an iterator for iterating over all entries
- pub fn entries(&self) -> Result<DiaryEntryIterator<'a>> {
- self.store
- .retrieve_for_module("diary")
- .map(|iter| DiaryEntryIterator::new(self.name, self.store, iter))
- .map_err(|e| DE::new(DEK::StoreReadError, Some(Box::new(e))))
+ fn entries(&self, diary_name: &str) -> Result<DiaryEntryIterator> {
+ self.retrieve_for_module("diary")
+ .map(|iter| DiaryEntryIterator::new(self, String::from(diary_name), iter))
+ .map_err_into(DEK::StoreReadError)
}
- pub fn delete_entry(&self, entry: Entry) -> Result<()> {
- if !entry.is_in_diary(self.name) {
- return Err(DE::new(DEK::EntryNotInDiary, None));
- }
- let id = entry.get_location().clone();
- drop(entry);
-
- self.store.delete(id)
- .map_err(|e| DE::new(DEK::StoreWriteError, Some(Box::new(e))))
- }
-
- pub fn get_youngest_entry(&self) -> Option<Result<Entry>> {
- match self.entries() {
+ fn get_youngest_entry_id(&self, diary_name: &str) -> Option<Result<DiaryId>> {
+ match Diary::entries(self, diary_name) {
Err(e) => Some(Err(e)),
Ok(entries) => {
- entries.sorted_by(|a, b| {
- match (a, b) {
- (&Ok(ref a), &Ok(ref b)) => {
- let a : NaiveDateTime = a.diary_id().into();
- let b : NaiveDateTime = b.diary_id().into();
-
- a.cmp(&b)
- },
-
- (&Ok(_), &Err(ref e)) => {
- trace_error(e);
- Ordering::Less
- },
- (&Err(ref e), &Ok(_)) => {
- trace_error(e);
- Ordering::Greater
- },
- (&Err(ref e1), &Err(ref e2)) => {
- trace_error(e1);
- trace_error(e2);
- Ordering::Equal
- },
- }
- }).into_iter().next()
+ entries
+ .map(|e| e.and_then(|e| e.diary_id()))
+ .sorted_by(|a, b| {
+ match (a, b) {
+ (&Ok(ref a), &Ok(ref b)) => {
+ let a : NaiveDateTime = a.clone().into();
+ let b : NaiveDateTime = b.clone().into();
+
+ a.cmp(&b)
+ },
+
+ (&Ok(_), &Err(ref e)) => {
+ trace_error(e);
+ Ordering::Less
+ },
+ (&Err(ref e), &Ok(_)) => {
+ trace_error(e);
+ Ordering::Greater
+ },
+ (&Err(ref e1), &Err(ref e2)) => {
+ trace_error(e1);
+ trace_error(e2);
+ Ordering::Equal
+ },
+ }
+ })
+ .into_iter()
+ //.map(|sidres| sidres.map(|sid| DiaryId::from_storeid(&sid)))
+ .next()
}
}
}
- pub fn name(&self) -> &'a str {
- &self.name
+ /// Get all diary names
+ fn diary_names(&self) -> Result<DiaryNameIterator> {
+ self.retrieve_for_module("diary")
+ .map_err_into(DEK::StoreReadError)
+ .map(DiaryNameIterator::new)
}
+
}
diff --git a/lib/domain/libimagdiary/src/entry.rs b/lib/domain/libimagdiary/src/entry.rs
index 0148b59d..2da96199 100644
--- a/lib/domain/libimagdiary/src/entry.rs
+++ b/lib/domain/libimagdiary/src/entry.rs
@@ -17,74 +17,24 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
-use std::ops::Deref;
-use std::ops::DerefMut;
-
-use libimagstore::store::FileLockEntry;
-use libimagentryedit::edit::Edit;
-use libimagentryedit::result::Result as EditResult;
-use libimagrt::runtime::Runtime;
+use libimagstore::store::Entry;
use diaryid::DiaryId;
use diaryid::FromStoreId;
+use result::Result;
-#[derive(Debug)]
-pub struct Entry<'a>(FileLockEntry<'a>);
-
-impl<'a> Deref for Entry<'a> {
- type Target = FileLockEntry<'a>;
-
- fn deref(&self) -> &FileLockEntry<'a> {
- &self.0
- }
-
-}
-
-impl<'a> DerefMut for Entry<'a> {
-
- fn deref_mut(&mut self) -> &mut FileLockEntry<'a> {
- &mut self.0
- }
-
+pub trait DiaryEntry {
+ fn diary_id(&self) -> Result<DiaryId>;
}
-impl<'a> Entry<'a> {
-
- pub fn new(fle: FileLockEntry<'a>) -> Entry<'a> {
- Entry(fle)
- }
+impl DiaryEntry for Entry {
/// Get the diary id for this entry.
///
/// TODO: calls Option::unwrap() as it assumes that an existing Entry has an ID that is parsable
- pub fn diary_id(&self) -> DiaryId {
- DiaryId::from_storeid(&self.0.get_location().clone()).unwrap()
- }
-
-}
-
-impl<'a> Into<FileLockEntry<'a>> for Entry<'a> {
-
- fn into(self) -> FileLockEntry<'a> {
- self.0
- }
-
-}
-
-impl<'a> From<FileLockEntry<'a>> for Entry<'a> {
-
- fn from(fle: FileLockEntry<'a>) -> Entry<'a> {
- Entry::new(fle)
+ fn diary_id(&self) -> Result<DiaryId> {
+ DiaryId::from_storeid(&self.get_location().clone())
}
}
-impl<'a> Edit for Entry<'a> {
-
- fn edit_content(&mut self, rt: &Runtime) -> EditResult<()> {
- self.0.edit_content(rt)
- }
-
-}
-
-
diff --git a/lib/domain/libimagdiary/src/error.rs b/lib/domain/libimagdiary/src/error.rs
index b5406b12..1164f806 100644
--- a/lib/domain/libimagdiary/src/error.rs
+++ b/lib/domain/libimagdiary/src/error.rs
@@ -28,7 +28,8 @@ generate_error_module!(
EntryNotInDiary => "Entry not in Diary",
IOError => "IO Error",
ViewError => "Error viewing diary entry",
- IdParseError => "Error while parsing ID"
+ IdParseError => "Error while parsing ID",
+ DiaryNameFindingError => "Error while finding a diary name"
);
);
diff --git a/lib/domain/libimagdiary/src/is_in_diary.rs b/lib/domain/libimagdiary/src/is_in_diary.rs
index 09228072..8b48e1cc 100644
--- a/lib/domain/libimagdiary/src/is_in_diary.rs
+++ b/lib/domain/libimagdiary/src/is_in_diary.rs
@@ -24,6 +24,8 @@ pub trait IsInDiary {
fn is_in_diary(&self, name: &str) -> bool;
+ fn is_a_diary_entry(&self) -> bool;
+
}
impl IsInDiary for Entry {
@@ -32,6 +34,10 @@ impl IsInDiary for Entry {
self.get_location().clone().is_in_diary(name)
}
+ fn is_a_diary_entry(&self) -> bool {
+ self.get_location().clone().is_a_diary_entry()
+ }
+
}
impl IsInDiary for StoreId {
@@ -40,5 +46,9 @@ impl IsInDiary for StoreId {
self.local().starts_with(format!("diary/{}", name))
}
+ fn is_a_diary_entry(&self) -> bool {
+ self.local().starts_with("diary")
+ }
+
}
diff --git a/lib/domain/libimagdiary/src/iter.rs b/lib/domain/libimagdiary/src/iter.rs
index de849872..32fe407c 100644
--- a/lib/domain/libimagdiary/src/iter.rs
+++ b/lib/domain/libimagdiary/src/iter.rs
@@ -21,21 +21,23 @@ use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;
use libimagstore::store::Store;
+use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreIdIterator;
+use libimagerror::trace::trace_error;
+use libimagerror::into::IntoError;
use diaryid::DiaryId;
use diaryid::FromStoreId;
-use is_in_diary::IsInDiary;
-use entry::Entry as DiaryEntry;
use error::DiaryError as DE;
use error::DiaryErrorKind as DEK;
+use error::MapErrInto;
use result::Result;
-use libimagerror::trace::trace_error;
+use is_in_diary::IsInDiary;
/// A iterator for iterating over diary entries
pub struct DiaryEntryIterator<'a> {
store: &'a Store,
- name: &'a str,
+ name: String,
iter: StoreIdIterator,
year: Option<i32>,
@@ -54,7 +56,7 @@ impl<'a> Debug for DiaryEntryIterator<'a> {
impl<'a> DiaryEntryIterator<'a> {
- pub fn new(diaryname: &'a str, store: &'a Store, iter: StoreIdIterator) -> DiaryEntryIterator<'a> {
+ pub fn new(store: &'a Store, diaryname: String, iter: StoreIdIterator) -> DiaryEntryIterator<'a> {
DiaryEntryIterator {
store: store,
name: diaryname,
@@ -87,9 +89,9 @@ impl<'a> DiaryEntryIterator<'a> {
}
impl<'a> Iterator for DiaryEntryIterator<'a> {
- type Item = Result<DiaryEntry<'a>>;
+ type Item = Result<FileLockEntry<'a>>;
- fn next(&mut self) -> Option<Result<DiaryEntry<'a>>> {
+ fn next(&mut self) -> Option<Self::Item> {
loop {
let next = match self.iter.next() {
Some(s) => s,
@@ -97,7 +99,7 @@ impl<'a> Iterator for DiaryEntryIterator<'a> {
};
debug!("Next element: {:?}", next);
- if next.is_in_diary(self.name) {
+ if next.is_in_diary(&self.name) {
debug!("Seems to be in diary: {:?}", next);
let id = match DiaryId::from_storeid(&next) {
Ok(i) => i,
@@ -118,7 +120,6 @@ impl<'a> Iterator for DiaryEntryIterator<'a> {
return Some(self
.store
.retrieve(next)
- .map(|fle| DiaryEntry::new(fle))
.map_err(|e| DE::new(DEK::StoreReadError, Some(Box::new(e))))
);
}
@@ -130,3 +131,37 @@ impl<'a> Iterator for DiaryEntryIterator<'a> {
}
+
+/// Get diary names.
+///
+/// # Warning
+///
+/// Does _not_ run a `unique` on the iterator!
+pub struct DiaryNameIterator(StoreIdIterator);
+
+impl DiaryNameIterator {
+ pub fn new(s: StoreIdIterator) -> DiaryNameIterator {
+ DiaryNameIterator(s)
+ }
+}
+
+impl Iterator for DiaryNameIterator {
+ type Item = Result<String>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0
+ .next()
+ .map(|s| {
+ s.to_str()
+ .map_err_into(DEK::DiaryNameFindingError)
+ .and_then(|s| {
+ s.split("diary/")
+ .nth(1)
+ .and_then(|n| n.split("/").nth(0).map(String::from))
+ .ok_or(DEK::DiaryNameFindingError.into_error())
+ })
+ })
+ }
+
+}
+
diff --git a/lib/domain/libimagdiary/src/viewer.rs b/lib/domain/libimagdiary/src/viewer.rs
index 93b155a7..c0c03fc6 100644
--- a/lib/domain/libimagdiary/src/viewer.rs
+++ b/lib/domain/libimagdiary/src/viewer.rs
@@ -19,13 +19,15 @@
//! A diary viewer built on libimagentryview.
-use entry::Entry;
+use entry::DiaryEntry;
use error::DiaryErrorKind as DEK;
use error::MapErrInto;
use result::Result;
+use libimagstore::store::FileLockEntry;
use libimagentryview::viewer::Viewer;
use libimagentryview::builtin::plain::PlainViewer;
+use libimagerror::trace::trace_error;
/// This viewer does _not_ implement libimagentryview::viewer::Viewer because we need to be able to
/// call some diary-type specific functions on the entries passed to this.
@@ -46,10 +48,12 @@ impl DiaryViewer {
/// View all entries from the iterator, or stop immediately if an error occurs, returning that
/// error.
- pub fn view_entries<'a, I: Iterator<Item = Entry<'a>>>(&self, entries: I) -> Result<()> {
+ pub fn view_entries<'a, I: Iterator<Item = FileLockEntry<'a>>>(&self, entries: I) -> Result<()> {
for entry in entries {
- let id = entry.diary_id();
- println!("{} :\n", id);
+ match entry.diary_id() {
+ Ok(id) => println!("{} :\n", id),
+ Err(e) => trace_error(&e),
+ }
let _ = try!(self.0
.view_entry(&entry)
.map_err_into(DEK::ViewError)
diff --git a/lib/domain/libimagmail/src/iter.rs b/lib/domain/libimagmail/src/iter.rs
index fe1e72a4..ee418765 100644
--- a/lib/domain/libimagmail/src/iter.rs
+++ b/lib/domain/libimagmail/src/iter.rs
@@ -27,16 +27,16 @@
use mail::Mail;
use result::Result;
-use libimagentryref::reference::Ref;
+use libimagstore::store::FileLockEntry;
use std::marker::PhantomData;
-pub struct MailIter<'a, I: 'a + Iterator<Item = Ref<'a>>> {
- _marker: PhantomData<&'a I>,
+pub struct MailIter<'a, I: Iterator<Item = FileLockEntry<'a>>> {
+ _marker: PhantomData<I>,
i: I,
}
-impl<'a, I: Iterator<Item = Ref<'a>>> MailIter<'a, I> {
+impl<'a, I: Iterator<Item = FileLockEntry<'a>>> MailIter<'a, I> {
pub fn new(i: I) -> MailIter<'a, I> {
MailIter { _marker: PhantomData, i: i }
@@ -44,12 +44,11 @@ impl<'a, I: Iterator<Item = Ref<'a>>> MailIter<'a, I> {
}
-impl<'a, I: Iterator<Item = Ref<'a>>> Iterator for MailIter<'a, I> {
-
+impl<'a, I: Iterator<Item = FileLockEntry<'a>>> Iterator for MailIter<'a, I> {
type Item = Result<Mail<'a>>;
- fn next(&mut self) -> Option<Result<Mail<'a>>> {
- self.i.next().map(Mail::from_ref)
+ fn next(&mut self) -> Option<Self::Item> {
+ self.i.next().map(Mail::from_fle)
}
}
diff --git a/lib/domain/libimagmail/src/mail.rs b/lib/domain/libimagmail/src/mail.rs
index ede27704..8f2e05c5 100644
--- a/lib/domain/libimagmail/src/mail.rs
+++ b/lib/domain/libimagmail/src/mail.rs
@@ -23,8 +23,10 @@ use std::fs::File;
use std::io::Read;
use libimagstore::store::Store;
+use libimagstore::store::FileLockEntry;
use libimagentryref::reference::Ref;
use libimagentryref::flags::RefFlags;
+use libimagentryref::refstore::RefStore;
use email::MimeMessage;
use email::results::ParsingResult as EmailParsingResult;
@@ -47,7 +49,7 @@ impl From<String> for Buffer {
}
}
-pub struct Mail<'a>(Ref<'a>, Buffer);
+pub struct Mail<'a>(FileLockEntry<'a>, Buffer);
impl<'a> Mail<'a> {
@@ -58,7 +60,7 @@ impl<'a> Mail<'a> {
let f = RefFlags::default().with_content_hashing(true).with_permission_tracking(false);
let p = PathBuf::from(p.as_ref());
- Ref::create_with_hasher(store, p, f, h)
+ store.create_with_hasher(p, f, h)
.map_err_into(MEK::RefCreationError)
.and_then(|reference| {
debug!("Build reference file: {:?}", reference);
@@ -79,20 +81,19 @@ impl<'a> Mail<'a> {
/// Opens a mail by the passed hash
pub fn open<S: AsRef<str>>(store: &Store, hash: S) -> Result<Option<Mail>> {
debug!("Opening Mail by Hash");
- Ref::get_by_hash(store, String::from(hash.as_ref()))
+ store.get_by_hash(String::from(hash.as_ref()))
.map_err_into(MEK::FetchByHashError)
.map_err_into(MEK::FetchError)
.and_then(|o| match o {
- Some(r) => Mail::from_ref(r).map(Some),
+ Some(r) => Mail::from_fle(r).map(Some),
None => Ok(None),
})
}
/// Implement me as TryFrom as soon as it is stable
- pub fn from_ref(r: Ref<'a>) -> Result<Mail> {
- debug!("Building Mail object from Ref: {:?}", r);
- r.fs_file()
+ pub fn from_fle(fle: FileLockEntry<'a>) -> Result<Mail<'a>> {
+ fle.fs_file()
.map_err_into(MEK::RefHandlingError)
.and_then(|path| File::open(path).map_err_into(MEK::IOError))
.and_then(|mut file| {
@@ -102,7 +103,7 @@ impl<'a> Mail<'a> {
.map_err_into(MEK::IOError)
})
.map(Buffer::from)
- .map(|buffer| Mail(r, buffer))
+ .map(|buffer| Mail(fle, buffer))
}
pub fn get_field(&self, field: &str) -> Result<Option<String>> {
diff --git a/lib/domain/libimagtodo/src/error.rs b/lib/domain/libimagtodo/src/error.rs
index 621d3249..de39049f 100644
--- a/lib/domain/libimagtodo/src/error.rs
+++ b/lib/domain/libimagtodo/src/error.rs
@@ -23,7 +23,10 @@ generate_error_module!(
StoreError => "Store Error",
StoreIdError => "Store Id handling error",
ImportError => "Error importing",
- UTF8Error => "Encountered non-UTF8 characters while reading input"
+ UTF8Error => "Encountered non-UTF8 characters while reading input",
+ HeaderFieldMissing => "Header field missing",
+ HeaderTypeError => "Header field type error",
+ UuidParserError => "Uuid parser error"
);
);
diff --git a/lib/domain/libimagtodo/src/lib.rs b/lib/domain/libimagtodo/src/lib.rs
index 7961a7a1..6c0c482e 100644
--- a/lib/domain/libimagtodo/src/lib.rs
+++ b/lib/domain/libimagtodo/src/lib.rs
@@ -48,4 +48,5 @@ module_entry_path_mod!("todo");
pub mod error;
pub mod result;
pub mod task;
+pub mod taskstore;
diff --git a/lib/domain/libimagtodo/src/task.rs b/lib/domain/libimagtodo/src/task.rs
index 3dbbd04c..b2b70696 100644
--- a/lib/domain/libimagtodo/src/task.rs
+++ b/lib/domain/libimagtodo/src/task.rs
@@ -17,271 +17,31 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
-use std::collections::BTreeMap;
-use std::ops::{Deref, DerefMut};
-use std::io::BufRead;
-use std::result::Result as RResult;
-
-use toml::Value;
-use uuid::Uuid;
-
-use task_hookrs::task::Task as TTask;
-use task_hookrs::import::{import_task, import_tasks};
-
-use libimagstore::store::{FileLockEntry, Store};
-use libimagstore::storeid::{IntoStoreId, StoreIdIterator, StoreId};
-use module_path::ModuleEntryPath;
-
-use error::{TodoErrorKind as TEK, MapErrInto};
+use error::TodoErrorKind as TEK;
+use error::MapErrInto;
use result::Result;
-/// Task struct containing a `FileLockEntry`
-#[derive(Debug)]
-pub struct Task<'a>(FileLockEntry<'a>);
-
-impl<'a> Task<'a> {
-
- /// Concstructs a new `Task` with a `FileLockEntry`
- pub fn new(fle: FileLockEntry<'a>) -> Task<'a> {
- Task(fle)
- }
-
- pub fn import<R: BufRead>(store: &'a Store, mut r: R) -> Result<(Task<'a>, String, Uuid)> {
- let mut line = String::new();
- try!(r.read_line(&mut line).map_err_into(TEK::UTF8Error));
- import_task(&line.as_str())
- .map_err_into(TEK::ImportError)
- .and_then(|t| {
- let uuid = t.uuid().clone();
- t.into_task(store).map(|t| (t, line, uuid))
- })
- }
-
- /// Get a task from an import string. That is: read the imported string, get the UUID from it
- /// and try to load this UUID from store.
- ///
- /// Possible return values are:
- ///
- /// * Ok(Ok(Task))
- /// * Ok(Err(String)) - where the String is the String read from the `r` parameter
- /// * Err(_) - where the error is an error that happened during evaluation
- ///
- pub fn get_from_import<R>(store: &'a Store, mut r: R) -> Result<RResult<Task<'a>, String>>
- where R: BufRead
- {
- let mut line = String::new();
- try!(r.read_line(&mut line).map_err_into(TEK::UTF8Error));
- Task::get_from_string(store, line)
- }
-
- /// Get a task from a String. The String is expected to contain the JSON-representation of the
- /// Task to get from the store (only the UUID really matters in this case)
- ///
- /// For an explanation on the return values see `Task::get_from_import()`.
- pub fn get_from_string(store: &'a Store, s: String) -> Result<RResult<Task<'a>, String>> {
- import_task(s.as_str())
- .map_err_into(TEK::ImportError)
- .map(|t| t.uuid().clone())
- .and_then(|uuid| Task::get_from_uuid(store, uuid))
- .and_then(|o| match o {
- None => Ok(Err(s)),
- Some(t) => Ok(Ok(t)),
- })
- }
-
- /// Get a task from an UUID.
- ///
- /// 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>>> {
- ModuleEntryPath::new(format!("taskwarrior/{}", uuid))
- .into_storeid()
- .and_then(|store_id| store.get(store_id))
- .map(|o| o.map(Task::new))
- .map_err_into(TEK::StoreError)
- }
-
- /// Same as Task::get_from_import() but uses Store::retrieve() rather than Store::get(), to
- /// implicitely create the task if it does not exist.
- pub fn retrieve_from_import<R: BufRead>(store: &'a Store, mut r: R) -> Result<Task<'a>> {
- let mut line = String::new();
- try!(r.read_line(&mut line).map_err_into(TEK::UTF8Error));
- Task::retrieve_from_string(store, line)
- }
-
- /// Retrieve a task from a String. The String is expected to contain the JSON-representation of
- /// the Task to retrieve from the store (only the UUID really matters in this case)
- pub fn retrieve_from_string(store: &'a Store, s: String) -> Result<Task<'a>> {
- Task::get_from_string(store, s)
- .and_then(|opt| match opt {
- Ok(task) => Ok(task),
- Err(string) => import_task(string.as_str())
- .map_err_into(TEK::ImportError)
- .and_then(|t| t.into_task(store)),
- })
- }
-
- pub fn delete_by_imports<R: BufRead>(store: &Store, r: R) -> Result<()> {
- use serde_json::ser::to_string as serde_to_string;
- use task_hookrs::status::TaskStatus;
-
- for (counter, res_ttask) in import_tasks(r).into_iter().enumerate() {
- match res_ttask {
- Ok(ttask) => {
- if counter % 2 == 1 {
- // Only every second task is needed, the first one is the
- // task before the change, and the second one after
- // the change. The (maybe modified) second one is
- // expected by taskwarrior.
- match serde_to_string(&ttask).map_err_into(TEK::ImportError) {
- // use println!() here, as we talk with TW
- Ok(val) => println!("{}", val),
- Err(e) => return Err(e),
- }
-
- // Taskwarrior does not have the concept of deleted tasks, but only modified
- // ones.
- //
- // Here we check if the status of a task is deleted and if yes, we delete it
- // from the store.
- if *ttask.status() == TaskStatus::Deleted {
- match Task::delete_by_uuid(store, *ttask.uuid()) {
- Ok(_) => info!("Deleted task {}", *ttask.uuid()),
- Err(e) => return Err(e),
- }
- }
- } // end if c % 2
- },
- Err(e) => return Err(e).map_err_into(TEK::ImportError),
- }
- }
- Ok(())
- }
-
- pub fn delete_by_uuid(store: &Store, uuid: Uuid) -> Result<()> {
- ModuleEntryPath::new(format!("taskwarrior/{}", uuid))
- .into_storeid()
- .and_then(|id| store.delete(id))
- .map_err_into(TEK::StoreError)
- }
-
- pub fn all_as_ids(store: &Store) -> Result<StoreIdIterator> {
- store.retrieve_for_module("todo/taskwarrior")
- .map_err_into(TEK::StoreError)
- }
-
- pub fn all(store: &Store) -> Result<TaskIterator> {
- Task::all_as_ids(store)
- .map(|iter| TaskIterator::new(store, iter))
- }
-
-}
-
-impl<'a> Deref for Task<'a> {
- type Target = FileLockEntry<'a>;
+use libimagstore::store::Entry;
+use libimagerror::into::IntoError;
- fn deref(&self) -> &FileLockEntry<'a> {
- &self.0
- }
-
-}
-
-impl<'a> DerefMut for Task<'a> {
-
- fn deref_mut(&mut self) -> &mut FileLockEntry<'a> {
- &mut self.0
- }
-
-}
-
-/// A trait to get a `libimagtodo::task::Task` out of the implementing object.
-pub trait IntoTask<'a> {
-
- /// # Usage
- /// ```ignore
- /// use std::io::stdin;
- ///
- /// use task_hookrs::task::Task;
- /// use task_hookrs::import::import;
- /// use libimagstore::store::{Store, FileLockEntry};
- ///
- /// if let Ok(task_hookrs_task) = import(stdin()) {
- /// // Store is given at runtime
- /// let task = task_hookrs_task.into_filelockentry(store);
- /// println!("Task with uuid: {}", task.flentry.get_header().get("todo.uuid"));