add scanner.scanDir
This commit is contained in:
@@ -57,20 +57,6 @@ type ScanOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scanner) ScanAndClean(opts ScanOptions) error {
|
func (s *Scanner) ScanAndClean(opts ScanOptions) error {
|
||||||
c := &collected{
|
|
||||||
seenTracks: map[int]struct{}{},
|
|
||||||
seenAlbums: map[int]struct{}{},
|
|
||||||
}
|
|
||||||
if err := s.scan(c, opts.IsFull); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.clean(c); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Scanner) scan(c *collected, isFull bool) error {
|
|
||||||
if s.IsScanning() {
|
if s.IsScanning() {
|
||||||
return ErrAlreadyScanning
|
return ErrAlreadyScanning
|
||||||
}
|
}
|
||||||
@@ -78,7 +64,11 @@ func (s *Scanner) scan(c *collected, isFull bool) error {
|
|||||||
defer atomic.StoreInt32(s.scanning, 0)
|
defer atomic.StoreInt32(s.scanning, 0)
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
itemErrs := multierr.Err{}
|
itemErrs := &multierr.Err{}
|
||||||
|
c := &collected{
|
||||||
|
seenTracks: map[int]struct{}{},
|
||||||
|
seenAlbums: map[int]struct{}{},
|
||||||
|
}
|
||||||
|
|
||||||
log.Println("starting scan")
|
log.Println("starting scan")
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -87,26 +77,29 @@ func (s *Scanner) scan(c *collected, isFull bool) error {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
for _, musicPath := range s.musicPaths {
|
for _, musicPath := range s.musicPaths {
|
||||||
err := godirwalk.Walk(musicPath, &godirwalk.Options{
|
err := s.scanPath(c, opts.IsFull, musicPath)
|
||||||
Callback: func(_ string, _ *godirwalk.Dirent) error {
|
var subItemErrs *multierr.Err
|
||||||
return nil
|
switch {
|
||||||
},
|
case errors.As(err, &subItemErrs):
|
||||||
PostChildrenCallback: func(itemPath string, _ *godirwalk.Dirent) error {
|
itemErrs.Extend(subItemErrs.Errors())
|
||||||
log.Printf("processing folder `%s`", itemPath)
|
case err != nil:
|
||||||
return s.callback(c, isFull, musicPath, itemPath)
|
return fmt.Errorf("scan %q: %w", musicPath, err)
|
||||||
},
|
|
||||||
Unsorted: !s.sorted,
|
|
||||||
FollowSymbolicLinks: true,
|
|
||||||
ErrorCallback: func(path string, err error) godirwalk.ErrorAction {
|
|
||||||
itemErrs.Add(fmt.Errorf("%q: %w", path, err))
|
|
||||||
return godirwalk.SkipNode
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("walking filesystem: %w", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := s.cleanTracks(c.seenTracks); err != nil {
|
||||||
|
return fmt.Errorf("clean tracks: %w", err)
|
||||||
|
}
|
||||||
|
if err := s.cleanAlbums(c.seenAlbums); err != nil {
|
||||||
|
return fmt.Errorf("clean albums: %w", err)
|
||||||
|
}
|
||||||
|
if err := s.cleanArtists(); err != nil {
|
||||||
|
return fmt.Errorf("clean artists: %w", err)
|
||||||
|
}
|
||||||
|
if err := s.cleanGenres(); err != nil {
|
||||||
|
return fmt.Errorf("clean genres: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.db.SetSetting("last_scan_time", strconv.FormatInt(time.Now().Unix(), 10)); err != nil {
|
if err := s.db.SetSetting("last_scan_time", strconv.FormatInt(time.Now().Unix(), 10)); err != nil {
|
||||||
return fmt.Errorf("set scan time: %w", err)
|
return fmt.Errorf("set scan time: %w", err)
|
||||||
}
|
}
|
||||||
@@ -118,28 +111,31 @@ func (s *Scanner) scan(c *collected, isFull bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scanner) clean(c *collected) error {
|
func (s *Scanner) scanPath(c *collected, isFull bool, musicPath string) error {
|
||||||
if err := s.cleanTracks(c.seenTracks); err != nil {
|
itemErrs := multierr.Err{}
|
||||||
return fmt.Errorf("clean tracks: %w", err)
|
return godirwalk.Walk(musicPath, &godirwalk.Options{
|
||||||
}
|
Callback: func(_ string, _ *godirwalk.Dirent) error {
|
||||||
if err := s.cleanAlbums(c.seenAlbums); err != nil {
|
return nil
|
||||||
return fmt.Errorf("clean albums: %w", err)
|
},
|
||||||
}
|
PostChildrenCallback: func(itemPath string, _ *godirwalk.Dirent) error {
|
||||||
if err := s.cleanArtists(); err != nil {
|
return s.callback(c, isFull, musicPath, itemPath)
|
||||||
return fmt.Errorf("clean artists: %w", err)
|
},
|
||||||
}
|
Unsorted: !s.sorted,
|
||||||
if err := s.cleanGenres(); err != nil {
|
FollowSymbolicLinks: true,
|
||||||
return fmt.Errorf("clean genres: %w", err)
|
ErrorCallback: func(path string, err error) godirwalk.ErrorAction {
|
||||||
}
|
itemErrs.Add(fmt.Errorf("%q: %w", path, err))
|
||||||
return nil
|
return godirwalk.SkipNode
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scanner) callback(c *collected, isFull bool, rootAbsPath string, itemAbsPath string) error {
|
func (s *Scanner) callback(c *collected, isFull bool, rootAbsPath string, itemAbsPath string) error {
|
||||||
|
relpath, _ := filepath.Rel(rootAbsPath, itemAbsPath)
|
||||||
|
log.Printf("processing folder `%s`", relpath)
|
||||||
if rootAbsPath == itemAbsPath {
|
if rootAbsPath == itemAbsPath {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
relpath, _ := filepath.Rel(rootAbsPath, itemAbsPath)
|
|
||||||
gs, err := godirwalk.NewScanner(itemAbsPath)
|
gs, err := godirwalk.NewScanner(itemAbsPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
Reference in New Issue
Block a user