diff --git a/Cargo.toml b/Cargo.toml index 4e1b299..89d1b95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,16 +6,29 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -crossterm = "0.26.1" -openssh = { version = "0.9.9", features = ["native-mux"], default-features = false } +crossterm = { version = "0.26.1", optional = true} +openssh = { version = "0.9.9", features = ["native-mux"], default-features = false, optional = true} +ratatui = { version = "0.20.1", optional = true} serde = { version = "1.0.159", features = ["derive"] } -serde_json = "1.0.95" -structopt = "0.3.26" -ratatui = "0.20.1" -tokio = { version = "1.27.0", features = ["rt"] } +serde_json = { version = "1.0.95", optional = true} +structopt = { version = "0.3.26", optional = true} +tokio = { version = "1.27.0", features = ["rt"], optional = true} uuid = { version = "1.3.0", features = ["serde"] } [dev-dependencies] mockall = "0.11.4" once_cell = "1.17.1" tempfile = "3.5.0" + +[features] +bin = ["structopt"] +database-json = ["serde_json"] +library-ssh = ["openssh", "tokio"] +tui = ["crossterm", "ratatui"] + +[[bin]] +name = "musichoard" +required-features = ["bin", "database-json", "library-ssh", "tui"] + +[package.metadata.docs.rs] +all-features = true diff --git a/README.md b/README.md index 8acd0c8..49ac8bb 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ env CARGO_TARGET_DIR=codecov \ env RUSTFLAGS="-C instrument-coverage" \ LLVM_PROFILE_FILE="codecov/debug/profraw/musichoard-%p-%m.profraw" \ CARGO_TARGET_DIR=codecov \ - cargo test + cargo test --all-features grcov codecov/debug/profraw \ --binary-path ./codecov/debug/ \ --output-types html \ diff --git a/src/database/mod.rs b/src/database/mod.rs index 045bc36..8434b7b 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -7,6 +7,7 @@ use serde::{de::DeserializeOwned, Serialize}; #[cfg(test)] use mockall::automock; +#[cfg(feature = "database-json")] pub mod json; /// Error type for database calls. diff --git a/src/library/beets/executor.rs b/src/library/beets/executor.rs index 2c45a6d..b1de79f 100644 --- a/src/library/beets/executor.rs +++ b/src/library/beets/executor.rs @@ -8,9 +8,6 @@ use std::{ str, }; -use openssh::{KnownHosts, Session}; -use tokio::runtime::{self, Runtime}; - use super::{BeetsLibraryExecutor, Error}; const BEET_DEFAULT: &str = "beet"; @@ -77,64 +74,73 @@ impl BeetsLibraryExecutor for BeetsLibraryProcessExecutor { impl BeetsLibraryExecutorPrivate for BeetsLibraryProcessExecutor {} // GRCOV_EXCL_START -/// Beets library executor that executes beets commands over SSH. -pub struct BeetsLibrarySshExecutor { - rt: Runtime, - session: Session, - bin: String, - config: Option, -} +#[cfg(feature = "library-ssh")] +pub mod ssh { -impl From for Error { - fn from(err: openssh::Error) -> Error { - Error::Executor(err.to_string()) - } -} + use openssh::{KnownHosts, Session}; + use tokio::runtime::{self, Runtime}; -impl BeetsLibrarySshExecutor { - /// Create a new [`BeetsLibrarySshExecutor`] that uses the default beets executable over an SSH - /// connection. This call will attempt to establish the connection and will fail if the - /// connection fails. - pub fn new>(host: H) -> Result { - Self::bin(host, BEET_DEFAULT) + use super::*; + + /// Beets library executor that executes beets commands over SSH. + pub struct BeetsLibrarySshExecutor { + rt: Runtime, + session: Session, + bin: String, + config: Option, } - /// Create a new [`BeetsLibrarySshExecutor`] that uses the provided beets executable over an SSH - /// connection. This call will attempt to establish the connection and will fail if the - /// connection fails. - pub fn bin, S: Into>(host: H, bin: S) -> Result { - let rt = runtime::Builder::new_current_thread() - .enable_all() - .build() - .unwrap(); - let session = rt.block_on(Session::connect_mux(host, KnownHosts::Strict))?; - Ok(BeetsLibrarySshExecutor { - rt, - session, - bin: bin.into(), - config: None, - }) - } - - /// Update the configuration file passed to the beets executable. - pub fn config>(mut self, path: Option

) -> Self { - self.config = path.map(|p| p.into()); - self - } -} - -impl BeetsLibraryExecutor for BeetsLibrarySshExecutor { - fn exec + 'static>(&mut self, arguments: &[S]) -> Result, Error> { - let mut cmd = self.session.command(&self.bin); - if let Some(ref path) = self.config { - cmd.arg("--config"); - cmd.arg(path); + impl From for Error { + fn from(err: openssh::Error) -> Error { + Error::Executor(err.to_string()) } - cmd.args(arguments.iter().map(|s| s.as_ref())); - let output = self.rt.block_on(cmd.output())?; - Self::output(output) } -} -impl BeetsLibraryExecutorPrivate for BeetsLibrarySshExecutor {} + impl BeetsLibrarySshExecutor { + /// Create a new [`BeetsLibrarySshExecutor`] that uses the default beets executable over an + /// SSH connection. This call will attempt to establish the connection and will fail if the + /// connection fails. + pub fn new>(host: H) -> Result { + Self::bin(host, BEET_DEFAULT) + } + + /// Create a new [`BeetsLibrarySshExecutor`] that uses the provided beets executable over an + /// SSH connection. This call will attempt to establish the connection and will fail if the + /// connection fails. + pub fn bin, S: Into>(host: H, bin: S) -> Result { + let rt = runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + let session = rt.block_on(Session::connect_mux(host, KnownHosts::Strict))?; + Ok(BeetsLibrarySshExecutor { + rt, + session, + bin: bin.into(), + config: None, + }) + } + + /// Update the configuration file passed to the beets executable. + pub fn config>(mut self, path: Option

) -> Self { + self.config = path.map(|p| p.into()); + self + } + } + + impl BeetsLibraryExecutor for BeetsLibrarySshExecutor { + fn exec + 'static>(&mut self, arguments: &[S]) -> Result, Error> { + let mut cmd = self.session.command(&self.bin); + if let Some(ref path) = self.config { + cmd.arg("--config"); + cmd.arg(path); + } + cmd.args(arguments.iter().map(|s| s.as_ref())); + let output = self.rt.block_on(cmd.output())?; + Self::output(output) + } + } + + impl BeetsLibraryExecutorPrivate for BeetsLibrarySshExecutor {} +} // GRCOV_EXCL_STOP diff --git a/src/main.rs b/src/main.rs index 66a5322..5e9c426 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ use musichoard::{ }, library::{ beets::{ - executor::{BeetsLibraryProcessExecutor, BeetsLibrarySshExecutor}, + executor::{ssh::BeetsLibrarySshExecutor, BeetsLibraryProcessExecutor}, BeetsLibrary, }, Library, diff --git a/tests/database/mod.rs b/tests/database/mod.rs index cff0e90..084073c 100644 --- a/tests/database/mod.rs +++ b/tests/database/mod.rs @@ -1 +1,2 @@ +#[cfg(feature = "database-json")] mod json;