diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2019-12-21 13:18:41 +0100 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2019-12-21 13:18:41 +0100 |
commit | 61b0fe9fa6939d4b3c42f68ead5888927b360733 (patch) | |
tree | caff6fde00ca2ccef95b5a76e08dc5755e90e089 | |
parent | 750e5b25f6e18803e0f0dd0c10c08545ae4a6fad (diff) | |
parent | 5d022d57c796a6715fb9ab5330c11eb90cc9c5e9 (diff) |
Merge branch 'imag-timetrack/noexit' into master
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r-- | bin/domain/imag-timetrack/Cargo.toml | 1 | ||||
-rw-r--r-- | bin/domain/imag-timetrack/src/cont.rs | 56 | ||||
-rw-r--r-- | bin/domain/imag-timetrack/src/day.rs | 54 | ||||
-rw-r--r-- | bin/domain/imag-timetrack/src/lib.rs | 23 | ||||
-rw-r--r-- | bin/domain/imag-timetrack/src/list.rs | 233 | ||||
-rw-r--r-- | bin/domain/imag-timetrack/src/month.rs | 53 | ||||
-rw-r--r-- | bin/domain/imag-timetrack/src/shell.rs | 65 | ||||
-rw-r--r-- | bin/domain/imag-timetrack/src/start.rs | 35 | ||||
-rw-r--r-- | bin/domain/imag-timetrack/src/stop.rs | 85 | ||||
-rw-r--r-- | bin/domain/imag-timetrack/src/track.rs | 62 | ||||
-rw-r--r-- | bin/domain/imag-timetrack/src/week.rs | 78 | ||||
-rw-r--r-- | bin/domain/imag-timetrack/src/year.rs | 69 |
12 files changed, 307 insertions, 507 deletions
diff --git a/bin/domain/imag-timetrack/Cargo.toml b/bin/domain/imag-timetrack/Cargo.toml index 88408449..ee4ae249 100644 --- a/bin/domain/imag-timetrack/Cargo.toml +++ b/bin/domain/imag-timetrack/Cargo.toml @@ -27,6 +27,7 @@ itertools = "0.8.0" prettytable-rs = "0.8.0" kairos = "0.3.0" failure = "0.1.5" +resiter = "0.4.0" libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" } libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } diff --git a/bin/domain/imag-timetrack/src/cont.rs b/bin/domain/imag-timetrack/src/cont.rs index e5efb16a..2c77e575 100644 --- a/bin/domain/imag-timetrack/src/cont.rs +++ b/bin/domain/imag-timetrack/src/cont.rs @@ -22,36 +22,35 @@ use std::cmp::Ord; use filters::filter::Filter; use itertools::Itertools; use chrono::NaiveDateTime; +use failure::Fallible as Result; +use failure::Error; +use resiter::Filter as RFilter; -use libimagerror::trace::trace_error; -use libimagerror::trace::MapErrTrace; -use libimagerror::iter::TraceIterator; -use libimagerror::exit::ExitUnwrap; use libimagtimetrack::store::TimeTrackStore; -use libimagtimetrack::timetracking::TimeTracking; use libimagtimetrack::iter::filter::*; +use libimagtimetrack::timetracking::TimeTracking; use libimagrt::runtime::Runtime; -pub fn cont(rt: &Runtime) -> i32 { +pub fn cont(rt: &Runtime) -> Result<()> { let groups = rt.store() - .get_timetrackings() - .map_err_trace_exit_unwrap() - .trace_unwrap() - .filter(|e| has_end_time.filter(&e)) + .get_timetrackings()? + .filter_ok(|e| has_end_time.filter(&e)) + + // It is very unfortunate that we have to collect() here, but this is the least complex + // solution for the problem of grouping elements of an Iterator<Item = Result<_>>. + .collect::<Result<Vec<_>>>()? + .into_iter() .group_by(|elem| match elem.get_end_datetime() { // Now group them by the end time + Err(_) => NaiveDateTime::from_timestamp(0, 0), // placeholder Ok(Some(dt)) => dt, - Ok(None) => { + Ok(None) => { // error. We expect all of them having an end-time. error!("Has no end time, but should be filtered out: {:?}", elem); error!("This is a bug. Please report."); error!("Will panic now"); panic!("Unknown bug") } - Err(e) => { - trace_error(&e); - NaiveDateTime::from_timestamp(0, 0) // placeholder - } }); // sort the trackings by key, so by end datetime @@ -76,28 +75,27 @@ pub fn cont(rt: &Runtime) -> i32 { Some((_, trackings)) => { // and then, for all trackings trackings - .fold(Ok(0), |acc, tracking| { + .collect::<Vec<_>>() + .into_iter() + .map(|tracking| { debug!("Having tracking: {:?}", tracking); - acc.and_then(|_| { - // create a new tracking with the same tag - let val = tracking - .get_timetrack_tag() - .and_then(|tag| rt.store().create_timetracking_now(&tag)) - .map(|_| 0) - .map_err_trace(); - - rt.report_touched(tracking.get_location()).unwrap_or_exit(); + // create a new tracking with the same tag + let val = tracking + .get_timetrack_tag() + .and_then(|tag| rt.store().create_timetracking_now(&tag)) + .map(|_| 0)?; - val - }) + rt.report_touched(tracking.get_location()).map_err(Error::from).map(|_| val) }) + .collect::<Result<Vec<_>>>() + .map(|_| ()) }, None => { info!("No trackings to continue"); - Ok(1) + Ok(()) }, - }.map_err_trace_exit_unwrap() + } } diff --git a/bin/domain/imag-timetrack/src/day.rs b/bin/domain/imag-timetrack/src/day.rs index 3bcd0990..287ca0e9 100644 --- a/bin/domain/imag-timetrack/src/day.rs +++ b/bin/domain/imag-timetrack/src/day.rs @@ -22,47 +22,32 @@ use std::str::FromStr; use filters::filter::Filter; use chrono::NaiveDateTime; +use failure::Fallible as Result; use failure::Error; +use resiter::AndThen; +use resiter::Filter as RFilter; -use libimagerror::trace::trace_error; -use libimagerror::trace::MapErrTrace; -use libimagerror::iter::TraceIterator; -use libimagerror::io::ToExitCode; -use libimagerror::exit::ExitUnwrap; use libimagstore::store::FileLockEntry; use libimagtimetrack::store::TimeTrackStore; -use libimagtimetrack::timetracking::TimeTracking; use libimagtimetrack::tag::TimeTrackingTag; use libimagtimetrack::iter::filter::*; +use libimagtimetrack::timetracking::TimeTracking; use libimagrt::runtime::Runtime; - -pub fn day(rt: &Runtime) -> i32 { +pub fn day(rt: &Runtime) -> Result<()> { let (_, cmd) = rt.cli().subcommand(); let cmd = cmd.unwrap(); // checked in main() let filter = { let start = match cmd.value_of("start").map(NaiveDateTime::from_str) { None => ::chrono::offset::Local::today().and_hms(0, 0, 0).naive_local(), - Some(s) => match s.map_err(Error::from) { - Ok(dt) => dt, - Err(e) => { - trace_error(&e); - return 1 - } - } + Some(s) => s.map_err(Error::from)?, }; let end = match cmd.value_of("end").map(NaiveDateTime::from_str) { None => ::chrono::offset::Local::today().and_hms(23, 59, 59).naive_local(), - Some(s) => match s.map_err(Error::from) { - Ok(dt) => dt, - Err(e) => { - trace_error(&e); - return 1 - } - } + Some(s) => s?, }; let tags = cmd @@ -88,11 +73,9 @@ pub fn day(rt: &Runtime) -> i32 { }; rt.store() - .get_timetrackings() - .map_err_trace_exit_unwrap() - .trace_unwrap() - .filter(|e| filter.filter(e)) - .map(|e| -> Result<_, Error> { + .get_timetrackings()? + .filter_ok(|e| filter.filter(e)) + .and_then_ok(|e| -> Result<_> { debug!("Processing {:?}", e.get_location()); let tag = e.get_timetrack_tag()?; @@ -104,21 +87,18 @@ pub fn day(rt: &Runtime) -> i32 { let end = e.get_end_datetime()?; debug!(" -> end = {:?}", end); - rt.report_touched(e.get_location()).unwrap_or_exit(); - - Ok((tag, start, end)) + rt.report_touched(e.get_location()) + .map_err(Error::from) + .map(|_| (tag, start, end)) }) - .trace_unwrap_exit() - .map(|(tag, start, end)| { + .and_then_ok(|(tag, start, end)| { match (start, end) { (None, _) => writeln!(rt.stdout(), "{} has no start time.", tag), (Some(s), None) => writeln!(rt.stdout(), "{} | {} - ...", tag, s), (Some(s), Some(e)) => writeln!(rt.stdout(), "{} | {} - {}", tag, s, e), - } - .to_exit_code() + }.map_err(Error::from) }) - .collect::<Result<Vec<()>, _>>() - .map(|_| 0) - .unwrap_or_else(|e| e.code()) + .collect::<Result<Vec<_>>>() + .map(|_| ()) } diff --git a/bin/domain/imag-timetrack/src/lib.rs b/bin/domain/imag-timetrack/src/lib.rs index 6b94477f..fb44f493 100644 --- a/bin/domain/imag-timetrack/src/lib.rs +++ b/bin/domain/imag-timetrack/src/lib.rs @@ -43,7 +43,8 @@ extern crate filters; extern crate itertools; extern crate prettytable; extern crate kairos; -extern crate failure; +#[macro_use] extern crate failure; +extern crate resiter; extern crate libimagerror; extern crate libimagstore; @@ -76,10 +77,10 @@ use crate::year::year; use clap::App; use failure::Fallible as Result; +use failure::err_msg; use libimagrt::runtime::Runtime; use libimagrt::application::ImagApplication; -use libimagerror::trace::MapErrTrace; /// Marker enum for implementing ImagApplication on /// @@ -89,8 +90,7 @@ pub enum ImagTimetrack {} impl ImagApplication for ImagTimetrack { fn run(rt: Runtime) -> Result<()> { let command = rt.cli().subcommand_name(); - let retval = if let Some(command) = command { - debug!("Call: {}", command); + if let Some(command) = command { match command { "continue" => cont(&rt), "day" => day(&rt), @@ -102,21 +102,20 @@ impl ImagApplication for ImagTimetrack { "track" => track(&rt), "week" => week(&rt), "year" => year(&rt), - other => { + other => { debug!("Unknown command"); - rt.handle_unknown_subcommand("imag-timetrack", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .unwrap_or(0) + if rt.handle_unknown_subcommand("imag-bookmark", other, rt.cli())?.success() { + Ok(()) + } else { + Err(err_msg("Failed to handle unknown subcommand")) + } }, } } else { let start = ::chrono::offset::Local::today().naive_local().and_hms(0, 0, 0); let end = ::chrono::offset::Local::today().naive_local().and_hms(23, 59, 59); list_impl(&rt, Some(start), Some(end), false, false) - }; - - ::std::process::exit(retval); + } } fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { diff --git a/bin/domain/imag-timetrack/src/list.rs b/bin/domain/imag-timetrack/src/list.rs index c323cf29..b44f7ed0 100644 --- a/bin/domain/imag-timetrack/src/list.rs +++ b/bin/domain/imag-timetrack/src/list.rs @@ -18,7 +18,6 @@ // use chrono::NaiveDateTime; -use filters::filter::Filter; use prettytable::Table; use prettytable::Row; use prettytable::Cell; @@ -27,60 +26,44 @@ use kairos::parser::parse as kairos_parse; use clap::ArgMatches; use failure::Fallible as Result; use failure::ResultExt; -use failure::err_msg; use failure::Error; +use resiter::Filter; +use resiter::AndThen; +use resiter::Map; -use libimagerror::trace::trace_error; -use libimagerror::trace::MapErrTrace; -use libimagerror::iter::TraceIterator; -use libimagerror::exit::ExitUnwrap; use libimagstore::store::FileLockEntry; -use libimagtimetrack::store::TimeTrackStore; use libimagtimetrack::timetracking::TimeTracking; +use libimagtimetrack::store::TimeTrackStore; use libimagrt::runtime::Runtime; -pub fn list(rt: &Runtime) -> i32 { +pub fn list(rt: &Runtime) -> Result<()> { let (_, cmd) = rt.cli().subcommand(); let cmd = cmd.unwrap(); // checked in main() let gettime = |cmd: &ArgMatches, name| { match cmd.value_of(name).map(kairos_parse) { - Some(Ok(Parsed::TimeType(tt))) => match tt.calculate() { - Ok(tt) => { - let dt = tt.get_moment().unwrap_or_else(|| { - error!("Failed to get date from '{}'", cmd.value_of(name).unwrap()); - ::std::process::exit(1) - }); - - Some(*dt) - }, - Err(e) => { - error!("Failed to calculate date from '{}': {:?}", - cmd.value_of(name).unwrap(), e); - ::std::process::exit(1) - }, + Some(Ok(Parsed::TimeType(tt))) => { + let tt = tt + .calculate() + .context(format_err!("Failed to calculate date from '{}'", cmd.value_of(name).unwrap()))?; + Ok(tt.get_moment().cloned()) }, Some(Ok(Parsed::Iterator(_))) => { - error!("Expected single point in time, got '{}', which yields a list of dates", cmd.value_of(name).unwrap()); - ::std::process::exit(1) + Err(format_err!("Expected single point in time, got '{}', which yields a list of dates", cmd.value_of(name).unwrap())) }, - Some(Err(e)) => { - let e = e; - trace_error(&e); - ::std::process::exit(1) - } - None => None, + Some(Err(e)) => Err(e), + None => Ok(None), } }; - let start = gettime(&cmd, "start-time"); - let end = gettime(&cmd, "end-time"); + let start = gettime(&cmd, "start-time")?; + let end = gettime(&cmd, "end-time")?; let list_not_ended = cmd.is_present("list-not-ended"); let show_duration = cmd.is_present("show-duration"); - list_impl(rt, start, end, list_not_ended, show_duration) + list_impl(rt, start.clone(), end.clone(), list_not_ended, show_duration) } pub fn list_impl(rt: &Runtime, @@ -88,34 +71,27 @@ pub fn list_impl(rt: &Runtime, end: Option<NaiveDateTime>, list_not_ended: bool, show_duration: bool) - -> i32 + -> Result<()> { + use filters::failable::filter::FailableFilter; - let start_time_filter = |timetracking: &FileLockEntry| { - start.map(|s| match timetracking.get_start_datetime() { - Ok(Some(dt)) => dt >= s, - Ok(None) => { + let start_time_filter = |timetracking: &FileLockEntry| -> Result<bool> { + start.map(|s| match timetracking.get_start_datetime()? { + Some(dt) => Ok(dt >= s), + None => { warn!("Funny things are happening: Timetracking has no start time"); - false - } - Err(e) => { - trace_error(&e); - false + Ok(false) } }) - .unwrap_or(true) + .unwrap_or(Ok(true)) }; - let end_time_filter = |timetracking: &FileLockEntry| { - end.map(|s| match timetracking.get_end_datetime() { - Ok(Some(dt)) => dt <= s, - Ok(None) => list_not_ended, - Err(e) => { - trace_error(&e); - false - } + let end_time_filter = |timetracking: &FileLockEntry| -> Result<bool> { + end.map(|s| match timetracking.get_end_datetime()? { + Some(dt) => Ok(dt <= s), + None => Ok(list_not_ended), }) - .unwrap_or(true) + .unwrap_or(Ok(true)) }; let filter = start_time_filter.and(end_time_filter); @@ -128,92 +104,83 @@ pub fn list_impl(rt: &Runtime, }; table.set_titles(title_row); - let mut table_empty = true; - - let table = rt.store() - .get_timetrackings() - .map_err_trace_exit_unwrap() - .trace_unwrap() - .filter(|e| filter.filter(e)) - .fold(Ok(table), |acc: Result<_>, e| { - acc.and_then(|mut tab: Table| { - debug!("Processing {:?}", e.get_location()); - - let tag = e.get_timetrack_tag()?; - debug!(" -> tag = {:?}", tag); - - let start = e.get_start_datetime()?; - debug!(" -> start = {:?}", start); - - let end = e.get_end_datetime()?; - debug!(" -> end = {:?}", end); - - let v = match (start, end) { - (None, _) => { - let mut v = vec![String::from(tag.as_str()), String::from(""), String::from("")]; - if show_duration { - v.push(String::from("")); - } - v - }, - (Some(s), None) => { - let mut v = vec![ - String::from(tag.as_str()), - format!("{}", s), - String::from(""), - ]; - - if show_duration { - v.push(String::from("")); - } - - v - }, - (Some(s), Some(e)) => { - let mut v = vec![ - String::from(tag.as_str()), - format!("{}", s), - format!("{}", e), - ]; - - if show_duration { - let duration = e - s; - let dur = format!("{days} Days, {hours} Hours, {minutes} Minutes, {seconds} Seconds", - days = duration.num_days(), - hours = duration.num_hours(), - minutes = duration.num_minutes(), - seconds = duration.num_seconds()); - - v.push(dur); - } - - v - }, - }; - - let cells : Vec<Cell> = v - .into_iter() - .map(|s| Cell::new(&s)) - .collect(); - tab.add_row(Row::new(cells)); - - rt.report_touched(e.get_location()).unwrap_or_exit(); - - table_empty = false; - Ok(tab) - }) + let table_empty = rt.store() + .get_timetrackings()? + .and_then_ok(|e| filter.filter(&e).map(|b| (b, e))) + .filter_ok(|tpl| tpl.0) + .map_ok(|tpl| tpl.1) + .and_then_ok(|e| { + debug!("Processing {:?}", e.get_location()); + + let tag = e.get_timetrack_tag()?; + debug!(" -> tag = {:?}", tag); + + let start = e.get_start_datetime()?; + debug!(" -> start = {:?}", start); + + let end = e.get_end_datetime()?; + debug!(" -> end = {:?}", end); + + let v = match (start, end) { + (None, _) => { + let mut v = vec![String::from(tag.as_str()), String::from(""), String::from("")]; + if show_duration { + v.push(String::from("")); + } + v + }, + (Some(s), None) => { + let mut v = vec![ + String::from(tag.as_str()), + format!("{}", s), + String::from(""), + ]; + + if show_duration { + v.push(String::from("")); + } + + v + }, + (Some(s), Some(e)) => { + let mut v = vec![ + String::from(tag.as_str()), + format!("{}", s), + format!("{}", e), + ]; + + if show_duration { + let duration = e - s; + let dur = format!("{days} Days, {hours} Hours, {minutes} Minutes, {seconds} Seconds", + days = duration.num_days(), + hours = duration.num_hours(), + minutes = duration.num_minutes(), + seconds = duration.num_seconds()); + + v.push(dur); + } + + v + }, + }; + + let cells : Vec<Cell> = v.iter().map(|s| Cell::new(s)).collect(); + table.add_row(Row::new(cells)); + + rt.report_touched(e.get_location())?; + Ok(false) }) - .map_err_trace_exit_unwrap(); + .collect::<Result<Vec<bool>>>()? + .iter() + .any(|b| !b); if !table_empty { table.print(&mut rt.stdout()) - .context(err_msg("Failed to print table")) + .context("Failed to print table") .map_err(Error::from) - .map(|_| 0) - .map_err_trace() - .unwrap_or(1) + .map(|_| ()) } else { - 0 + Ok(()) } } diff --git a/bin/domain/imag-timetrack/src/month.rs b/bin/domain/imag-timetrack/src/month.rs index 19d12ebe..4d4c7e65 100644 --- a/bin/domain/imag-timetrack/src/month.rs +++ b/bin/domain/imag-timetrack/src/month.rs @@ -23,21 +23,19 @@ use std::str::FromStr; use filters::filter::Filter; use chrono::NaiveDateTime; use failure::Error; +use failure::Fallible as Result; +use resiter::AndThen; +use resiter::Filter as RFilter; -use libimagerror::trace::trace_error; -use libimagerror::trace::MapErrTrace; -use libimagerror::io::ToExitCode; -use libimagerror::iter::TraceIterator; -use libimagerror::exit::ExitUnwrap; use libimagstore::store::FileLockEntry; use libimagtimetrack::store::TimeTrackStore; -use libimagtimetrack::timetracking::TimeTracking; use libimagtimetrack::tag::TimeTrackingTag; use libimagtimetrack::iter::filter::*; +use libimagtimetrack::timetracking::TimeTracking; use libimagrt::runtime::Runtime; -pub fn month(rt: &Runtime) -> i32 { +pub fn month(rt: &Runtime) -> Result<()> { let cmd = rt.cli().subcommand().1.unwrap(); // checked in main let filter = { @@ -49,13 +47,7 @@ pub fn month(rt: &Runtime) -> i32 { let start = match cmd.value_of("start").map(::chrono::naive::NaiveDateTime::from_str) { None => NaiveDate::from_ymd(now.year(), now.month(), 1).and_hms(0, 0, 0), - Some(s) => match s.map_err(Error::from) { - Ok(dt) => dt, - Err(e) => { - trace_error(&e); - return 1 - } - } + Some(s) => s?, }; let end = match cmd.value_of("end").map(::chrono::naive::NaiveDateTime::from_str) { @@ -71,13 +63,7 @@ pub fn month(rt: &Runtime) -> i32 { NaiveDate::from_ymd(year, month, 1).and_hms(0, 0, 0) }, - Some(s) => match s.map_err(Error::from) { - Ok(dt) => dt, - Err(e) => { - trace_error(&e); - return 1 - } - } + Some(s) => s?, }; let tags = cmd @@ -103,11 +89,9 @@ pub fn month(rt: &Runtime) -> i32 { }; rt.store() - .get_timetrackings() - .map_err_trace_exit_unwrap() - .trace_unwrap() - .filter(|e| filter.filter(e)) - .map(|e| -> Result<_, Error> { + .get_timetrackings()? + .filter_ok(|e| filter.filter(e)) + .and_then_ok(|e| -> Result<_> { debug!("Processing {:?}", e.get_location()); let tag = e.get_timetrack_tag()?; @@ -119,21 +103,18 @@ pub fn month(rt: &Runtime) -> i32 { let end = e.get_end_datetime()?; debug!(" -> end = {:?}", end); - rt.report_touched(e.get_location()).unwrap_or_exit(); - - Ok((tag, start, end)) + rt.report_touched(e.get_location()) + .map_err(Error::from) + .map(|_| (tag, start, end)) }) - .trace_unwrap_exit() - .map(|(tag, start, end)| { + .and_then_ok(|(tag, start, end)| { match (start, end) { (None, _) => writeln!(rt.stdout(), "{} has no start time.", tag), (Some(s), None) => writeln!(rt.stdout(), "{} | {} - ...", tag, s), (Some(s), Some(e)) => writeln!(rt.stdout(), "{} | {} - {}", tag, s, e), - } - .to_exit_code() + }.map_err(Error::from) }) - .collect::<Result<Vec<()>, _>>() - .map(|_| 0) - .unwrap_or_else(|e| e.code()) + .collect::<Result<Vec<_>>>() + .map(|_| ()) } diff --git a/bin/domain/imag-timetrack/src/shell.rs b/bin/domain/imag-timetrack/src/shell.rs index c66bfe13..30693438 100644 --- a/bin/domain/imag-timetrack/src/shell.rs +++ b/bin/domain/imag-timetrack/src/shell.rs @@ -21,19 +21,19 @@ use std::env; use std::process::Command; use filters::filter::Filter; +use failure::Fallible as Result; +use failure::err_msg; +use failure::Error; +use resiter::Filter as RFilter; +use resiter::AndThen; -use libimagerror::exit::ExitUnwrap; -use libimagerror::iter::TraceIterator; -use libimagerror::trace::MapErrTrace; -use libimagerror::trace::trace_error; use libimagrt::runtime::Runtime; use libimagtimetrack::iter::filter::has_one_of_tags; use libimagtimetrack::store::TimeTrackStore; use libimagtimetrack::tag::TimeTrackingTag; use libimagtimetrack::timetracking::TimeTracking; -use libimagutil::warn_result::*; -pub fn shell(rt: &Runtime) -> i32 { +pub fn shell(rt: &Runtime) -> Result<()> { let (_, cmd) = rt.cli().subcommand(); let cmd = cmd.unwrap(); // checked in main() @@ -54,57 +54,42 @@ pub fn shell(rt: &Runtime) -> i32 { }; if let Some(s) = cmd.value_of("shell") { - mkshell(s.to_owned()) + Ok(mkshell(s.to_owned())) } else { env::var("SHELL") .map(mkshell) .map_err(|e| match e { env::VarError::NotPresent => { - error!("No $SHELL variable in environment, cannot work!"); - ::std::process::exit(1) + err_msg("No $SHELL variable in environment, cannot work!") }, env::VarError::NotUnicode(_) => { - error!("$SHELL variable is not unicode, cannot work!"); - ::std::process::exit(1) + err_msg("SHELL variable is not unicode, cannot work!") } }) - .unwrap() } - }; + }?; for tag in tags.iter() { - match rt.store().create_timetracking_at(&start, tag) { - Err(e) => trace_error(&e), - Ok(entry) => { - rt.report_touched(entry.get_location()).unwrap_or_exit(); - } - } + let entry = rt.store().create_timetracking_at(&start, tag)?; + rt.report_touched(entry.get_location())?; } - let exit_code = match shellcmd.status() { - Ok(estat) => estat.code().unwrap_or(0), - Err(e) => { - error!("Error starting shell: {:?}", e); - ::std::process::exit(2) - }, - }; + if !shellcmd.status()?.success() { + return Err(format_err!("Failed to execute {:?}", shellcmd)) + } + let stop = ::chrono::offset::Local::now().naive_local(); + let filter = has_one_of_tags(&tags); - let stop = ::chrono::offset::Local::now().naive_local(); - let filter = has_one_of_tags(&tags); rt.store() - .get_timetrackings() - .map_warn_err_str("Getting timetrackings failed") - .map_err_trace_exit_unwrap() - .trace_unwrap() - .filter(|e| filter.filter(e)) - .for_each(|mut elem| if let Err(e) = elem.set_end_datetime(stop.clone()) { - trace_error(&e) - } else { + .get_timetrackings()? + .filter_ok(|e| filter.filter(e)) + .and_then_ok(|mut elem| { + let _ = elem.set_end_datetime(stop.clone())?; debug!("Setting end time worked: {:?}", elem); - rt.report_touched(elem.get_location()).unwrap_or_exit(); - }); - - ::std::process::exit(exit_code) + rt.report_touched(elem.get_location()).map_err(Error::from) + }) + .collect::<Result<Vec<_>>>() + .map(|_| ()) } diff --git a/bin/domain/imag-timetrack/src/start.rs b/bin/domain/imag-timetrack/src/start.rs index a4f99e91..e3d10f01 100644 --- a/bin/domain/imag-timetrack/src/start.rs +++ b/bin/domain/imag-timetrack/src/start.rs @@ -21,49 +21,34 @@ use std::str::FromStr; use chrono::naive::NaiveDateTime; use failure::Error; +use failure::Fallible as Result; use libimagrt::runtime::Runtime; -use libimagerror::trace::trace_error; -use libimagerror::exit::ExitUnwrap; use libimagtimetrack::tag::TimeTrackingTag; use libimagtimetrack::store::TimeTrackStore; -pub fn start(rt: &Runtime) -> i32 { +pub fn start(rt: &Runtime) -> Result<()> { let (_, cmd) = rt.cli().subcommand(); let cmd = cmd.unwrap(); // checked in main() let start = { let startstr = cmd.value_of("start-time").unwrap(); // safe by clap if startstr == "now" { - ::chrono::offset::Local::now().naive_local() + Ok(::chrono::offset::Local::now().naive_local()) } else { - match NaiveDateTime::from_str(startstr).map_err(Error::from) { - Ok(ndt) => ndt, - Err(e) => { - trace_error(&e); - error!("Cannot continue, not having start time"); - return 1 - }, - } + NaiveDateTime::from_str(startstr) } - }; + }?; cmd.values_of("tags") .unwrap() // enforced by clap .map(String::from) .map(TimeTrackingTag::from) - .fold(0, |acc, ttt| { - match rt.store().create_timetracking_at(&start, &ttt) { - Err(e) => { - trace_error(&e); - 1 - }, - Ok(entry) => { - rt.report_touched(entry.get_location()).unwrap_or_exit(); - - acc - } - } + .map(|ttt| { + let entry = rt.store().create_timetracking_at(&start, &ttt)?; + rt.report_touched(entry.get_location()).map_err(Error::from) }) + .collect::<Result<Vec<_>>>() + .map(|_| ()) } diff --git a/bin/domain/imag-timetrack/src/stop.rs b/bin/domain/imag-timetrack/src/stop.rs index 5a7f76a3..a4e8c466 100644 --- a/bin/domain/imag-timetrack/src/stop.rs +++ b/bin/domain/imag-timetrack/src/stop.rs @@ -21,82 +21,65 @@ use std::str::FromStr; use filters::filter::Filter; use chrono::NaiveDateTime; +use failure::Fallible as Result; use failure::Error; +use resiter::Filter as RFilter; +use resiter::Map; +use resiter::AndThen; -use libimagerror::trace::trace_error; -use libimagerror::iter::TraceIterator; -use libimagerror::trace::MapErrTrace; -use libimagerror::exit::ExitUnwrap; use libimagrt::runtime::Runtime; - -use libimagtimetrack::timetracking::TimeTracking; use libimagtimetrack::tag::TimeTrackingTag; use libimagtimetrack::store::*; use libimagtimetrack::iter::filter::has_end_time; use libimagtimetrack::iter::filter::has_one_of_tags; -use libimagutil::warn_result::*; +use libimagtimetrack::timetracking::TimeTracking; |