@@ -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,11 @@ 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+ modTime , createTime := timeSpec .ModTime (), timeSpec .ModTime ()
369+ if timeSpec .HasBirthTime () {
370+ createTime = timeSpec .BirthTime ()
371+ }
372+ if err := populateAlbum (tx , album , trags , modTime , createTime ); err != nil {
367373 return fmt .Errorf ("populate album: %w" , err )
368374 }
369375
@@ -372,6 +378,10 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db
372378 }
373379 }
374380
381+ stat , err := os .Stat (absPath )
382+ if err != nil {
383+ return fmt .Errorf ("stating %q: %w" , basename , err )
384+ }
375385 if err := populateTrack (tx , album , & track , trags , basename , int (stat .Size ())); err != nil {
376386 return fmt .Errorf ("process %q: %w" , basename , err )
377387 }
@@ -402,7 +412,7 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db
402412 return nil
403413}
404414
405- func populateAlbum (tx * db.DB , album * db.Album , trags tagcommon.Info , modTime time.Time ) error {
415+ func populateAlbum (tx * db.DB , album * db.Album , trags tagcommon.Info , modTime , createTime time.Time ) error {
406416 albumName := tagcommon .MustAlbum (trags )
407417 album .TagTitle = albumName
408418 album .TagTitleUDec = decoded (albumName )
@@ -411,8 +421,8 @@ func populateAlbum(tx *db.DB, album *db.Album, trags tagcommon.Info, modTime tim
411421 album .TagYear = trags .Year ()
412422
413423 album .ModifiedAt = modTime
414- if album .CreatedAt .After (modTime ) {
415- album .CreatedAt = modTime // reset created at to match filesytem for new albums
424+ if album .CreatedAt .After (createTime ) {
425+ album .CreatedAt = createTime // reset created at to match filesytem for new albums
416426 }
417427
418428 if err := tx .Save (& album ).Error ; err != nil {
0 commit comments