mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-13 02:37:18 +03:00
Follow symlinks to directories when scanning
This commit is contained in:
parent
79c9d8f4f4
commit
5a072fbd10
@ -61,7 +61,12 @@ func (s *ChangeDetector) loadDir(dirPath string) (children []string, lastUpdated
|
||||
return
|
||||
}
|
||||
for _, f := range files {
|
||||
if f.IsDir() {
|
||||
isDir, err := IsDirOrSymlinkToDir(dirPath, f)
|
||||
// Skip invalid symlinks
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if isDir {
|
||||
children = append(children, filepath.Join(dirPath, f.Name()))
|
||||
} else {
|
||||
if f.ModTime().After(lastUpdated) {
|
||||
@ -72,6 +77,26 @@ func (s *ChangeDetector) loadDir(dirPath string) (children []string, lastUpdated
|
||||
return
|
||||
}
|
||||
|
||||
// IsDirOrSymlinkToDir returns true if and only if the Dirent represents a file
|
||||
// system directory, or a symbolic link to a directory. Note that if the Dirent
|
||||
// is not a directory but is a symbolic link, this method will resolve by
|
||||
// sending a request to the operating system to follow the symbolic link.
|
||||
// Copied from github.com/karrick/godirwalk
|
||||
func IsDirOrSymlinkToDir(baseDir string, info os.FileInfo) (bool, error) {
|
||||
if info.IsDir() {
|
||||
return true, nil
|
||||
}
|
||||
if info.Mode()&os.ModeSymlink == 0 {
|
||||
return false, nil
|
||||
}
|
||||
// Does this symlink point to a directory?
|
||||
info, err := os.Stat(filepath.Join(baseDir, info.Name()))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return info.IsDir(), nil
|
||||
}
|
||||
|
||||
func (s *ChangeDetector) loadMap(dirMap dirInfoMap, path string, since time.Time, maybe bool) error {
|
||||
children, lastUpdated, err := s.loadDir(path)
|
||||
if err != nil {
|
||||
|
@ -110,6 +110,25 @@ var _ = Describe("ChangeDetector", func() {
|
||||
Expect(deleted).To(BeEmpty())
|
||||
Expect(changed).To(ConsistOf(P("a/b")))
|
||||
})
|
||||
|
||||
Describe("IsDirOrSymlinkToDir", func() {
|
||||
It("returns true for normal dirs", func() {
|
||||
dir, _ := os.Stat("tests/fixtures")
|
||||
Expect(IsDirOrSymlinkToDir("tests", dir)).To(BeTrue())
|
||||
})
|
||||
It("returns true for symlinks to dirs", func() {
|
||||
dir, _ := os.Stat("tests/fixtures/symlink2dir")
|
||||
Expect(IsDirOrSymlinkToDir("tests/fixtures", dir)).To(BeTrue())
|
||||
})
|
||||
It("returns false for files", func() {
|
||||
dir, _ := os.Stat("tests/fixtures/test.mp3")
|
||||
Expect(IsDirOrSymlinkToDir("tests/fixtures", dir)).To(BeFalse())
|
||||
})
|
||||
It("returns false for symlinks to files", func() {
|
||||
dir, _ := os.Stat("tests/fixtures/symlink")
|
||||
Expect(IsDirOrSymlinkToDir("tests/fixtures", dir)).To(BeFalse())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// I hate time-based tests....
|
||||
|
1
tests/fixtures/symlink
vendored
Symbolic link
1
tests/fixtures/symlink
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
index.html
|
1
tests/fixtures/symlink2dir
vendored
Symbolic link
1
tests/fixtures/symlink2dir
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../
|
1
tests/fixtures/synlink_invalid
vendored
Symbolic link
1
tests/fixtures/synlink_invalid
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
INVALID
|
Loading…
x
Reference in New Issue
Block a user