Break down the musichoard files #165
@ -8,7 +8,7 @@ use musichoard::{
|
|||||||
MusicHoard, MusicHoardBuilder, NoLibrary,
|
MusicHoard, MusicHoardBuilder, NoLibrary,
|
||||||
};
|
};
|
||||||
|
|
||||||
type MH = MusicHoard<NoLibrary, JsonDatabase<JsonDatabaseFileBackend>>;
|
type MH = MusicHoard<JsonDatabase<JsonDatabaseFileBackend>, NoLibrary>;
|
||||||
|
|
||||||
#[derive(StructOpt, Debug)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(about = "musichoard-edit: edit the MusicHoard database",
|
#[structopt(about = "musichoard-edit: edit the MusicHoard database",
|
||||||
|
@ -18,13 +18,13 @@ use crate::core::{
|
|||||||
/// The Music Hoard. It is responsible for pulling information from both the library and the
|
/// The Music Hoard. It is responsible for pulling information from both the library and the
|
||||||
/// database, ensuring its consistent and writing back any changes.
|
/// database, ensuring its consistent and writing back any changes.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MusicHoard<LIB, DB> {
|
pub struct MusicHoard<Database, Library> {
|
||||||
collection: Collection,
|
collection: Collection,
|
||||||
pre_commit: Collection,
|
pre_commit: Collection,
|
||||||
library: LIB,
|
database: Database,
|
||||||
database: DB,
|
|
||||||
library_cache: HashMap<ArtistId, Artist>,
|
|
||||||
database_cache: Collection,
|
database_cache: Collection,
|
||||||
|
library: Library,
|
||||||
|
library_cache: HashMap<ArtistId, Artist>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Phantom type for when a library implementation is not needed.
|
/// Phantom type for when a library implementation is not needed.
|
||||||
@ -35,28 +35,28 @@ pub struct NoLibrary;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NoDatabase;
|
pub struct NoDatabase;
|
||||||
|
|
||||||
impl Default for MusicHoard<NoLibrary, NoDatabase> {
|
impl Default for MusicHoard<NoDatabase, NoLibrary> {
|
||||||
/// Create a new [`MusicHoard`] without any library or database.
|
/// Create a new [`MusicHoard`] without any library or database.
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
MusicHoard::empty()
|
MusicHoard::empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MusicHoard<NoLibrary, NoDatabase> {
|
impl MusicHoard<NoDatabase, NoLibrary> {
|
||||||
/// Create a new [`MusicHoard`] without any library or database.
|
/// Create a new [`MusicHoard`] without any library or database.
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
MusicHoard {
|
MusicHoard {
|
||||||
collection: vec![],
|
collection: vec![],
|
||||||
pre_commit: vec![],
|
pre_commit: vec![],
|
||||||
library: NoLibrary,
|
|
||||||
database: NoDatabase,
|
database: NoDatabase,
|
||||||
library_cache: HashMap::new(),
|
|
||||||
database_cache: vec![],
|
database_cache: vec![],
|
||||||
|
library: NoLibrary,
|
||||||
|
library_cache: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<LIB, DB> MusicHoard<LIB, DB> {
|
impl<Database, Library> MusicHoard<Database, Library> {
|
||||||
/// Retrieve the [`Collection`].
|
/// Retrieve the [`Collection`].
|
||||||
pub fn get_collection(&self) -> &Collection {
|
pub fn get_collection(&self) -> &Collection {
|
||||||
&self.collection
|
&self.collection
|
||||||
@ -191,16 +191,16 @@ impl<LIB, DB> MusicHoard<LIB, DB> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<LIB: ILibrary> MusicHoard<LIB, NoDatabase> {
|
impl<Library: ILibrary> MusicHoard<NoDatabase, Library> {
|
||||||
/// Create a new [`MusicHoard`] with the provided [`ILibrary`] and no database.
|
/// Create a new [`MusicHoard`] with the provided [`ILibrary`] and no database.
|
||||||
pub fn library(library: LIB) -> Self {
|
pub fn library(library: Library) -> Self {
|
||||||
MusicHoard {
|
MusicHoard {
|
||||||
collection: vec![],
|
collection: vec![],
|
||||||
pre_commit: vec![],
|
pre_commit: vec![],
|
||||||
library,
|
|
||||||
database: NoDatabase,
|
database: NoDatabase,
|
||||||
library_cache: HashMap::new(),
|
|
||||||
database_cache: vec![],
|
database_cache: vec![],
|
||||||
|
library,
|
||||||
|
library_cache: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ impl<LIB: ILibrary> MusicHoard<LIB, NoDatabase> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<LIB: ILibrary, DB> MusicHoard<LIB, DB> {
|
impl<Database, Library: ILibrary> MusicHoard<Database, Library> {
|
||||||
fn rescan_library_inner(&mut self) -> Result<Collection, Error> {
|
fn rescan_library_inner(&mut self) -> Result<Collection, Error> {
|
||||||
let items = self.library.list(&Query::new())?;
|
let items = self.library.list(&Query::new())?;
|
||||||
self.library_cache = Self::items_to_artists(items)?;
|
self.library_cache = Self::items_to_artists(items)?;
|
||||||
@ -221,30 +221,30 @@ impl<LIB: ILibrary, DB> MusicHoard<LIB, DB> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DB: IDatabase> MusicHoard<NoLibrary, DB> {
|
impl<Database: IDatabase> MusicHoard<Database, NoLibrary> {
|
||||||
/// Create a new [`MusicHoard`] with the provided [`IDatabase`] and no library.
|
/// Create a new [`MusicHoard`] with the provided [`IDatabase`] and no library.
|
||||||
pub fn database(database: DB) -> Result<Self, Error> {
|
pub fn database(database: Database) -> Result<Self, Error> {
|
||||||
let mut mh = MusicHoard {
|
let mut mh = MusicHoard {
|
||||||
collection: vec![],
|
collection: vec![],
|
||||||
pre_commit: vec![],
|
pre_commit: vec![],
|
||||||
library: NoLibrary,
|
|
||||||
database,
|
database,
|
||||||
library_cache: HashMap::new(),
|
|
||||||
database_cache: vec![],
|
database_cache: vec![],
|
||||||
|
library: NoLibrary,
|
||||||
|
library_cache: HashMap::new(),
|
||||||
};
|
};
|
||||||
mh.reload_database()?;
|
mh.reload_database()?;
|
||||||
Ok(mh)
|
Ok(mh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<LIB> MusicHoard<LIB, NoDatabase> {
|
impl<Library> MusicHoard<NoDatabase, Library> {
|
||||||
fn commit(&mut self) -> Result<(), Error> {
|
fn commit(&mut self) -> Result<(), Error> {
|
||||||
self.collection = self.pre_commit.clone();
|
self.collection = self.pre_commit.clone();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<LIB, DB: IDatabase> MusicHoard<LIB, DB> {
|
impl<Database: IDatabase, Library> MusicHoard<Database, Library> {
|
||||||
/// Load the database and merge with the in-memory collection.
|
/// Load the database and merge with the in-memory collection.
|
||||||
pub fn reload_database(&mut self) -> Result<(), Error> {
|
pub fn reload_database(&mut self) -> Result<(), Error> {
|
||||||
self.database_cache = self.database.load()?;
|
self.database_cache = self.database.load()?;
|
||||||
@ -448,16 +448,16 @@ impl<LIB, DB: IDatabase> MusicHoard<LIB, DB> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<LIB: ILibrary, DB: IDatabase> MusicHoard<LIB, DB> {
|
impl<Database: IDatabase, Library: ILibrary> MusicHoard<Database, Library> {
|
||||||
/// Create a new [`MusicHoard`] with the provided [`ILibrary`] and [`IDatabase`].
|
/// Create a new [`MusicHoard`] with the provided [`ILibrary`] and [`IDatabase`].
|
||||||
pub fn new(library: LIB, database: DB) -> Result<Self, Error> {
|
pub fn new(database: Database, library: Library) -> Result<Self, Error> {
|
||||||
let mut mh = MusicHoard {
|
let mut mh = MusicHoard {
|
||||||
collection: vec![],
|
collection: vec![],
|
||||||
pre_commit: vec![],
|
pre_commit: vec![],
|
||||||
library,
|
|
||||||
database,
|
database,
|
||||||
library_cache: HashMap::new(),
|
|
||||||
database_cache: vec![],
|
database_cache: vec![],
|
||||||
|
library,
|
||||||
|
library_cache: HashMap::new(),
|
||||||
};
|
};
|
||||||
mh.reload_database()?;
|
mh.reload_database()?;
|
||||||
Ok(mh)
|
Ok(mh)
|
||||||
@ -542,7 +542,7 @@ mod tests {
|
|||||||
database.expect_load().times(1).returning(|| Ok(vec![]));
|
database.expect_load().times(1).returning(|| Ok(vec![]));
|
||||||
database.expect_save().times(4).returning(|_| Ok(()));
|
database.expect_save().times(4).returning(|_| Ok(()));
|
||||||
|
|
||||||
type MH = MusicHoard<NoLibrary, MockIDatabase>;
|
type MH = MusicHoard<MockIDatabase, NoLibrary>;
|
||||||
let mut music_hoard: MH = MusicHoard::database(database).unwrap();
|
let mut music_hoard: MH = MusicHoard::database(database).unwrap();
|
||||||
|
|
||||||
let artist_1_id = ArtistId::new("the artist");
|
let artist_1_id = ArtistId::new("the artist");
|
||||||
@ -935,7 +935,7 @@ mod tests {
|
|||||||
.times(1)
|
.times(1)
|
||||||
.return_once(|_| Ok(()));
|
.return_once(|_| Ok(()));
|
||||||
|
|
||||||
let mut music_hoard = MusicHoard::new(library, database).unwrap();
|
let mut music_hoard = MusicHoard::new(database, library).unwrap();
|
||||||
|
|
||||||
music_hoard.rescan_library().unwrap();
|
music_hoard.rescan_library().unwrap();
|
||||||
assert_eq!(music_hoard.get_collection(), &*LIBRARY_COLLECTION);
|
assert_eq!(music_hoard.get_collection(), &*LIBRARY_COLLECTION);
|
||||||
@ -1083,7 +1083,7 @@ mod tests {
|
|||||||
.times(1)
|
.times(1)
|
||||||
.return_once(|| Ok(FULL_COLLECTION.to_owned()));
|
.return_once(|| Ok(FULL_COLLECTION.to_owned()));
|
||||||
|
|
||||||
let music_hoard = MusicHoard::new(library, database).unwrap();
|
let music_hoard = MusicHoard::new(database, library).unwrap();
|
||||||
|
|
||||||
assert_eq!(music_hoard.get_collection(), &*FULL_COLLECTION);
|
assert_eq!(music_hoard.get_collection(), &*FULL_COLLECTION);
|
||||||
}
|
}
|
||||||
|
@ -8,71 +8,77 @@ use crate::{
|
|||||||
|
|
||||||
/// Builder for [`MusicHoard`]. Its purpose is to make it easier to set various combinations of
|
/// Builder for [`MusicHoard`]. Its purpose is to make it easier to set various combinations of
|
||||||
/// library/database or their absence.
|
/// library/database or their absence.
|
||||||
pub struct MusicHoardBuilder<LIB, DB> {
|
pub struct MusicHoardBuilder<Database, Library> {
|
||||||
library: LIB,
|
database: Database,
|
||||||
database: DB,
|
library: Library,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MusicHoardBuilder<NoLibrary, NoDatabase> {
|
impl Default for MusicHoardBuilder<NoDatabase, NoLibrary> {
|
||||||
/// Create a [`MusicHoardBuilder`].
|
/// Create a [`MusicHoardBuilder`].
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MusicHoardBuilder<NoLibrary, NoDatabase> {
|
impl MusicHoardBuilder<NoDatabase, NoLibrary> {
|
||||||
/// Create a [`MusicHoardBuilder`].
|
/// Create a [`MusicHoardBuilder`].
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
MusicHoardBuilder {
|
MusicHoardBuilder {
|
||||||
library: NoLibrary,
|
|
||||||
database: NoDatabase,
|
database: NoDatabase,
|
||||||
|
library: NoLibrary,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<LIB, DB> MusicHoardBuilder<LIB, DB> {
|
impl<Database, Library> MusicHoardBuilder<Database, Library> {
|
||||||
/// Set a library for [`MusicHoard`].
|
/// Set a library for [`MusicHoard`].
|
||||||
pub fn set_library<NEWLIB: ILibrary>(self, library: NEWLIB) -> MusicHoardBuilder<NEWLIB, DB> {
|
pub fn set_library<NewLibrary: ILibrary>(
|
||||||
|
self,
|
||||||
|
library: NewLibrary,
|
||||||
|
) -> MusicHoardBuilder<Database, NewLibrary> {
|
||||||
MusicHoardBuilder {
|
MusicHoardBuilder {
|
||||||
library,
|
|
||||||
database: self.database,
|
database: self.database,
|
||||||
|
library,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a database for [`MusicHoard`].
|
/// Set a database for [`MusicHoard`].
|
||||||
pub fn set_database<NEWDB: IDatabase>(self, database: NEWDB) -> MusicHoardBuilder<LIB, NEWDB> {
|
pub fn set_database<NewDatabase: IDatabase>(
|
||||||
|
self,
|
||||||
|
database: NewDatabase,
|
||||||
|
) -> MusicHoardBuilder<NewDatabase, Library> {
|
||||||
MusicHoardBuilder {
|
MusicHoardBuilder {
|
||||||
library: self.library,
|
|
||||||
database,
|
database,
|
||||||
|
library: self.library,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MusicHoardBuilder<NoLibrary, NoDatabase> {
|
impl MusicHoardBuilder<NoDatabase, NoLibrary> {
|
||||||
/// Build [`MusicHoard`] with the currently set library and database.
|
/// Build [`MusicHoard`] with the currently set library and database.
|
||||||
pub fn build(self) -> MusicHoard<NoLibrary, NoDatabase> {
|
pub fn build(self) -> MusicHoard<NoDatabase, NoLibrary> {
|
||||||
MusicHoard::empty()
|
MusicHoard::empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<LIB: ILibrary> MusicHoardBuilder<LIB, NoDatabase> {
|
impl<Library: ILibrary> MusicHoardBuilder<NoDatabase, Library> {
|
||||||
/// Build [`MusicHoard`] with the currently set library and database.
|
/// Build [`MusicHoard`] with the currently set library and database.
|
||||||
pub fn build(self) -> MusicHoard<LIB, NoDatabase> {
|
pub fn build(self) -> MusicHoard<NoDatabase, Library> {
|
||||||
MusicHoard::library(self.library)
|
MusicHoard::library(self.library)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DB: IDatabase> MusicHoardBuilder<NoLibrary, DB> {
|
impl<Database: IDatabase> MusicHoardBuilder<Database, NoLibrary> {
|
||||||
/// Build [`MusicHoard`] with the currently set library and database.
|
/// Build [`MusicHoard`] with the currently set library and database.
|
||||||
pub fn build(self) -> Result<MusicHoard<NoLibrary, DB>, Error> {
|
pub fn build(self) -> Result<MusicHoard<Database, NoLibrary>, Error> {
|
||||||
MusicHoard::database(self.database)
|
MusicHoard::database(self.database)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<LIB: ILibrary, DB: IDatabase> MusicHoardBuilder<LIB, DB> {
|
impl<Database: IDatabase, Library: ILibrary> MusicHoardBuilder<Database, Library> {
|
||||||
/// Build [`MusicHoard`] with the currently set library and database.
|
/// Build [`MusicHoard`] with the currently set library and database.
|
||||||
pub fn build(self) -> Result<MusicHoard<LIB, DB>, Error> {
|
pub fn build(self) -> Result<MusicHoard<Database, Library>, Error> {
|
||||||
MusicHoard::new(self.library, self.database)
|
MusicHoard::new(self.database, self.library)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ struct DbOpt {
|
|||||||
no_database: bool,
|
no_database: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with<LIB: ILibrary, DB: IDatabase>(builder: MusicHoardBuilder<LIB, DB>) {
|
fn with<Database: IDatabase, Library: ILibrary>(builder: MusicHoardBuilder<Database, Library>) {
|
||||||
let music_hoard = builder.build().expect("failed to initialise MusicHoard");
|
let music_hoard = builder.build().expect("failed to initialise MusicHoard");
|
||||||
|
|
||||||
// Initialize the terminal user interface.
|
// Initialize the terminal user interface.
|
||||||
@ -76,7 +76,10 @@ fn with<LIB: ILibrary, DB: IDatabase>(builder: MusicHoardBuilder<LIB, DB>) {
|
|||||||
Tui::run(terminal, app, ui, handler, listener).expect("failed to run tui");
|
Tui::run(terminal, app, ui, handler, listener).expect("failed to run tui");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_database<LIB: ILibrary>(db_opt: DbOpt, builder: MusicHoardBuilder<LIB, NoDatabase>) {
|
fn with_database<Library: ILibrary>(
|
||||||
|
db_opt: DbOpt,
|
||||||
|
builder: MusicHoardBuilder<NoDatabase, Library>,
|
||||||
|
) {
|
||||||
if db_opt.no_database {
|
if db_opt.no_database {
|
||||||
with(builder.set_database(NullDatabase));
|
with(builder.set_database(NullDatabase));
|
||||||
} else {
|
} else {
|
||||||
@ -103,7 +106,7 @@ fn with_database<LIB: ILibrary>(db_opt: DbOpt, builder: MusicHoardBuilder<LIB, N
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_library(lib_opt: LibOpt, db_opt: DbOpt, builder: MusicHoardBuilder<NoLibrary, NoDatabase>) {
|
fn with_library(lib_opt: LibOpt, db_opt: DbOpt, builder: MusicHoardBuilder<NoDatabase, NoLibrary>) {
|
||||||
if lib_opt.no_library {
|
if lib_opt.no_library {
|
||||||
with_database(db_opt, builder.set_library(NullLibrary));
|
with_database(db_opt, builder.set_library(NullLibrary));
|
||||||
} else if let Some(uri) = lib_opt.beets_ssh_uri {
|
} else if let Some(uri) = lib_opt.beets_ssh_uri {
|
||||||
|
@ -14,9 +14,9 @@ pub trait IMusicHoard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GRCOV_EXCL_START
|
// GRCOV_EXCL_START
|
||||||
impl<LIB: ILibrary, DB: IDatabase> IMusicHoard for MusicHoard<LIB, DB> {
|
impl<Database: IDatabase, Library: ILibrary> IMusicHoard for MusicHoard<Database, Library> {
|
||||||
fn rescan_library(&mut self) -> Result<(), musichoard::Error> {
|
fn rescan_library(&mut self) -> Result<(), musichoard::Error> {
|
||||||
MusicHoard::<LIB, DB>::rescan_library(self)
|
MusicHoard::<Database, Library>::rescan_library(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reload_database(&mut self) -> Result<(), musichoard::Error> {
|
fn reload_database(&mut self) -> Result<(), musichoard::Error> {
|
||||||
|
@ -29,7 +29,7 @@ fn merge_library_then_database() {
|
|||||||
let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE);
|
let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE);
|
||||||
let database = JsonDatabase::new(backend);
|
let database = JsonDatabase::new(backend);
|
||||||
|
|
||||||
let mut music_hoard = MusicHoard::new(library, database).unwrap();
|
let mut music_hoard = MusicHoard::new(database, library).unwrap();
|
||||||
|
|
||||||
music_hoard.rescan_library().unwrap();
|
music_hoard.rescan_library().unwrap();
|
||||||
music_hoard.reload_database().unwrap();
|
music_hoard.reload_database().unwrap();
|
||||||
@ -52,7 +52,7 @@ fn merge_database_then_library() {
|
|||||||
let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE);
|
let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE);
|
||||||
let database = JsonDatabase::new(backend);
|
let database = JsonDatabase::new(backend);
|
||||||
|
|
||||||
let mut music_hoard = MusicHoard::new(library, database).unwrap();
|
let mut music_hoard = MusicHoard::new(database, library).unwrap();
|
||||||
|
|
||||||
music_hoard.reload_database().unwrap();
|
music_hoard.reload_database().unwrap();
|
||||||
music_hoard.rescan_library().unwrap();
|
music_hoard.rescan_library().unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user