From 8dc9ff69785240af08f564102057db7e6090d84c Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 11 Jan 2024 22:40:43 +0100 Subject: [PATCH 1/3] Enable running without library or database --- src/bin/musichoard-edit.rs | 2 +- src/lib.rs | 61 ++++++++++++----------------------- src/main.rs | 66 +++++++++++++++++++++++--------------- 3 files changed, 61 insertions(+), 68 deletions(-) diff --git a/src/bin/musichoard-edit.rs b/src/bin/musichoard-edit.rs index 5d20230..9173ff7 100644 --- a/src/bin/musichoard-edit.rs +++ b/src/bin/musichoard-edit.rs @@ -16,7 +16,7 @@ type MH = MusicHoard>; struct Opt { #[structopt( long = "database", - name = "database file path", + help = "Database file path", default_value = "database.json" )] database_file_path: PathBuf, diff --git a/src/lib.rs b/src/lib.rs index 0c6d87c..47c152c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -788,45 +788,34 @@ impl MusicHoard { } pub fn rescan_library(&mut self) -> Result<(), Error> { - match self.library { - Some(ref mut library) => { - let items = library.list(&Query::new())?; - let mut library_collection = Self::items_to_artists(items); - Self::sort(&mut library_collection); + if let Some(ref mut library) = self.library { + let items = library.list(&Query::new())?; + let mut library_collection = Self::items_to_artists(items); + Self::sort(&mut library_collection); - let collection = mem::take(&mut self.collection); - self.collection = Self::merge(library_collection, collection); - - Ok(()) - } - None => Err(Error::LibraryError(String::from("library not provided"))), + let collection = mem::take(&mut self.collection); + self.collection = Self::merge(library_collection, collection); } + Ok(()) } pub fn load_from_database(&mut self) -> Result<(), Error> { - match self.database { - Some(ref mut database) => { - let mut database_collection: Collection = vec![]; - database.load(&mut database_collection)?; - Self::sort(&mut database_collection); + if let Some(ref mut database) = self.database { + let mut database_collection: Collection = vec![]; + database.load(&mut database_collection)?; + Self::sort(&mut database_collection); - let collection = mem::take(&mut self.collection); - self.collection = Self::merge(collection, database_collection); - - Ok(()) - } - None => Err(Error::DatabaseError(String::from("database not provided"))), + let collection = mem::take(&mut self.collection); + self.collection = Self::merge(collection, database_collection); } + Ok(()) } pub fn save_to_database(&mut self) -> Result<(), Error> { - match self.database { - Some(ref mut database) => { - database.save(&self.collection)?; - Ok(()) - } - None => Err(Error::DatabaseError(String::from("database not provided"))), + if let Some(ref mut database) = self.database { + database.save(&self.collection)?; } + Ok(()) } pub fn add_artist>(&mut self, artist_id: ID) { @@ -1963,10 +1952,7 @@ mod tests { let database = Some(MockIDatabase::new()); let mut music_hoard = MusicHoard::new(library, database); - let actual_err = music_hoard.rescan_library().unwrap_err(); - let expected_err = Error::LibraryError(String::from("library not provided")); - - assert_eq!(actual_err, expected_err); + assert!(music_hoard.rescan_library().is_ok()); } #[test] @@ -1997,15 +1983,8 @@ mod tests { let database: Option = None; let mut music_hoard = MusicHoard::new(library, database); - let expected_err = Error::DatabaseError(String::from("database not provided")); - - let actual_err = music_hoard.load_from_database().unwrap_err(); - assert_eq!(actual_err, expected_err); - assert_eq!(actual_err.to_string(), expected_err.to_string()); - - let actual_err = music_hoard.save_to_database().unwrap_err(); - assert_eq!(actual_err, expected_err); - assert_eq!(actual_err.to_string(), expected_err.to_string()); + assert!(music_hoard.load_from_database().is_ok()); + assert!(music_hoard.save_to_database().is_ok()); } #[test] diff --git a/src/main.rs b/src/main.rs index ac7ecd4..44d4fc0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use std::{ffi::OsString, io}; use musichoard::Collection; +use musichoard::library::NoLibrary; use ratatui::{backend::CrosstermBackend, Terminal}; use structopt::StructOpt; @@ -27,22 +28,28 @@ use tui::{event::EventChannel, handler::EventHandler, listener::EventListener, T #[derive(StructOpt)] struct Opt { - #[structopt(long = "ssh", name = "beets SSH URI")] + #[structopt(long = "ssh", help = "Beets SSH URI")] beets_ssh_uri: Option, - #[structopt(long = "beets", name = "beets config file path")] + #[structopt(long = "beets", help = "Beets config file path")] beets_config_file_path: Option, + #[structopt(long = "no-library", help = "Do not connect to the library")] + no_library: bool, + #[structopt( long = "database", - name = "database file path", + help = "Database file path", default_value = "database.json" )] database_file_path: PathBuf, + + #[structopt(long = "no-database", help = "Do not read from/write to the database")] + no_database: bool, } -fn with(lib: LIB, db: DB) { - let music_hoard = MusicHoard::new(Some(lib), Some(db)); +fn with(lib: Option, db: Option) { + let music_hoard = MusicHoard::new(lib, db); // Initialize the terminal user interface. let backend = CrosstermBackend::new(io::stdout()); @@ -61,27 +68,34 @@ fn with(lib: LIB, db: DB) { fn main() { let opt = Opt::from_args(); - // Create an empty database file if it does not exist. - match OpenOptions::new() - .write(true) - .create_new(true) - .open(&opt.database_file_path) - { - Ok(f) => { - drop(f); - JsonDatabase::new(JsonDatabaseFileBackend::new(&opt.database_file_path)) - .save::(&vec![]) - .expect("failed to create empty database"); + let db = if opt.no_database { + None + } else { + // Create an empty database file if it does not exist. + match OpenOptions::new() + .write(true) + .create_new(true) + .open(&opt.database_file_path) + { + Ok(f) => { + drop(f); + JsonDatabase::new(JsonDatabaseFileBackend::new(&opt.database_file_path)) + .save::(&vec![]) + .expect("failed to create empty database"); + } + Err(e) => match e.kind() { + io::ErrorKind::AlreadyExists => {} + _ => panic!("failed to access database file"), + }, } - Err(e) => match e.kind() { - io::ErrorKind::AlreadyExists => {} - _ => panic!("failed to access database file"), - }, - } - // Create the application. - let db_exec = JsonDatabaseFileBackend::new(&opt.database_file_path); - if let Some(uri) = opt.beets_ssh_uri { + let db_exec = JsonDatabaseFileBackend::new(&opt.database_file_path); + Some(JsonDatabase::new(db_exec)) + }; + + if opt.no_library { + with(None::, db); + } else if let Some(uri) = opt.beets_ssh_uri { let uri = uri.into_string().expect("invalid SSH URI"); let beets_config_file_path = opt .beets_config_file_path @@ -91,10 +105,10 @@ fn main() { let lib_exec = BeetsLibrarySshExecutor::new(uri) .expect("failed to initialise beets") .config(beets_config_file_path); - with(BeetsLibrary::new(lib_exec), JsonDatabase::new(db_exec)); + with(Some(BeetsLibrary::new(lib_exec)), db); } else { let lib_exec = BeetsLibraryProcessExecutor::default().config(opt.beets_config_file_path); - with(BeetsLibrary::new(lib_exec), JsonDatabase::new(db_exec)); + with(Some(BeetsLibrary::new(lib_exec)), db); } } -- 2.45.2 From 45844e448fce1fbf007884cea48b31ca006f12c5 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 11 Jan 2024 22:41:19 +0100 Subject: [PATCH 2/3] Formatting --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 44d4fc0..f4b1e08 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,8 +2,8 @@ use std::fs::OpenOptions; use std::path::PathBuf; use std::{ffi::OsString, io}; -use musichoard::Collection; use musichoard::library::NoLibrary; +use musichoard::Collection; use ratatui::{backend::CrosstermBackend, Terminal}; use structopt::StructOpt; -- 2.45.2 From a192e2631e8a1a2423ef8fadbde9b5cb3c9f0f60 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 11 Jan 2024 22:50:04 +0100 Subject: [PATCH 3/3] Tidier main --- src/main.rs | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/main.rs b/src/main.rs index f4b1e08..48cd409 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use std::fs::OpenOptions; use std::path::PathBuf; use std::{ffi::OsString, io}; +use musichoard::database::NoDatabase; use musichoard::library::NoLibrary; use musichoard::Collection; use ratatui::{backend::CrosstermBackend, Terminal}; @@ -65,11 +66,31 @@ fn with(lib: Option, db: Option) { Tui::run(terminal, ui, handler, listener).expect("failed to run tui"); } +fn with_database(opt: Opt, db: Option) { + if opt.no_library { + with(None::, db); + } else if let Some(uri) = opt.beets_ssh_uri { + let uri = uri.into_string().expect("invalid SSH URI"); + let beets_config_file_path = opt + .beets_config_file_path + .map(|s| s.into_string()) + .transpose() + .expect("failed to extract beets config file path"); + let lib_exec = BeetsLibrarySshExecutor::new(uri) + .expect("failed to initialise beets") + .config(beets_config_file_path); + with(Some(BeetsLibrary::new(lib_exec)), db); + } else { + let lib_exec = BeetsLibraryProcessExecutor::default().config(opt.beets_config_file_path); + with(Some(BeetsLibrary::new(lib_exec)), db); + } +} + fn main() { let opt = Opt::from_args(); - let db = if opt.no_database { - None + if opt.no_database { + with_database(opt, None::); } else { // Create an empty database file if it does not exist. match OpenOptions::new() @@ -90,26 +111,8 @@ fn main() { } let db_exec = JsonDatabaseFileBackend::new(&opt.database_file_path); - Some(JsonDatabase::new(db_exec)) + with_database(opt, Some(JsonDatabase::new(db_exec))); }; - - if opt.no_library { - with(None::, db); - } else if let Some(uri) = opt.beets_ssh_uri { - let uri = uri.into_string().expect("invalid SSH URI"); - let beets_config_file_path = opt - .beets_config_file_path - .map(|s| s.into_string()) - .transpose() - .expect("failed to extract beets config file path"); - let lib_exec = BeetsLibrarySshExecutor::new(uri) - .expect("failed to initialise beets") - .config(beets_config_file_path); - with(Some(BeetsLibrary::new(lib_exec)), db); - } else { - let lib_exec = BeetsLibraryProcessExecutor::default().config(opt.beets_config_file_path); - with(Some(BeetsLibrary::new(lib_exec)), db); - } } #[cfg(test)] -- 2.45.2