@@ -17,6 +17,7 @@ import (
17
17
"sync/atomic"
18
18
"time"
19
19
20
+ "github.com/djherbis/times"
20
21
"github.com/fsnotify/fsnotify"
21
22
"github.com/jinzhu/gorm"
22
23
"github.com/rainycape/unidecode"
@@ -314,17 +315,18 @@ func (s *Scanner) scanDir(tx *db.DB, st *State, absPath string) error {
314
315
}
315
316
316
317
func (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 )
318
320
if err != nil {
319
- return fmt .Errorf ("stating %q: %w" , basename , err )
321
+ return fmt .Errorf ("get times %q: %w" , basename , err )
320
322
}
321
323
322
324
var track db.Track
323
325
if err := tx .Where ("album_id=? AND filename=?" , album .ID , filepath .Base (basename )).First (& track ).Error ; err != nil && ! errors .Is (err , gorm .ErrRecordNotFound ) {
324
326
return fmt .Errorf ("query track: %w" , err )
325
327
}
326
328
327
- if ! st .isFull && track .ID != 0 && stat .ModTime ().Before (track .UpdatedAt ) {
329
+ if ! st .isFull && track .ID != 0 && timeSpec .ModTime ().Before (track .UpdatedAt ) {
328
330
st .seenTracks [track .ID ] = struct {}{}
329
331
return nil
330
332
}
@@ -363,7 +365,11 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db
363
365
return fmt .Errorf ("populate track artists: %w" , err )
364
366
}
365
367
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 {
367
373
return fmt .Errorf ("populate album: %w" , err )
368
374
}
369
375
@@ -372,6 +378,10 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db
372
378
}
373
379
}
374
380
381
+ stat , err := os .Stat (absPath )
382
+ if err != nil {
383
+ return fmt .Errorf ("stating %q: %w" , basename , err )
384
+ }
375
385
if err := populateTrack (tx , album , & track , trags , basename , int (stat .Size ())); err != nil {
376
386
return fmt .Errorf ("process %q: %w" , basename , err )
377
387
}
@@ -402,7 +412,7 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db
402
412
return nil
403
413
}
404
414
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 {
406
416
albumName := tagcommon .MustAlbum (trags )
407
417
album .TagTitle = albumName
408
418
album .TagTitleUDec = decoded (albumName )
@@ -411,8 +421,8 @@ func populateAlbum(tx *db.DB, album *db.Album, trags tagcommon.Info, modTime tim
411
421
album .TagYear = trags .Year ()
412
422
413
423
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
416
426
}
417
427
418
428
if err := tx .Save (& album ).Error ; err != nil {
0 commit comments