From 7bb92dc7bda46201fe84f4b5a67b670ee5544083 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Tue, 27 Aug 2024 14:35:40 +0200 Subject: [PATCH] archiver: use ExtendedStat from FS interface With this change, NodeFromFileInfo is the last function that bypasses the FS interface in the archiver. --- internal/archiver/archiver.go | 4 ++-- internal/archiver/archiver_test.go | 11 ++++++----- internal/fs/fs_local.go | 5 +++++ internal/fs/fs_reader.go | 6 ++++++ internal/fs/interface.go | 1 + 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/internal/archiver/archiver.go b/internal/archiver/archiver.go index eab65bb5f..a783f6c7f 100644 --- a/internal/archiver/archiver.go +++ b/internal/archiver/archiver.go @@ -459,7 +459,7 @@ func (arch *Archiver) save(ctx context.Context, snPath, target string, previous // check if the file has not changed before performing a fopen operation (more expensive, specially // in network filesystems) - if previous != nil && !fileChanged(fi, previous, arch.ChangeIgnoreFlags) { + if previous != nil && !fileChanged(arch.FS, fi, previous, arch.ChangeIgnoreFlags) { if arch.allBlobsPresent(previous) { debug.Log("%v hasn't changed, using old list of blobs", target) arch.trackItem(snPath, previous, previous, ItemStats{}, time.Since(start)) @@ -579,7 +579,7 @@ func (arch *Archiver) save(ctx context.Context, snPath, target string, previous // fileChanged tries to detect whether a file's content has changed compared // to the contents of node, which describes the same path in the parent backup. // It should only be run for regular files. -func fileChanged(fi os.FileInfo, node *restic.Node, ignoreFlags uint) bool { +func fileChanged(fs fs.FS, fi os.FileInfo, node *restic.Node, ignoreFlags uint) bool { switch { case node == nil: return true diff --git a/internal/archiver/archiver_test.go b/internal/archiver/archiver_test.go index b56452182..962fd5481 100644 --- a/internal/archiver/archiver_test.go +++ b/internal/archiver/archiver_test.go @@ -686,10 +686,11 @@ func TestFileChanged(t *testing.T) { } save(t, filename, content) + fs := &fs.Local{} fiBefore := lstat(t, filename) node := nodeFromFI(t, filename, fiBefore) - if fileChanged(fiBefore, node, 0) { + if fileChanged(fs, fiBefore, node, 0) { t.Fatalf("unchanged file detected as changed") } @@ -699,12 +700,12 @@ func TestFileChanged(t *testing.T) { if test.SameFile { // file should be detected as unchanged - if fileChanged(fiAfter, node, test.ChangeIgnore) { + if fileChanged(fs, fiAfter, node, test.ChangeIgnore) { t.Fatalf("unmodified file detected as changed") } } else { // file should be detected as changed - if !fileChanged(fiAfter, node, test.ChangeIgnore) && !test.SameFile { + if !fileChanged(fs, fiAfter, node, test.ChangeIgnore) && !test.SameFile { t.Fatalf("modified file detected as unchanged") } } @@ -721,7 +722,7 @@ func TestFilChangedSpecialCases(t *testing.T) { t.Run("nil-node", func(t *testing.T) { fi := lstat(t, filename) - if !fileChanged(fi, nil, 0) { + if !fileChanged(&fs.Local{}, fi, nil, 0) { t.Fatal("nil node detected as unchanged") } }) @@ -730,7 +731,7 @@ func TestFilChangedSpecialCases(t *testing.T) { fi := lstat(t, filename) node := nodeFromFI(t, filename, fi) node.Type = "symlink" - if !fileChanged(fi, node, 0) { + if !fileChanged(&fs.Local{}, fi, node, 0) { t.Fatal("node with changed type detected as unchanged") } }) diff --git a/internal/fs/fs_local.go b/internal/fs/fs_local.go index 019069a55..034d1aa24 100644 --- a/internal/fs/fs_local.go +++ b/internal/fs/fs_local.go @@ -52,6 +52,11 @@ func (fs Local) DeviceID(fi os.FileInfo) (id uint64, err error) { return deviceID(fi) } +// ExtendedStat converts the give FileInfo into ExtendedFileInfo. +func (fs Local) ExtendedStat(fi os.FileInfo) ExtendedFileInfo { + return ExtendedStat(fi) +} + // Join joins any number of path elements into a single path, adding a // Separator if necessary. Join calls Clean on the result; in particular, all // empty strings are ignored. On Windows, the result is a UNC path if and only diff --git a/internal/fs/fs_reader.go b/internal/fs/fs_reader.go index b3371a8c9..84a79168e 100644 --- a/internal/fs/fs_reader.go +++ b/internal/fs/fs_reader.go @@ -126,6 +126,12 @@ func (fs *Reader) DeviceID(_ os.FileInfo) (deviceID uint64, err error) { return 0, errors.New("Device IDs are not supported") } +func (fs *Reader) ExtendedStat(fi os.FileInfo) ExtendedFileInfo { + return ExtendedFileInfo{ + FileInfo: fi, + } +} + // Join joins any number of path elements into a single path, adding a // Separator if necessary. Join calls Clean on the result; in particular, all // empty strings are ignored. On Windows, the result is a UNC path if and only diff --git a/internal/fs/interface.go b/internal/fs/interface.go index 1c27c1c13..bc6aab44a 100644 --- a/internal/fs/interface.go +++ b/internal/fs/interface.go @@ -11,6 +11,7 @@ type FS interface { Stat(name string) (os.FileInfo, error) Lstat(name string) (os.FileInfo, error) DeviceID(fi os.FileInfo) (deviceID uint64, err error) + ExtendedStat(fi os.FileInfo) ExtendedFileInfo Join(elem ...string) string Separator() string