mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-08 02:17:25 +02:00
Merge b33b351dee into 52135913d4
This commit is contained in:
commit
6b2e9924f9
5 changed files with 32 additions and 5 deletions
|
|
@ -90,6 +90,7 @@ const (
|
|||
|
||||
I18nFolder = "i18n"
|
||||
ScanIgnoreFile = ".ndignore"
|
||||
NoMediaFile = ".nomedia"
|
||||
ArtworkFolder = "artwork"
|
||||
// HashedArtworkFolder is a subtree of ArtworkFolder, kept apart from the name-addressed
|
||||
// upload folders beside it so Prune's sweep never reaches them.
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ flowchart TD
|
|||
1. **Folder Traversal**
|
||||
- Uses `walkDirTree` to traverse the directory structure
|
||||
- Handles symbolic links and hidden files
|
||||
- Processes `.ndignore` files for exclusions
|
||||
- Processes `.ndignore` files for exclusions, and skips folders containing a `.nomedia` file
|
||||
- Maps files to appropriate types (audio, image, playlist)
|
||||
|
||||
2. **Metadata Extraction**
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import (
|
|||
ignore "github.com/sabhiram/go-gitignore"
|
||||
)
|
||||
|
||||
const ignoreAllPattern = "**/*"
|
||||
|
||||
// IgnoreChecker manages .ndignore patterns using a stack-based approach.
|
||||
// Use Push() to add patterns when entering a folder, Pop() when leaving,
|
||||
// and ShouldIgnore() to check if a path should be ignored.
|
||||
|
|
@ -102,8 +104,13 @@ func (ic *IgnoreChecker) ShouldIgnore(ctx context.Context, relPath string) bool
|
|||
|
||||
// loadPatternsFromFolder reads the .ndignore file in the specified folder and returns the patterns.
|
||||
// If the file doesn't exist, returns an empty slice.
|
||||
// If the file exists but is empty, returns a pattern to ignore everything ("**/*").
|
||||
// If the file exists but is empty, or a .nomedia file exists, returns a pattern to ignore everything.
|
||||
func (ic *IgnoreChecker) loadPatternsFromFolder(ctx context.Context, folder string) []string {
|
||||
if _, err := fs.Stat(ic.fsys, path.Join(folder, consts.NoMediaFile)); err == nil {
|
||||
log.Trace(ctx, "Scanner: .nomedia file found, ignoring everything", "path", folder)
|
||||
return []string{ignoreAllPattern}
|
||||
}
|
||||
|
||||
ignoreFilePath := path.Join(folder, consts.ScanIgnoreFile)
|
||||
var patterns []string
|
||||
|
||||
|
|
@ -138,7 +145,7 @@ func (ic *IgnoreChecker) loadPatternsFromFolder(ctx context.Context, folder stri
|
|||
// If the .ndignore file is empty, ignore everything
|
||||
if len(patterns) == 0 {
|
||||
log.Trace(ctx, "Scanner: .ndignore file is empty, ignoring everything", "path", folder)
|
||||
patterns = []string{"**/*"}
|
||||
patterns = []string{ignoreAllPattern}
|
||||
}
|
||||
|
||||
return patterns
|
||||
|
|
|
|||
|
|
@ -37,6 +37,20 @@ var _ = Describe("IgnoreChecker", func() {
|
|||
})
|
||||
})
|
||||
|
||||
DescribeTable("when .nomedia file exists",
|
||||
func(files fstest.MapFS) {
|
||||
ic = newIgnoreChecker(files)
|
||||
patterns := ic.loadPatternsFromFolder(ctx, ".")
|
||||
Expect(patterns).To(Equal([]string{"**/*"}))
|
||||
},
|
||||
Entry("empty", fstest.MapFS{".nomedia": &fstest.MapFile{}}),
|
||||
Entry("with content", fstest.MapFS{".nomedia": &fstest.MapFile{Data: []byte("*.txt")}}),
|
||||
Entry("alongside .ndignore", fstest.MapFS{
|
||||
".nomedia": &fstest.MapFile{},
|
||||
".ndignore": &fstest.MapFile{Data: []byte("*.txt")},
|
||||
}),
|
||||
)
|
||||
|
||||
DescribeTable("parsing .ndignore content",
|
||||
func(content string, expectedPatterns []string) {
|
||||
fsys := fstest.MapFS{
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ var _ = Describe("walk_dir_tree", func() {
|
|||
"root/h/.hidden.mp3": {},
|
||||
"root/i/.git/config": {},
|
||||
"root/i/.streams/stream.mp3": {},
|
||||
"root/j/.nomedia": {},
|
||||
"root/j/f1.mp3": {},
|
||||
"root/j/sub/f2.mp3": {},
|
||||
},
|
||||
}
|
||||
job = &scanJob{
|
||||
|
|
@ -100,6 +103,8 @@ var _ = Describe("walk_dir_tree", func() {
|
|||
Expect(folders["root/c"].audioFiles).To(BeEmpty())
|
||||
Expect(folders["root/c"].imageFiles).To(BeEmpty())
|
||||
Expect(folders).ToNot(HaveKey("root/d"))
|
||||
Expect(folders["root/j"].audioFiles).To(BeEmpty())
|
||||
Expect(folders).ToNot(HaveKey("root/j/sub"))
|
||||
|
||||
// By default (Scanner.IgnoreDotFolders == true), dot-prefixed
|
||||
// folders are skipped, dot-prefixed files are not indexed, and
|
||||
|
|
@ -122,8 +127,8 @@ var _ = Describe("walk_dir_tree", func() {
|
|||
Expect(folders["root/f"].audioFiles).ToNot(HaveKey("evil.mp3"))
|
||||
}
|
||||
},
|
||||
Entry("with symlinks enabled", true, 11),
|
||||
Entry("with symlinks disabled", false, 10),
|
||||
Entry("with symlinks enabled", true, 12),
|
||||
Entry("with symlinks disabled", false, 11),
|
||||
)
|
||||
|
||||
DescribeTable("dot-prefixed folders with IgnoreDotFolders disabled",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue