From c5b3a1ce1e11dfc86caad82768a28e52b90398de Mon Sep 17 00:00:00 2001 From: sentriz Date: Wed, 15 May 2024 14:17:43 +0200 Subject: [PATCH] scanner: use create time if we have it --- go.mod | 3 ++- go.sum | 3 +++ scanner/scanner.go | 22 ++++++++++++++-------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 92b04a28..d9f6ac2b 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/andybalholm/cascadia v1.3.2 github.com/dexterlb/mpvipc v0.0.0-20230829142118-145d6eabdc37 github.com/disintegration/imaging v1.6.2 + github.com/djherbis/times v1.6.0 github.com/dustin/go-humanize v1.0.1 github.com/fatih/structs v1.1.0 github.com/fsnotify/fsnotify v1.7.0 @@ -28,6 +29,7 @@ require ( go.senan.xyz/flagconf v0.1.8 golang.org/x/net v0.24.0 golang.org/x/sync v0.7.0 + golang.org/x/sys v0.19.0 gopkg.in/gormigrate.v1 v1.6.0 jaytaylor.com/html2text v0.0.0-20230321000545-74c2419ad056 ) @@ -60,7 +62,6 @@ require ( github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect golang.org/x/crypto v0.22.0 // indirect golang.org/x/image v0.15.0 // indirect - golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index e3f815a8..4f423af3 100644 --- a/go.sum +++ b/go.sum @@ -21,6 +21,8 @@ github.com/dexterlb/mpvipc v0.0.0-20230829142118-145d6eabdc37 h1:s+qNFsO3VsdsKro github.com/dexterlb/mpvipc v0.0.0-20230829142118-145d6eabdc37/go.mod h1:CXCwawNJCtFDip7gvbaQVgw0cGjldpyHDIp7oA5prOg= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= +github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= +github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= @@ -174,6 +176,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/scanner/scanner.go b/scanner/scanner.go index 9c428824..f46c6ece 100644 --- a/scanner/scanner.go +++ b/scanner/scanner.go @@ -17,6 +17,7 @@ import ( "sync/atomic" "time" + "github.com/djherbis/times" "github.com/fsnotify/fsnotify" "github.com/jinzhu/gorm" "github.com/rainycape/unidecode" @@ -314,9 +315,10 @@ func (s *Scanner) scanDir(tx *db.DB, st *State, absPath string) error { } func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db.Album, basename string, absPath string) error { - stat, err := os.Stat(absPath) + // useful to get the real create/birth time for filesystems and kernels which support it + timeSpec, err := times.Stat(absPath) if err != nil { - return fmt.Errorf("stating %q: %w", basename, err) + return fmt.Errorf("get times %q: %w", basename, err) } var track db.Track @@ -324,7 +326,7 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db return fmt.Errorf("query track: %w", err) } - if !st.isFull && track.ID != 0 && stat.ModTime().Before(track.UpdatedAt) { + if !st.isFull && track.ID != 0 && timeSpec.ModTime().Before(track.UpdatedAt) { st.seenTracks[track.ID] = struct{}{} return nil } @@ -363,7 +365,7 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db return fmt.Errorf("populate track artists: %w", err) } - if err := populateAlbum(tx, album, trags, stat.ModTime()); err != nil { + if err := populateAlbum(tx, album, trags, timeSpec.ChangeTime(), timeSpec.BirthTime()); err != nil { return fmt.Errorf("populate album: %w", err) } @@ -372,6 +374,10 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db } } + stat, err := os.Stat(absPath) + if err != nil { + return fmt.Errorf("stating %q: %w", basename, err) + } if err := populateTrack(tx, album, &track, trags, basename, int(stat.Size())); err != nil { return fmt.Errorf("process %q: %w", basename, err) } @@ -402,7 +408,7 @@ func (s *Scanner) populateTrackAndArtists(tx *db.DB, st *State, i int, album *db return nil } -func populateAlbum(tx *db.DB, album *db.Album, trags tagcommon.Info, modTime time.Time) error { +func populateAlbum(tx *db.DB, album *db.Album, trags tagcommon.Info, modifiedAt, createdAt time.Time) error { albumName := tagcommon.MustAlbum(trags) album.TagTitle = albumName album.TagTitleUDec = decoded(albumName) @@ -410,9 +416,9 @@ func populateAlbum(tx *db.DB, album *db.Album, trags tagcommon.Info, modTime tim album.TagBrainzID = trags.AlbumBrainzID() album.TagYear = trags.Year() - album.ModifiedAt = modTime - if album.CreatedAt.After(modTime) { - album.CreatedAt = modTime // reset created at to match filesytem for new albums + album.ModifiedAt = modifiedAt + if album.CreatedAt.After(createdAt) { + album.CreatedAt = createdAt // reset created at to match filesytem for new albums } if err := tx.Save(&album).Error; err != nil {