@@ -17,6 +17,7 @@ import (
1717 "sync/atomic"
1818 "time"
1919
20+ "github.com/djherbis/times"
2021 "github.com/fsnotify/fsnotify"
2122 "github.com/jinzhu/gorm"
2223 "github.com/rainycape/unidecode"
@@ -314,17 +315,18 @@ func (s *Scanner) scanDir(tx *db.DB, st *State, absPath string) error {
314315}
315316
316317func (s * Scanner ) populateTrackAndArtists (tx * db.DB , st * State , i int , album * db.Album , basename string , absPath string ) error {
317- stat , err := os .Stat (absPath )
318+ // useful to get the real create/birth time for filesystems and kernels which support it
319+ timeSpec , err := times .Stat (absPath )
318320 if err != nil {
319- return fmt .Errorf ("stating %q: %w" , basename , err )
321+ return fmt .Errorf ("get times %q: %w" , basename , err )
320322 }
321323
322324 var track db.Track
323325 if err := tx .Where ("album_id=? AND filename=?" , album .ID , filepath .Base (basename )).First (& track ).Error ; err != nil && ! errors .Is (err , gorm .ErrRecordNotFound ) {
324326 return fmt .Errorf ("query track: %w" , err )
325327 }
326328
327- if ! st .isFull && track .ID != 0 && stat .ModTime ().Before (track .UpdatedAt ) {
329+ if ! st .isFull && track .ID != 0 && timeSpec .ModTime ().Before (track .UpdatedAt ) {
328330 st .seenTracks [track .ID ] = struct {}{}
329331 return nil
330332 }
@@ -363,7 +365,7 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db
363365 return fmt .Errorf ("populate track artists: %w" , err )
364366 }
365367
366- if err := populateAlbum (tx , album , trags , stat . ModTime ()); err != nil {
368+ if err := populateAlbum (tx , album , trags , timeSpec . ChangeTime (), timeSpec . BirthTime ()); err != nil {
367369 return fmt .Errorf ("populate album: %w" , err )
368370 }
369371
@@ -372,6 +374,10 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db
372374 }
373375 }
374376
377+ stat , err := os .Stat (absPath )
378+ if err != nil {
379+ return fmt .Errorf ("stating %q: %w" , basename , err )
380+ }
375381 if err := populateTrack (tx , album , & track , trags , basename , int (stat .Size ())); err != nil {
376382 return fmt .Errorf ("process %q: %w" , basename , err )
377383 }
@@ -402,17 +408,17 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db
402408 return nil
403409}
404410
405- func populateAlbum (tx * db.DB , album * db.Album , trags tagcommon.Info , modTime time.Time ) error {
411+ func populateAlbum (tx * db.DB , album * db.Album , trags tagcommon.Info , modifiedAt , createdAt time.Time ) error {
406412 albumName := tagcommon .MustAlbum (trags )
407413 album .TagTitle = albumName
408414 album .TagTitleUDec = decoded (albumName )
409415 album .TagAlbumArtist = tagcommon .MustAlbumArtist (trags )
410416 album .TagBrainzID = trags .AlbumBrainzID ()
411417 album .TagYear = trags .Year ()
412418
413- album .ModifiedAt = modTime
414- if album .CreatedAt .After (modTime ) {
415- album .CreatedAt = modTime // reset created at to match filesytem for new albums
419+ album .ModifiedAt = modifiedAt
420+ if album .CreatedAt .After (createdAt ) {
421+ album .CreatedAt = createdAt // reset created at to match filesytem for new albums
416422 }
417423
418424 if err := tx .Save (& album ).Error ; err != nil {
0 commit comments