From d765b3da73400fd3745631bae05b7ce5fb15d16b Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Fri, 3 Jan 2025 08:50:31 +0100 Subject: [PATCH 1/6] Commonise album lib id serde code --- src/external/database/serde/common.rs | 15 +++++++++++++++ src/external/database/serde/deserialize.rs | 15 +++------------ src/external/database/serde/serialize.rs | 18 +++--------------- 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/external/database/serde/common.rs b/src/external/database/serde/common.rs index ff75896..ff3e01f 100644 --- a/src/external/database/serde/common.rs +++ b/src/external/database/serde/common.rs @@ -13,6 +13,21 @@ pub enum AlbumLibIdDef { None, } +#[derive(Debug, Deserialize, Serialize)] +pub struct SerdeAlbumLibId(#[serde(with = "AlbumLibIdDef")] AlbumLibId); + +impl From for AlbumLibId { + fn from(value: SerdeAlbumLibId) -> Self { + value.0 + } +} + +impl From for SerdeAlbumLibId { + fn from(value: AlbumLibId) -> Self { + SerdeAlbumLibId(value) + } +} + #[derive(Debug, Deserialize, Serialize)] #[serde(remote = "MbRefOption")] pub enum MbRefOptionDef { diff --git a/src/external/database/serde/deserialize.rs b/src/external/database/serde/deserialize.rs index 49eeffc..4a361ab 100644 --- a/src/external/database/serde/deserialize.rs +++ b/src/external/database/serde/deserialize.rs @@ -4,7 +4,7 @@ use serde::{de::Visitor, Deserialize, Deserializer}; use crate::{ collection::{ - album::{AlbumInfo, AlbumLibId, AlbumMeta}, + album::{AlbumInfo, AlbumMeta}, artist::{ArtistInfo, ArtistMeta}, musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption, Mbid}, }, @@ -14,7 +14,7 @@ use crate::{ Collection, Error as CollectionError, }, external::database::serde::common::{ - AlbumLibIdDef, MbRefOptionDef, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType, + MbRefOptionDef, SerdeAlbumLibId, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType, }, }; @@ -45,22 +45,13 @@ pub struct DeserializeArtist { #[derive(Debug, Deserialize)] pub struct DeserializeAlbum { title: String, - lib_id: DeserializeAlbumLibId, + lib_id: SerdeAlbumLibId, seq: u8, musicbrainz: DeserializeMbRefOption, primary_type: Option, secondary_types: Vec, } -#[derive(Debug, Deserialize)] -pub struct DeserializeAlbumLibId(#[serde(with = "AlbumLibIdDef")] AlbumLibId); - -impl From for AlbumLibId { - fn from(value: DeserializeAlbumLibId) -> Self { - value.0 - } -} - #[derive(Debug, Deserialize)] pub struct DeserializeMbRefOption(#[serde(with = "MbRefOptionDef")] MbRefOption); diff --git a/src/external/database/serde/serialize.rs b/src/external/database/serde/serialize.rs index a895a22..70ab598 100644 --- a/src/external/database/serde/serialize.rs +++ b/src/external/database/serde/serialize.rs @@ -3,13 +3,10 @@ use std::collections::BTreeMap; use serde::Serialize; use crate::{ - collection::{ - album::AlbumLibId, - musicbrainz::{MbRefOption, Mbid}, - }, + collection::musicbrainz::{MbRefOption, Mbid}, core::collection::{album::Album, artist::Artist, musicbrainz::IMusicBrainzRef, Collection}, external::database::serde::common::{ - AlbumLibIdDef, MbRefOptionDef, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType, + MbRefOptionDef, SerdeAlbumLibId, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType, }, }; @@ -36,22 +33,13 @@ pub struct SerializeArtist<'a> { #[derive(Debug, Serialize)] pub struct SerializeAlbum<'a> { title: &'a str, - lib_id: SerializeAlbumLibId, + lib_id: SerdeAlbumLibId, seq: u8, musicbrainz: SerializeMbRefOption<'a>, primary_type: Option, secondary_types: Vec, } -#[derive(Debug, Serialize)] -pub struct SerializeAlbumLibId(#[serde(with = "AlbumLibIdDef")] AlbumLibId); - -impl From for SerializeAlbumLibId { - fn from(value: AlbumLibId) -> Self { - SerializeAlbumLibId(value) - } -} - #[derive(Debug, Serialize)] pub struct SerializeMbRefOption<'a>( #[serde(with = "MbRefOptionDef")] MbRefOption>, -- 2.47.1 From 36106a2c83b123af5dccd472fddcf1f79fd2be1e Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Fri, 3 Jan 2025 09:04:09 +0100 Subject: [PATCH 2/6] Add date to the database entries --- src/core/collection/album.rs | 5 +++- src/external/database/serde/common.rs | 29 +++++++++++++++++++--- src/external/database/serde/deserialize.rs | 20 +++++++-------- src/external/database/serde/serialize.rs | 9 ++++--- 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index 0d3fd74..d8bc3cd 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -65,7 +65,7 @@ impl MergeName for Album { // There are crates for handling dates, but we don't need much complexity beyond year-month-day. /// The album's release date. -#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] pub struct AlbumDate { pub year: Option, pub month: Option, @@ -271,6 +271,9 @@ impl Merge for AlbumMeta { fn merge_in_place(&mut self, other: Self) { assert!(self.id.compatible(&other.id)); self.id.mb_ref = self.id.mb_ref.take().or(other.id.mb_ref); + if self.date.year.is_none() && other.date.year.is_some() { + self.date = other.date; + } self.seq = std::cmp::max(self.seq, other.seq); self.info.merge_in_place(other.info); } diff --git a/src/external/database/serde/common.rs b/src/external/database/serde/common.rs index ff3e01f..1cc230e 100644 --- a/src/external/database/serde/common.rs +++ b/src/external/database/serde/common.rs @@ -1,8 +1,8 @@ use serde::{Deserialize, Serialize}; -use crate::{ - collection::musicbrainz::MbRefOption, - core::collection::album::{AlbumLibId, AlbumPrimaryType, AlbumSecondaryType}, +use crate::core::collection::{ + album::{AlbumDate, AlbumLibId, AlbumPrimaryType, AlbumSecondaryType}, + musicbrainz::MbRefOption, }; #[derive(Debug, Deserialize, Serialize)] @@ -28,6 +28,29 @@ impl From for SerdeAlbumLibId { } } +#[derive(Debug, Deserialize, Serialize)] +#[serde(remote = "AlbumDate")] +pub struct AlbumDateDef { + year: Option, + month: Option, + day: Option, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct SerdeAlbumDate(#[serde(with = "AlbumDateDef")] AlbumDate); + +impl From for AlbumDate { + fn from(value: SerdeAlbumDate) -> Self { + value.0 + } +} + +impl From for SerdeAlbumDate { + fn from(value: AlbumDate) -> Self { + SerdeAlbumDate(value) + } +} + #[derive(Debug, Deserialize, Serialize)] #[serde(remote = "MbRefOption")] pub enum MbRefOptionDef { diff --git a/src/external/database/serde/deserialize.rs b/src/external/database/serde/deserialize.rs index 4a361ab..182c9c6 100644 --- a/src/external/database/serde/deserialize.rs +++ b/src/external/database/serde/deserialize.rs @@ -3,30 +3,27 @@ use std::{collections::HashMap, fmt}; use serde::{de::Visitor, Deserialize, Deserializer}; use crate::{ - collection::{ - album::{AlbumInfo, AlbumMeta}, - artist::{ArtistInfo, ArtistMeta}, - musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption, Mbid}, - }, core::collection::{ - album::{Album, AlbumDate, AlbumId, AlbumSeq}, - artist::{Artist, ArtistId}, + album::{Album, AlbumId, AlbumInfo, AlbumMeta, AlbumSeq}, + artist::{Artist, ArtistId, ArtistInfo, ArtistMeta}, + musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption, Mbid}, Collection, Error as CollectionError, }, external::database::serde::common::{ - MbRefOptionDef, SerdeAlbumLibId, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType, + MbRefOptionDef, SerdeAlbumDate, SerdeAlbumLibId, SerdeAlbumPrimaryType, + SerdeAlbumSecondaryType, }, }; #[derive(Debug, Deserialize)] pub enum DeserializeDatabase { - V20250101(Vec), + V20250103(Vec), } impl From for Collection { fn from(database: DeserializeDatabase) -> Self { match database { - DeserializeDatabase::V20250101(collection) => { + DeserializeDatabase::V20250103(collection) => { collection.into_iter().map(Into::into).collect() } } @@ -46,6 +43,7 @@ pub struct DeserializeArtist { pub struct DeserializeAlbum { title: String, lib_id: SerdeAlbumLibId, + date: SerdeAlbumDate, seq: u8, musicbrainz: DeserializeMbRefOption, primary_type: Option, @@ -137,7 +135,7 @@ impl From for Album { lib_id: album.lib_id.into(), mb_ref: album.musicbrainz.into(), }, - date: AlbumDate::default(), + date: album.date.into(), seq: AlbumSeq(album.seq), info: AlbumInfo { primary_type: album.primary_type.map(Into::into), diff --git a/src/external/database/serde/serialize.rs b/src/external/database/serde/serialize.rs index 70ab598..a88657f 100644 --- a/src/external/database/serde/serialize.rs +++ b/src/external/database/serde/serialize.rs @@ -6,18 +6,19 @@ use crate::{ collection::musicbrainz::{MbRefOption, Mbid}, core::collection::{album::Album, artist::Artist, musicbrainz::IMusicBrainzRef, Collection}, external::database::serde::common::{ - MbRefOptionDef, SerdeAlbumLibId, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType, + MbRefOptionDef, SerdeAlbumDate, SerdeAlbumLibId, SerdeAlbumPrimaryType, + SerdeAlbumSecondaryType, }, }; #[derive(Debug, Serialize)] pub enum SerializeDatabase<'a> { - V20250101(Vec>), + V20250103(Vec>), } impl<'a> From<&'a Collection> for SerializeDatabase<'a> { fn from(collection: &'a Collection) -> Self { - SerializeDatabase::V20250101(collection.iter().map(Into::into).collect()) + SerializeDatabase::V20250103(collection.iter().map(Into::into).collect()) } } @@ -34,6 +35,7 @@ pub struct SerializeArtist<'a> { pub struct SerializeAlbum<'a> { title: &'a str, lib_id: SerdeAlbumLibId, + date: SerdeAlbumDate, seq: u8, musicbrainz: SerializeMbRefOption<'a>, primary_type: Option, @@ -92,6 +94,7 @@ impl<'a> From<&'a Album> for SerializeAlbum<'a> { SerializeAlbum { title: &album.meta.id.title, lib_id: album.meta.id.lib_id.into(), + date: album.meta.date.into(), seq: album.meta.seq.0, musicbrainz: (&album.meta.id.mb_ref).into(), primary_type: album.meta.info.primary_type.map(Into::into), -- 2.47.1 From 6329f472fcf191bbe9ab543791d97cb0b4fc67d9 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Fri, 3 Jan 2025 09:52:58 +0100 Subject: [PATCH 3/6] Minor unrelated fixes --- src/core/collection/album.rs | 11 +---------- src/core/collection/merge.rs | 4 ++-- src/core/musichoard/base.rs | 2 +- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index d8bc3cd..0bb0161 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -1,7 +1,4 @@ -use std::{ - fmt::{self, Display}, - mem, -}; +use std::mem; use crate::core::collection::{ merge::{Merge, MergeName, MergeSorted}, @@ -332,12 +329,6 @@ impl AlbumId { } } -impl Display for AlbumId { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.title) - } -} - #[cfg(test)] mod tests { use crate::core::testmod::FULL_COLLECTION; diff --git a/src/core/collection/merge.rs b/src/core/collection/merge.rs index 51b5b79..bbfc0fe 100644 --- a/src/core/collection/merge.rs +++ b/src/core/collection/merge.rs @@ -91,7 +91,7 @@ pub struct MergeCollections { impl MergeCollections where - T: MergeName + Merge + Ord, + T: MergeName + Merge, IT: IntoIterator)>, { pub fn merge_by_name(primary_items: &mut Vec, secondary: IT) { @@ -102,7 +102,7 @@ where assert_eq!(secondary_items.len(), 1); primary_item.merge_in_place(secondary_items.pop().unwrap()); } - None => primary_items.append(&mut secondary_items), + None => primary_items.extend(secondary_items), } } } diff --git a/src/core/musichoard/base.rs b/src/core/musichoard/base.rs index 32a429c..50c9340 100644 --- a/src/core/musichoard/base.rs +++ b/src/core/musichoard/base.rs @@ -110,7 +110,7 @@ impl IMusicHoardBasePrivate for MusicHoard Self::get_album_mut(artist, album_id).ok_or_else(|| { Error::CollectionError(format!( "album '{}' does not belong to the artist", - album_id + album_id.title )) }) } -- 2.47.1 From 7296b6f31df163f956798de11daf1bb1824a7d2a Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Fri, 3 Jan 2025 10:01:58 +0100 Subject: [PATCH 4/6] Fix tests --- src/core/collection/album.rs | 4 +-- src/external/database/json/mod.rs | 3 +-- src/external/database/json/testmod.rs | 39 +++++++++++++++++++-------- tests/database/json.rs | 3 +-- tests/files/database/database.json | 2 +- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index 0bb0161..b4c8c66 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -352,11 +352,11 @@ mod tests { let date: AlbumDate = (2024, 3, 2).into(); let album_id_1 = AlbumId::new("album z"); - let mut album_1 = Album::new(album_id_1).with_date(date.clone()); + let mut album_1 = Album::new(album_id_1).with_date(date); album_1.meta.set_seq(AlbumSeq(1)); let album_id_2 = AlbumId::new("album a"); - let mut album_2 = Album::new(album_id_2).with_date(date.clone()); + let mut album_2 = Album::new(album_id_2).with_date(date); album_2.meta.set_seq(AlbumSeq(2)); assert_ne!(album_1, album_2); diff --git a/src/external/database/json/mod.rs b/src/external/database/json/mod.rs index 126a4bd..0b7edf9 100644 --- a/src/external/database/json/mod.rs +++ b/src/external/database/json/mod.rs @@ -73,7 +73,7 @@ mod tests { use mockall::predicate; use crate::core::{ - collection::{album::AlbumDate, artist::Artist, Collection}, + collection::{artist::Artist, Collection}, testmod::FULL_COLLECTION, }; @@ -84,7 +84,6 @@ mod tests { let mut expected = FULL_COLLECTION.to_owned(); for artist in expected.iter_mut() { for album in artist.albums.iter_mut() { - album.meta.date = AlbumDate::default(); album.tracks.clear(); } } diff --git a/src/external/database/json/testmod.rs b/src/external/database/json/testmod.rs index 0f2f602..04fd2b1 100644 --- a/src/external/database/json/testmod.rs +++ b/src/external/database/json/testmod.rs @@ -1,5 +1,5 @@ pub static DATABASE_JSON: &str = "{\ - \"V20250101\":\ + \"V20250103\":\ [\ {\ \"name\":\"Album_Artist ‘A’\",\ @@ -11,12 +11,15 @@ pub static DATABASE_JSON: &str = "{\ },\ \"albums\":[\ {\ - \"title\":\"album_title a.a\",\"lib_id\":{\"Value\":1},\"seq\":1,\ + \"title\":\"album_title a.a\",\"lib_id\":{\"Value\":1},\ + \"date\":{\"year\":1998,\"month\":null,\"day\":null},\"seq\":1,\ \"musicbrainz\":{\"Some\":\"00000000-0000-0000-0000-000000000000\"},\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title a.b\",\"lib_id\":{\"Value\":2},\"seq\":1,\"musicbrainz\":\"None\",\ + \"title\":\"album_title a.b\",\"lib_id\":{\"Value\":2},\ + \"date\":{\"year\":2015,\"month\":4,\"day\":null},\"seq\":1,\ + \"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ @@ -35,21 +38,27 @@ pub static DATABASE_JSON: &str = "{\ },\ \"albums\":[\ {\ - \"title\":\"album_title b.a\",\"lib_id\":{\"Value\":3},\"seq\":1,\"musicbrainz\":\"None\",\ + \"title\":\"album_title b.a\",\"lib_id\":{\"Value\":3},\ + \"date\":{\"year\":2003,\"month\":6,\"day\":6},\"seq\":1,\ + \"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title b.b\",\"lib_id\":{\"Value\":4},\"seq\":3,\ + \"title\":\"album_title b.b\",\"lib_id\":{\"Value\":4},\ + \"date\":{\"year\":2008,\"month\":null,\"day\":null},\"seq\":3,\ \"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111111\"},\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title b.c\",\"lib_id\":{\"Value\":5},\"seq\":2,\ + \"title\":\"album_title b.c\",\"lib_id\":{\"Value\":5},\ + \"date\":{\"year\":2009,\"month\":null,\"day\":null},\"seq\":2,\ \"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111112\"},\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title b.d\",\"lib_id\":{\"Value\":6},\"seq\":4,\"musicbrainz\":\"None\",\ + \"title\":\"album_title b.d\",\"lib_id\":{\"Value\":6},\ + \"date\":{\"year\":2015,\"month\":null,\"day\":null},\"seq\":4,\ + \"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ @@ -61,11 +70,15 @@ pub static DATABASE_JSON: &str = "{\ \"properties\":{},\ \"albums\":[\ {\ - \"title\":\"album_title c.a\",\"lib_id\":{\"Value\":7},\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title c.a\",\"lib_id\":{\"Value\":7},\ + \"date\":{\"year\":1985,\"month\":null,\"day\":null},\"seq\":0,\ + \"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title c.b\",\"lib_id\":{\"Value\":8},\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title c.b\",\"lib_id\":{\"Value\":8},\ + \"date\":{\"year\":2018,\"month\":null,\"day\":null},\"seq\":0,\ + \"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ @@ -77,11 +90,15 @@ pub static DATABASE_JSON: &str = "{\ \"properties\":{},\ \"albums\":[\ {\ - \"title\":\"album_title d.a\",\"lib_id\":{\"Value\":9},\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title d.a\",\"lib_id\":{\"Value\":9},\ + \"date\":{\"year\":1995,\"month\":null,\"day\":null},\"seq\":0,\ + \"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title d.b\",\"lib_id\":{\"Value\":10},\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title d.b\",\"lib_id\":{\"Value\":10},\ + \"date\":{\"year\":2028,\"month\":null,\"day\":null},\"seq\":0,\ + \"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ diff --git a/tests/database/json.rs b/tests/database/json.rs index 2ee6755..da96d9e 100644 --- a/tests/database/json.rs +++ b/tests/database/json.rs @@ -4,7 +4,7 @@ use once_cell::sync::Lazy; use tempfile::NamedTempFile; use musichoard::{ - collection::{album::AlbumDate, artist::Artist, Collection}, + collection::{artist::Artist, Collection}, external::database::json::{backend::JsonDatabaseFileBackend, JsonDatabase}, interface::database::IDatabase, }; @@ -18,7 +18,6 @@ fn expected() -> Collection { let mut expected = COLLECTION.to_owned(); for artist in expected.iter_mut() { for album in artist.albums.iter_mut() { - album.meta.date = AlbumDate::default(); album.tracks.clear(); } } diff --git a/tests/files/database/database.json b/tests/files/database/database.json index 93fb18a..ccce86d 100644 --- a/tests/files/database/database.json +++ b/tests/files/database/database.json @@ -1 +1 @@ -{"V20250101":[{"name":"Аркона","sort":"Arkona","musicbrainz":{"Some":"baad262d-55ef-427a-83c7-f7530964f212"},"properties":{"Bandcamp":["https://arkonamoscow.bandcamp.com/"],"MusicButler":["https://www.musicbutler.io/artist-page/283448581"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/arkona/download-streaming-albums"]},"albums":[{"title":"Slovo","lib_id":{"Value":7},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":{"Some":"8000598a-5edb-401c-8e6d-36b167feaf38"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/269358403"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/eluveitie/download-streaming-albums"]},"albums":[{"title":"Vên [re‐recorded]","lib_id":{"Value":1},"seq":0,"musicbrainz":"None","primary_type":"Ep","secondary_types":[]},{"title":"Slania","lib_id":{"Value":2},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":{"Some":"3a901353-fccd-4afd-ad01-9c03f451b490"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/826588800"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/frontside/download-streaming-albums"]},"albums":[{"title":"…nasze jest królestwo, potęga i chwała na wieki…","lib_id":{"Value":3},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":{"Some":"c2c4d56a-d599-4a18-bd2f-ae644e2198cc"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/291158685"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/heaven-s-basement/download-streaming-albums"]},"albums":[{"title":"Paper Plague","lib_id":"Singleton","seq":0,"musicbrainz":"None","primary_type":null,"secondary_types":[]},{"title":"Unbreakable","lib_id":{"Value":4},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":{"Some":"65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/3996865"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/metallica/download-streaming-albums"]},"albums":[{"title":"Ride the Lightning","lib_id":{"Value":5},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]},{"title":"S&M","lib_id":{"Value":6},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":["Live"]}]}]} \ No newline at end of file +{"V20250103":[{"name":"Аркона","sort":"Arkona","musicbrainz":{"Some":"baad262d-55ef-427a-83c7-f7530964f212"},"properties":{"Bandcamp":["https://arkonamoscow.bandcamp.com/"],"MusicButler":["https://www.musicbutler.io/artist-page/283448581"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/arkona/download-streaming-albums"]},"albums":[{"title":"Slovo","lib_id":{"Value":7},"date":{"year":2011,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":{"Some":"8000598a-5edb-401c-8e6d-36b167feaf38"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/269358403"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/eluveitie/download-streaming-albums"]},"albums":[{"title":"Vên [re‐recorded]","lib_id":{"Value":1},"date":{"year":2004,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Ep","secondary_types":[]},{"title":"Slania","lib_id":{"Value":2},"date":{"year":2008,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":{"Some":"3a901353-fccd-4afd-ad01-9c03f451b490"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/826588800"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/frontside/download-streaming-albums"]},"albums":[{"title":"…nasze jest królestwo, potęga i chwała na wieki…","lib_id":{"Value":3},"date":{"year":2001,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":{"Some":"c2c4d56a-d599-4a18-bd2f-ae644e2198cc"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/291158685"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/heaven-s-basement/download-streaming-albums"]},"albums":[{"title":"Paper Plague","lib_id":"Singleton","date":{"year":2011,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":null,"secondary_types":[]},{"title":"Unbreakable","lib_id":{"Value":4},"date":{"year":2011,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":{"Some":"65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/3996865"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/metallica/download-streaming-albums"]},"albums":[{"title":"Ride the Lightning","lib_id":{"Value":5},"date":{"year":1984,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]},{"title":"S&M","lib_id":{"Value":6},"date":{"year":1999,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":["Live"]}]}]} \ No newline at end of file -- 2.47.1 From 19345d37ebb296fd4d2332d2cef2e3ca7991125b Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Fri, 3 Jan 2025 10:19:18 +0100 Subject: [PATCH 5/6] Add UT for date merge --- src/core/collection/album.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index b4c8c66..0833f67 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -419,4 +419,39 @@ mod tests { let merged = left.clone().merge(right); assert_eq!(expected, merged); } + + #[test] + fn merge_album_dates() { + let meta = AlbumMeta::new(AlbumId::new("An album")); + + // No merge if years are different. + let left = meta.clone().with_date((2000, 1, 6)); + let right = meta.clone().with_date((1000, 2, 7)); + let expected = meta.clone().with_date(left.date); + assert_eq!(expected, left.merge(right)); + + // No merge if years are the same but months/days are different. + let left = meta.clone().with_date((2000, 1, 6)); + let right = meta.clone().with_date((2000, 2, 7)); + let expected = meta.clone().with_date(left.date); + assert_eq!(expected, left.merge(right)); + + // No merge if right has no date. + let left = meta.clone().with_date((2000, 1, 6)); + let right = meta.clone(); + let expected = meta.clone().with_date(left.date); + assert_eq!(expected, left.merge(right)); + + // Merge if left has no date. + let left = meta.clone(); + let right = meta.clone().with_date((2000, 2, 7)); + let expected = meta.clone().with_date(right.date); + assert_eq!(expected, left.merge(right)); + + // Merge if left has no year but has months/days. + let left = meta.clone().with_date(AlbumDate::new(None, Some(1), Some(6))); + let right = meta.clone().with_date((2000, 2, 7)); + let expected = meta.clone().with_date(right.date); + assert_eq!(expected, left.merge(right)); + } } -- 2.47.1 From 5f6106ee29b7f8c4621aabbd1394d922ca921cb6 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Fri, 3 Jan 2025 10:23:19 +0100 Subject: [PATCH 6/6] Lint --- src/core/collection/album.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index 0833f67..cd53346 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -449,7 +449,9 @@ mod tests { assert_eq!(expected, left.merge(right)); // Merge if left has no year but has months/days. - let left = meta.clone().with_date(AlbumDate::new(None, Some(1), Some(6))); + let left = meta + .clone() + .with_date(AlbumDate::new(None, Some(1), Some(6))); let right = meta.clone().with_date((2000, 2, 7)); let expected = meta.clone().with_date(right.date); assert_eq!(expected, left.merge(right)); -- 2.47.1