mirror of
https://github.com/navidrome/navidrome.git
synced 2025-05-15 09:36:38 +03:00
fix(server): optimize playlist import
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
0954928b14
commit
19cbd93698
@ -9,6 +9,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -228,31 +229,39 @@ func (s *playlists) normalizePaths(ctx context.Context, pls *model.Playlist, fol
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Normalize paths to be relative to the library root. Search for roots in any library
|
|
||||||
var res []string
|
// Create regex patterns for each library path
|
||||||
|
patterns := make([]string, len(libs))
|
||||||
|
for i, lib := range libs {
|
||||||
|
cleanPath := filepath.Clean(lib.Path)
|
||||||
|
escapedPath := regexp.QuoteMeta(cleanPath)
|
||||||
|
patterns[i] = fmt.Sprintf("^%s(?:/|$)", escapedPath)
|
||||||
|
}
|
||||||
|
// Combine all patterns into a single regex
|
||||||
|
combinedPattern := strings.Join(patterns, "|")
|
||||||
|
libRegex := regexp.MustCompile(combinedPattern)
|
||||||
|
|
||||||
|
res := make([]string, 0, len(lines))
|
||||||
for idx, line := range lines {
|
for idx, line := range lines {
|
||||||
var libPath string
|
var libPath string
|
||||||
var filePath string
|
var filePath string
|
||||||
|
|
||||||
if folder != nil && !filepath.IsAbs(line) {
|
if folder != nil && !filepath.IsAbs(line) {
|
||||||
libPath = folder.LibraryPath
|
libPath = folder.LibraryPath
|
||||||
filePath = filepath.Join(folder.AbsolutePath(), line)
|
filePath = filepath.Join(folder.AbsolutePath(), line)
|
||||||
} else {
|
} else {
|
||||||
for _, lib := range libs {
|
cleanLine := filepath.Clean(line)
|
||||||
if strings.HasPrefix(line, lib.Path) {
|
if libPath = libRegex.FindString(cleanLine); libPath != "" {
|
||||||
libPath = lib.Path
|
filePath = cleanLine
|
||||||
filePath = line
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if libPath != "" {
|
if libPath != "" {
|
||||||
var err error
|
if rel, err := filepath.Rel(libPath, filePath); err == nil {
|
||||||
filePath, err = filepath.Rel(libPath, filePath)
|
res = append(res, rel)
|
||||||
if err != nil {
|
} else {
|
||||||
log.Trace(ctx, "Error getting relative path", "playlist", pls.Name, "path", line, "folder", folder, err)
|
log.Trace(ctx, "Error getting relative path", "playlist", pls.Name, "path", line, "folder", folder, err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
res = append(res, filePath)
|
|
||||||
} else {
|
} else {
|
||||||
log.Warn(ctx, "Path in playlist not found in any library", "path", line, "line", idx)
|
log.Warn(ctx, "Path in playlist not found in any library", "path", line, "line", idx)
|
||||||
}
|
}
|
||||||
|
@ -56,10 +56,9 @@ var _ = Describe("Playlists", func() {
|
|||||||
pls, err := ps.ImportFile(ctx, folder, "pls1.m3u")
|
pls, err := ps.ImportFile(ctx, folder, "pls1.m3u")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(pls.OwnerID).To(Equal("123"))
|
Expect(pls.OwnerID).To(Equal("123"))
|
||||||
Expect(pls.Tracks).To(HaveLen(3))
|
Expect(pls.Tracks).To(HaveLen(2))
|
||||||
Expect(pls.Tracks[0].Path).To(Equal("tests/fixtures/playlists/test.mp3"))
|
Expect(pls.Tracks[0].Path).To(Equal("tests/fixtures/playlists/test.mp3"))
|
||||||
Expect(pls.Tracks[1].Path).To(Equal("tests/fixtures/playlists/test.ogg"))
|
Expect(pls.Tracks[1].Path).To(Equal("tests/fixtures/playlists/test.ogg"))
|
||||||
Expect(pls.Tracks[2].Path).To(Equal("tests/fixtures/01 Invisible (RED) Edit Version.mp3"))
|
|
||||||
Expect(mockPlsRepo.last).To(Equal(pls))
|
Expect(mockPlsRepo.last).To(Equal(pls))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
3
tests/fixtures/playlists/pls1.m3u
vendored
3
tests/fixtures/playlists/pls1.m3u
vendored
@ -1,3 +1,2 @@
|
|||||||
test.mp3
|
test.mp3
|
||||||
test.ogg
|
test.ogg
|
||||||
file:///tests/fixtures/01%20Invisible%20(RED)%20Edit%20Version.mp3
|
|
@ -2,7 +2,6 @@ package tests
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io/fs"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
@ -18,7 +17,7 @@ func TempFileName(t testingT, prefix, suffix string) string {
|
|||||||
return filepath.Join(t.TempDir(), prefix+id.NewRandom()+suffix)
|
return filepath.Join(t.TempDir(), prefix+id.NewRandom()+suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TempFile(t testingT, prefix, suffix string) (fs.File, string, error) {
|
func TempFile(t testingT, prefix, suffix string) (*os.File, string, error) {
|
||||||
name := TempFileName(t, prefix, suffix)
|
name := TempFileName(t, prefix, suffix)
|
||||||
f, err := os.Create(name)
|
f, err := os.Create(name)
|
||||||
return f, name, err
|
return f, name, err
|
||||||
|
@ -140,7 +140,7 @@ var _ = Describe("Slice Utils", func() {
|
|||||||
Expect(count).To(Equal(expected))
|
Expect(count).To(Equal(expected))
|
||||||
},
|
},
|
||||||
Entry("returns empty slice for an empty input", "tests/fixtures/empty.txt", 0),
|
Entry("returns empty slice for an empty input", "tests/fixtures/empty.txt", 0),
|
||||||
Entry("returns the lines of a file", "tests/fixtures/playlists/pls1.m3u", 3),
|
Entry("returns the lines of a file", "tests/fixtures/playlists/pls1.m3u", 2),
|
||||||
Entry("returns empty if file does not exist", "tests/fixtures/NON-EXISTENT", 0),
|
Entry("returns empty if file does not exist", "tests/fixtures/NON-EXISTENT", 0),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user