Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan 2025-11-07 16:54:07 -05:00
parent 0248a23f96
commit 107f1a4359
2 changed files with 18 additions and 27 deletions

View File

@ -315,20 +315,12 @@ type pathResolver struct {
// newPathResolver creates a pathResolver with libraries loaded from the datastore. // newPathResolver creates a pathResolver with libraries loaded from the datastore.
func newPathResolver(ctx context.Context, ds model.DataStore) (*pathResolver, error) { func newPathResolver(ctx context.Context, ds model.DataStore) (*pathResolver, error) {
matcher, err := buildLibraryMatcher(ctx, ds)
if err != nil {
return nil, err
}
return &pathResolver{matcher: matcher}, nil
}
// buildLibraryMatcher creates a libraryMatcher with libraries sorted by path length (longest first).
func buildLibraryMatcher(ctx context.Context, ds model.DataStore) (*libraryMatcher, error) {
libs, err := ds.Library(ctx).GetAll() libs, err := ds.Library(ctx).GetAll()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return newLibraryMatcher(libs), nil matcher := newLibraryMatcher(libs)
return &pathResolver{matcher: matcher}, nil
} }
// resolvePath determines the absolute path and library path for a playlist entry. // resolvePath determines the absolute path and library path for a playlist entry.

View File

@ -10,7 +10,7 @@ import (
"golang.org/x/text/unicode/norm" "golang.org/x/text/unicode/norm"
) )
var _ = Describe("buildLibraryMatcher", func() { var _ = Describe("libraryMatcher", func() {
var ds *tests.MockDataStore var ds *tests.MockDataStore
var mockLibRepo *tests.MockLibraryRepo var mockLibRepo *tests.MockLibraryRepo
ctx := context.Background() ctx := context.Background()
@ -22,6 +22,13 @@ var _ = Describe("buildLibraryMatcher", func() {
} }
}) })
// Helper function to create a libraryMatcher from the mock datastore
createMatcher := func(ds model.DataStore) *libraryMatcher {
libs, err := ds.Library(ctx).GetAll()
Expect(err).ToNot(HaveOccurred())
return newLibraryMatcher(libs)
}
Describe("Longest library path matching", func() { Describe("Longest library path matching", func() {
It("matches the longest library path when multiple libraries share a prefix", func() { It("matches the longest library path when multiple libraries share a prefix", func() {
// Setup libraries with prefix conflicts // Setup libraries with prefix conflicts
@ -31,8 +38,7 @@ var _ = Describe("buildLibraryMatcher", func() {
{ID: 3, Path: "/music-classical/opera"}, {ID: 3, Path: "/music-classical/opera"},
}) })
matcher, err := buildLibraryMatcher(ctx, ds) matcher := createMatcher(ds)
Expect(err).ToNot(HaveOccurred())
// Test that longest path matches first and returns correct library ID // Test that longest path matches first and returns correct library ID
testCases := []struct { testCases := []struct {
@ -59,8 +65,7 @@ var _ = Describe("buildLibraryMatcher", func() {
{ID: 2, Path: "/home/user/music-backup"}, {ID: 2, Path: "/home/user/music-backup"},
}) })
matcher, err := buildLibraryMatcher(ctx, ds) matcher := createMatcher(ds)
Expect(err).ToNot(HaveOccurred())
// Test that music-backup library is matched correctly // Test that music-backup library is matched correctly
libID, libPath := matcher.findLibraryForPath("/home/user/music-backup/track.mp3") libID, libPath := matcher.findLibraryForPath("/home/user/music-backup/track.mp3")
@ -79,8 +84,7 @@ var _ = Describe("buildLibraryMatcher", func() {
{ID: 2, Path: "/music-classical"}, {ID: 2, Path: "/music-classical"},
}) })
matcher, err := buildLibraryMatcher(ctx, ds) matcher := createMatcher(ds)
Expect(err).ToNot(HaveOccurred())
// Exact library path should match // Exact library path should match
libID, libPath := matcher.findLibraryForPath("/music-classical") libID, libPath := matcher.findLibraryForPath("/music-classical")
@ -96,8 +100,7 @@ var _ = Describe("buildLibraryMatcher", func() {
{ID: 4, Path: "/media/audio/classical/baroque"}, {ID: 4, Path: "/media/audio/classical/baroque"},
}) })
matcher, err := buildLibraryMatcher(ctx, ds) matcher := createMatcher(ds)
Expect(err).ToNot(HaveOccurred())
testCases := []struct { testCases := []struct {
path string path string
@ -122,8 +125,7 @@ var _ = Describe("buildLibraryMatcher", func() {
It("handles empty library list", func() { It("handles empty library list", func() {
mockLibRepo.SetData([]model.Library{}) mockLibRepo.SetData([]model.Library{})
matcher, err := buildLibraryMatcher(ctx, ds) matcher := createMatcher(ds)
Expect(err).ToNot(HaveOccurred())
Expect(matcher).ToNot(BeNil()) Expect(matcher).ToNot(BeNil())
// Should not match anything // Should not match anything
@ -137,8 +139,7 @@ var _ = Describe("buildLibraryMatcher", func() {
{ID: 1, Path: "/music"}, {ID: 1, Path: "/music"},
}) })
matcher, err := buildLibraryMatcher(ctx, ds) matcher := createMatcher(ds)
Expect(err).ToNot(HaveOccurred())
libID, libPath := matcher.findLibraryForPath("/music/track.mp3") libID, libPath := matcher.findLibraryForPath("/music/track.mp3")
Expect(libID).To(Equal(1)) Expect(libID).To(Equal(1))
@ -151,8 +152,7 @@ var _ = Describe("buildLibraryMatcher", func() {
{ID: 2, Path: "/music(backup)"}, {ID: 2, Path: "/music(backup)"},
}) })
matcher, err := buildLibraryMatcher(ctx, ds) matcher := createMatcher(ds)
Expect(err).ToNot(HaveOccurred())
Expect(matcher).ToNot(BeNil()) Expect(matcher).ToNot(BeNil())
// Special characters should match literally // Special characters should match literally
@ -170,8 +170,7 @@ var _ = Describe("buildLibraryMatcher", func() {
{ID: 3, Path: "/abc"}, {ID: 3, Path: "/abc"},
}) })
matcher, err := buildLibraryMatcher(ctx, ds) matcher := createMatcher(ds)
Expect(err).ToNot(HaveOccurred())
// Verify that longer paths match correctly (not cut off by shorter prefix) // Verify that longer paths match correctly (not cut off by shorter prefix)
testCases := []struct { testCases := []struct {