feat: an album holding a song twice beside its single keeps one copy (#5401)
A cross-release group was only ever linked, never merged, so an album that held the song twice among the releases kept both: Humanz has Saturnz Barz, Andromeda, We Got the Power and Garage Palace as its FLAC and a YouTube mp3, each beside the single. The resolver now merges an album's extra copies into its best (the one that is not a video rip, else ProposeSurvivor: lossless first) with ReplaceTrack, history and all, then links what is left as one song. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,8 @@ package library
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
@@ -218,3 +220,68 @@ func songKeys(t *testing.T, q *dbq.Queries, ids ...pgtype.UUID) []pgtype.UUID {
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// A cross-release group whose album holds the song twice (Humanz: Saturnz
|
||||
// Barz as a FLAC and a YouTube mp3, beside the single, #5401): the album's
|
||||
// extra copy is merged into its FLAC, the single stays, and the two copies
|
||||
// left are linked as one song.
|
||||
func TestResolveDuplicates_FoldsAnAlbumsExtraCopyInACrossReleaseGroup_Integration(t *testing.T) {
|
||||
pool := newPool(t)
|
||||
ctx := context.Background()
|
||||
q := dbq.New(pool)
|
||||
dir := t.TempDir()
|
||||
artist, err := q.UpsertArtist(ctx, dbq.UpsertArtistParams{Name: "Gorillaz", SortName: "Gorillaz"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
track := func(album, name, format string) dbq.Track {
|
||||
t.Helper()
|
||||
a, err := q.UpsertAlbum(ctx, dbq.UpsertAlbumParams{Title: album, SortTitle: album, ArtistID: artist.ID})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
path := filepath.Join(dir, album, name)
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(path, []byte("audio"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tr, err := q.UpsertTrack(ctx, dbq.UpsertTrackParams{
|
||||
Title: "Saturnz Barz", AlbumID: a.ID, ArtistID: artist.ID,
|
||||
DurationMs: 181000, FilePath: path, FileSize: 100, FileFormat: format,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return tr
|
||||
}
|
||||
flac := track("Humanz", "04 Saturnz Barz.flac", "flac")
|
||||
mp3 := track("Humanz", "06 Saturnz Barz (feat. Popcaan).mp3", "mp3")
|
||||
single := track("Saturnz Barz", "01 Saturnz Barz.mp3", "mp3")
|
||||
var groupID pgtype.UUID
|
||||
if err := pool.QueryRow(ctx,
|
||||
`INSERT INTO duplicate_groups (member_key, tier) VALUES ('humanz-saturnz', 'exact') RETURNING id`,
|
||||
).Scan(&groupID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := pool.Exec(ctx, `INSERT INTO duplicate_group_members (group_id, track_id) VALUES ($1, $2), ($1, $3), ($1, $4)`,
|
||||
groupID, flac.ID, mp3.ID, single.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
res, err := ResolveDuplicates(ctx, pool, nil, "", true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if res.Merged != 1 || exists(mp3.FilePath) || !exists(flac.FilePath) || !exists(single.FilePath) {
|
||||
t.Fatalf("result %+v, mp3 %v flac %v single %v; want only the album's mp3 merged away",
|
||||
res, exists(mp3.FilePath), exists(flac.FilePath), exists(single.FilePath))
|
||||
}
|
||||
if _, err := q.GetTrackByID(ctx, mp3.ID); err == nil {
|
||||
t.Error("the album's extra copy is still a track")
|
||||
}
|
||||
if res.SongsLinked != 1 {
|
||||
t.Errorf("songs linked = %d, want the FLAC and the single linked as one song", res.SongsLinked)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user