From f41f45f600ff9b7e0ca4321eb743ab0f99357e9f Mon Sep 17 00:00:00 2001 From: Antoine Gersant Date: Sat, 4 Jan 2020 16:42:28 -0800 Subject: [PATCH] Simplified error boilerplate --- Cargo.lock | 30 +++++++++++- Cargo.toml | 3 +- src/api.rs | 122 ++++++++++++++++++++-------------------------- src/config.rs | 3 +- src/db/mod.rs | 4 +- src/ddns.rs | 40 +++------------ src/errors.rs | 57 ---------------------- src/index.rs | 51 +++++++++---------- src/lastfm.rs | 12 ++--- src/main.rs | 22 ++------- src/metadata.rs | 7 +-- src/playlist.rs | 2 +- src/server.rs | 4 +- src/thumbnails.rs | 2 +- src/user.rs | 5 +- src/utils.rs | 6 +-- src/vfs.rs | 3 +- 17 files changed, 139 insertions(+), 234 deletions(-) delete mode 100644 src/errors.rs diff --git a/Cargo.lock b/Cargo.lock index 08b34b1..3c403fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,11 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "anyhow" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ape" version = "0.2.0" @@ -553,7 +558,6 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1457,12 +1461,12 @@ dependencies = [ name = "polaris" version = "0.11.0" dependencies = [ + "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "ape 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "flame 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "flamer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1486,6 +1490,7 @@ dependencies = [ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "simplelog 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "unix-daemonize 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2195,6 +2200,24 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "thiserror" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "thread-id" version = "3.3.0" @@ -2620,6 +2643,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" "checksum ape 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "890eeb3dc52632a4b762e3ea6ac37475a35577f22fce09bb6e758c2aaf38a229" "checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" @@ -2858,6 +2882,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" +"checksum thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6f357d1814b33bc2dc221243f8424104bfe72dbe911d5b71b3816a2dff1c977e" +"checksum thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2e25d25307eb8436894f727aba8f65d07adf02e5b35a13cebed48bd282bfef" "checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum tiff 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b7c2cfc4742bd8a32f2e614339dd8ce30dbcf676bb262bd63a2327bc5df57d" diff --git a/Cargo.toml b/Cargo.toml index ee0b87b..b32923f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,12 +9,12 @@ ui = [] profile-index = ["flame", "flamer"] [dependencies] +anyhow = "1.0" ape = "0.2.0" app_dirs = "1.1.1" base64 = "0.11.0" diesel = { version = "1.4", features = ["sqlite"] } diesel_migrations = { version = "1.4", features = ["sqlite"] } -error-chain = "0.12.0" flame = { version = "0.2.2", optional = true } flamer = { version = "0.4", optional = true } getopts = "0.2.15" @@ -36,6 +36,7 @@ serde = { version = "1.0", features = ["derive"] } serde_derive = "1.0" serde_json = "1.0" simplelog = "0.7" +thiserror = "1.0" toml = "0.5" [dependencies.rocket_contrib] diff --git a/src/api.rs b/src/api.rs index 4ae9436..635de60 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,4 +1,4 @@ -use error_chain::bail; +use anyhow::*; use rocket::http::{Cookie, Cookies, RawStr, Status}; use rocket::request::{self, FromParam, FromRequest, Request}; use rocket::response::content::Html; @@ -11,10 +11,10 @@ use std::path::PathBuf; use std::str; use std::str::FromStr; use std::sync::Arc; +use thiserror::Error; use crate::config::{self, Config, Preferences}; use crate::db::DB; -use crate::errors; use crate::index; use crate::lastfm; use crate::playlist; @@ -58,6 +58,30 @@ pub fn get_routes() -> Vec { ] } +#[derive(Error, Debug)] +enum APIError { + #[error("Incorrect Credentials")] + IncorrectCredentials, + #[error("Unspecified")] + Unspecified, +} + +impl<'r> rocket::response::Responder<'r> for APIError { + fn respond_to(self, _: &rocket::request::Request<'_>) -> rocket::response::Result<'r> { + let status = match self { + APIError::IncorrectCredentials => rocket::http::Status::Unauthorized, + _ => rocket::http::Status::InternalServerError, + }; + rocket::response::Response::build().status(status).ok() + } +} + +impl From for APIError { + fn from(_: anyhow::Error) -> Self { + APIError::Unspecified + } +} + struct Auth { username: String, } @@ -168,7 +192,7 @@ pub struct InitialSetup { } #[get("/initial_setup")] -fn initial_setup(db: State<'_, Arc>) -> Result, errors::Error> { +fn initial_setup(db: State<'_, Arc>) -> Result> { let initial_setup = InitialSetup { has_any_users: user::count::(&db)? > 0, }; @@ -176,10 +200,7 @@ fn initial_setup(db: State<'_, Arc>) -> Result, errors::E } #[get("/settings")] -fn get_settings( - db: State<'_, Arc>, - _admin_rights: AdminRights, -) -> Result, errors::Error> { +fn get_settings(db: State<'_, Arc>, _admin_rights: AdminRights) -> Result> { let config = config::read::(&db)?; Ok(Json(config)) } @@ -189,13 +210,13 @@ fn put_settings( db: State<'_, Arc>, _admin_rights: AdminRights, config: Json, -) -> Result<(), errors::Error> { +) -> Result<()> { config::amend::(&db, &config)?; Ok(()) } #[get("/preferences")] -fn get_preferences(db: State<'_, Arc>, auth: Auth) -> Result, errors::Error> { +fn get_preferences(db: State<'_, Arc>, auth: Auth) -> Result> { let preferences = config::read_preferences::(&db, &auth.username)?; Ok(Json(preferences)) } @@ -205,7 +226,7 @@ fn put_preferences( db: State<'_, Arc>, auth: Auth, preferences: Json, -) -> Result<(), errors::Error> { +) -> Result<()> { config::write_preferences::(&db, &auth.username, &preferences)?; Ok(()) } @@ -214,7 +235,7 @@ fn put_preferences( fn trigger_index( command_sender: State<'_, Arc>, _admin_rights: AdminRights, -) -> Result<(), errors::Error> { +) -> Result<()> { command_sender.trigger_reindex()?; Ok(()) } @@ -235,9 +256,9 @@ fn auth( db: State<'_, Arc>, credentials: Json, mut cookies: Cookies<'_>, -) -> Result, errors::Error> { +) -> std::result::Result, APIError> { if !user::auth::(&db, &credentials.username, &credentials.password)? { - bail!(errors::ErrorKind::IncorrectCredentials) + return Err(APIError::IncorrectCredentials); } cookies.add_private(get_session_cookie(&credentials.username)); @@ -249,10 +270,7 @@ fn auth( } #[get("/browse")] -fn browse_root( - db: State<'_, Arc>, - _auth: Auth, -) -> Result>, errors::Error> { +fn browse_root(db: State<'_, Arc>, _auth: Auth) -> Result>> { let result = index::browse(db.deref().deref(), &PathBuf::new())?; Ok(Json(result)) } @@ -262,16 +280,13 @@ fn browse( db: State<'_, Arc>, _auth: Auth, path: VFSPathBuf, -) -> Result>, errors::Error> { +) -> Result>> { let result = index::browse(db.deref().deref(), &path.into() as &PathBuf)?; Ok(Json(result)) } #[get("/flatten")] -fn flatten_root( - db: State<'_, Arc>, - _auth: Auth, -) -> Result>, errors::Error> { +fn flatten_root(db: State<'_, Arc>, _auth: Auth) -> Result>> { let result = index::flatten(db.deref().deref(), &PathBuf::new())?; Ok(Json(result)) } @@ -281,34 +296,25 @@ fn flatten( db: State<'_, Arc>, _auth: Auth, path: VFSPathBuf, -) -> Result>, errors::Error> { +) -> Result>> { let result = index::flatten(db.deref().deref(), &path.into() as &PathBuf)?; Ok(Json(result)) } #[get("/random")] -fn random( - db: State<'_, Arc>, - _auth: Auth, -) -> Result>, errors::Error> { +fn random(db: State<'_, Arc>, _auth: Auth) -> Result>> { let result = index::get_random_albums(db.deref().deref(), 20)?; Ok(Json(result)) } #[get("/recent")] -fn recent( - db: State<'_, Arc>, - _auth: Auth, -) -> Result>, errors::Error> { +fn recent(db: State<'_, Arc>, _auth: Auth) -> Result>> { let result = index::get_recent_albums(db.deref().deref(), 20)?; Ok(Json(result)) } #[get("/search")] -fn search_root( - db: State<'_, Arc>, - _auth: Auth, -) -> Result>, errors::Error> { +fn search_root(db: State<'_, Arc>, _auth: Auth) -> Result>> { let result = index::search(db.deref().deref(), "")?; Ok(Json(result)) } @@ -318,7 +324,7 @@ fn search( db: State<'_, Arc>, _auth: Auth, query: String, -) -> Result>, errors::Error> { +) -> Result>> { let result = index::search(db.deref().deref(), &query)?; Ok(Json(result)) } @@ -328,7 +334,7 @@ fn serve( db: State<'_, Arc>, _auth: Auth, path: VFSPathBuf, -) -> Result, errors::Error> { +) -> Result> { let db: &DB = db.deref().deref(); let vfs = db.get_vfs()?; let real_path = vfs.virtual_to_real(&path.into() as &PathBuf)?; @@ -349,10 +355,7 @@ pub struct ListPlaylistsEntry { } #[get("/playlists")] -fn list_playlists( - db: State<'_, Arc>, - auth: Auth, -) -> Result>, errors::Error> { +fn list_playlists(db: State<'_, Arc>, auth: Auth) -> Result>> { let playlist_names = playlist::list_playlists(&auth.username, db.deref().deref())?; let playlists: Vec = playlist_names .into_iter() @@ -373,7 +376,7 @@ fn save_playlist( auth: Auth, name: String, playlist: Json, -) -> Result<(), errors::Error> { +) -> Result<()> { playlist::save_playlist(&name, &auth.username, &playlist.tracks, db.deref().deref())?; Ok(()) } @@ -383,33 +386,25 @@ fn read_playlist( db: State<'_, Arc>, auth: Auth, name: String, -) -> Result>, errors::Error> { +) -> Result>> { let songs = playlist::read_playlist(&name, &auth.username, db.deref().deref())?; Ok(Json(songs)) } #[delete("/playlist/")] -fn delete_playlist(db: State<'_, Arc>, auth: Auth, name: String) -> Result<(), errors::Error> { +fn delete_playlist(db: State<'_, Arc>, auth: Auth, name: String) -> Result<()> { playlist::delete_playlist(&name, &auth.username, db.deref().deref())?; Ok(()) } #[put("/lastfm/now_playing/")] -fn lastfm_now_playing( - db: State<'_, Arc>, - auth: Auth, - path: VFSPathBuf, -) -> Result<(), errors::Error> { +fn lastfm_now_playing(db: State<'_, Arc>, auth: Auth, path: VFSPathBuf) -> Result<()> { lastfm::now_playing(db.deref().deref(), &auth.username, &path.into() as &PathBuf)?; Ok(()) } #[post("/lastfm/scrobble/")] -fn lastfm_scrobble( - db: State<'_, Arc>, - auth: Auth, - path: VFSPathBuf, -) -> Result<(), errors::Error> { +fn lastfm_scrobble(db: State<'_, Arc>, auth: Auth, path: VFSPathBuf) -> Result<()> { lastfm::scrobble(db.deref().deref(), &auth.username, &path.into() as &PathBuf)?; Ok(()) } @@ -420,32 +415,23 @@ fn lastfm_link( auth: Auth, token: String, content: String, -) -> Result, errors::Error> { +) -> Result> { lastfm::link(db.deref().deref(), &auth.username, &token)?; // Percent decode - let base64_content = match RawStr::from_str(&content).percent_decode() { - Ok(s) => s, - Err(_) => bail!(errors::ErrorKind::EncodingError), - }; + let base64_content = RawStr::from_str(&content).percent_decode()?; // Base64 decode - let popup_content = match base64::decode(base64_content.as_bytes()) { - Ok(c) => c, - Err(_) => bail!(errors::ErrorKind::EncodingError), - }; + let popup_content = base64::decode(base64_content.as_bytes())?; // UTF-8 decode - let popup_content_string = match str::from_utf8(&popup_content) { - Ok(s) => s, - Err(_) => bail!(errors::ErrorKind::EncodingError), - }; + let popup_content_string = str::from_utf8(&popup_content)?; Ok(Html(popup_content_string.to_string())) } #[delete("/lastfm/link")] -fn lastfm_unlink(db: State<'_, Arc>, auth: Auth) -> Result<(), errors::Error> { +fn lastfm_unlink(db: State<'_, Arc>, auth: Auth) -> Result<()> { lastfm::unlink(db.deref().deref(), &auth.username)?; Ok(()) } diff --git a/src/config.rs b/src/config.rs index 921debd..4622327 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,7 +1,7 @@ +use anyhow::*; use core::ops::Deref; use diesel; use diesel::prelude::*; -use error_chain::bail; use log::info; use regex::Regex; use serde::{Deserialize, Serialize}; @@ -13,7 +13,6 @@ use toml; use crate::db::ConnectionSource; use crate::db::{ddns_config, misc_settings, mount_points, users}; use crate::ddns::DDNSConfig; -use crate::errors::*; use crate::user::*; use crate::vfs::MountPoint; diff --git a/src/db/mod.rs b/src/db/mod.rs index bc38aa9..17e5ea3 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,14 +1,12 @@ +use anyhow::*; use core::ops::Deref; use diesel::prelude::*; use diesel::sqlite::SqliteConnection; use diesel_migrations; -use error_chain::bail; use log::info; use std::path::Path; use std::sync::{Arc, Mutex, MutexGuard}; -use crate::errors::*; - mod schema; pub use self::schema::*; diff --git a/src/ddns.rs b/src/ddns.rs index 1760048..c5f5e4e 100644 --- a/src/ddns.rs +++ b/src/ddns.rs @@ -1,15 +1,14 @@ +use anyhow::*; use core::ops::Deref; use diesel::prelude::*; use log::{error, info}; use reqwest; use serde::{Deserialize, Serialize}; -use std::io; use std::thread; use std::time; use crate::db::ddns_config; use crate::db::{ConnectionSource, DB}; -use crate::errors; #[derive(Clone, Debug, Deserialize, Insertable, PartialEq, Queryable, Serialize)] #[table_name = "ddns_config"] @@ -20,11 +19,11 @@ pub struct DDNSConfig { } pub trait DDNSConfigSource { - fn get_ddns_config(&self) -> errors::Result; + fn get_ddns_config(&self) -> Result; } impl DDNSConfigSource for DB { - fn get_ddns_config(&self) -> errors::Result { + fn get_ddns_config(&self) -> Result { use self::ddns_config::dsl::*; let connection = self.get_connection(); Ok(ddns_config @@ -33,35 +32,9 @@ impl DDNSConfigSource for DB { } } -#[derive(Debug)] -enum DDNSError { - Internal(errors::Error), - Io(io::Error), - Reqwest(reqwest::Error), - Update(reqwest::StatusCode), -} - -impl From for DDNSError { - fn from(err: io::Error) -> DDNSError { - DDNSError::Io(err) - } -} - -impl From for DDNSError { - fn from(err: errors::Error) -> DDNSError { - DDNSError::Internal(err) - } -} - -impl From for DDNSError { - fn from(err: reqwest::Error) -> DDNSError { - DDNSError::Reqwest(err) - } -} - const DDNS_UPDATE_URL: &str = "https://ydns.io/api/v1/update/"; -fn update_my_ip(config_source: &T) -> Result<(), DDNSError> +fn update_my_ip(config_source: &T) -> Result<()> where T: DDNSConfigSource, { @@ -78,7 +51,10 @@ where .basic_auth(config.username, Some(config.password)) .send()?; if !res.status().is_success() { - return Err(DDNSError::Update(res.status())); + bail!( + "DDNS update query failed with status code: {}", + res.status() + ); } Ok(()) } diff --git a/src/errors.rs b/src/errors.rs deleted file mode 100644 index 1daa77b..0000000 --- a/src/errors.rs +++ /dev/null @@ -1,57 +0,0 @@ -use ape; -use core; -use diesel; -use diesel_migrations; -use error_chain::error_chain; -use getopts; -use id3; -use image; -use lewton; -use metaflac; -use regex; -use rocket; -use rustfm_scrobble; -use serde_json; -use std; -use toml; - -error_chain! { - foreign_links { - Ape(ape::Error); - Diesel(diesel::result::Error); - DieselConnection(diesel::ConnectionError); - DieselMigration(diesel_migrations::RunMigrationsError); - Encoding(core::str::Utf8Error); - Flac(metaflac::Error); - GetOpts(getopts::Fail); - Id3(id3::Error); - Image(image::ImageError); - Io(std::io::Error); - Json(serde_json::Error); - Time(std::time::SystemTimeError); - Toml(toml::de::Error); - Regex(regex::Error); - RocketConfig(rocket::config::ConfigError); - Scrobbler(rustfm_scrobble::ScrobblerError); - Vorbis(lewton::VorbisError); - } - - errors { - DaemonError {} - IncorrectCredentials {} - EncodingError {} - MissingLastFMCredentials {} - } -} - -impl<'r> rocket::response::Responder<'r> for Error { - fn respond_to(self, _: &rocket::request::Request<'_>) -> rocket::response::Result<'r> { - let mut build = rocket::response::Response::build(); - build - .status(match self.0 { - ErrorKind::IncorrectCredentials => rocket::http::Status::Unauthorized, - _ => rocket::http::Status::InternalServerError, - }) - .ok() - } -} diff --git a/src/index.rs b/src/index.rs index d8d5835..d41cc98 100644 --- a/src/index.rs +++ b/src/index.rs @@ -1,10 +1,10 @@ +use anyhow::*; use core::ops::Deref; use diesel; use diesel::dsl::sql; use diesel::prelude::*; use diesel::sql_types; use diesel::sqlite::SqliteConnection; -use error_chain::bail; #[cfg(feature = "profile-index")] use flame; use log::{error, info}; @@ -24,7 +24,6 @@ use crate::config::MiscSettings; use crate::db; use crate::db::{directories, misc_settings, songs}; use crate::db::{ConnectionSource, DB}; -use crate::errors; use crate::metadata; use crate::vfs::{VFSSource, VFS}; @@ -63,7 +62,7 @@ impl CommandSender { } } - pub fn trigger_reindex(&self) -> Result<(), errors::Error> { + pub fn trigger_reindex(&self) -> Result<()> { let sender = self.sender.lock().unwrap(); match sender.send(Command::REINDEX) { Ok(_) => Ok(()), @@ -72,7 +71,7 @@ impl CommandSender { } #[allow(dead_code)] - pub fn exit(&self) -> Result<(), errors::Error> { + pub fn exit(&self) -> Result<()> { let sender = self.sender.lock().unwrap(); match sender.send(Command::EXIT) { Ok(_) => Ok(()), @@ -175,7 +174,7 @@ impl<'conn> IndexBuilder<'conn> { fn new( connection: &Mutex, album_art_pattern: Regex, - ) -> Result, errors::Error> { + ) -> Result> { let mut new_songs = Vec::new(); let mut new_directories = Vec::new(); new_songs.reserve_exact(INDEX_BUILDING_INSERT_BUFFER_SIZE); @@ -189,10 +188,10 @@ impl<'conn> IndexBuilder<'conn> { } #[cfg_attr(feature = "profile-index", flame)] - fn flush_songs(&mut self) -> Result<(), errors::Error> { + fn flush_songs(&mut self) -> Result<()> { let connection = self.connection.lock().unwrap(); let connection = connection.deref(); - connection.transaction::<_, errors::Error, _>(|| { + connection.transaction::<_, anyhow::Error, _>(|| { diesel::insert_into(songs::table) .values(&self.new_songs) .execute(connection)?; @@ -203,10 +202,10 @@ impl<'conn> IndexBuilder<'conn> { } #[cfg_attr(feature = "profile-index", flame)] - fn flush_directories(&mut self) -> Result<(), errors::Error> { + fn flush_directories(&mut self) -> Result<()> { let connection = self.connection.lock().unwrap(); let connection = connection.deref(); - connection.transaction::<_, errors::Error, _>(|| { + connection.transaction::<_, anyhow::Error, _>(|| { diesel::insert_into(directories::table) .values(&self.new_directories) .execute(connection)?; @@ -217,7 +216,7 @@ impl<'conn> IndexBuilder<'conn> { } #[cfg_attr(feature = "profile-index", flame)] - fn push_song(&mut self, song: NewSong) -> Result<(), errors::Error> { + fn push_song(&mut self, song: NewSong) -> Result<()> { if self.new_songs.len() >= self.new_songs.capacity() { self.flush_songs()?; } @@ -226,7 +225,7 @@ impl<'conn> IndexBuilder<'conn> { } #[cfg_attr(feature = "profile-index", flame)] - fn push_directory(&mut self, directory: NewDirectory) -> Result<(), errors::Error> { + fn push_directory(&mut self, directory: NewDirectory) -> Result<()> { if self.new_directories.len() >= self.new_directories.capacity() { self.flush_directories()?; } @@ -234,7 +233,7 @@ impl<'conn> IndexBuilder<'conn> { Ok(()) } - fn get_artwork(&self, dir: &Path) -> Result, errors::Error> { + fn get_artwork(&self, dir: &Path) -> Result> { for file in fs::read_dir(dir)? { let file = file?; if let Some(name_string) = file.file_name().to_str() { @@ -247,17 +246,13 @@ impl<'conn> IndexBuilder<'conn> { } #[cfg_attr(feature = "profile-index", flame)] - fn populate_directory( - &mut self, - parent: Option<&Path>, - path: &Path, - ) -> Result<(), errors::Error> { + fn populate_directory(&mut self, parent: Option<&Path>, path: &Path) -> Result<()> { // Find artwork let artwork = self.get_artwork(path).unwrap_or(None); // Extract path and parent path let parent_string = parent.and_then(|p| p.to_str()).map(|s| s.to_owned()); - let path_string = path.to_str().ok_or("Invalid directory path")?; + let path_string = path.to_str().ok_or(anyhow!("Invalid directory path"))?; // Find date added let metadata = fs::metadata(path_string)?; @@ -369,7 +364,7 @@ impl<'conn> IndexBuilder<'conn> { } #[cfg_attr(feature = "profile-index", flame)] -fn clean(db: &T) -> Result<(), errors::Error> +fn clean(db: &T) -> Result<()> where T: ConnectionSource + VFSSource, { @@ -429,7 +424,7 @@ where } #[cfg_attr(feature = "profile-index", flame)] -fn populate(db: &T) -> Result<(), errors::Error> +fn populate(db: &T) -> Result<()> where T: ConnectionSource + VFSSource, { @@ -453,7 +448,7 @@ where Ok(()) } -pub fn update(db: &T) -> Result<(), errors::Error> +pub fn update(db: &T) -> Result<()> where T: ConnectionSource + VFSSource, { @@ -512,7 +507,7 @@ where let sleep_duration; { let connection = db.get_connection(); - let settings: Result = misc_settings::table + let settings: Result = misc_settings::table .get_result(connection.deref()) .map_err(|e| e.into()); if let Err(ref e) = settings { @@ -556,7 +551,7 @@ fn virtualize_directory(vfs: &VFS, mut directory: Directory) -> Option(db: &T, virtual_path: P) -> Result, errors::Error> +pub fn browse(db: &T, virtual_path: P) -> Result> where T: ConnectionSource + VFSSource, P: AsRef, @@ -601,7 +596,7 @@ where Ok(output) } -pub fn flatten(db: &T, virtual_path: P) -> Result, errors::Error> +pub fn flatten(db: &T, virtual_path: P) -> Result> where T: ConnectionSource + VFSSource, P: AsRef, @@ -627,7 +622,7 @@ where Ok(virtual_songs.collect::>()) } -pub fn get_random_albums(db: &T, count: i64) -> Result, errors::Error> +pub fn get_random_albums(db: &T, count: i64) -> Result> where T: ConnectionSource + VFSSource, { @@ -645,7 +640,7 @@ where Ok(virtual_directories.collect::>()) } -pub fn get_recent_albums(db: &T, count: i64) -> Result, errors::Error> +pub fn get_recent_albums(db: &T, count: i64) -> Result> where T: ConnectionSource + VFSSource, { @@ -663,7 +658,7 @@ where Ok(virtual_directories.collect::>()) } -pub fn search(db: &T, query: &str) -> Result, errors::Error> +pub fn search(db: &T, query: &str) -> Result> where T: ConnectionSource + VFSSource, { @@ -711,7 +706,7 @@ where Ok(output) } -pub fn get_song(db: &T, virtual_path: &Path) -> Result +pub fn get_song(db: &T, virtual_path: &Path) -> Result where T: ConnectionSource + VFSSource, { diff --git a/src/lastfm.rs b/src/lastfm.rs index eea9701..843e8a6 100644 --- a/src/lastfm.rs +++ b/src/lastfm.rs @@ -1,9 +1,9 @@ +use anyhow::*; use rustfm_scrobble::{Scrobble, Scrobbler}; use serde::Deserialize; use std::path::Path; use crate::db::ConnectionSource; -use crate::errors; use crate::index; use crate::user; use crate::vfs::VFSSource; @@ -42,7 +42,7 @@ struct AuthResponse { pub session: AuthResponseSession, } -fn scrobble_from_path(db: &T, track: &Path) -> Result +fn scrobble_from_path(db: &T, track: &Path) -> Result where T: ConnectionSource + VFSSource, { @@ -54,7 +54,7 @@ where )) } -pub fn link(db: &T, username: &str, token: &str) -> Result<(), errors::Error> +pub fn link(db: &T, username: &str, token: &str) -> Result<()> where T: ConnectionSource + VFSSource, { @@ -64,14 +64,14 @@ where user::lastfm_link(db, username, &auth_response.name, &auth_response.key) } -pub fn unlink(db: &T, username: &str) -> Result<(), errors::Error> +pub fn unlink(db: &T, username: &str) -> Result<()> where T: ConnectionSource + VFSSource, { user::lastfm_unlink(db, username) } -pub fn scrobble(db: &T, username: &str, track: &Path) -> Result<(), errors::Error> +pub fn scrobble(db: &T, username: &str, track: &Path) -> Result<()> where T: ConnectionSource + VFSSource, { @@ -83,7 +83,7 @@ where Ok(()) } -pub fn now_playing(db: &T, username: &str, track: &Path) -> Result<(), errors::Error> +pub fn now_playing(db: &T, username: &str, track: &Path) -> Result<()> where T: ConnectionSource + VFSSource, { diff --git a/src/main.rs b/src/main.rs index 07d989d..18b7d7c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,9 +20,8 @@ use std::io::prelude::*; #[cfg(unix)] use unix_daemonize::{daemonize_redirect, ChdirMode}; -use crate::errors::*; +use anyhow::*; use core::ops::Deref; -use error_chain::bail; use getopts::Options; use log::info; use simplelog::{LevelFilter, SimpleLogger, TermLogger, TerminalMode}; @@ -35,7 +34,6 @@ mod api_tests; mod config; mod db; mod ddns; -mod errors; mod index; mod lastfm; mod metadata; @@ -58,20 +56,6 @@ fn log_config() -> simplelog::Config { .build() } -fn main() { - if let Err(ref e) = run() { - println!("Error: {}", e); - - for e in e.iter().skip(1) { - println!("caused by: {}", e); - } - if let Some(backtrace) = e.backtrace() { - println!("backtrace: {:?}", backtrace); - } - ::std::process::exit(1); - } -} - #[cfg(unix)] fn daemonize(options: &getopts::Matches) -> Result<()> { if options.opt_present("f") { @@ -128,7 +112,7 @@ fn notify_ready() { #[cfg(not(unix))] fn notify_ready() {} -fn run() -> Result<()> { +fn main() -> Result<()> { // Parse CLI options let args: Vec = std::env::args().collect(); let mut options = Options::new(); @@ -241,7 +225,7 @@ fn run() -> Result<()> { .opt_str("p") .unwrap_or_else(|| "5050".to_owned()) .parse() - .or(Err("invalid port number"))?; + .with_context(|| "Invalid port number")?; let server = server::get_server( port, diff --git a/src/metadata.rs b/src/metadata.rs index 65e3bcd..033530a 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -1,5 +1,5 @@ +use anyhow::*; use ape; -use error_chain::bail; use id3; use lewton::inside_ogg::OggStreamReader; use metaflac; @@ -8,7 +8,6 @@ use regex::Regex; use std::fs; use std::path::Path; -use crate::errors::*; use crate::utils; use crate::utils::AudioFormat; @@ -151,7 +150,9 @@ fn read_vorbis(path: &Path) -> Result { #[cfg_attr(feature = "profile-index", flame)] fn read_flac(path: &Path) -> Result { let tag = metaflac::Tag::read_from_path(path)?; - let vorbis = tag.vorbis_comments().ok_or("Missing Vorbis comments")?; + let vorbis = tag + .vorbis_comments() + .ok_or(anyhow!("Missing Vorbis comments"))?; let disc_number = vorbis .get("DISCNUMBER") .and_then(|d| d[0].parse::().ok()); diff --git a/src/playlist.rs b/src/playlist.rs index 8411c3a..5d66843 100644 --- a/src/playlist.rs +++ b/src/playlist.rs @@ -1,3 +1,4 @@ +use anyhow::*; use core::clone::Clone; use core::ops::Deref; use diesel; @@ -10,7 +11,6 @@ use std::path::Path; use crate::db; use crate::db::ConnectionSource; use crate::db::{playlist_songs, playlists, users}; -use crate::errors::*; use crate::index::{self, Song}; use crate::vfs::VFSSource; diff --git a/src/server.rs b/src/server.rs index 6113d43..adbf35a 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,10 +1,10 @@ +use anyhow::*; use rocket; use rocket_contrib::serve::StaticFiles; use std::path::PathBuf; use std::sync::Arc; use crate::db::DB; -use crate::errors; use crate::index::CommandSender; pub fn get_server( @@ -17,7 +17,7 @@ pub fn get_server( swagger_dir_path: &PathBuf, db: Arc, command_sender: Arc, -) -> Result { +) -> Result { let mut config = rocket::Config::build(rocket::config::Environment::Production) .port(port) .keep_alive(0) diff --git a/src/thumbnails.rs b/src/thumbnails.rs index 48d0d82..1ec32b1 100644 --- a/src/thumbnails.rs +++ b/src/thumbnails.rs @@ -1,3 +1,4 @@ +use anyhow::*; use image; use image::DynamicImage; use image::FilterType; @@ -11,7 +12,6 @@ use std::fs::{DirBuilder, File}; use std::hash::{Hash, Hasher}; use std::path::*; -use crate::errors::*; use crate::utils; const THUMBNAILS_PATH: &str = "thumbnails"; diff --git a/src/user.rs b/src/user.rs index 306abd5..f3b90ed 100644 --- a/src/user.rs +++ b/src/user.rs @@ -1,11 +1,10 @@ +use anyhow::*; use core::ops::Deref; use diesel; use diesel::prelude::*; -use error_chain::bail; use crate::db::users; use crate::db::ConnectionSource; -use crate::errors::*; #[derive(Debug, Insertable, Queryable)] #[table_name = "users"] @@ -109,7 +108,7 @@ where .get_result(connection.deref())?; match token { Some(t) => Ok(t), - _ => bail!(ErrorKind::MissingLastFMCredentials), + _ => Err(anyhow!("Missing LastFM credentials")), } } diff --git a/src/utils.rs b/src/utils.rs index f6abe49..813cd2f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,10 +1,8 @@ +use anyhow::*; use app_dirs::{app_root, AppDataType, AppInfo}; -use error_chain::bail; use std::fs; use std::path::{Path, PathBuf}; -use crate::errors::*; - #[cfg(not(target_os = "linux"))] const APP_INFO: AppInfo = AppInfo { name: "Polaris", @@ -19,7 +17,7 @@ const APP_INFO: AppInfo = AppInfo { pub fn get_data_root() -> Result { if let Ok(root) = app_root(AppDataType::UserData, &APP_INFO) { - fs::create_dir_all(&root).chain_err(|| format!("opening user data: {}", root.display()))?; + fs::create_dir_all(&root)?; return Ok(root); } bail!("Could not retrieve data directory root"); diff --git a/src/vfs.rs b/src/vfs.rs index 8c6adf7..44f8584 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -1,6 +1,6 @@ +use anyhow::*; use core::ops::Deref; use diesel::prelude::*; -use error_chain::bail; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::Path; @@ -8,7 +8,6 @@ use std::path::PathBuf; use crate::db::mount_points; use crate::db::{ConnectionSource, DB}; -use crate::errors::*; pub trait VFSSource { fn get_vfs(&self) -> Result;