Transform imag-bookmark to not call exit() but propagate errors to main()
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
parent
b6facfff6b
commit
641c6c7761
2 changed files with 79 additions and 108 deletions
|
@ -24,6 +24,7 @@ log = "0.4.6"
|
||||||
toml = "0.5.1"
|
toml = "0.5.1"
|
||||||
toml-query = "0.9.2"
|
toml-query = "0.9.2"
|
||||||
failure = "0.1.5"
|
failure = "0.1.5"
|
||||||
|
resiter = "0.4.0"
|
||||||
|
|
||||||
libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }
|
libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }
|
||||||
libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" }
|
libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" }
|
||||||
|
|
|
@ -39,6 +39,7 @@ extern crate clap;
|
||||||
extern crate toml;
|
extern crate toml;
|
||||||
extern crate toml_query;
|
extern crate toml_query;
|
||||||
#[macro_use] extern crate failure;
|
#[macro_use] extern crate failure;
|
||||||
|
extern crate resiter;
|
||||||
|
|
||||||
extern crate libimagbookmark;
|
extern crate libimagbookmark;
|
||||||
extern crate libimagrt;
|
extern crate libimagrt;
|
||||||
|
@ -47,12 +48,13 @@ extern crate libimagutil;
|
||||||
extern crate libimagentrylink;
|
extern crate libimagentrylink;
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::exit;
|
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
use toml_query::read::TomlValueReadTypeExt;
|
use toml_query::read::TomlValueReadTypeExt;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use failure::err_msg;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use resiter::AndThen;
|
||||||
use clap::App;
|
use clap::App;
|
||||||
|
|
||||||
use libimagrt::runtime::Runtime;
|
use libimagrt::runtime::Runtime;
|
||||||
|
@ -60,10 +62,6 @@ use libimagrt::application::ImagApplication;
|
||||||
use libimagbookmark::collection::BookmarkCollection;
|
use libimagbookmark::collection::BookmarkCollection;
|
||||||
use libimagbookmark::collection::BookmarkCollectionStore;
|
use libimagbookmark::collection::BookmarkCollectionStore;
|
||||||
use libimagbookmark::link::Link as BookmarkLink;
|
use libimagbookmark::link::Link as BookmarkLink;
|
||||||
use libimagerror::trace::{MapErrTrace, trace_error};
|
|
||||||
use libimagerror::io::ToExitCode;
|
|
||||||
use libimagerror::exit::ExitUnwrap;
|
|
||||||
use libimagutil::debug_result::DebugResult;
|
|
||||||
use libimagentrylink::linkable::Linkable;
|
use libimagentrylink::linkable::Linkable;
|
||||||
|
|
||||||
mod ui;
|
mod ui;
|
||||||
|
@ -75,24 +73,20 @@ mod ui;
|
||||||
pub enum ImagBookmark {}
|
pub enum ImagBookmark {}
|
||||||
impl ImagApplication for ImagBookmark {
|
impl ImagApplication for ImagBookmark {
|
||||||
fn run(rt: Runtime) -> Result<()> {
|
fn run(rt: Runtime) -> Result<()> {
|
||||||
if let Some(name) = rt.cli().subcommand_name() {
|
match rt.cli().subcommand_name().ok_or_else(|| err_msg("No subcommand called"))? {
|
||||||
debug!("Call {}", name);
|
"add" => add(&rt),
|
||||||
match name {
|
"collection" => collection(&rt),
|
||||||
"add" => add(&rt),
|
"list" => list(&rt),
|
||||||
"collection" => collection(&rt),
|
"remove" => remove(&rt),
|
||||||
"list" => list(&rt),
|
other => {
|
||||||
"remove" => remove(&rt),
|
debug!("Unknown command");
|
||||||
other => {
|
if rt.handle_unknown_subcommand("imag-bookmark", other, rt.cli())?.success() {
|
||||||
debug!("Unknown command");
|
Ok(())
|
||||||
let _ = rt.handle_unknown_subcommand("imag-bookmark", other, rt.cli())
|
} else {
|
||||||
.map_err_trace_exit_unwrap()
|
Err(err_msg("Failed to handle unknown subcommand"))
|
||||||
.code()
|
}
|
||||||
.map(::std::process::exit);
|
},
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
|
fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
|
||||||
|
@ -112,131 +106,107 @@ impl ImagApplication for ImagBookmark {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(rt: &Runtime) {
|
fn add(rt: &Runtime) -> Result<()> {
|
||||||
let scmd = rt.cli().subcommand_matches("add").unwrap();
|
let scmd = rt.cli().subcommand_matches("add").unwrap();
|
||||||
let coll = get_collection_name(rt, "add", "collection");
|
let coll = get_collection_name(rt, "add", "collection")?;
|
||||||
|
|
||||||
let mut collection = BookmarkCollectionStore::get(rt.store(), &coll)
|
let mut collection = BookmarkCollectionStore::get(rt.store(), &coll)?
|
||||||
.map_err_trace_exit_unwrap()
|
.ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))?;
|
||||||
.ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))
|
|
||||||
.map_err_trace_exit_unwrap();
|
|
||||||
|
|
||||||
rt.report_touched(collection.get_location()).unwrap_or_exit();
|
rt.report_touched(collection.get_location())?;
|
||||||
|
|
||||||
for url in scmd.values_of("urls").unwrap() { // unwrap saved by clap
|
scmd.values_of("urls")
|
||||||
let new_ids = BookmarkCollection::add_link(collection.deref_mut(), rt.store(), BookmarkLink::from(url))
|
.unwrap()
|
||||||
.map_err_trace_exit_unwrap();
|
.into_iter()
|
||||||
|
.map(|url| {
|
||||||
rt.report_all_touched(new_ids.into_iter()).unwrap_or_exit();
|
let new_ids = BookmarkCollection::add_link(collection.deref_mut(), rt.store(), BookmarkLink::from(url))?;
|
||||||
}
|
rt.report_all_touched(new_ids.into_iter()).map_err(Error::from)
|
||||||
|
})
|
||||||
info!("Ready");
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collection(rt: &Runtime) {
|
fn collection(rt: &Runtime) -> Result<()> {
|
||||||
let scmd = rt.cli().subcommand_matches("collection").unwrap();
|
let scmd = rt.cli().subcommand_matches("collection").unwrap();
|
||||||
|
|
||||||
if scmd.is_present("add") { // adding a new collection
|
if scmd.is_present("add") { // adding a new collection
|
||||||
let name = scmd.value_of("add").unwrap();
|
let name = scmd.value_of("add").unwrap();
|
||||||
if let Ok(id) = BookmarkCollectionStore::new(rt.store(), &name) {
|
let id = BookmarkCollectionStore::new(rt.store(), &name)?;
|
||||||
rt.report_touched(id.get_location()).unwrap_or_exit();
|
rt.report_touched(id.get_location())?;
|
||||||
info!("Created: {}", name);
|
info!("Created: {}", name);
|
||||||
} else {
|
|
||||||
warn!("Creating collection {} failed", name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if scmd.is_present("remove") { // remove a collection
|
if scmd.is_present("remove") { // remove a collection
|
||||||
let name = scmd.value_of("remove").unwrap();
|
let name = scmd.value_of("remove").unwrap();
|
||||||
|
|
||||||
{ // remove all links
|
{ // remove all links
|
||||||
BookmarkCollectionStore::get(rt.store(), &name)
|
BookmarkCollectionStore::get(rt.store(), &name)?
|
||||||
.map_err_trace_exit_unwrap()
|
.ok_or_else(|| format_err!("Collection does not exist: {}", name))?
|
||||||
.ok_or_else(|| format_err!("Collection does not exist: {}", name))
|
.unlink(rt.store())?;
|
||||||
.map_err_trace_exit_unwrap()
|
|
||||||
.unlink(rt.store())
|
|
||||||
.map_err_trace_exit_unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if BookmarkCollectionStore::delete(rt.store(), &name).is_ok() {
|
BookmarkCollectionStore::delete(rt.store(), &name)?;
|
||||||
info!("Deleted: {}", name);
|
info!("Deleted: {}", name);
|
||||||
} else {
|
|
||||||
warn!("Deleting collection {} failed", name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list(rt: &Runtime) {
|
fn list(rt: &Runtime) -> Result<()> {
|
||||||
let coll = get_collection_name(rt, "list", "collection");
|
let coll = get_collection_name(rt, "list", "collection")?;
|
||||||
|
|
||||||
let collection = BookmarkCollectionStore::get(rt.store(), &coll)
|
let collection = BookmarkCollectionStore::get(rt.store(), &coll)?
|
||||||
.map_err_trace_exit_unwrap()
|
.ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))?;
|
||||||
.ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))
|
|
||||||
.map_err_trace_exit_unwrap();
|
|
||||||
|
|
||||||
rt.report_touched(collection.get_location()).unwrap_or_exit();
|
rt.report_touched(collection.get_location())?;
|
||||||
|
|
||||||
|
let mut i = 0; // poor mans enumerate()
|
||||||
|
|
||||||
collection
|
collection
|
||||||
.get_links(rt.store())
|
.get_links(rt.store())?
|
||||||
.map_dbg_str("Listing...")
|
.and_then_ok(|link| {
|
||||||
.map_err_trace_exit_unwrap()
|
let r = writeln!(rt.stdout(), "{: >3}: {}", i, link).map_err(Error::from);
|
||||||
.enumerate()
|
i += 1;
|
||||||
.for_each(|(i, link)| match link {
|
r
|
||||||
Ok(link) => writeln!(rt.stdout(), "{: >3}: {}", i, link).to_exit_code().unwrap_or_exit(),
|
})
|
||||||
Err(e) => trace_error(&e)
|
.collect()
|
||||||
});
|
|
||||||
debug!("... ready with listing");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove(rt: &Runtime) {
|
fn remove(rt: &Runtime) -> Result<()> {
|
||||||
let scmd = rt.cli().subcommand_matches("remove").unwrap();
|
let scmd = rt.cli().subcommand_matches("remove").unwrap();
|
||||||
let coll = get_collection_name(rt, "list", "collection");
|
let coll = get_collection_name(rt, "list", "collection")?;
|
||||||
|
|
||||||
let mut collection = BookmarkCollectionStore::get(rt.store(), &coll)
|
let mut collection = BookmarkCollectionStore::get(rt.store(), &coll)?
|
||||||
.map_err_trace_exit_unwrap()
|
.ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))?;
|
||||||
.ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))
|
|
||||||
.map_err_trace_exit_unwrap();
|
|
||||||
|
|
||||||
rt.report_touched(collection.get_location()).unwrap_or_exit();
|
rt.report_touched(collection.get_location())?;
|
||||||
|
|
||||||
for url in scmd.values_of("urls").unwrap() { // enforced by clap
|
scmd.values_of("urls")
|
||||||
let removed_links = BookmarkCollection::remove_link(collection.deref_mut(), rt.store(), BookmarkLink::from(url))
|
.unwrap()
|
||||||
.map_err_trace_exit_unwrap();
|
.into_iter()
|
||||||
|
.map(|url| {
|
||||||
rt.report_all_touched(removed_links.into_iter()).unwrap_or_exit();
|
let removed_links = BookmarkCollection::remove_link(collection.deref_mut(), rt.store(), BookmarkLink::from(url))?;
|
||||||
}
|
rt.report_all_touched(removed_links.into_iter()).map_err(Error::from)
|
||||||
|
})
|
||||||
info!("Ready");
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn get_collection_name(rt: &Runtime,
|
fn get_collection_name(rt: &Runtime,
|
||||||
subcommand_name: &str,
|
subcommand_name: &str,
|
||||||
collection_argument_name: &str)
|
collection_argument_name: &str)
|
||||||
-> String
|
-> Result<String>
|
||||||
{
|
{
|
||||||
rt.cli()
|
if let Some(cn) = rt.cli()
|
||||||
.subcommand_matches(subcommand_name)
|
.subcommand_matches(subcommand_name)
|
||||||
.and_then(|scmd| scmd.value_of(collection_argument_name).map(String::from))
|
.and_then(|scmd| scmd.value_of(collection_argument_name).map(String::from))
|
||||||
.unwrap_or_else(|| {
|
{
|
||||||
rt.config()
|
return Ok(cn)
|
||||||
.map(|cfg| {
|
} else {
|
||||||
cfg.read_string("bookmark.default_collection")
|
rt.config().ok_or_else(|| err_msg("No configuration availablew"))
|
||||||
.map_err(Error::from)
|
.and_then(|cfg| {
|
||||||
.map_err_trace_exit_unwrap()
|
cfg.read_string("bookmark.default_collection")?
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| err_msg("Missing config: 'bookmark.default_collection'."))
|
||||||
error!("Missing config: 'bookmark.default_collection'. Set or use commandline to specify.");
|
})
|
||||||
exit(1)
|
}
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
error!("Failed to read configuration");
|
|
||||||
exit(1)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue