Introduce proper error handling in IdPathProvider

Prior to this change, the IdPathProvider implementation would be
responsible for exiting the process on insufficient / wrong arguments.
However, such error handling should be performed together with the
business logic and not in CLI-parsing related code.

This change introduces a clear separation: both parsing errors and
insufficient id path arguments can now be return from inside the
`get_ids`-method, and get passed up to the application logic to be
handled.

This change is reflected in all instances of IdPathProvider and their
surrounding code.

Signed-off-by: Leon Schuermann <leon.git@is.currently.online>
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
Leon Schuermann 2019-05-18 02:42:38 +02:00 committed by Matthias Beyer
parent fcdded90b2
commit ed457495c8
29 changed files with 378 additions and 411 deletions

View file

@ -97,7 +97,14 @@ fn main() {
fn add(rt: &Runtime) {
let scmd = rt.cli().subcommand_matches("add").unwrap(); // safed by main()
let mut ids = rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap().into_iter();
let mut ids = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No StoreId supplied");
::std::process::exit(1);
})
.into_iter();
if let Some(first) = ids.next() {
let mut annotation = rt.store()
@ -144,7 +151,14 @@ fn remove(rt: &Runtime) {
let scmd = rt.cli().subcommand_matches("remove").unwrap(); // safed by main()
let annotation_name = scmd.value_of("annotation_name").unwrap(); // safed by clap
let delete = scmd.is_present("delete-annotation");
let ids = rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap();
let ids = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter();
ids.into_iter().for_each(|id| {
let mut entry = rt.store()
@ -181,7 +195,14 @@ fn remove(rt: &Runtime) {
fn list(rt: &Runtime) {
let scmd = rt.cli().subcommand_matches("list").unwrap(); // safed by clap
let with_text = scmd.is_present("list-with-text");
let ids = rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap();
let ids = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter();
if ids.len() != 0 {
let _ = ids

View file

@ -24,7 +24,8 @@ use clap::{Arg, ArgMatches, App, SubCommand};
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
use failure::Fallible as Result;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app
@ -97,53 +98,24 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId> {
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
fn get_id_paths(subm: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
subm.values_of("entry")
.map(|v| v
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>>>()
)
.transpose()
}
match matches.subcommand() {
("add", Some(subm)) => {
subm.values_of("entry")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
},
("remove", Some(subm)) => {
subm.values_of("entry")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
},
("list", Some(subm)) => {
subm.values_of("entry")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
},
("add", Some(subm)) => get_id_paths(subm),
("remove", Some(subm)) => get_id_paths(subm),
("list", Some(subm)) => get_id_paths(subm),
(other, _) => {
error!("Not a known command: {}", other);
::std::process::exit(1)
Err(format_err!("Not a known command: {}", other))
}
}
}

View file

@ -23,6 +23,7 @@ maintenance = { status = "actively-developed" }
log = "0.4.0"
toml = "0.4"
toml-query = "0.8"
failure = "0.1"
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }

View file

@ -37,6 +37,8 @@
extern crate clap;
#[macro_use]
extern crate log;
#[macro_use]
extern crate failure;
extern crate libimagentrycategory;
extern crate libimagerror;
@ -92,7 +94,14 @@ fn main() {
fn set(rt: &Runtime) {
let scmd = rt.cli().subcommand_matches("set").unwrap(); // safed by main()
let name = scmd.value_of("set-name").map(String::from).unwrap(); // safed by clap
let sids = rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap();
let sids = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter();
StoreIdIterator::new(Box::new(sids.into_iter().map(Ok)))
.into_get_iter(rt.store())
@ -109,9 +118,16 @@ fn set(rt: &Runtime) {
}
fn get(rt: &Runtime) {
let sids = rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap();
let out = rt.stdout();
let mut outlock = out.lock();
let sids = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter();
StoreIdIterator::new(Box::new(sids.into_iter().map(Ok)))
.into_get_iter(rt.store())

View file

@ -20,11 +20,11 @@
use std::path::PathBuf;
use clap::{Arg, ArgMatches, App, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app
@ -103,60 +103,30 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId> {
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
fn no_ids_error() -> Result<Option<Vec<StoreId>>> {
Err(format_err!("Command does not get IDs as input"))
}
fn get_id_paths(field: &str, subm: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
subm.values_of(field)
.map(|v| v
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>>>()
)
.transpose()
}
match matches.subcommand() {
("create-category", _) => {
error!("Command does not get IDs as input");
::std::process::exit(1)
},
("delete-category", _) => {
error!("Command does not get IDs as input");
::std::process::exit(1)
},
("list-categories", _) => {
error!("Command does not get IDs as input");
::std::process::exit(1)
},
("list-category", _) => {
error!("Command does not get IDs as input");
::std::process::exit(1)
},
("set", Some(subm)) => {
subm.values_of("set-ids")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
},
("get", Some(subm)) => {
subm.values_of("get-ids")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
},
(other, _) => {
error!("Not a known command: {}", other);
::std::process::exit(1)
}
("create-category", _) => no_ids_error(),
("delete-category", _) => no_ids_error(),
("list-categories", _) => no_ids_error(),
("list-category", _) => no_ids_error(),
("set", Some(subm)) => get_id_paths("set-ids", subm),
("get", Some(subm)) => get_id_paths("get-ids", subm),
(other, _) => Err(format_err!("Not a known command: {}", other)),
}
}
}

View file

@ -24,6 +24,7 @@ log = "0.4"
version = "3"
toml = "0.4"
toml-query = "0.8"
failure = "0.1"
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }

View file

@ -36,6 +36,7 @@
extern crate clap;
#[macro_use] extern crate log;
extern crate failure;
extern crate libimagentryedit;
extern crate libimagerror;
@ -63,7 +64,14 @@ fn main() {
let edit_header = rt.cli().is_present("edit-header");
let edit_header_only = rt.cli().is_present("edit-header-only");
let sids = rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap();
let sids = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter();
StoreIdIterator::new(Box::new(sids.into_iter().map(Ok)))
.into_get_iter(rt.store())

View file

@ -20,11 +20,11 @@
use std::path::PathBuf;
use clap::{Arg, ArgMatches, App};
use failure::Fallible as Result;
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreId;
use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app
@ -54,18 +54,14 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId> {
matches
.values_of("entry")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
matches.values_of("entry")
.map(|v| v
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
.collect::<Result<Vec<_>>>()
)
.transpose()
}
}

View file

@ -35,9 +35,8 @@
)]
extern crate clap;
#[macro_use]
extern crate log;
extern crate failure;
#[macro_use] extern crate log;
#[macro_use] extern crate failure;
extern crate libimagentrygps;
#[macro_use] extern crate libimagrt;
@ -52,6 +51,7 @@ use std::str::FromStr;
use failure::Error;
use failure::err_msg;
use libimagstore::storeid::StoreId;
use libimagentrygps::types::*;
use libimagentrygps::entry::*;
use libimagrt::setup::generate_runtime_setup;
@ -69,8 +69,7 @@ fn main() {
"Add GPS coordinates to entries",
ui::build_ui);
rt.cli()
.subcommand_name()
rt.cli().subcommand_name()
.map(|name| {
match name {
"add" => add(&rt),
@ -87,6 +86,16 @@ fn main() {
});
}
fn rt_get_ids(rt: &Runtime) -> Vec<StoreId> {
rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
}
fn add(rt: &Runtime) {
let c = {
let parse = |value: &str| -> (i64, i64, i64) {
@ -124,8 +133,7 @@ fn add(rt: &Runtime) {
Coordinates::new(long, lati)
};
rt.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
rt_get_ids(&rt)
.into_iter()
.for_each(|id| {
rt.store()
@ -149,8 +157,7 @@ fn remove(rt: &Runtime) {
.unwrap()
.is_present("print-removed"); // safed by main()
rt.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
rt_get_ids(&rt)
.into_iter()
.for_each(|id| {
let removed_value = rt
@ -179,8 +186,8 @@ fn remove(rt: &Runtime) {
fn get(rt: &Runtime) {
let mut stdout = rt.stdout();
rt.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
rt_get_ids(&rt)
.into_iter()
.for_each(|id| {
let value = rt

View file

@ -20,11 +20,11 @@
use std::path::PathBuf;
use clap::{Arg, ArgMatches, App, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreId;
use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app
@ -99,54 +99,23 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId> {
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
fn get_id_paths(field: &str, subm: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
subm.values_of(field)
.map(|v| v
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>>>()
)
.transpose()
}
match matches.subcommand() {
("add", Some(subm)) => {
subm.values_of("entry")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
},
("remove", Some(subm)) => {
subm.values_of("entry")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
},
("get", Some(subm)) => {
subm.values_of("get-ids")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
},
(other, _) => {
error!("Not a known command: {}", other);
::std::process::exit(1)
}
("add", Some(subm)) => get_id_paths("entry", subm),
("remove", Some(subm)) => get_id_paths("entry", subm),
("get", Some(subm)) => get_id_paths("get-ids", subm),
(other, _) => Err(format_err!("Not a known command: {}", other)),
}
}
}

View file

@ -79,7 +79,14 @@ fn main() {
trace!("list_output_with_ids = {:?}", list_output_with_ids );
trace!("list_output_with_ids_fmt = {:?}", list_output_with_ids_fmt);
let sids = rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap();
let sids = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter();
let iter = StoreIdIterator::new(Box::new(sids.into_iter().map(Ok)))
.into_get_iter(rt.store())

View file

@ -20,11 +20,11 @@
use std::path::PathBuf;
use clap::{Arg, ArgMatches, App, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app
@ -234,11 +234,14 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId> {
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
matches.values_of("id")
.unwrap()
.map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap())
.collect()
.map(|v| v
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>>>()
)
.transpose()
}
}

View file

@ -41,7 +41,7 @@ extern crate filters;
#[macro_use] extern crate is_match;
extern crate toml;
extern crate toml_query;
extern crate failure;
#[macro_use] extern crate failure;
#[cfg(test)]
extern crate env_logger;
@ -93,7 +93,13 @@ fn main() {
let iterator = if rt.ids_from_stdin() {
debug!("Fetching IDs from stdin...");
let ids = rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap();
let ids = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
});
Box::new(ids.into_iter().map(Ok))
as Box<Iterator<Item = Result<StoreId, _>>>
} else {

View file

@ -18,6 +18,7 @@
//
use clap::{Arg, ArgMatches, App, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId;
use libimagrt::runtime::IdPathProvider;
@ -54,8 +55,7 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(_matches: &ArgMatches) -> Vec<StoreId> {
error!("imag-ids does not get IDs via CLI, only via stdin if applying a filter!");
::std::process::exit(1)
fn get_ids(_matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
Err(format_err!("imag-ids does not get IDs via CLI, only via stdin if applying a filter!"))
}
}

View file

@ -209,8 +209,13 @@ fn remove_linking(rt: &Runtime) {
})
.unwrap();
rt.ids::<crate::ui::PathProvider>()
rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter()
.for_each(|id| match rt.store().get(id.clone()) {
Err(e) => trace_error(&e),
@ -245,7 +250,15 @@ fn remove_linking(rt: &Runtime) {
}
fn unlink(rt: &Runtime) {
rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap().into_iter().for_each(|id| {
rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter()
.for_each(|id| {
rt.store()
.get(id.clone())
.map_err_trace_exit_unwrap()
@ -271,7 +284,15 @@ fn list_linkings(rt: &Runtime) {
let mut tab = ::prettytable::Table::new();
tab.set_titles(row!["#", "Link"]);
rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap().into_iter().for_each(|id| {
rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter()
.for_each(|id| {
match rt.store().get(id.clone()) {
Ok(Some(entry)) => {
for (i, link) in entry.get_internal_links().map_err_trace_exit_unwrap().enumerate() {

View file

@ -20,11 +20,11 @@
use std::path::PathBuf;
use clap::{Arg, ArgMatches, App, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app
@ -117,65 +117,25 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
/// It has to be fetched by main() by hand.
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId> {
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
fn get_id_paths(field: &str, subm: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
subm.values_of(field)
.map(|v| v
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>>>()
)
.transpose()
}
let ids = match matches.subcommand() {
("remove", Some(subm)) => {
let to = subm.values_of("to")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap();
Some(to)
},
("unlink", Some(subm)) => {
let ids = subm
.values_of("from")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap();
Some(ids)
},
("list", Some(subm)) => {
let ids = subm
.values_of("entries")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap();
Some(ids)
},
("remove", Some(subm)) => Some(get_id_paths("to", subm)),
("unlink", Some(subm)) => Some(get_id_paths("from", subm)),
("list", Some(subm)) => Some(get_id_paths("entries", subm)),
_ => None,
};
ids.unwrap_or_else(|| {
matches.values_of("to")
.unwrap()
.map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap())
.collect()
})
ids
.unwrap_or_else(|| get_id_paths("to", matches))
}
}

View file

@ -65,8 +65,13 @@ fn main() {
let out = rt.stdout();
let mut outlock = out.lock();
let iter = rt.ids::<crate::ui::PathProvider>()
let iter = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter()
.map(Ok)
.into_get_iter(rt.store())

View file

@ -20,11 +20,11 @@
use std::path::PathBuf;
use clap::{Arg, ArgMatches, App};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app
@ -47,18 +47,15 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId> {
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
matches.values_of("entry")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.map(|v| v
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
.collect::<Result<Vec<_>>>()
)
.transpose()
}
}

View file

@ -36,7 +36,7 @@
#[macro_use] extern crate log;
extern crate clap;
extern crate failure;
#[macro_use] extern crate failure;
extern crate libimagstore;
#[macro_use] extern crate libimagrt;
@ -92,12 +92,18 @@ fn main() {
fn deref(rt: &Runtime) {
let cmd = rt.cli().subcommand_matches("deref").unwrap();
let basepath = cmd.value_of("override-basepath");
let ids = rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap();
let cfg = get_ref_config(&rt, "imag-ref").map_err_trace_exit_unwrap();
let out = rt.stdout();
let mut outlock = out.lock();
ids.into_iter()
rt
.ids::<::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter()
.for_each(|id| {
match rt.store().get(id.clone()).map_err_trace_exit_unwrap() {
Some(entry) => {
@ -130,7 +136,6 @@ fn remove(rt: &Runtime) {
let cmd = rt.cli().subcommand_matches("remove").unwrap();
let yes = cmd.is_present("yes");
let ids = rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap();
let mut input = rt.stdin().unwrap_or_else(|| {
error!("No input stream. Cannot ask for permission");
@ -139,7 +144,14 @@ fn remove(rt: &Runtime) {
let mut output = rt.stdout();
ids.into_iter()
rt
.ids::<::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter()
.for_each(|id| {
match rt.store().get(id.clone()).map_err_trace_exit_unwrap() {
Some(mut entry) => {
@ -169,8 +181,13 @@ fn list_dead(rt: &Runtime) {
let list_id = cmd.is_present("list-dead-ids");
let mut output = rt.stdout();
rt.ids::<crate::ui::PathProvider>()
rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter()
.for_each(|id| {
match rt.store().get(id.clone()).map_err_trace_exit_unwrap() {

View file

@ -20,11 +20,11 @@
use std::path::PathBuf;
use clap::{Arg, App, ArgMatches, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app
@ -133,60 +133,24 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId> {
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
fn get_id_paths(subm: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
subm.values_of("ID")
.map(|v| v
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>>>()
)
.transpose()
}
match matches.subcommand() {
("deref", Some(subm)) => {
subm.values_of("ID")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
},
("remove", Some(subm)) => {
subm.values_of("ID")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
},
("list-dead", Some(subm)) => {
subm.values_of("ID")
.ok_or_else(|| {
error!("No StoreId found");
::std::process::exit(1)
})
.unwrap()
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>, _>>()
.map_err_trace_exit_unwrap()
},
("create", _) => {
error!("Command does not get IDs as input");
::std::process::exit(1)
},
(other, _) => {
error!("Not a known command: {}", other);
::std::process::exit(1)
}
("deref", Some(subm)) => get_id_paths(subm),
("remove", Some(subm)) => get_id_paths(subm),
("list-dead", Some(subm)) => get_id_paths(subm),
("create", _) => Err(format_err!("Command does not get IDs as input")),
(other, _) => Err(format_err!("Not a known command: {}", other)),
}
}
}

View file

@ -22,6 +22,7 @@ maintenance = { status = "actively-developed" }
[dependencies]
log = "0.4.0"
toml = "0.4"
failure = "0.1"
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }
@ -37,7 +38,6 @@ features = ["color", "suggestions", "wrap_help"]
[dev-dependencies]
toml-query = "0.8"
env_logger = "0.5"
failure = "0.1"
[dev-dependencies.libimagutil]
version = "0.10.0"

View file

@ -38,7 +38,7 @@ extern crate clap;
#[macro_use] extern crate log;
#[cfg(test)] extern crate toml;
#[cfg(test)] extern crate failure;
extern crate failure;
extern crate libimagstore;
#[macro_use] extern crate libimagrt;
@ -84,7 +84,14 @@ fn main() {
"Direct interface to the store. Use with great care!",
build_ui);
let ids = rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap();
let ids = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter();
rt.cli()
.subcommand_name()

View file

@ -20,11 +20,11 @@
use std::path::PathBuf;
use clap::{Arg, ArgMatches, ArgGroup, App, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
use libimagentrytag::tag::is_tag;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
@ -105,11 +105,15 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId> {
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
matches.values_of("id")
.unwrap()
.map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap())
.collect()
.map(|v| v
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>>>()
)
.transpose()
}
}

View file

@ -82,8 +82,13 @@ fn main() {
let view_header = rt.cli().is_present("view-header");
let hide_content = rt.cli().is_present("not-view-content");
let entries = rt.ids::<crate::ui::PathProvider>()
let entries = rt
.ids::<::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter()
.map(Ok)
.into_get_iter(rt.store())

View file

@ -20,11 +20,11 @@
use std::path::PathBuf;
use clap::{Arg, ArgMatches, App};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app
@ -90,10 +90,14 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId> {
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
matches.values_of("id")
.unwrap()
.map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap())
.collect()
.map(|v| v
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>>>()
)
.transpose()
}
}

View file

@ -20,6 +20,7 @@ libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror"
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagentrytag = { version = "0.10.0", path = "../../../lib/entry/libimagentrytag" }
libimagutil = { version = "0.10.0", path = "../../../lib/etc/libimagutil" }
failure = "0.1"
log = "0.4.0"
[badges]

View file

@ -131,7 +131,7 @@ fn list(rt: &Runtime) {
let print_content = scmd.is_present("list-read");
if print_content {
/// TODO: Check whether workaround with "{}" is still necessary when updating "indoc"
// TODO: Check whether workaround with "{}" is still necessary when updating "indoc"
warn!("{}", indoc!(r#"You requested to print the content of the mail as well.
We use the 'mailparse' crate underneath, but its implementation is nonoptimal.
Thus, the content might be printed as empty (no text in the email)
@ -215,8 +215,13 @@ fn list(rt: &Runtime) {
}
if rt.ids_from_stdin() {
let iter = rt.ids::<crate::ui::PathProvider>()
let iter = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter()
.map(Ok);

View file

@ -18,11 +18,11 @@
//
use std::path::PathBuf;
use failure::Fallible as Result;
use libimagstore::storeid::StoreId;
use libimagrt::runtime::IdPathProvider;
use libimagstore::storeid::IntoStoreId;
use libimagerror::trace::MapErrTrace;
use clap::{Arg, ArgMatches, App, SubCommand};
@ -80,15 +80,16 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider;
impl IdPathProvider for PathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId> {
if matches.is_present("list-id") {
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> {
matches.values_of("list-id")
.unwrap()
.map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap())
.collect()
} else {
vec![]
}
.map(|v| v
.into_iter()
.map(PathBuf::from)
.map(|pb| pb.into_storeid())
.collect::<Result<Vec<_>>>()
)
.unwrap_or(Ok(Vec::new()))
.map(Some)
}
}

View file

@ -398,7 +398,7 @@ impl<'a> Runtime<'a> {
self.has_input_pipe
}
pub fn ids<T: IdPathProvider>(&self) -> Result<Vec<StoreId>> {
pub fn ids<T: IdPathProvider>(&self) -> Result<Option<Vec<StoreId>>> {
use std::io::Read;
if self.has_input_pipe {
@ -417,8 +417,9 @@ impl<'a> Runtime<'a> {
.map(|id| StoreId::new(id).map_err(Error::from))
.collect()
})
.map(Some)
} else {
Ok(T::get_ids(self.cli()))
Ok(T::get_ids(self.cli())?)
}
}
@ -607,12 +608,11 @@ impl<'a> Runtime<'a> {
}
}
/// A trait for the path provider functionality
/// A trait for providing ids from clap argument matches
///
/// This trait can be implement on a type so that it can provide IDs when given a ArgMatches
/// object.
///
/// It can be used with Runtime::ids() and libimagrt handles "stdin-provides-ids" cases
/// It can be used with Runtime::ids(), and libimagrt handles "stdin-provides-ids" cases
/// automatically:
///
/// ```ignore
@ -630,13 +630,12 @@ impl<'a> Runtime<'a> {
///
/// # Returns
///
/// In case of error, the IdPathProvider::get_ids() function should exit the application
/// with the appropriate error message(s).
///
/// In case no store ids could be matched, the function should return `Ok(None)` instance.
/// On success, the StoreId objects to operate on are returned from the ArgMatches.
/// Otherwise, an appropriate error may be returned.
///
pub trait IdPathProvider {
fn get_ids(matches: &ArgMatches) -> Vec<StoreId>;
fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>>;
}
/// Exported for the `imag` command, you probably do not want to use that.