Remove calls to exit() and replace them with error propagation up to main()
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
parent
df2c5faf73
commit
f881f44d06
2 changed files with 101 additions and 116 deletions
|
@ -26,6 +26,7 @@ toml = "0.5.1"
|
||||||
toml-query = "0.9.2"
|
toml-query = "0.9.2"
|
||||||
filters = "0.3.0"
|
filters = "0.3.0"
|
||||||
failure = "0.1.5"
|
failure = "0.1.5"
|
||||||
|
resiter = "0.3.0"
|
||||||
|
|
||||||
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" }
|
||||||
|
|
|
@ -34,10 +34,11 @@
|
||||||
|
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
|
#[macro_use] extern crate failure;
|
||||||
extern crate toml;
|
extern crate toml;
|
||||||
extern crate toml_query;
|
extern crate toml_query;
|
||||||
extern crate filters;
|
extern crate filters;
|
||||||
extern crate failure;
|
extern crate resiter;
|
||||||
|
|
||||||
extern crate libimagentryedit;
|
extern crate libimagentryedit;
|
||||||
extern crate libimagerror;
|
extern crate libimagerror;
|
||||||
|
@ -52,18 +53,17 @@ use std::string::ToString;
|
||||||
use clap::{App, ArgMatches};
|
use clap::{App, ArgMatches};
|
||||||
use filters::filter::Filter;
|
use filters::filter::Filter;
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
use failure::{Fallible as Result, Error};
|
use failure::Error;
|
||||||
|
use failure::Fallible as Result;
|
||||||
|
use failure::err_msg;
|
||||||
|
use resiter::FilterMap;
|
||||||
|
use resiter::AndThen;
|
||||||
|
|
||||||
use libimagerror::exit::ExitCode;
|
|
||||||
use libimagerror::exit::ExitUnwrap;
|
|
||||||
use libimagerror::io::ToExitCode;
|
|
||||||
use libimagerror::iter::TraceIterator;
|
|
||||||
use libimagerror::trace::MapErrTrace;
|
|
||||||
use libimagrt::runtime::Runtime;
|
use libimagrt::runtime::Runtime;
|
||||||
use libimagrt::application::ImagApplication;
|
use libimagrt::application::ImagApplication;
|
||||||
use libimagstore::iter::get::StoreIdGetIteratorExtension;
|
use libimagstore::iter::get::StoreIdGetIteratorExtension;
|
||||||
use libimagstore::store::FileLockEntry;
|
use libimagstore::store::FileLockEntry;
|
||||||
use libimagstore::storeid::StoreIdIterator;
|
use libimagerror::iter::IterInnerOkOrElse;
|
||||||
|
|
||||||
use toml_query::read::TomlValueReadExt;
|
use toml_query::read::TomlValueReadExt;
|
||||||
use toml_query::read::TomlValueReadTypeExt;
|
use toml_query::read::TomlValueReadTypeExt;
|
||||||
|
@ -85,22 +85,16 @@ impl ImagApplication for ImagHeader {
|
||||||
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
|
let iter = rt
|
||||||
.ids::<crate::ui::PathProvider>()
|
.ids::<crate::ui::PathProvider>()?
|
||||||
.map_err_trace_exit_unwrap()
|
.ok_or_else(|| err_msg("No ids supplied"))?
|
||||||
.unwrap_or_else(|| {
|
.into_iter()
|
||||||
error!("No ids supplied");
|
.map(Ok)
|
||||||
::std::process::exit(1);
|
|
||||||
})
|
|
||||||
.into_iter();
|
|
||||||
|
|
||||||
let iter = StoreIdIterator::new(Box::new(sids.map(Ok)))
|
|
||||||
.into_get_iter(rt.store())
|
.into_get_iter(rt.store())
|
||||||
.trace_unwrap_exit()
|
.map_inner_ok_or_else(|| err_msg("Did not find one entry"));
|
||||||
.filter_map(|x| x);
|
|
||||||
|
|
||||||
match rt.cli().subcommand() {
|
match rt.cli().subcommand() {
|
||||||
("read", Some(mtch)) => ::std::process::exit(read(&rt, mtch, iter)),
|
("read", Some(mtch)) => read(&rt, mtch, iter),
|
||||||
("has", Some(mtch)) => has(&rt, mtch, iter),
|
("has", Some(mtch)) => has(&rt, mtch, iter),
|
||||||
("hasnt", Some(mtch)) => hasnt(&rt, mtch, iter),
|
("hasnt", Some(mtch)) => hasnt(&rt, mtch, iter),
|
||||||
("int", Some(mtch)) => int(&rt, mtch, iter),
|
("int", Some(mtch)) => int(&rt, mtch, iter),
|
||||||
|
@ -109,16 +103,16 @@ impl ImagApplication for ImagHeader {
|
||||||
("bool", Some(mtch)) => boolean(&rt, mtch, iter),
|
("bool", Some(mtch)) => boolean(&rt, mtch, iter),
|
||||||
(other, _mtchs) => {
|
(other, _mtchs) => {
|
||||||
debug!("Unknown command");
|
debug!("Unknown command");
|
||||||
::std::process::exit({
|
if rt.handle_unknown_subcommand("imag-header", other, rt.cli())
|
||||||
rt.handle_unknown_subcommand("imag-header", other, rt.cli())
|
.map_err(Error::from)?
|
||||||
.map_err_trace_exit_unwrap()
|
.success()
|
||||||
.code()
|
{
|
||||||
.unwrap_or(1)
|
Ok(())
|
||||||
});
|
} else {
|
||||||
|
Err(format_err!("Subcommand failed"))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
|
fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
|
||||||
|
@ -138,21 +132,20 @@ impl ImagApplication for ImagHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I) -> i32
|
fn read<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I) -> Result<()>
|
||||||
where I: Iterator<Item = FileLockEntry<'e>>
|
where I: Iterator<Item = Result<FileLockEntry<'e>>>
|
||||||
{
|
{
|
||||||
debug!("Processing headers: reading value");
|
debug!("Processing headers: reading value");
|
||||||
let header_path = get_header_path(mtch, "header-value-path");
|
let header_path = get_header_path(mtch, "header-value-path");
|
||||||
let mut output = rt.stdout();
|
let mut output = rt.stdout();
|
||||||
trace!("Got output: {:?}", output);
|
trace!("Got output: {:?}", output);
|
||||||
|
|
||||||
iter.fold(0, |accu, entry| {
|
iter.and_then_ok(|entry| {
|
||||||
trace!("Processing headers: working on {:?}", entry.get_location());
|
trace!("Processing headers: working on {:?}", entry.get_location());
|
||||||
entry.get_header()
|
entry.get_header()
|
||||||
.read(header_path)
|
.read(header_path)?
|
||||||
.map_err(Error::from)
|
.ok_or_else(|| format_err!("Value not present for entry {} at {}", entry.get_location(), header_path))
|
||||||
.map_err_trace_exit_unwrap()
|
.and_then(|value| {
|
||||||
.map(|value| {
|
|
||||||
trace!("Processing headers: Got value {:?}", value);
|
trace!("Processing headers: Got value {:?}", value);
|
||||||
|
|
||||||
let string_representation = match value {
|
let string_representation = match value {
|
||||||
|
@ -164,65 +157,56 @@ fn read<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I) -> i32
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(repr) = string_representation {
|
if let Some(repr) = string_representation {
|
||||||
writeln!(output, "{}", repr)
|
writeln!(output, "{}", repr)?;
|
||||||
} else {
|
} else {
|
||||||
writeln!(output, "{}", value)
|
writeln!(output, "{}", value)?;
|
||||||
}
|
}
|
||||||
.to_exit_code()
|
Ok(())
|
||||||
.map(|_| accu)
|
|
||||||
.unwrap_or_else(ExitCode::code)
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
// if value not present and configured
|
|
||||||
error!("Value not present for entry {} at {}", entry.get_location(), header_path);
|
|
||||||
1
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
.collect::<Result<()>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I)
|
fn has<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I) -> Result<()>
|
||||||
where I: Iterator<Item = FileLockEntry<'e>>
|
where I: Iterator<Item = Result<FileLockEntry<'e>>>
|
||||||
{
|
{
|
||||||
debug!("Processing headers: has value");
|
debug!("Processing headers: has value");
|
||||||
let header_path = get_header_path(mtch, "header-value-path");
|
let header_path = get_header_path(mtch, "header-value-path");
|
||||||
let mut output = rt.stdout();
|
let mut output = rt.stdout();
|
||||||
|
|
||||||
iter.for_each(|entry| {
|
iter.and_then_ok(|entry| {
|
||||||
trace!("Processing headers: working on {:?}", entry.get_location());
|
trace!("Processing headers: working on {:?}", entry.get_location());
|
||||||
if entry.get_header()
|
if let Some(_) = entry.get_header().read(header_path)? {
|
||||||
.read(header_path)
|
if !rt.output_is_pipe() {
|
||||||
.map_err(Error::from)
|
writeln!(output, "{}", entry.get_location())?;
|
||||||
.map_err_trace_exit_unwrap()
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
rt.report_touched(entry.get_location()).unwrap_or_exit();
|
|
||||||
if !rt.output_is_pipe() {
|
|
||||||
writeln!(output, "{}", entry.get_location()).to_exit_code().unwrap_or_exit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
rt.report_touched(entry.get_location()).map_err(Error::from)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
.collect::<Result<()>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hasnt<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I)
|
fn hasnt<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I) -> Result<()>
|
||||||
where I: Iterator<Item = FileLockEntry<'e>>
|
where I: Iterator<Item = Result<FileLockEntry<'e>>>
|
||||||
{
|
{
|
||||||
debug!("Processing headers: hasnt value");
|
debug!("Processing headers: hasnt value");
|
||||||
let header_path = get_header_path(mtch, "header-value-path");
|
let header_path = get_header_path(mtch, "header-value-path");
|
||||||
let mut output = rt.stdout();
|
let mut output = rt.stdout();
|
||||||
|
|
||||||
iter.for_each(|entry| {
|
iter.and_then_ok(|entry| {
|
||||||
trace!("Processing headers: working on {:?}", entry.get_location());
|
trace!("Processing headers: working on {:?}", entry.get_location());
|
||||||
if entry.get_header()
|
if let Some(_) = entry.get_header().read(header_path)? {
|
||||||
.read(header_path)
|
Ok(())
|
||||||
.map_err(Error::from)
|
} else {
|
||||||
.map_err_trace_exit_unwrap()
|
if !rt.output_is_pipe() {
|
||||||
.is_none() {
|
writeln!(output, "{}", entry.get_location())?;
|
||||||
rt.report_touched(entry.get_location()).unwrap_or_exit();
|
|
||||||
if !rt.output_is_pipe() {
|
|
||||||
writeln!(output, "{}", entry.get_location()).to_exit_code().unwrap_or_exit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
rt.report_touched(entry.get_location()).map_err(Error::from)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! implement_compare {
|
macro_rules! implement_compare {
|
||||||
|
@ -238,8 +222,8 @@ macro_rules! implement_compare {
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn int<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I)
|
fn int<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I) -> Result<()>
|
||||||
where I: Iterator<Item = FileLockEntry<'e>>
|
where I: Iterator<Item = Result<FileLockEntry<'e>>>
|
||||||
{
|
{
|
||||||
debug!("Processing headers: int value");
|
debug!("Processing headers: int value");
|
||||||
let header_path = get_header_path(mtch, "header-value-path");
|
let header_path = get_header_path(mtch, "header-value-path");
|
||||||
|
@ -264,20 +248,20 @@ fn int<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I)
|
||||||
implement_compare!(mtch, "header-int-gte", i64, |cmp| *i >= cmp)
|
implement_compare!(mtch, "header-int-gte", i64, |cmp| *i >= cmp)
|
||||||
});
|
});
|
||||||
|
|
||||||
iter.filter(|entry| if let Some(hdr) = entry.get_header()
|
iter.and_then_ok(|entry| {
|
||||||
.read_int(header_path)
|
if let Some(hdr) = entry.get_header().read_int(header_path)? {
|
||||||
.map_err(Error::from)
|
Ok((filter.filter(&hdr), entry))
|
||||||
.map_err_trace_exit_unwrap()
|
|
||||||
{
|
|
||||||
filter.filter(&hdr)
|
|
||||||
} else {
|
} else {
|
||||||
false
|
Ok((false, entry))
|
||||||
})
|
}
|
||||||
.for_each(|entry| rt.report_touched(entry.get_location()).unwrap_or_exit())
|
})
|
||||||
|
.filter_map_ok(|(b, e)| if b { Some(e) } else { None })
|
||||||
|
.and_then_ok(|entry| rt.report_touched(entry.get_location()).map_err(Error::from))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn float<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I)
|
fn float<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I) -> Result<()>
|
||||||
where I: Iterator<Item = FileLockEntry<'e>>
|
where I: Iterator<Item = Result<FileLockEntry<'e>>>
|
||||||
{
|
{
|
||||||
debug!("Processing headers: float value");
|
debug!("Processing headers: float value");
|
||||||
let header_path = get_header_path(mtch, "header-value-path");
|
let header_path = get_header_path(mtch, "header-value-path");
|
||||||
|
@ -302,20 +286,20 @@ fn float<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I)
|
||||||
implement_compare!(mtch, "header-float-gte", f64, |cmp| *i >= cmp)
|
implement_compare!(mtch, "header-float-gte", f64, |cmp| *i >= cmp)
|
||||||
});
|
});
|
||||||
|
|
||||||
iter.filter(|entry| if let Some(hdr) = entry.get_header()
|
iter.and_then_ok(|entry| {
|
||||||
.read_float(header_path)
|
if let Some(hdr) = entry.get_header().read_float(header_path)? {
|
||||||
.map_err(Error::from)
|
Ok((filter.filter(&hdr), entry))
|
||||||
.map_err_trace_exit_unwrap()
|
|
||||||
{
|
|
||||||
filter.filter(&hdr)
|
|
||||||
} else {
|
} else {
|
||||||
false
|
Ok((false, entry))
|
||||||
})
|
}
|
||||||
.for_each(|entry| rt.report_touched(entry.get_location()).unwrap_or_exit())
|
})
|
||||||
|
.filter_map_ok(|(b, e)| if b { Some(e) } else { None })
|
||||||
|
.and_then_ok(|entry| rt.report_touched(entry.get_location()).map_err(Error::from))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I)
|
fn string<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I) -> Result<()>
|
||||||
where I: Iterator<Item = FileLockEntry<'e>>
|
where I: Iterator<Item = Result<FileLockEntry<'e>>>
|
||||||
{
|
{
|
||||||
debug!("Processing headers: string value");
|
debug!("Processing headers: string value");
|
||||||
let header_path = get_header_path(mtch, "header-value-path");
|
let header_path = get_header_path(mtch, "header-value-path");
|
||||||
|
@ -328,20 +312,20 @@ fn string<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I)
|
||||||
implement_compare!(mtch, "header-string-neq", String, |cmp| *i != cmp)
|
implement_compare!(mtch, "header-string-neq", String, |cmp| *i != cmp)
|
||||||
});
|
});
|
||||||
|
|
||||||
iter.filter(|entry| if let Some(hdr) = entry.get_header()
|
iter.and_then_ok(|entry| {
|
||||||
.read_string(header_path)
|
if let Some(hdr) = entry.get_header().read_string(header_path)? {
|
||||||
.map_err(Error::from)
|
Ok((filter.filter(&hdr), entry))
|
||||||
.map_err_trace_exit_unwrap()
|
|
||||||
{
|
|
||||||
filter.filter(&hdr)
|
|
||||||
} else {
|
} else {
|
||||||
false
|
Ok((false, entry))
|
||||||
})
|
}
|
||||||
.for_each(|entry| rt.report_touched(entry.get_location()).unwrap_or_exit())
|
})
|
||||||
|
.filter_map_ok(|(b, e)| if b { Some(e) } else { None })
|
||||||
|
.and_then_ok(|entry| rt.report_touched(entry.get_location()).map_err(Error::from))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn boolean<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I)
|
fn boolean<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I) -> Result<()>
|
||||||
where I: Iterator<Item = FileLockEntry<'e>>
|
where I: Iterator<Item = Result<FileLockEntry<'e>>>
|
||||||
{
|
{
|
||||||
debug!("Processing headers: bool value");
|
debug!("Processing headers: bool value");
|
||||||
let header_path = get_header_path(mtch, "header-value-path");
|
let header_path = get_header_path(mtch, "header-value-path");
|
||||||
|
@ -350,16 +334,16 @@ fn boolean<'a, 'e, I>(rt: &Runtime, mtch: &ArgMatches<'a>, iter: I)
|
||||||
.and(|i: &bool| -> bool { *i })
|
.and(|i: &bool| -> bool { *i })
|
||||||
.and(|i: &bool| -> bool { *i });
|
.and(|i: &bool| -> bool { *i });
|
||||||
|
|
||||||
iter.filter(|entry| if let Some(hdr) = entry.get_header()
|
iter.and_then_ok(|entry| {
|
||||||
.read_bool(header_path)
|
if let Some(hdr) = entry.get_header().read_bool(header_path)? {
|
||||||
.map_err(Error::from)
|
Ok((filter.filter(&hdr), entry))
|
||||||
.map_err_trace_exit_unwrap()
|
|
||||||
{
|
|
||||||
filter.filter(&hdr)
|
|
||||||
} else {
|
} else {
|
||||||
false
|
Ok((false, entry))
|
||||||
})
|
}
|
||||||
.for_each(|entry| rt.report_touched(entry.get_location()).unwrap_or_exit())
|
})
|
||||||
|
.filter_map_ok(|(b, e)| if b { Some(e) } else { None })
|
||||||
|
.and_then_ok(|entry| rt.report_touched(entry.get_location()).map_err(Error::from))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue