From 141f60f8fb09b6d8abe5ae276faa2a0b3697e487 Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Fri, 3 May 2024 13:10:05 +1000 Subject: [PATCH] Fix interactive speed being lost when file is moved (#4799) --- pkg/file/scan.go | 33 ++++++++++++++++++++------------- pkg/models/model_file.go | 21 +++++++++++++++++++++ 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/pkg/file/scan.go b/pkg/file/scan.go index e32095744..7cd6d5aab 100644 --- a/pkg/file/scan.go +++ b/pkg/file/scan.go @@ -895,28 +895,35 @@ func (s *scanJob) handleRename(ctx context.Context, f models.File, fp []models.F // assume does not exist, update existing file // it's possible that there may be multiple missing files. // just use the first one to rename. + // #4775 - using the new file instance means that any changes made to the existing + // file will be lost. Update the existing file instead. other := missing[0] - otherBase := other.Base() + updated := other.Clone() + updatedBase := updated.Base() - fBase := f.Base() + fBaseCopy := *(f.Base()) - logger.Infof("%s moved to %s. Updating path...", otherBase.Path, fBase.Path) - fBase.ID = otherBase.ID - fBase.CreatedAt = otherBase.CreatedAt - fBase.Fingerprints = otherBase.Fingerprints + oldPath := updatedBase.Path + newPath := fBaseCopy.Path + + logger.Infof("%s moved to %s. Updating path...", oldPath, newPath) + fBaseCopy.ID = updatedBase.ID + fBaseCopy.CreatedAt = updatedBase.CreatedAt + fBaseCopy.Fingerprints = updatedBase.Fingerprints + *updatedBase = fBaseCopy if err := s.withTxn(ctx, func(ctx context.Context) error { - if err := s.Repository.File.Update(ctx, f); err != nil { - return fmt.Errorf("updating file for rename %q: %w", fBase.Path, err) + if err := s.Repository.File.Update(ctx, updated); err != nil { + return fmt.Errorf("updating file for rename %q: %w", newPath, err) } - if s.isZipFile(fBase.Basename) { - if err := transferZipHierarchy(ctx, s.Repository.Folder, s.Repository.File, fBase.ID, otherBase.Path, fBase.Path); err != nil { - return fmt.Errorf("moving zip hierarchy for renamed zip file %q: %w", fBase.Path, err) + if s.isZipFile(updatedBase.Basename) { + if err := transferZipHierarchy(ctx, s.Repository.Folder, s.Repository.File, updatedBase.ID, oldPath, newPath); err != nil { + return fmt.Errorf("moving zip hierarchy for renamed zip file %q: %w", newPath, err) } } - if err := s.fireHandlers(ctx, f, other); err != nil { + if err := s.fireHandlers(ctx, updated, other); err != nil { return err } @@ -925,7 +932,7 @@ func (s *scanJob) handleRename(ctx context.Context, f models.File, fp []models.F return nil, err } - return f, nil + return updated, nil } func (s *scanJob) isHandlerRequired(ctx context.Context, f models.File) bool { diff --git a/pkg/models/model_file.go b/pkg/models/model_file.go index 6e4183aa0..45e755474 100644 --- a/pkg/models/model_file.go +++ b/pkg/models/model_file.go @@ -111,6 +111,7 @@ type File interface { Base() *BaseFile SetFingerprints(fp Fingerprints) Open(fs FS) (io.ReadCloser, error) + Clone() File } // BaseFile represents a file in the file system. @@ -173,6 +174,12 @@ func (f *BaseFile) Open(fs FS) (io.ReadCloser, error) { return fs.Open(f.Path) } +func (f *BaseFile) Clone() (ret File) { + clone := *f + ret = &clone + return +} + func (f *BaseFile) Info(fs FS) (fs.FileInfo, error) { return f.info(fs, f.Path) } @@ -249,6 +256,13 @@ func (f ImageFile) GetFormat() string { return f.Format } +func (f ImageFile) Clone() (ret File) { + clone := f + clone.BaseFile = f.BaseFile.Clone().(*BaseFile) + ret = &clone + return +} + // VideoFile is an extension of BaseFile to represent video files. type VideoFile struct { *BaseFile @@ -277,6 +291,13 @@ func (f VideoFile) GetFormat() string { return f.Format } +func (f VideoFile) Clone() (ret File) { + clone := f + clone.BaseFile = f.BaseFile.Clone().(*BaseFile) + ret = &clone + return +} + // #1572 - Inf and NaN values cause the JSON marshaller to fail // Replace these values with 0 rather than erroring