libimagtodo: Move from error-chain to failure
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
parent
1956099e2e
commit
d3c0826188
6 changed files with 48 additions and 127 deletions
|
@ -20,13 +20,13 @@ is-it-maintained-open-issues = { repository = "matthiasbeyer/imag" }
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
task-hookrs = { git = "https://github.com/matthiasbeyer/task-hookrs", branch = "master" }
|
task-hookrs = { git = "https://github.com/matthiasbeyer/task-hookrs", branch = "failure" }
|
||||||
uuid = "0.7"
|
uuid = "0.7"
|
||||||
toml = "0.4"
|
toml = "0.4"
|
||||||
toml-query = "0.7"
|
toml-query = { git = "https://github.com/matthiasbeyer/toml-query", branch = "failure" }
|
||||||
log = "0.4.0"
|
log = "0.4.0"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
error-chain = "0.12"
|
failure = "0.1"
|
||||||
|
|
||||||
libimagstore = { version = "0.9.0", path = "../../../lib/core/libimagstore" }
|
libimagstore = { version = "0.9.0", path = "../../../lib/core/libimagstore" }
|
||||||
libimagerror = { version = "0.9.0", path = "../../../lib/core/libimagerror" }
|
libimagerror = { version = "0.9.0", path = "../../../lib/core/libimagerror" }
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
//
|
|
||||||
// imag - the personal information management suite for the commandline
|
|
||||||
// Copyright (C) 2015-2018 Matthias Beyer <mail@beyermatthias.de> and contributors
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; version
|
|
||||||
// 2.1 of the License.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
//
|
|
||||||
|
|
||||||
error_chain! {
|
|
||||||
types {
|
|
||||||
TodoError, TodoErrorKind, ResultExt, Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
links {
|
|
||||||
StoreError(::libimagstore::error::StoreError, ::libimagstore::error::StoreErrorKind);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreign_links {
|
|
||||||
TomlQueryError(::toml_query::error::Error);
|
|
||||||
}
|
|
||||||
|
|
||||||
errors {
|
|
||||||
ConversionError {
|
|
||||||
description("Conversion Error")
|
|
||||||
display("Conversion Error")
|
|
||||||
}
|
|
||||||
|
|
||||||
StoreIdError {
|
|
||||||
description("Store Id handling error")
|
|
||||||
display("Store Id handling error")
|
|
||||||
}
|
|
||||||
|
|
||||||
ImportError {
|
|
||||||
description("Error importing")
|
|
||||||
display("Error importing")
|
|
||||||
}
|
|
||||||
|
|
||||||
UTF8Error {
|
|
||||||
description("Encountered non-UTF8 characters while reading input")
|
|
||||||
display("Encountered non-UTF8 characters while reading input")
|
|
||||||
}
|
|
||||||
|
|
||||||
HeaderFieldMissing {
|
|
||||||
description("Header field missing")
|
|
||||||
display("Header field missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
HeaderTypeError {
|
|
||||||
description("Header field type error")
|
|
||||||
display("Header field type error")
|
|
||||||
}
|
|
||||||
|
|
||||||
UuidParserError {
|
|
||||||
description("Uuid parser error")
|
|
||||||
display("Uuid parser error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,8 +20,7 @@
|
||||||
use libimagstore::storeid::StoreIdIterator;
|
use libimagstore::storeid::StoreIdIterator;
|
||||||
use libimagstore::storeid::StoreId;
|
use libimagstore::storeid::StoreId;
|
||||||
|
|
||||||
use error::Result;
|
use failure::Fallible as Result;
|
||||||
use error::TodoError as TE;
|
|
||||||
|
|
||||||
pub struct TaskIdIterator(StoreIdIterator);
|
pub struct TaskIdIterator(StoreIdIterator);
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ impl Iterator for TaskIdIterator {
|
||||||
loop {
|
loop {
|
||||||
match self.0.next() {
|
match self.0.next() {
|
||||||
None => return None,
|
None => return None,
|
||||||
Some(Err(e)) => return Some(Err(e).map_err(TE::from)),
|
Some(Err(e)) => return Some(Err(e)),
|
||||||
Some(Ok(n)) => if n.is_in_collection(&["todo", "taskwarrior"]) {
|
Some(Ok(n)) => if n.is_in_collection(&["todo", "taskwarrior"]) {
|
||||||
return Some(Ok(n))
|
return Some(Ok(n))
|
||||||
}, // else continue
|
}, // else continue
|
||||||
|
|
|
@ -40,7 +40,7 @@ extern crate toml;
|
||||||
extern crate toml_query;
|
extern crate toml_query;
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
#[macro_use] extern crate error_chain;
|
extern crate failure;
|
||||||
|
|
||||||
#[macro_use] extern crate libimagstore;
|
#[macro_use] extern crate libimagstore;
|
||||||
extern crate libimagerror;
|
extern crate libimagerror;
|
||||||
|
@ -48,7 +48,6 @@ extern crate task_hookrs;
|
||||||
|
|
||||||
module_entry_path_mod!("todo");
|
module_entry_path_mod!("todo");
|
||||||
|
|
||||||
pub mod error;
|
|
||||||
pub mod task;
|
pub mod task;
|
||||||
pub mod taskstore;
|
pub mod taskstore;
|
||||||
pub mod iter;
|
pub mod iter;
|
||||||
|
|
|
@ -17,12 +17,13 @@
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
//
|
//
|
||||||
|
|
||||||
use error::TodoError as TE;
|
use failure::ResultExt;
|
||||||
use error::TodoErrorKind as TEK;
|
use failure::Error;
|
||||||
use error::ResultExt;
|
use failure::err_msg;
|
||||||
use error::Result;
|
use failure::Fallible as Result;
|
||||||
|
|
||||||
use libimagstore::store::Entry;
|
use libimagstore::store::Entry;
|
||||||
|
use libimagerror::errors::ErrorMsg as EM;
|
||||||
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use toml_query::read::TomlValueReadTypeExt;
|
use toml_query::read::TomlValueReadTypeExt;
|
||||||
|
@ -35,8 +36,10 @@ impl Task for Entry {
|
||||||
fn get_uuid(&self) -> Result<Uuid> {
|
fn get_uuid(&self) -> Result<Uuid> {
|
||||||
self.get_header()
|
self.get_header()
|
||||||
.read_string("todo.uuid")?
|
.read_string("todo.uuid")?
|
||||||
.ok_or(TE::from_kind(TEK::HeaderFieldMissing))
|
.ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("todo.uuid")))
|
||||||
.and_then(|u| Uuid::parse_str(&u).chain_err(|| TEK::UuidParserError))
|
.and_then(|u| {
|
||||||
|
Uuid::parse_str(&u).context(err_msg("UUID Parser error")).map_err(Error::from)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,15 +26,16 @@ use uuid::Uuid;
|
||||||
|
|
||||||
use task_hookrs::task::Task as TTask;
|
use task_hookrs::task::Task as TTask;
|
||||||
use task_hookrs::import::{import_task, import_tasks};
|
use task_hookrs::import::{import_task, import_tasks};
|
||||||
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
|
use failure::Error;
|
||||||
|
use failure::err_msg;
|
||||||
|
|
||||||
use libimagstore::store::{FileLockEntry, Store};
|
use libimagstore::store::{FileLockEntry, Store};
|
||||||
use libimagstore::storeid::IntoStoreId;
|
use libimagstore::storeid::IntoStoreId;
|
||||||
|
use libimagerror::errors::ErrorMsg as EM;
|
||||||
use module_path::ModuleEntryPath;
|
use module_path::ModuleEntryPath;
|
||||||
|
|
||||||
use error::TodoErrorKind as TEK;
|
|
||||||
use error::TodoError as TE;
|
|
||||||
use error::Result;
|
|
||||||
use error::ResultExt;
|
|
||||||
use iter::TaskIdIterator;
|
use iter::TaskIdIterator;
|
||||||
|
|
||||||
/// Task struct containing a `FileLockEntry`
|
/// Task struct containing a `FileLockEntry`
|
||||||
|
@ -55,9 +56,10 @@ impl<'a> TaskStore<'a> for Store {
|
||||||
|
|
||||||
fn import_task_from_reader<R: BufRead>(&'a self, mut r: R) -> Result<(FileLockEntry<'a>, String, Uuid)> {
|
fn import_task_from_reader<R: BufRead>(&'a self, mut r: R) -> Result<(FileLockEntry<'a>, String, Uuid)> {
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
r.read_line(&mut line).map_err(|_| TE::from_kind(TEK::UTF8Error))?;
|
r.read_line(&mut line).context(EM::UTF8Error)?;
|
||||||
import_task(&line.as_str())
|
import_task(&line.as_str())
|
||||||
.map_err(|_| TE::from_kind(TEK::ImportError))
|
.context(err_msg("Error importing"))
|
||||||
|
.map_err(Error::from)
|
||||||
.and_then(|t| {
|
.and_then(|t| {
|
||||||
let uuid = t.uuid().clone();
|
let uuid = t.uuid().clone();
|
||||||
self.new_from_twtask(t).map(|t| (t, line, uuid))
|
self.new_from_twtask(t).map(|t| (t, line, uuid))
|
||||||
|
@ -75,7 +77,7 @@ impl<'a> TaskStore<'a> for Store {
|
||||||
///
|
///
|
||||||
fn get_task_from_import<R: BufRead>(&'a self, mut r: R) -> Result<RResult<FileLockEntry<'a>, String>> {
|
fn get_task_from_import<R: BufRead>(&'a self, mut r: R) -> Result<RResult<FileLockEntry<'a>, String>> {
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
r.read_line(&mut line).chain_err(|| TEK::UTF8Error)?;
|
r.read_line(&mut line).context(EM::UTF8Error)?;
|
||||||
self.get_task_from_string(line)
|
self.get_task_from_string(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +87,8 @@ impl<'a> TaskStore<'a> for Store {
|
||||||
/// For an explanation on the return values see `Task::get_from_import()`.
|
/// For an explanation on the return values see `Task::get_from_import()`.
|
||||||
fn get_task_from_string(&'a self, s: String) -> Result<RResult<FileLockEntry<'a>, String>> {
|
fn get_task_from_string(&'a self, s: String) -> Result<RResult<FileLockEntry<'a>, String>> {
|
||||||
import_task(s.as_str())
|
import_task(s.as_str())
|
||||||
.map_err(|_| TE::from_kind(TEK::ImportError))
|
.context(err_msg("Import error"))
|
||||||
|
.map_err(Error::from)
|
||||||
.map(|t| t.uuid().clone())
|
.map(|t| t.uuid().clone())
|
||||||
.and_then(|uuid| self.get_task_from_uuid(uuid))
|
.and_then(|uuid| self.get_task_from_uuid(uuid))
|
||||||
.and_then(|o| match o {
|
.and_then(|o| match o {
|
||||||
|
@ -101,14 +104,13 @@ impl<'a> TaskStore<'a> for Store {
|
||||||
ModuleEntryPath::new(format!("taskwarrior/{}", uuid))
|
ModuleEntryPath::new(format!("taskwarrior/{}", uuid))
|
||||||
.into_storeid()
|
.into_storeid()
|
||||||
.and_then(|store_id| self.get(store_id))
|
.and_then(|store_id| self.get(store_id))
|
||||||
.map_err(TE::from)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as Task::get_from_import() but uses Store::retrieve() rather than Store::get(), to
|
/// Same as Task::get_from_import() but uses Store::retrieve() rather than Store::get(), to
|
||||||
/// implicitely create the task if it does not exist.
|
/// implicitely create the task if it does not exist.
|
||||||
fn retrieve_task_from_import<R: BufRead>(&'a self, mut r: R) -> Result<FileLockEntry<'a>> {
|
fn retrieve_task_from_import<R: BufRead>(&'a self, mut r: R) -> Result<FileLockEntry<'a>> {
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
r.read_line(&mut line).chain_err(|| TEK::UTF8Error)?;
|
r.read_line(&mut line).context(EM::UTF8Error)?;
|
||||||
self.retrieve_task_from_string(line)
|
self.retrieve_task_from_string(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +121,8 @@ impl<'a> TaskStore<'a> for Store {
|
||||||
.and_then(|opt| match opt {
|
.and_then(|opt| match opt {
|
||||||
Ok(task) => Ok(task),
|
Ok(task) => Ok(task),
|
||||||
Err(string) => import_task(string.as_str())
|
Err(string) => import_task(string.as_str())
|
||||||
.map_err(|_| TE::from_kind(TEK::ImportError))
|
.context(err_msg("Import error"))
|
||||||
|
.map_err(Error::from)
|
||||||
.and_then(|t| self.new_from_twtask(t)),
|
.and_then(|t| self.new_from_twtask(t)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -129,33 +132,25 @@ impl<'a> TaskStore<'a> for Store {
|
||||||
use task_hookrs::status::TaskStatus;
|
use task_hookrs::status::TaskStatus;
|
||||||
|
|
||||||
for (counter, res_ttask) in import_tasks(r).into_iter().enumerate() {
|
for (counter, res_ttask) in import_tasks(r).into_iter().enumerate() {
|
||||||
match res_ttask {
|
let ttask = res_ttask.context(err_msg("Import error"))?;
|
||||||
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).chain_err(|| 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
|
if counter % 2 == 1 {
|
||||||
// ones.
|
// Only every second task is needed, the first one is the
|
||||||
//
|
// task before the change, and the second one after
|
||||||
// Here we check if the status of a task is deleted and if yes, we delete it
|
// the change. The (maybe modified) second one is
|
||||||
// from the store.
|
// expected by taskwarrior.
|
||||||
if *ttask.status() == TaskStatus::Deleted {
|
let val = serde_to_string(&ttask).context(err_msg("Import error"))?;
|
||||||
match self.delete_task_by_uuid(*ttask.uuid()) {
|
println!("{}", val);
|
||||||
Ok(_) => info!("Deleted task {}", *ttask.uuid()),
|
|
||||||
Err(e) => return Err(e),
|
// Taskwarrior does not have the concept of deleted tasks, but only modified
|
||||||
}
|
// ones.
|
||||||
}
|
//
|
||||||
} // end if c % 2
|
// Here we check if the status of a task is deleted and if yes, we delete it
|
||||||
},
|
// from the store.
|
||||||
Err(_) => return Err(TE::from_kind(TEK::ImportError)),
|
if *ttask.status() == TaskStatus::Deleted {
|
||||||
|
let _ = self.delete_task_by_uuid(*ttask.uuid())?;
|
||||||
|
info!("Deleted task {}", *ttask.uuid());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -165,13 +160,10 @@ impl<'a> TaskStore<'a> for Store {
|
||||||
ModuleEntryPath::new(format!("taskwarrior/{}", uuid))
|
ModuleEntryPath::new(format!("taskwarrior/{}", uuid))
|
||||||
.into_storeid()
|
.into_storeid()
|
||||||
.and_then(|id| self.delete(id))
|
.and_then(|id| self.delete(id))
|
||||||
.map_err(TE::from)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn all_tasks(&self) -> Result<TaskIdIterator> {
|
fn all_tasks(&self) -> Result<TaskIdIterator> {
|
||||||
self.entries()
|
self.entries().map(|i| TaskIdIterator::new(i.without_store()))
|
||||||
.map(|i| TaskIdIterator::new(i.without_store()))
|
|
||||||
.map_err(TE::from)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_from_twtask(&'a self, task: TTask) -> Result<FileLockEntry<'a>> {
|
fn new_from_twtask(&'a self, task: TTask) -> Result<FileLockEntry<'a>> {
|
||||||
|
@ -181,10 +173,8 @@ impl<'a> TaskStore<'a> for Store {
|
||||||
let uuid = task.uuid();
|
let uuid = task.uuid();
|
||||||
ModuleEntryPath::new(format!("taskwarrior/{}", uuid))
|
ModuleEntryPath::new(format!("taskwarrior/{}", uuid))
|
||||||
.into_storeid()
|
.into_storeid()
|
||||||
.chain_err(|| TEK::StoreIdError)
|
|
||||||
.and_then(|id| {
|
.and_then(|id| {
|
||||||
self.retrieve(id)
|
self.retrieve(id)
|
||||||
.map_err(TE::from)
|
|
||||||
.and_then(|mut fle| {
|
.and_then(|mut fle| {
|
||||||
{
|
{
|
||||||
let hdr = fle.get_header_mut();
|
let hdr = fle.get_header_mut();
|
||||||
|
|
Loading…
Reference in a new issue