Remove unsafe from BeetsLibraryCommandExecutor (#23)

Closes #22

Reviewed-on: https://git.wojciechkozlowski.eu/wojtek/musichoard/pulls/23
This commit is contained in:
Wojciech Kozlowski 2023-04-10 22:03:04 +02:00
parent 67ba032247
commit 4f28d97cf3
4 changed files with 19 additions and 35 deletions

View File

@ -237,13 +237,6 @@ impl LibraryPrivate for BeetsLibrary {
} }
/// Beets library executor that executes beets commands in their own process. /// Beets library executor that executes beets commands in their own process.
///
/// # Safety
///
/// The beets executable is not safe to call concurrently for operations on the same
/// database/library. Therefore, all functions that create a [BeetsLibraryCommandExecutor] or modify
/// which library it works with are marked unsafe. It is the caller's responsibility to make sure
/// the library is not being concurrently accessed from anywhere else.
pub struct BeetsLibraryCommandExecutor { pub struct BeetsLibraryCommandExecutor {
bin: String, bin: String,
config: Option<PathBuf>, config: Option<PathBuf>,
@ -251,37 +244,27 @@ pub struct BeetsLibraryCommandExecutor {
impl BeetsLibraryCommandExecutor { impl BeetsLibraryCommandExecutor {
/// Create a new [BeetsLibraryCommandExecutor] that uses the provided beets executable. /// Create a new [BeetsLibraryCommandExecutor] that uses the provided beets executable.
/// pub fn new(bin: &str) -> Self {
/// # Safety
///
/// The caller must ensure the library is not being concurrently accessed from anywhere else.
pub unsafe fn new(bin: &str) -> Self {
BeetsLibraryCommandExecutor { BeetsLibraryCommandExecutor {
bin: bin.to_string(), bin: bin.to_string(),
config: None, config: None,
} }
} }
/// Create a new [BeetsLibraryCommandExecutor] that uses the system's default beets executable.
///
/// # Safety
///
/// The caller must ensure the library is not being concurrently accessed from anywhere else.
pub unsafe fn default() -> Self {
BeetsLibraryCommandExecutor::new("beet")
}
/// Update the configuration file passed to the beets executable. /// Update the configuration file passed to the beets executable.
/// pub fn config(mut self, path: Option<&Path>) -> Self {
/// # Safety
///
/// The caller must ensure the library is not being concurrently accessed from anywhere else.
pub unsafe fn config(mut self, path: Option<&Path>) -> Self {
self.config = path.map(|p| p.to_path_buf()); self.config = path.map(|p| p.to_path_buf());
self self
} }
} }
impl Default for BeetsLibraryCommandExecutor {
/// Create a new [BeetsLibraryCommandExecutor] that uses the system's default beets executable.
fn default() -> Self {
BeetsLibraryCommandExecutor::new("beet")
}
}
impl BeetsLibraryExecutor for BeetsLibraryCommandExecutor { impl BeetsLibraryExecutor for BeetsLibraryCommandExecutor {
fn exec(&mut self, arguments: &[String]) -> Result<Vec<String>, Error> { fn exec(&mut self, arguments: &[String]) -> Result<Vec<String>, Error> {
let mut cmd = Command::new(&self.bin); let mut cmd = Command::new(&self.bin);

View File

@ -29,6 +29,7 @@ impl<T> QueryOption<T> {
} }
impl<T> Default for QueryOption<T> { impl<T> Default for QueryOption<T> {
/// Create a [QueryOption::None] for type `T`.
fn default() -> Self { fn default() -> Self {
Self::None Self::None
} }

View File

@ -36,9 +36,9 @@ struct Opt {
fn main() { fn main() {
let opt = Opt::from_args(); let opt = Opt::from_args();
let mut beets = BeetsLibrary::new(Box::new(unsafe { let mut beets = BeetsLibrary::new(Box::new(
BeetsLibraryCommandExecutor::default().config(opt.beets_config_file_path.as_deref()) BeetsLibraryCommandExecutor::default().config(opt.beets_config_file_path.as_deref()),
})); ));
let collection = beets let collection = beets
.list(&Query::new()) .list(&Query::new())

View File

@ -16,17 +16,17 @@ use musichoard::{
use crate::COLLECTION; use crate::COLLECTION;
static BEETS_EMPTY_CONFIG: Lazy<Arc<Mutex<BeetsLibrary>>> = Lazy::new(|| { static BEETS_EMPTY_CONFIG: Lazy<Arc<Mutex<BeetsLibrary>>> = Lazy::new(|| {
Arc::new(Mutex::new(BeetsLibrary::new(Box::new(unsafe { Arc::new(Mutex::new(BeetsLibrary::new(Box::new(
BeetsLibraryCommandExecutor::default() BeetsLibraryCommandExecutor::default(),
})))) ))))
}); });
static BEETS_TEST_CONFIG: Lazy<Arc<Mutex<BeetsLibrary>>> = Lazy::new(|| { static BEETS_TEST_CONFIG: Lazy<Arc<Mutex<BeetsLibrary>>> = Lazy::new(|| {
Arc::new(Mutex::new(BeetsLibrary::new(Box::new(unsafe { Arc::new(Mutex::new(BeetsLibrary::new(Box::new(
BeetsLibraryCommandExecutor::default().config(Some( BeetsLibraryCommandExecutor::default().config(Some(
&fs::canonicalize("./tests/files/library/config.yml").unwrap(), &fs::canonicalize("./tests/files/library/config.yml").unwrap(),
)) )),
})))) ))))
}); });
#[test] #[test]