summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2018-11-07 19:49:21 -0500
committerJesse Luehrs <doy@tozt.net>2018-11-07 20:07:14 -0500
commitb18c6b8135bfdc884b0a0cf03196d3de0a343490 (patch)
tree4c3c1e758e73e51557492af22d1e2d774f5b30d2
parent1e1a47061c455a5324d8a62fa9bcee9ecdf9c4cb (diff)
downloadlastfm-query-b18c6b8135bfdc884b0a0cf03196d3de0a343490.tar.gz
lastfm-query-b18c6b8135bfdc884b0a0cf03196d3de0a343490.zip
better top level error handling
-rw-r--r--src/db.rs23
-rw-r--r--src/main.rs46
2 files changed, 59 insertions, 10 deletions
diff --git a/src/db.rs b/src/db.rs
index b291e86..0d81d7e 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -1,6 +1,8 @@
use error::Result;
use lastfm;
+use failure::Fail;
+
const SCHEMA: &'static str = "
CREATE TABLE `tracks` (
artist varchar(1024) NOT NULL,
@@ -17,7 +19,14 @@ pub struct DB {
impl DB {
pub fn new<P: AsRef<std::path::Path>>(path: &P) -> Result<DB> {
let conn = if path.as_ref().exists() {
- rusqlite::Connection::open(path)?
+ rusqlite::Connection::open(path)
+ .map_err(|e| {
+ let msg = format!(
+ "couldn't open db at {}",
+ path.as_ref().display()
+ );
+ e.context(msg)
+ })?
}
else {
Self::create(path)?
@@ -36,8 +45,16 @@ impl DB {
if let Some(parent) = path.as_ref().parent() {
std::fs::create_dir_all(parent)?;
- let conn = rusqlite::Connection::open(path)?;
- conn.execute(SCHEMA, rusqlite::NO_PARAMS)?;
+ let conn = rusqlite::Connection::open(path)
+ .map_err(|e| {
+ let msg = format!(
+ "couldn't create db at {}",
+ path.as_ref().display()
+ );
+ e.context(msg)
+ })?;
+ conn.execute(SCHEMA, rusqlite::NO_PARAMS)
+ .map_err(|e| e.context("failed to execute schema"))?;
Ok(conn)
}
else {
diff --git a/src/main.rs b/src/main.rs
index c4c255e..4d66a92 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,7 @@
#[macro_use]
extern crate clap;
extern crate directories;
+#[macro_use]
extern crate failure;
extern crate indicatif;
extern crate reqwest;
@@ -17,15 +18,14 @@ mod lastfm;
mod paths;
mod db;
-fn main() {
- let opts = cli::get_options();
+use error::Result;
- let db = db::DB::new(&paths::dbpath())
- .expect("failed to create db");
+fn run(opts: cli::Options) -> Result<()> {
+ let db = db::DB::new(&paths::dbpath())?;
let lastfm = lastfm::LastFMClient::new(&opts.api_key, &opts.username);
let exporter = exporter::Exporter::new(&db, &lastfm);
- let to_fetch = exporter.tracks_to_sync().unwrap();
+ let to_fetch = exporter.tracks_to_sync()?;
println!("need to download {} tracks", to_fetch);
let bar = indicatif::ProgressBar::new(to_fetch);
@@ -35,8 +35,40 @@ fn main() {
.template("{percent:>3}% [{wide_bar}] {eta:5}")
);
- exporter.sync(|_| { bar.inc(1); })
- .expect("failed to update db");
+ exporter.sync(|_| { bar.inc(1); })?;
bar.finish_with_message("done");
+
+ Ok(())
+}
+
+fn program_name() -> Result<String> {
+ let program = std::env::args()
+ .next()
+ .ok_or_else(|| format_err!("no program name found"))?;
+ let path = std::path::Path::new(&program);
+ let filename = path.file_name()
+ .ok_or_else(|| format_err!("invalid filename found"))?
+ .to_string_lossy()
+ .to_string();
+ Ok(filename)
+}
+
+fn main() {
+ let opts = cli::get_options();
+ match run(opts) {
+ Ok(_) => {},
+ Err(e) => {
+ let name = program_name()
+ .unwrap_or_else(|e| {
+ eprintln!("{}", e);
+ "?".to_string()
+ });
+ let cause = e
+ .iter_chain()
+ .fold(String::new(), |acc, x| acc + ": " + &format!("{}", x));
+ eprintln!("{}{}", name, cause);
+ std::process::exit(1);
+ }
+ }
}