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:
Matthias Beyer 2019-10-19 08:54:57 +02:00
parent e67f5374be
commit 58e303116d
8 changed files with 88 additions and 108 deletions

View file

@ -23,6 +23,7 @@ maintenance = { status = "actively-developed" }
log = "0.4.6" log = "0.4.6"
toml = "0.5.1" toml = "0.5.1"
failure = "0.1.5" failure = "0.1.5"
resiter = "0.3.0"
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore", features = ["verify"] } libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore", features = ["verify"] }
libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }

View file

@ -17,34 +17,32 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
// //
use std::ops::DerefMut;
use std::path::PathBuf; use std::path::PathBuf;
use std::io::stdin; use std::io::stdin;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::Read; use std::io::Read;
use std::ops::DerefMut;
use clap::ArgMatches; use clap::ArgMatches;
use toml::Value; use toml::Value;
use failure::Fallible as Result; use failure::Fallible as Result;
use failure::Error;
use failure::err_msg; use failure::err_msg;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagstore::store::Entry; use libimagstore::store::Entry;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagerror::trace::MapErrTrace;
use libimagerror::exit::ExitUnwrap;
use libimagutil::debug_result::*;
use crate::util::build_toml_header; use crate::util::build_toml_header;
pub fn create(rt: &Runtime) { pub fn create(rt: &Runtime) -> Result<()> {
let scmd = rt.cli().subcommand_matches("create").unwrap(); let scmd = rt.cli().subcommand_matches("create").unwrap();
debug!("Found 'create' subcommand..."); debug!("Found 'create' subcommand...");
// unwrap is safe as value is required // unwrap is safe as value is required
let path = scmd.value_of("path").unwrap(); let path = scmd.value_of("path").unwrap();
let path = PathBuf::from(path); let path = PathBuf::from(path);
let path = StoreId::new(path).map_err_trace_exit_unwrap(); let path = StoreId::new(path)?;
debug!("path = {:?}", path); debug!("path = {:?}", path);
@ -55,15 +53,13 @@ pub fn create(rt: &Runtime) {
.or_else(|_| create_with_content_and_header(rt, .or_else(|_| create_with_content_and_header(rt,
&path, &path,
String::new(), String::new(),
Entry::default_header())) Entry::default_header()))?;
} else { } else {
debug!("Creating entry"); debug!("Creating entry");
create_with_content_and_header(rt, &path, String::new(), create_with_content_and_header(rt, &path, String::new(), Entry::default_header())?;
Entry::default_header())
} }
.map_err_trace_exit_unwrap();
rt.report_touched(&path).unwrap_or_exit(); rt.report_touched(&path).map_err(Error::from)
} }
fn create_from_cli_spec(rt: &Runtime, matches: &ArgMatches, path: &StoreId) -> Result<()> { fn create_from_cli_spec(rt: &Runtime, matches: &ArgMatches, path: &StoreId) -> Result<()> {
@ -99,19 +95,13 @@ fn create_from_source(rt: &Runtime, matches: &ArgMatches, path: &StoreId) -> Res
debug!("Content with len = {}", content.len()); debug!("Content with len = {}", content.len());
Entry::from_str(path.clone(), &content[..]) Entry::from_str(path.clone(), &content[..])
.map_dbg_err(|e| format!("Error building entry: {:?}", e))
.and_then(|new_e| { .and_then(|new_e| {
let r = rt.store() rt.store()
.create(path.clone()) .create(path.clone())
.map_dbg_err(|e| format!("Error in Store::create(): {:?}", e))
.map(|mut old_e| { .map(|mut old_e| {
*old_e.deref_mut() = new_e; *old_e.deref_mut() = new_e;
});
debug!("Entry build");
r
}) })
.map_dbg_err(|e| format!("Error storing entry: {:?}", e)) })
} }
fn create_with_content_and_header(rt: &Runtime, fn create_with_content_and_header(rt: &Runtime,
@ -122,7 +112,6 @@ fn create_with_content_and_header(rt: &Runtime,
debug!("Creating entry with content at {:?}", path); debug!("Creating entry with content at {:?}", path);
rt.store() rt.store()
.create(path.clone()) .create(path.clone())
.map_dbg_err(|e| format!("Error in Store::create(): {:?}", e))
.map(|mut element| { .map(|mut element| {
{ {
let e_content = element.get_content_mut(); let e_content = element.get_content_mut();
@ -177,7 +166,7 @@ mod tests {
let test_name = "test_create_simple"; let test_name = "test_create_simple";
let rt = generate_test_runtime(vec!["create", "test_create_simple"]).unwrap(); let rt = generate_test_runtime(vec!["create", "test_create_simple"]).unwrap();
create(&rt); create(&rt).unwrap();
let e = rt.store().get(PathBuf::from(test_name)); let e = rt.store().get(PathBuf::from(test_name));
assert!(e.is_ok()); assert!(e.is_ok());

View file

@ -19,22 +19,19 @@
use std::path::PathBuf; use std::path::PathBuf;
use libimagrt::runtime::Runtime; use failure::Fallible as Result;
use libimagerror::trace::MapErrTrace;
use libimagstore::storeid::StoreId;
use libimagutil::warn_result::*;
pub fn delete(rt: &Runtime) { use libimagrt::runtime::Runtime;
use libimagstore::storeid::StoreId;
pub fn delete(rt: &Runtime) -> Result<()> {
let scmd = rt.cli().subcommand_matches("delete").unwrap(); let scmd = rt.cli().subcommand_matches("delete").unwrap();
let id = scmd.value_of("id").unwrap(); // safe by clap let id = scmd.value_of("id").unwrap(); // safe by clap
let path = PathBuf::from(id); let path = PathBuf::from(id);
let path = StoreId::new(path).map_err_trace_exit_unwrap(); let path = StoreId::new(path)?;
debug!("Deleting file at {:?}", id); debug!("Deleting file at {:?}", id);
rt.store() rt.store().delete(path)
.delete(path)
.map_warn_err(|e| format!("Error: {:?}", e))
.map_err_trace_exit_unwrap();
} }
#[cfg(test)] #[cfg(test)]
@ -59,11 +56,11 @@ mod tests {
let test_name = "test_create_simple"; let test_name = "test_create_simple";
let rt = generate_test_runtime(vec!["create", "test_create_simple"]).unwrap(); let rt = generate_test_runtime(vec!["create", "test_create_simple"]).unwrap();
create(&rt); create(&rt).unwrap();
let rt = reset_test_runtime(vec!["delete", "test_create_simple"], rt).unwrap(); let rt = reset_test_runtime(vec!["delete", "test_create_simple"], rt).unwrap();
delete(&rt); delete(&rt).unwrap();
let e = rt.store().get(PathBuf::from(test_name)); let e = rt.store().get(PathBuf::from(test_name));
assert!(e.is_ok()); assert!(e.is_ok());

View file

@ -19,27 +19,29 @@
use std::path::PathBuf; use std::path::PathBuf;
use failure::Fallible as Result;
use failure::Error;
use failure::err_msg;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagerror::trace::MapErrTrace;
use libimagerror::exit::ExitUnwrap;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use crate::retrieve::print_entry; use crate::retrieve::print_entry;
pub fn get(rt: &Runtime) { pub fn get(rt: &Runtime) -> Result<()> {
let scmd = rt.cli().subcommand_matches("get").unwrap(); let scmd = rt.cli().subcommand_matches("get").unwrap();
let id = scmd.value_of("id").unwrap(); // safe by clap let id = scmd.value_of("id").unwrap(); // safe by clap
let path = PathBuf::from(id); let path = PathBuf::from(id);
let path = StoreId::new(path).map_err_trace_exit_unwrap(); let path = StoreId::new(path)?;
debug!("path = {:?}", path); debug!("path = {:?}", path);
match rt.store().get(path.clone()).map_err_trace_exit_unwrap() { match rt.store().get(path.clone())? {
None => Err(err_msg("No entry found")),
Some(entry) => { Some(entry) => {
print_entry(rt, scmd, entry); print_entry(rt, scmd, entry)?;
rt.report_touched(&path).unwrap_or_exit(); rt.report_touched(&path).map_err(Error::from)
}, },
None => info!("No entry found"), }
};
} }

View file

@ -37,8 +37,9 @@
extern crate clap; extern crate clap;
#[macro_use] extern crate log; #[macro_use] extern crate log;
extern crate toml; extern crate toml;
extern crate resiter;
#[cfg(test)] extern crate toml_query; #[cfg(test)] extern crate toml_query;
extern crate failure; #[macro_use] extern crate failure;
extern crate libimagrt; extern crate libimagrt;
extern crate libimagstore; extern crate libimagstore;
@ -53,7 +54,9 @@ extern crate libimagutil;
use libimagrt::application::ImagApplication; use libimagrt::application::ImagApplication;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagerror::trace::MapErrTrace;
use failure::Fallible as Result;
use failure::err_msg;
mod create; mod create;
mod delete; mod delete;
@ -66,7 +69,6 @@ mod util;
use std::ops::Deref; use std::ops::Deref;
use failure::Fallible as Result;
use clap::App; use clap::App;
use crate::create::create; use crate::create::create;
@ -83,9 +85,7 @@ use crate::verify::verify;
pub enum ImagStore {} pub enum ImagStore {}
impl ImagApplication for ImagStore { impl ImagApplication for ImagStore {
fn run(rt: Runtime) -> Result<()> { fn run(rt: Runtime) -> Result<()> {
let command = rt.cli().subcommand_name().map(String::from); if let Some(command) = rt.cli().subcommand_name() {
if let Some(command) = command {
debug!("Call: {}", command); debug!("Call: {}", command);
match command.deref() { match command.deref() {
"create" => create(&rt), "create" => create(&rt),
@ -96,17 +96,16 @@ impl ImagApplication for ImagStore {
"verify" => verify(&rt), "verify" => verify(&rt),
other => { other => {
debug!("Unknown command"); debug!("Unknown command");
let _ = rt.handle_unknown_subcommand("imag-store", other, rt.cli()) if rt.handle_unknown_subcommand("imag-store", other, rt.cli())?.success() {
.map_err_trace_exit_unwrap()
.code()
.map(::std::process::exit);
},
};
} else {
debug!("No command");
}
Ok(()) Ok(())
} else {
Err(format_err!("Subcommand failed"))
}
},
}
} else {
Err(err_msg("No command"))
}
} }
fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> {

View file

@ -20,41 +20,32 @@
use std::path::PathBuf; use std::path::PathBuf;
use std::io::Write; use std::io::Write;
use failure::Fallible as Result;
use failure::Error;
use clap::ArgMatches; use clap::ArgMatches;
use libimagstore::store::FileLockEntry; use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagerror::trace::MapErrTrace;
use libimagerror::io::ToExitCode;
use libimagerror::exit::ExitUnwrap;
use libimagutil::debug_result::*;
pub fn retrieve(rt: &Runtime) { pub fn retrieve(rt: &Runtime) -> Result<()> {
if let Some(scmd) = rt.cli().subcommand_matches("retrieve") { let scmd = rt.cli().subcommand_matches("retrieve").unwrap();
// unwrap() is safe as arg is required
let id = scmd.value_of("id").unwrap(); let id = scmd.value_of("id").unwrap();
let path = PathBuf::from(id); let path = PathBuf::from(id);
let path = StoreId::new(path).map_err_trace_exit_unwrap(); let path = StoreId::new(path)?;
debug!("path = {:?}", path); debug!("path = {:?}", path);
rt.store() rt.store()
.retrieve(path.clone()) .retrieve(path.clone())
.map(|e| print_entry(rt, scmd, e)) .and_then(|e| print_entry(rt, scmd, e))?;
.map_dbg_str("No entry")
.map_dbg(|e| format!("{:?}", e))
.map_err_trace_exit_unwrap();
rt.report_touched(&path).unwrap_or_exit(); rt.report_touched(&path).map_err(Error::from)
}
} }
pub fn print_entry(rt: &Runtime, scmd: &ArgMatches, e: FileLockEntry) { pub fn print_entry(rt: &Runtime, scmd: &ArgMatches, e: FileLockEntry) -> Result<()> {
if do_print_raw(scmd) { if do_print_raw(scmd) {
debug!("Printing raw content..."); debug!("Printing raw content...");
writeln!(rt.stdout(), "{}", e.to_str().map_err_trace_exit_unwrap()) writeln!(rt.stdout(), "{}", e.to_str()?)?;
.to_exit_code()
.unwrap_or_exit();
} else if do_filter(scmd) { } else if do_filter(scmd) {
debug!("Filtering..."); debug!("Filtering...");
warn!("Filtering via header specs is currently now supported."); warn!("Filtering via header specs is currently now supported.");
@ -71,20 +62,17 @@ pub fn print_entry(rt: &Runtime, scmd: &ArgMatches, e: FileLockEntry) {
unimplemented!() unimplemented!()
} else { } else {
debug!("Printing header as TOML..."); debug!("Printing header as TOML...");
writeln!(rt.stdout(), "{}", e.get_header()) writeln!(rt.stdout(), "{}", e.get_header())?;
.to_exit_code()
.unwrap_or_exit();
} }
} }
if do_print_content(scmd) { if do_print_content(scmd) {
debug!("Printing content..."); debug!("Printing content...");
writeln!(rt.stdout(), "{}", e.get_content()) writeln!(rt.stdout(), "{}", e.get_content())?;
.to_exit_code() }
.unwrap_or_exit();
} }
} Ok(())
} }
fn do_print_header(m: &ArgMatches) -> bool { fn do_print_header(m: &ArgMatches) -> bool {

View file

@ -20,22 +20,23 @@
use std::ops::DerefMut; use std::ops::DerefMut;
use std::path::PathBuf; use std::path::PathBuf;
use failure::Fallible as Result;
use failure::Error;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagerror::trace::MapErrTrace;
use libimagerror::exit::ExitUnwrap;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use crate::util::build_toml_header; use crate::util::build_toml_header;
pub fn update(rt: &Runtime) { pub fn update(rt: &Runtime) -> Result<()> {
let scmd = rt.cli().subcommand_matches("update").unwrap(); let scmd = rt.cli().subcommand_matches("update").unwrap();
let id = scmd.value_of("id").unwrap(); // Safe by clap let id = scmd.value_of("id").unwrap(); // Safe by clap
let path = PathBuf::from(id); let path = PathBuf::from(id);
let path = StoreId::new(path).map_err_trace_exit_unwrap(); let path = StoreId::new(path)?;
let _ = rt.store() rt.store()
.retrieve(path) .retrieve(path)
.map(|mut locked_e| { .and_then(|mut locked_e| {
{ {
let e = locked_e.deref_mut(); let e = locked_e.deref_mut();
@ -48,7 +49,7 @@ pub fn update(rt: &Runtime) {
debug!("New header set"); debug!("New header set");
} }
rt.report_touched(locked_e.get_location()).unwrap_or_exit(); rt.report_touched(locked_e.get_location()).map_err(Error::from)
}); })
} }

View file

@ -19,26 +19,25 @@
use std::ops::Deref; use std::ops::Deref;
use failure::Fallible as Result;
use failure::err_msg;
use resiter::AndThen;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagutil::warn_exit::warn_exit; use libimagerror::iter::IterInnerOkOrElse;
use libimagerror::trace::MapErrTrace;
use libimagerror::exit::ExitUnwrap;
use libimagerror::iter::TraceIterator;
/// Verify the store. /// Verify the store.
/// ///
/// This function is not intended to be called by normal programs but only by `imag-store`. /// This function is not intended to be called by normal programs but only by `imag-store`.
pub fn verify(rt: &Runtime) { pub fn verify(rt: &Runtime) -> Result<()> {
info!("Header | Content length | Path"); info!("Header | Content length | Path");
info!("-------+----------------+-----"); info!("-------+----------------+-----");
let result = rt let result = rt
.store() .store()
.entries() .entries()?
.map_err_trace_exit_unwrap()
.into_get_iter() .into_get_iter()
.trace_unwrap_exit() .map_inner_ok_or_else(|| err_msg("Did not find one entry"))
.filter_map(|x| x) .and_then_ok(|fle| {
.all(|fle| {
let p = fle.get_location(); let p = fle.get_location();
let content_len = fle.get_content().len(); let content_len = fle.get_content().len();
let (verify, status) = if fle.verify().is_ok() { let (verify, status) = if fle.verify().is_ok() {
@ -48,14 +47,18 @@ pub fn verify(rt: &Runtime) {
}; };
info!("{: >6} | {: >14} | {:?}", verify, content_len, p.deref()); info!("{: >6} | {: >14} | {:?}", verify, content_len, p.deref());
rt.report_touched(fle.get_location()).unwrap_or_exit(); rt.report_touched(fle.get_location())?;
status Ok(status)
}); })
.collect::<Result<Vec<_>>>()?
.iter()
.all(|x| *x);
if result { if result {
info!("Store seems to be fine"); info!("Store seems to be fine");
Ok(())
} else { } else {
warn_exit("Store seems to be broken somehow", 1); Err(err_msg("Store seems to be broken somehow"))
} }
} }