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

@ -96,8 +96,15 @@ fn main() {
} }
fn add(rt: &Runtime) { fn add(rt: &Runtime) {
let scmd = rt.cli().subcommand_matches("add").unwrap(); // safed by main() 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() { if let Some(first) = ids.next() {
let mut annotation = rt.store() let mut annotation = rt.store()
@ -141,10 +148,17 @@ fn add(rt: &Runtime) {
} }
fn remove(rt: &Runtime) { fn remove(rt: &Runtime) {
let scmd = rt.cli().subcommand_matches("remove").unwrap(); // safed by main() let scmd = rt.cli().subcommand_matches("remove").unwrap(); // safed by main()
let annotation_name = scmd.value_of("annotation_name").unwrap(); // safed by clap let annotation_name = scmd.value_of("annotation_name").unwrap(); // safed by clap
let delete = scmd.is_present("delete-annotation"); 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| { ids.into_iter().for_each(|id| {
let mut entry = rt.store() let mut entry = rt.store()
@ -179,9 +193,16 @@ fn remove(rt: &Runtime) {
} }
fn list(rt: &Runtime) { fn list(rt: &Runtime) {
let scmd = rt.cli().subcommand_matches("list").unwrap(); // safed by clap let scmd = rt.cli().subcommand_matches("list").unwrap(); // safed by clap
let with_text = scmd.is_present("list-with-text"); 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 { if ids.len() != 0 {
let _ = ids let _ = ids

View file

@ -24,7 +24,8 @@ use clap::{Arg, ArgMatches, App, SubCommand};
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider; 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> { pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app app
@ -97,53 +98,24 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider; pub struct PathProvider;
impl IdPathProvider for 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() { match matches.subcommand() {
("add", Some(subm)) => { ("add", Some(subm)) => get_id_paths(subm),
subm.values_of("entry") ("remove", Some(subm)) => get_id_paths(subm),
.ok_or_else(|| { ("list", Some(subm)) => get_id_paths(subm),
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()
},
(other, _) => { (other, _) => {
error!("Not a known command: {}", other); Err(format_err!("Not a known command: {}", other))
::std::process::exit(1)
} }
} }
} }

View file

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

View file

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

View file

@ -20,11 +20,11 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::{Arg, ArgMatches, App, SubCommand}; use clap::{Arg, ArgMatches, App, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider; use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app app
@ -103,60 +103,30 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider; pub struct PathProvider;
impl IdPathProvider for 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() { match matches.subcommand() {
("create-category", _) => { ("create-category", _) => no_ids_error(),
error!("Command does not get IDs as input"); ("delete-category", _) => no_ids_error(),
::std::process::exit(1) ("list-categories", _) => no_ids_error(),
}, ("list-category", _) => no_ids_error(),
("set", Some(subm)) => get_id_paths("set-ids", subm),
("delete-category", _) => { ("get", Some(subm)) => get_id_paths("get-ids", subm),
error!("Command does not get IDs as input"); (other, _) => Err(format_err!("Not a known command: {}", other)),
::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)
}
} }
} }
} }

View file

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

View file

@ -36,6 +36,7 @@
extern crate clap; extern crate clap;
#[macro_use] extern crate log; #[macro_use] extern crate log;
extern crate failure;
extern crate libimagentryedit; extern crate libimagentryedit;
extern crate libimagerror; extern crate libimagerror;
@ -63,7 +64,14 @@ fn main() {
let edit_header = rt.cli().is_present("edit-header"); let edit_header = rt.cli().is_present("edit-header");
let edit_header_only = rt.cli().is_present("edit-header-only"); 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))) StoreIdIterator::new(Box::new(sids.into_iter().map(Ok)))
.into_get_iter(rt.store()) .into_get_iter(rt.store())

View file

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

View file

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

View file

@ -20,11 +20,11 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::{Arg, ArgMatches, App, SubCommand}; use clap::{Arg, ArgMatches, App, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagrt::runtime::IdPathProvider; use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app app
@ -99,54 +99,23 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider; pub struct PathProvider;
impl IdPathProvider for 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() { match matches.subcommand() {
("add", Some(subm)) => { ("add", Some(subm)) => get_id_paths("entry", subm),
subm.values_of("entry") ("remove", Some(subm)) => get_id_paths("entry", subm),
.ok_or_else(|| { ("get", Some(subm)) => get_id_paths("get-ids", subm),
error!("No StoreId found"); (other, _) => Err(format_err!("Not a known command: {}", other)),
::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)
}
} }
} }
} }

View file

@ -79,7 +79,14 @@ fn main() {
trace!("list_output_with_ids = {:?}", list_output_with_ids ); trace!("list_output_with_ids = {:?}", list_output_with_ids );
trace!("list_output_with_ids_fmt = {:?}", list_output_with_ids_fmt); 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))) let iter = StoreIdIterator::new(Box::new(sids.into_iter().map(Ok)))
.into_get_iter(rt.store()) .into_get_iter(rt.store())

View file

@ -20,11 +20,11 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::{Arg, ArgMatches, App, SubCommand}; use clap::{Arg, ArgMatches, App, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider; use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app app
@ -234,11 +234,14 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider; pub struct PathProvider;
impl IdPathProvider for 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") matches.values_of("id")
.unwrap() .map(|v| v
.map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap()) .into_iter()
.collect() .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; #[macro_use] extern crate is_match;
extern crate toml; extern crate toml;
extern crate toml_query; extern crate toml_query;
extern crate failure; #[macro_use] extern crate failure;
#[cfg(test)] #[cfg(test)]
extern crate env_logger; extern crate env_logger;
@ -93,7 +93,13 @@ fn main() {
let iterator = if rt.ids_from_stdin() { let iterator = if rt.ids_from_stdin() {
debug!("Fetching 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)) Box::new(ids.into_iter().map(Ok))
as Box<Iterator<Item = Result<StoreId, _>>> as Box<Iterator<Item = Result<StoreId, _>>>
} else { } else {

View file

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

View file

@ -209,8 +209,13 @@ fn remove_linking(rt: &Runtime) {
}) })
.unwrap(); .unwrap();
rt.ids::<crate::ui::PathProvider>() rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap() .map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter() .into_iter()
.for_each(|id| match rt.store().get(id.clone()) { .for_each(|id| match rt.store().get(id.clone()) {
Err(e) => trace_error(&e), Err(e) => trace_error(&e),
@ -245,19 +250,27 @@ fn remove_linking(rt: &Runtime) {
} }
fn unlink(rt: &Runtime) { fn unlink(rt: &Runtime) {
rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap().into_iter().for_each(|id| { rt
rt.store() .ids::<crate::ui::PathProvider>()
.get(id.clone()) .map_err_trace_exit_unwrap()
.map_err_trace_exit_unwrap() .unwrap_or_else(|| {
.unwrap_or_else(|| { error!("No ids supplied");
warn!("No entry for {}", id); ::std::process::exit(1);
::std::process::exit(1) })
}) .into_iter()
.unlink(rt.store()) .for_each(|id| {
.map_err_trace_exit_unwrap(); rt.store()
.get(id.clone())
.map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
warn!("No entry for {}", id);
::std::process::exit(1)
})
.unlink(rt.store())
.map_err_trace_exit_unwrap();
let _ = rt.report_touched(&id).unwrap_or_exit(); let _ = rt.report_touched(&id).unwrap_or_exit();
}); });
} }
fn list_linkings(rt: &Runtime) { fn list_linkings(rt: &Runtime) {
@ -271,35 +284,24 @@ fn list_linkings(rt: &Runtime) {
let mut tab = ::prettytable::Table::new(); let mut tab = ::prettytable::Table::new();
tab.set_titles(row!["#", "Link"]); tab.set_titles(row!["#", "Link"]);
rt.ids::<crate::ui::PathProvider>().map_err_trace_exit_unwrap().into_iter().for_each(|id| { rt
match rt.store().get(id.clone()) { .ids::<crate::ui::PathProvider>()
Ok(Some(entry)) => { .map_err_trace_exit_unwrap()
for (i, link) in entry.get_internal_links().map_err_trace_exit_unwrap().enumerate() { .unwrap_or_else(|| {
let link = link error!("No ids supplied");
.to_str() ::std::process::exit(1);
.map_warn_err(|e| format!("Failed to convert StoreId to string: {:?}", e)) })
.ok(); .into_iter()
.for_each(|id| {
if let Some(link) = link { match rt.store().get(id.clone()) {
if list_plain { Ok(Some(entry)) => {
let _ = writeln!(rt.stdout(), "{: <3}: {}", i, link) for (i, link) in entry.get_internal_links().map_err_trace_exit_unwrap().enumerate() {
.to_exit_code() let link = link
.unwrap_or_exit(); .to_str()
} else { .map_warn_err(|e| format!("Failed to convert StoreId to string: {:?}", e))
tab.add_row(row![i, link]); .ok();
}
}
}
if list_externals {
entry.get_external_links(rt.store())
.map_err_trace_exit_unwrap()
.enumerate()
.for_each(|(i, link)| {
let link = link
.map_err_trace_exit_unwrap()
.into_string();
if let Some(link) = link {
if list_plain { if list_plain {
let _ = writeln!(rt.stdout(), "{: <3}: {}", i, link) let _ = writeln!(rt.stdout(), "{: <3}: {}", i, link)
.to_exit_code() .to_exit_code()
@ -307,18 +309,37 @@ fn list_linkings(rt: &Runtime) {
} else { } else {
tab.add_row(row![i, link]); tab.add_row(row![i, link]);
} }
}) }
} }
let _ = rt.report_touched(entry.get_location()).unwrap_or_exit(); if list_externals {
entry.get_external_links(rt.store())
.map_err_trace_exit_unwrap()
.enumerate()
.for_each(|(i, link)| {
let link = link
.map_err_trace_exit_unwrap()
.into_string();
}, if list_plain {
Ok(None) => warn!("Not found: {}", id), let _ = writeln!(rt.stdout(), "{: <3}: {}", i, link)
Err(e) => trace_error(&e), .to_exit_code()
} .unwrap_or_exit();
} else {
tab.add_row(row![i, link]);
}
})
}
let _ = rt.report_touched(&id).unwrap_or_exit(); let _ = rt.report_touched(entry.get_location()).unwrap_or_exit();
});
},
Ok(None) => warn!("Not found: {}", id),
Err(e) => trace_error(&e),
}
let _ = rt.report_touched(&id).unwrap_or_exit();
});
if !list_plain { if !list_plain {
let out = rt.stdout(); let out = rt.stdout();

View file

@ -20,11 +20,11 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::{Arg, ArgMatches, App, SubCommand}; use clap::{Arg, ArgMatches, App, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider; use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app 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. /// It has to be fetched by main() by hand.
pub struct PathProvider; pub struct PathProvider;
impl IdPathProvider for 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() { let ids = match matches.subcommand() {
("remove", Some(subm)) => { ("remove", Some(subm)) => Some(get_id_paths("to", subm)),
let to = subm.values_of("to") ("unlink", Some(subm)) => Some(get_id_paths("from", subm)),
.ok_or_else(|| { ("list", Some(subm)) => Some(get_id_paths("entries", subm)),
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)
},
_ => None, _ => None,
}; };
ids.unwrap_or_else(|| { ids
matches.values_of("to") .unwrap_or_else(|| get_id_paths("to", matches))
.unwrap()
.map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap())
.collect()
})
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -38,7 +38,7 @@ extern crate clap;
#[macro_use] extern crate log; #[macro_use] extern crate log;
#[cfg(test)] extern crate toml; #[cfg(test)] extern crate toml;
#[cfg(test)] extern crate failure; extern crate failure;
extern crate libimagstore; extern crate libimagstore;
#[macro_use] extern crate libimagrt; #[macro_use] extern crate libimagrt;
@ -84,7 +84,14 @@ fn main() {
"Direct interface to the store. Use with great care!", "Direct interface to the store. Use with great care!",
build_ui); 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() rt.cli()
.subcommand_name() .subcommand_name()

View file

@ -20,11 +20,11 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::{Arg, ArgMatches, ArgGroup, App, SubCommand}; use clap::{Arg, ArgMatches, ArgGroup, App, SubCommand};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider; use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
use libimagentrytag::tag::is_tag; use libimagentrytag::tag::is_tag;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { 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; pub struct PathProvider;
impl IdPathProvider for 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") matches.values_of("id")
.unwrap() .map(|v| v
.map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap()) .into_iter()
.collect() .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 view_header = rt.cli().is_present("view-header");
let hide_content = rt.cli().is_present("not-view-content"); 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() .map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter() .into_iter()
.map(Ok) .map(Ok)
.into_get_iter(rt.store()) .into_get_iter(rt.store())

View file

@ -20,11 +20,11 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::{Arg, ArgMatches, App}; use clap::{Arg, ArgMatches, App};
use failure::Fallible as Result;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::IntoStoreId;
use libimagrt::runtime::IdPathProvider; use libimagrt::runtime::IdPathProvider;
use libimagerror::trace::MapErrTrace;
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app app
@ -90,10 +90,14 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
pub struct PathProvider; pub struct PathProvider;
impl IdPathProvider for 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") matches.values_of("id")
.unwrap() .map(|v| v
.map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap()) .into_iter()
.collect() .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" } libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagentrytag = { version = "0.10.0", path = "../../../lib/entry/libimagentrytag" } libimagentrytag = { version = "0.10.0", path = "../../../lib/entry/libimagentrytag" }
libimagutil = { version = "0.10.0", path = "../../../lib/etc/libimagutil" } libimagutil = { version = "0.10.0", path = "../../../lib/etc/libimagutil" }
failure = "0.1"
log = "0.4.0" log = "0.4.0"
[badges] [badges]

View file

@ -131,7 +131,7 @@ fn list(rt: &Runtime) {
let print_content = scmd.is_present("list-read"); let print_content = scmd.is_present("list-read");
if print_content { 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. 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. We use the 'mailparse' crate underneath, but its implementation is nonoptimal.
Thus, the content might be printed as empty (no text in the email) 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() { if rt.ids_from_stdin() {
let iter = rt.ids::<crate::ui::PathProvider>() let iter = rt
.ids::<crate::ui::PathProvider>()
.map_err_trace_exit_unwrap() .map_err_trace_exit_unwrap()
.unwrap_or_else(|| {
error!("No ids supplied");
::std::process::exit(1);
})
.into_iter() .into_iter()
.map(Ok); .map(Ok);

View file

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

View file

@ -398,7 +398,7 @@ impl<'a> Runtime<'a> {
self.has_input_pipe 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; use std::io::Read;
if self.has_input_pipe { if self.has_input_pipe {
@ -417,8 +417,9 @@ impl<'a> Runtime<'a> {
.map(|id| StoreId::new(id).map_err(Error::from)) .map(|id| StoreId::new(id).map_err(Error::from))
.collect() .collect()
}) })
.map(Some)
} else { } 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 /// This trait can be implement on a type so that it can provide IDs when given a ArgMatches
/// object. /// 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: /// automatically:
/// ///
/// ```ignore /// ```ignore
@ -630,13 +630,12 @@ impl<'a> Runtime<'a> {
/// ///
/// # Returns /// # Returns
/// ///
/// In case of error, the IdPathProvider::get_ids() function should exit the application /// In case no store ids could be matched, the function should return `Ok(None)` instance.
/// with the appropriate error message(s).
///
/// On success, the StoreId objects to operate on are returned from the ArgMatches. /// On success, the StoreId objects to operate on are returned from the ArgMatches.
/// Otherwise, an appropriate error may be returned.
/// ///
pub trait IdPathProvider { 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. /// Exported for the `imag` command, you probably do not want to use that.