diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index f300d07..a34f221 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -27,4 +27,4 @@ jobs: - name: Build run: cargo build --verbose - name: Run tests - run: cargo test --verbose --features=integration-tests + run: cargo test --verbose --features=integration-tests --test-threads=1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7354219..a9d1bd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog ## blissify 0.5.2 +* Put the `--config-path` argument after the subcommand for consistency's sake. +* Use XDG_CONFIG_HOME instead of XDG_DATA_HOME to put config files, making + sure to still check XDG_DATA_HOME for users with an existing database. * Integration tests can now be run using `cargo test --features=integration-tests`. ## blissify 0.5.1 diff --git a/Cargo.lock b/Cargo.lock index 3f4a140..96ac641 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -139,8 +139,7 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bliss-audio" version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7550cbcf4faf8d9fb8db7ddaabda90eaa84a234142c06066c84c7bcd860fced7" +source = "git+https://github.com/Polochon-street/bliss-rs?branch=library-change-xdg-thing#599c7a8ae038210b770b47669dc3a07c3b4c4c40" dependencies = [ "adler32", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index acdb417..b2c46b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ rpi = ["bliss-audio/rpi"] integration-tests = ["bliss-audio/integration-tests"] [dependencies] -bliss-audio = "0.9.2" +bliss-audio = {git = "https://github.com/Polochon-street/bliss-rs", branch = "library-change-xdg-thing"} mpd = "0.1.0" dirs = "3.0.1" tempdir = "0.3.7" diff --git a/README.md b/README.md index 6feab10..df6b33b 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,10 @@ It will create a configuration file `config.json` and a database file `songs.db` in `~/.local/share/bliss-rs`. If you want to specify a different path for the configuration file and the database file, running ``` -$ blissify -c /path/to/configuration.json init -d /path/to/database.db /path/to/mpd/root +$ blissify init -d /path/to/database.db /path/to/mpd/root -c /path/to/configuration.json ``` should do the trick. All the subsequent blissify commands should start -with `blissify -c /path/to/configuration.json` in order to work. +with `blissify -c /path/to/configuration.json` in order to work. Note that it may take several minutes (up to some hours, on very large libraries with more than for instance 20k songs) to complete. diff --git a/src/main.rs b/src/main.rs index 4289c83..485c6fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -805,20 +805,20 @@ fn parse_number_cores(matches: &ArgMatches) -> Result, Blis fn main() -> Result<()> { env_logger::init_from_env(env_logger::Env::default().filter_or("RUST_LOG", "warn")); + let config_argument = Arg::with_name("config-path") + .short("c") + .long("config-path") + .help( + "Optional argument specifying the configuration path, for both loading and initializing blissify. Example: \"/path/to/config.json\". If not specified, defaults to \"XDG_CONFIG_HOME/bliss-rs/config.json\", e.g. \"/home/user/.config/bliss-rs/config.json\".", + ) + .required(false) + .takes_value(true); let matches = App::new("blissify") .version(env!("CARGO_PKG_VERSION")) .author("Polochon_street") .about("Analyze and make smart playlists from an MPD music database.") - .arg(Arg::with_name("config-path") - .short("c") - .long("config-path") - .help( - "Optional argument specifying the configuration path, for both loading and initializing blissify. Example: \"/path/to/config.json\".", - ) - .required(false) - .takes_value(true) - ) + .arg(config_argument.clone().hidden(true)) .subcommand( SubCommand::with_name("list-db") .about("Print songs that have been analyzed and are in blissify's database.") @@ -826,19 +826,27 @@ fn main() -> Result<()> { .takes_value(false) .help("Display analyzed song paths, as well as the corresponding analysis.") ) + .arg(config_argument.clone()) ) .subcommand( SubCommand::with_name("init") - .about("Initializes an MPD library") + .about( + "Initialize blissify on an MPD library.\n\ + By default, it creates the configuration folder \"bliss-rs\" \ + in XDG_CONFIG_HOME, most likely `/home/user/.config/bliss-rs`, \ + and analyzes the songs in the given MPD library.\n\ + It can take some time." + ) .arg(Arg::with_name("MPD_BASE_PATH") .help("MPD base path. The value of `music_directory` in your mpd.conf.") .required(true) ) + .arg(config_argument.clone()) .arg(Arg::with_name("database-path") .short("d") .long("database-path") .help( - "Optional argument specifying where to store the database containing analyzed songs. Example: \"/path/to/bliss.db\"", + "Optional argument specifying where to store the database containing analyzed songs. Example: \"/path/to/bliss.db\". If not specified, defaults to \"XDG_CONFIG_HOME/bliss-rs/songs.db\", e.g. \"/home/user/.config/bliss-rs/songs.db\"." ) .required(false) .takes_value(true) @@ -854,6 +862,7 @@ Useful to avoid a too heavy load on a machine.") ) .subcommand( SubCommand::with_name("rescan") + .arg(config_argument.clone()) .arg(Arg::with_name("number-cores") .long("number-cores") .help( @@ -866,6 +875,7 @@ Useful to avoid a too heavy load on a machine.") ) .subcommand( SubCommand::with_name("update") + .arg(config_argument.clone()) .arg(Arg::with_name("number-cores") .long("number-cores") .help( @@ -879,6 +889,7 @@ Useful to avoid a too heavy load on a machine.") .subcommand( SubCommand::with_name("playlist") .about("Make a playlist from the currently playing song, clearing the queue and queuing NUMBER_SONGS songs similar to the currently playing song. See the other flags if you want to e.g. preserve the queue.") + .arg(config_argument.clone()) .arg(Arg::with_name("NUMBER_SONGS") .help("Number of items to queue, including the first song.") .required(true) @@ -942,6 +953,7 @@ Useful to avoid a too heavy load on a machine.") .about( "Make a playlist, prompting a set of close songs, and asking which one will be the most appropriate." ) + .arg(config_argument.clone()) .arg(Arg::with_name("continue") .long("continue") .help( @@ -960,7 +972,13 @@ Defaults to 3, cannot be more than 9." ) .get_matches(); - let config_path = matches.value_of("config-path").map(PathBuf::from); + let mut config_path = match matches.subcommand() { + (_, Some(sub_m)) => sub_m.value_of("config-path").map(PathBuf::from), + _ => None, + }; + if config_path.is_none() { + config_path = matches.value_of("config-path").map(PathBuf::from); + } if let Some(sub_m) = matches.subcommand_matches("list-db") { let library = MPDLibrary::from_config_path(config_path)?; let mut songs: Vec> = library.library.songs_from_library()?; diff --git a/tests/cli.rs b/tests/cli.rs index a9fd6d6..0c96d5e 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -20,9 +20,9 @@ mod tests { "#; struct TestSettings { - mpd_conf_file: assert_fs::NamedTempFile, + _mpd_conf_file: assert_fs::NamedTempFile, socket_file: assert_fs::NamedTempFile, - handle: Child, + _handle: Child, } fn start_mpd() -> Result> { @@ -47,9 +47,9 @@ mod tests { .spawn()?; Ok(TestSettings { - mpd_conf_file, + _mpd_conf_file: mpd_conf_file, socket_file, - handle, + _handle: handle, }) } @@ -105,12 +105,12 @@ mod tests { } let mut cmd = Command::cargo_bin("blissify")?; - cmd.arg("-c") - .arg(temp_dir.path().join("test.json")) - .arg("init") + cmd.arg("init") .arg(data_directory) .arg("-d") .arg(temp_dir.path().join("test.db")) + .arg("-c") + .arg(temp_dir.path().join("test.json")) .env("MPD_HOST", socket_path); cmd.assert().success(); assert!(temp_dir.path().join("test.json").exists()); @@ -122,6 +122,12 @@ mod tests { fn test_list_db_fail() -> Result<(), Box> { let mut cmd = Command::cargo_bin("blissify")?; + cmd.arg("list-db").arg("-c").arg("/tmp/nonexisting"); + cmd.assert() + .failure() + .stderr(predicate::str::contains("No such file or directory")); + + let mut cmd = Command::cargo_bin("blissify")?; cmd.arg("-c").arg("/tmp/nonexisting").arg("list-db"); cmd.assert() .failure()