Move database and library implementations out of core (#162)
Closes #159 Reviewed-on: #162
This commit is contained in:
parent
bd7e9ceb4d
commit
8550f7d6da
@ -31,12 +31,12 @@ default = ["database-json", "library-beets"]
|
|||||||
bin = ["structopt"]
|
bin = ["structopt"]
|
||||||
database-json = ["serde", "serde_json"]
|
database-json = ["serde", "serde_json"]
|
||||||
library-beets = []
|
library-beets = []
|
||||||
ssh-library = ["openssh", "tokio"]
|
library-beets-ssh = ["openssh", "tokio"]
|
||||||
tui = ["aho-corasick", "crossterm", "once_cell", "ratatui"]
|
tui = ["aho-corasick", "crossterm", "once_cell", "ratatui"]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "musichoard"
|
name = "musichoard"
|
||||||
required-features = ["bin", "database-json", "library-beets", "ssh-library", "tui"]
|
required-features = ["bin", "database-json", "library-beets", "library-beets-ssh", "tui"]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "musichoard-edit"
|
name = "musichoard-edit"
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
//! Module for storing MusicHoard data in a database.
|
//! Module for storing MusicHoard data in a database.
|
||||||
|
|
||||||
#[cfg(feature = "database-json")]
|
|
||||||
pub mod json;
|
|
||||||
#[cfg(feature = "database-json")]
|
|
||||||
mod serde;
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
@ -1,8 +1,5 @@
|
|||||||
//! Module for interacting with the music library.
|
//! Module for interacting with the music library.
|
||||||
|
|
||||||
#[cfg(feature = "library-beets")]
|
|
||||||
pub mod beets;
|
|
||||||
|
|
||||||
use std::{collections::HashSet, fmt, num::ParseIntError, str::Utf8Error};
|
use std::{collections::HashSet, fmt, num::ParseIntError, str::Utf8Error};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -59,26 +56,16 @@ pub enum Field {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A library query. Can include or exclude particular fields.
|
/// A library query. Can include or exclude particular fields.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, Default, PartialEq, Eq)]
|
||||||
pub struct Query {
|
pub struct Query {
|
||||||
include: HashSet<Field>,
|
pub include: HashSet<Field>,
|
||||||
exclude: HashSet<Field>,
|
pub exclude: HashSet<Field>,
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Query {
|
|
||||||
/// Create an empty query.
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Query {
|
impl Query {
|
||||||
/// Create an empty query.
|
/// Create an empty query.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Query {
|
Query::default()
|
||||||
include: HashSet::new(),
|
|
||||||
exclude: HashSet::new(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Refine the query to include a particular search term.
|
/// Refine the query to include a particular search term.
|
@ -2,7 +2,7 @@ use once_cell::sync::Lazy;
|
|||||||
|
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
collection::{album::AlbumMonth, track::TrackFormat},
|
collection::{album::AlbumMonth, track::TrackFormat},
|
||||||
library::Item,
|
interface::library::Item,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
2
src/core/interface/mod.rs
Normal file
2
src/core/interface/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod database;
|
||||||
|
pub mod library;
|
@ -1,6 +1,5 @@
|
|||||||
pub mod collection;
|
pub mod collection;
|
||||||
pub mod database;
|
pub mod interface;
|
||||||
pub mod library;
|
|
||||||
pub mod musichoard;
|
pub mod musichoard;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -6,7 +6,10 @@ pub mod musichoard_builder;
|
|||||||
|
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
use crate::core::{collection, database, library};
|
use crate::core::{
|
||||||
|
collection,
|
||||||
|
interface::{database, library},
|
||||||
|
};
|
||||||
|
|
||||||
/// Error type for `musichoard`.
|
/// Error type for `musichoard`.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
@ -8,8 +8,10 @@ use crate::core::{
|
|||||||
track::{Track, TrackId, TrackNum, TrackQuality},
|
track::{Track, TrackId, TrackNum, TrackQuality},
|
||||||
Collection, MergeCollections,
|
Collection, MergeCollections,
|
||||||
},
|
},
|
||||||
database::IDatabase,
|
interface::{
|
||||||
library::{ILibrary, Item, Query},
|
database::IDatabase,
|
||||||
|
library::{ILibrary, Item, Query},
|
||||||
|
},
|
||||||
musichoard::Error,
|
musichoard::Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -468,8 +470,10 @@ mod tests {
|
|||||||
|
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
collection::{artist::ArtistId, musicbrainz::MusicBrainz},
|
collection::{artist::ArtistId, musicbrainz::MusicBrainz},
|
||||||
database::{self, MockIDatabase},
|
interface::{
|
||||||
library::{self, testmod::LIBRARY_ITEMS, MockILibrary},
|
database::{self, MockIDatabase},
|
||||||
|
library::{self, testmod::LIBRARY_ITEMS, MockILibrary},
|
||||||
|
},
|
||||||
testmod::{FULL_COLLECTION, LIBRARY_COLLECTION},
|
testmod::{FULL_COLLECTION, LIBRARY_COLLECTION},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{
|
||||||
database::IDatabase,
|
interface::{database::IDatabase, library::ILibrary},
|
||||||
library::ILibrary,
|
|
||||||
musichoard::musichoard::{MusicHoard, NoDatabase, NoLibrary},
|
musichoard::musichoard::{MusicHoard, NoDatabase, NoLibrary},
|
||||||
},
|
},
|
||||||
Error,
|
Error,
|
||||||
@ -79,7 +78,7 @@ impl<LIB: ILibrary, DB: IDatabase> MusicHoardBuilder<LIB, DB> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::core::{database::NullDatabase, library::NullLibrary};
|
use crate::core::interface::{database::NullDatabase, library::NullLibrary};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::core::database::json::IJsonDatabaseBackend;
|
use crate::database::json::IJsonDatabaseBackend;
|
||||||
|
|
||||||
/// JSON database backend that uses a local file for persistent storage.
|
/// JSON database backend that uses a local file for persistent storage.
|
||||||
pub struct JsonDatabaseFileBackend {
|
pub struct JsonDatabaseFileBackend {
|
@ -7,7 +7,7 @@ use mockall::automock;
|
|||||||
|
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
collection::Collection,
|
collection::Collection,
|
||||||
database::{IDatabase, LoadError, SaveError},
|
interface::database::{IDatabase, LoadError, SaveError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::serde::{deserialize::DeserializeDatabase, serialize::SerializeDatabase};
|
use super::serde::{deserialize::DeserializeDatabase, serialize::SerializeDatabase};
|
4
src/database/mod.rs
Normal file
4
src/database/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#[cfg(feature = "database-json")]
|
||||||
|
pub mod json;
|
||||||
|
#[cfg(feature = "database-json")]
|
||||||
|
mod serde;
|
@ -9,7 +9,7 @@ use crate::core::{
|
|||||||
musicbrainz::MusicBrainz,
|
musicbrainz::MusicBrainz,
|
||||||
Collection,
|
Collection,
|
||||||
},
|
},
|
||||||
database::LoadError,
|
interface::database::LoadError,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
@ -1,10 +1,11 @@
|
|||||||
//! MusicHoard - a music collection manager.
|
//! MusicHoard - a music collection manager.
|
||||||
|
|
||||||
mod core;
|
mod core;
|
||||||
|
pub mod database;
|
||||||
|
pub mod library;
|
||||||
|
|
||||||
pub use core::collection;
|
pub use core::collection;
|
||||||
pub use core::database;
|
pub use core::interface;
|
||||||
pub use core::library;
|
|
||||||
|
|
||||||
pub use core::musichoard::{
|
pub use core::musichoard::{
|
||||||
musichoard::{MusicHoard, NoDatabase, NoLibrary},
|
musichoard::{MusicHoard, NoDatabase, NoLibrary},
|
||||||
|
@ -8,7 +8,8 @@ use std::{
|
|||||||
str,
|
str,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::core::library::{beets::IBeetsLibraryExecutor, Error};
|
use crate::core::interface::library::Error;
|
||||||
|
use crate::library::beets::IBeetsLibraryExecutor;
|
||||||
|
|
||||||
const BEET_DEFAULT: &str = "beet";
|
const BEET_DEFAULT: &str = "beet";
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ impl IBeetsLibraryExecutor for BeetsLibraryProcessExecutor {
|
|||||||
impl IBeetsLibraryExecutorPrivate for BeetsLibraryProcessExecutor {}
|
impl IBeetsLibraryExecutorPrivate for BeetsLibraryProcessExecutor {}
|
||||||
|
|
||||||
// GRCOV_EXCL_START
|
// GRCOV_EXCL_START
|
||||||
#[cfg(feature = "ssh-library")]
|
#[cfg(feature = "library-beets-ssh")]
|
||||||
pub mod ssh {
|
pub mod ssh {
|
||||||
//! Module for interacting with the music library via
|
//! Module for interacting with the music library via
|
||||||
//! [beets](https://beets.readthedocs.io/en/stable/) over SSH.
|
//! [beets](https://beets.readthedocs.io/en/stable/) over SSH.
|
@ -8,7 +8,7 @@ use mockall::automock;
|
|||||||
|
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
collection::track::TrackFormat,
|
collection::track::TrackFormat,
|
||||||
library::{Error, Field, ILibrary, Item, Query},
|
interface::library::{Error, Field, ILibrary, Item, Query},
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! list_format_separator {
|
macro_rules! list_format_separator {
|
||||||
@ -201,7 +201,7 @@ mod testmod;
|
|||||||
mod tests {
|
mod tests {
|
||||||
use mockall::predicate;
|
use mockall::predicate;
|
||||||
|
|
||||||
use crate::{collection::album::AlbumMonth, core::library::testmod::LIBRARY_ITEMS};
|
use crate::{collection::album::AlbumMonth, core::interface::library::testmod::LIBRARY_ITEMS};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use testmod::LIBRARY_BEETS;
|
use testmod::LIBRARY_BEETS;
|
2
src/library/mod.rs
Normal file
2
src/library/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#[cfg(feature = "library-beets")]
|
||||||
|
pub mod beets;
|
16
src/main.rs
16
src/main.rs
@ -10,16 +10,14 @@ use ratatui::{backend::CrosstermBackend, Terminal};
|
|||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use musichoard::{
|
use musichoard::{
|
||||||
database::{
|
database::json::{backend::JsonDatabaseFileBackend, JsonDatabase},
|
||||||
json::{backend::JsonDatabaseFileBackend, JsonDatabase},
|
interface::{
|
||||||
IDatabase, NullDatabase,
|
database::{IDatabase, NullDatabase},
|
||||||
|
library::{ILibrary, NullLibrary},
|
||||||
},
|
},
|
||||||
library::{
|
library::beets::{
|
||||||
beets::{
|
executor::{ssh::BeetsLibrarySshExecutor, BeetsLibraryProcessExecutor},
|
||||||
executor::{ssh::BeetsLibrarySshExecutor, BeetsLibraryProcessExecutor},
|
BeetsLibrary,
|
||||||
BeetsLibrary,
|
|
||||||
},
|
|
||||||
ILibrary, NullLibrary,
|
|
||||||
},
|
},
|
||||||
MusicHoardBuilder, NoDatabase, NoLibrary,
|
MusicHoardBuilder, NoDatabase, NoLibrary,
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use musichoard::{collection::Collection, database::IDatabase, library::ILibrary, MusicHoard};
|
use musichoard::{
|
||||||
|
collection::Collection, interface::database::IDatabase, interface::library::ILibrary,
|
||||||
|
MusicHoard,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use mockall::automock;
|
use mockall::automock;
|
||||||
|
@ -5,10 +5,8 @@ use tempfile::NamedTempFile;
|
|||||||
|
|
||||||
use musichoard::{
|
use musichoard::{
|
||||||
collection::{album::AlbumDate, artist::Artist, Collection},
|
collection::{album::AlbumDate, artist::Artist, Collection},
|
||||||
database::{
|
database::json::{backend::JsonDatabaseFileBackend, JsonDatabase},
|
||||||
json::{backend::JsonDatabaseFileBackend, JsonDatabase},
|
interface::database::IDatabase,
|
||||||
IDatabase,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::testlib::COLLECTION;
|
use crate::testlib::COLLECTION;
|
||||||
|
@ -7,9 +7,9 @@ use std::{
|
|||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use musichoard::library::{
|
use musichoard::{
|
||||||
beets::{executor::BeetsLibraryProcessExecutor, BeetsLibrary},
|
interface::library::{Field, ILibrary, Item, Query},
|
||||||
Field, ILibrary, Item, Query,
|
library::beets::{executor::BeetsLibraryProcessExecutor, BeetsLibrary},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::library::testmod::LIBRARY_ITEMS;
|
use crate::library::testmod::LIBRARY_ITEMS;
|
||||||
|
@ -2,7 +2,7 @@ use once_cell::sync::Lazy;
|
|||||||
|
|
||||||
use musichoard::{
|
use musichoard::{
|
||||||
collection::{album::AlbumMonth, track::TrackFormat},
|
collection::{album::AlbumMonth, track::TrackFormat},
|
||||||
library::Item,
|
interface::library::Item,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
pub static LIBRARY_ITEMS: Lazy<Vec<Item>> = Lazy::new(|| -> Vec<Item> {
|
||||||
|
Loading…
Reference in New Issue
Block a user