diff options
Diffstat (limited to 'internal/restorer/restorer.go')
-rw-r--r-- | internal/restorer/restorer.go | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/internal/restorer/restorer.go b/internal/restorer/restorer.go index 4dfe3c3a8..3c60aca1b 100644 --- a/internal/restorer/restorer.go +++ b/internal/restorer/restorer.go @@ -10,6 +10,7 @@ import ( "github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/fs" "github.com/restic/restic/internal/restic" + restoreui "github.com/restic/restic/internal/ui/restore" "golang.org/x/sync/errgroup" ) @@ -20,6 +21,8 @@ type Restorer struct { sn *restic.Snapshot sparse bool + progress *restoreui.Progress + Error func(location string, err error) error SelectFilter func(item string, dstpath string, node *restic.Node) (selectedForRestore bool, childMayBeSelected bool) } @@ -27,12 +30,14 @@ type Restorer struct { var restorerAbortOnAllErrors = func(location string, err error) error { return err } // NewRestorer creates a restorer preloaded with the content from the snapshot id. -func NewRestorer(ctx context.Context, repo restic.Repository, sn *restic.Snapshot, sparse bool) *Restorer { +func NewRestorer(repo restic.Repository, sn *restic.Snapshot, sparse bool, + progress *restoreui.Progress) *Restorer { r := &Restorer{ repo: repo, sparse: sparse, Error: restorerAbortOnAllErrors, SelectFilter: func(string, string, *restic.Node) (bool, bool) { return true, true }, + progress: progress, sn: sn, } @@ -161,12 +166,14 @@ func (res *Restorer) restoreNodeTo(ctx context.Context, node *restic.Node, targe err := node.CreateAt(ctx, target, res.repo) if err != nil { debug.Log("node.CreateAt(%s) error %v", target, err) + return err } - if err == nil { - err = res.restoreNodeMetadataTo(node, target, location) + + if res.progress != nil { + res.progress.AddProgress(location, 0, 0) } - return err + return res.restoreNodeMetadataTo(node, target, location) } func (res *Restorer) restoreNodeMetadataTo(node *restic.Node, target, location string) error { @@ -186,6 +193,11 @@ func (res *Restorer) restoreHardlinkAt(node *restic.Node, target, path, location if err != nil { return errors.WithStack(err) } + + if res.progress != nil { + res.progress.AddProgress(location, 0, 0) + } + // TODO investigate if hardlinks have separate metadata on any supported system return res.restoreNodeMetadataTo(node, path, location) } @@ -200,6 +212,10 @@ func (res *Restorer) restoreEmptyFileAt(node *restic.Node, target, location stri return err } + if res.progress != nil { + res.progress.AddProgress(location, 0, 0) + } + return res.restoreNodeMetadataTo(node, target, location) } @@ -215,7 +231,8 @@ func (res *Restorer) RestoreTo(ctx context.Context, dst string) error { } idx := NewHardlinkIndex() - filerestorer := newFileRestorer(dst, res.repo.Backend().Load, res.repo.Key(), res.repo.Index().Lookup, res.repo.Connections(), res.sparse) + filerestorer := newFileRestorer(dst, res.repo.Backend().Load, res.repo.Key(), res.repo.Index().Lookup, + res.repo.Connections(), res.sparse, res.progress) filerestorer.Error = res.Error debug.Log("first pass for %q", dst) @@ -224,6 +241,9 @@ func (res *Restorer) RestoreTo(ctx context.Context, dst string) error { _, err = res.traverseTree(ctx, dst, string(filepath.Separator), *res.sn.Tree, treeVisitor{ enterDir: func(node *restic.Node, target, location string) error { debug.Log("first pass, enterDir: mkdir %q, leaveDir should restore metadata", location) + if res.progress != nil { + res.progress.AddFile(0) + } // create dir with default permissions // #leaveDir restores dir metadata after visiting all children return fs.MkdirAll(target, 0700) @@ -239,20 +259,34 @@ func (res *Restorer) RestoreTo(ctx context.Context, dst string) error { } if node.Type != "file" { + if res.progress != nil { + res.progress.AddFile(0) + } return nil } if node.Size == 0 { + if res.progress != nil { + res.progress.AddFile(node.Size) + } return nil // deal with empty files later } if node.Links > 1 { if idx.Has(node.Inode, node.DeviceID) { + if res.progress != nil { + // a hardlinked file does not increase the restore size + res.progress.AddFile(0) + } return nil } idx.Add(node.Inode, node.DeviceID, location) } + if res.progress != nil { + res.progress.AddFile(node.Size) + } + filerestorer.addFile(location, node.Content, int64(node.Size)) return nil @@ -291,7 +325,13 @@ func (res *Restorer) RestoreTo(ctx context.Context, dst string) error { return res.restoreNodeMetadataTo(node, target, location) }, - leaveDir: res.restoreNodeMetadataTo, + leaveDir: func(node *restic.Node, target, location string) error { + err := res.restoreNodeMetadataTo(node, target, location) + if err == nil && res.progress != nil { + res.progress.AddProgress(location, 0, 0) + } + return err + }, }) return err } |