diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2017-09-04 21:59:54 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-04 21:59:54 +0200 |
commit | 6d1dab31179eb4414b45d9a94f453833ddc558ce (patch) | |
tree | 8bca1ca131e17a647a98d083087e0a42124067eb /lib | |
parent | f025416cf7d96b5f2a41d545c75255cab9fe2d06 (diff) | |
parent | 6583ba04a2151d940d99d4277713df4f50bf9eac (diff) |
Merge pull request #1029 from matthiasbeyer/all-extensions-as-traits
All extensions as traits
Diffstat (limited to 'lib')
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")); |