mirror of
https://github.com/restic/restic.git
synced 2026-06-21 08:04:18 +00:00
archiver: pass ItemAction to progress reporter instead of data.Node (#21886)
This commit is contained in:
@@ -110,11 +110,11 @@ type Archiver struct {
|
||||
// particular file/dir.
|
||||
//
|
||||
// Once reading a file has completed successfully (but not saving it yet),
|
||||
// CompleteItem will be called with current == nil.
|
||||
// CompleteItem will be called with a zero ItemAction.
|
||||
//
|
||||
// CompleteItem may be called asynchronously from several different
|
||||
// goroutines!
|
||||
CompleteItem func(item string, previous, current *data.Node, s ItemStats, d time.Duration)
|
||||
CompleteItem func(item string, action ItemAction, s ItemStats, d time.Duration)
|
||||
|
||||
// StartFile is called when a file is being processed by a worker.
|
||||
StartFile func(filename string)
|
||||
@@ -180,7 +180,7 @@ func New(repo archiverRepo, filesystem fs.FS, opts Options) *Archiver {
|
||||
FS: filesystem,
|
||||
Options: opts.applyDefaults(),
|
||||
|
||||
CompleteItem: func(string, *data.Node, *data.Node, ItemStats, time.Duration) {},
|
||||
CompleteItem: func(string, ItemAction, ItemStats, time.Duration) {},
|
||||
StartFile: func(string) {},
|
||||
CompleteBlob: func(uint64) {},
|
||||
}
|
||||
@@ -211,40 +211,35 @@ func (arch *Archiver) error(item string, err error) error {
|
||||
}
|
||||
|
||||
func (arch *Archiver) trackItem(item string, previous, current *data.Node, s ItemStats, d time.Duration) {
|
||||
arch.CompleteItem(item, previous, current, s, d)
|
||||
action := itemProgressAction(previous, current)
|
||||
arch.CompleteItem(item, action, s, d)
|
||||
|
||||
arch.mu.Lock()
|
||||
defer arch.mu.Unlock()
|
||||
|
||||
arch.summary.ItemStats.Add(s)
|
||||
|
||||
if current != nil {
|
||||
arch.summary.ProcessedBytes += current.Size
|
||||
} else {
|
||||
if action.IsZero() {
|
||||
// last item or an error occurred
|
||||
return
|
||||
}
|
||||
|
||||
switch current.Type {
|
||||
case data.NodeTypeDir:
|
||||
switch {
|
||||
case previous == nil:
|
||||
arch.summary.Dirs.New++
|
||||
case previous.Equals(*current):
|
||||
arch.summary.Dirs.Unchanged++
|
||||
default:
|
||||
arch.summary.Dirs.Changed++
|
||||
}
|
||||
arch.summary.ProcessedBytes += current.Size
|
||||
|
||||
case data.NodeTypeFile:
|
||||
switch {
|
||||
case previous == nil:
|
||||
arch.summary.Files.New++
|
||||
case previous.Equals(*current):
|
||||
arch.summary.Files.Unchanged++
|
||||
default:
|
||||
arch.summary.Files.Changed++
|
||||
}
|
||||
switch action {
|
||||
case ActionDirNew:
|
||||
arch.summary.Dirs.New++
|
||||
case ActionDirUnchanged:
|
||||
arch.summary.Dirs.Unchanged++
|
||||
case ActionDirModified:
|
||||
arch.summary.Dirs.Changed++
|
||||
|
||||
case ActionFileNew:
|
||||
arch.summary.Files.New++
|
||||
case ActionFileUnchanged:
|
||||
arch.summary.Files.Unchanged++
|
||||
case ActionFileModified:
|
||||
arch.summary.Files.Changed++
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package archiver
|
||||
|
||||
import "github.com/restic/restic/internal/data"
|
||||
|
||||
// ItemAction describes backup progress for a single file or directory.
|
||||
// The zero value indicates an error or incomplete item.
|
||||
type ItemAction string
|
||||
|
||||
// Constants for the different CompleteItem actions.
|
||||
const (
|
||||
ActionDirNew ItemAction = "dir new"
|
||||
ActionDirUnchanged ItemAction = "dir unchanged"
|
||||
ActionDirModified ItemAction = "dir modified"
|
||||
ActionFileNew ItemAction = "file new"
|
||||
ActionFileUnchanged ItemAction = "file unchanged"
|
||||
ActionFileModified ItemAction = "file modified"
|
||||
)
|
||||
|
||||
// IsZero reports whether the action describes a zero value.
|
||||
func (a ItemAction) IsZero() bool {
|
||||
return a == ""
|
||||
}
|
||||
|
||||
func itemProgressAction(previous, current *data.Node) ItemAction {
|
||||
if current == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch current.Type {
|
||||
case data.NodeTypeDir:
|
||||
switch {
|
||||
case previous == nil:
|
||||
return ActionDirNew
|
||||
case previous.Equals(*current):
|
||||
return ActionDirUnchanged
|
||||
default:
|
||||
return ActionDirModified
|
||||
}
|
||||
|
||||
case data.NodeTypeFile:
|
||||
switch {
|
||||
case previous == nil:
|
||||
return ActionFileNew
|
||||
case previous.Equals(*current):
|
||||
return ActionFileUnchanged
|
||||
default:
|
||||
return ActionFileModified
|
||||
}
|
||||
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/restic/restic/internal/archiver"
|
||||
"github.com/restic/restic/internal/data"
|
||||
"github.com/restic/restic/internal/restic"
|
||||
"github.com/restic/restic/internal/ui/progress"
|
||||
)
|
||||
@@ -118,44 +117,28 @@ func (p *Progress) CompleteBlob(bytes uint64) {
|
||||
|
||||
// CompleteItem is the status callback function for the archiver when a
|
||||
// file/dir has been saved successfully.
|
||||
func (p *Progress) CompleteItem(item string, previous, current *data.Node, s archiver.ItemStats, d time.Duration) {
|
||||
if current == nil {
|
||||
// error occurred, tell the status display to remove the line
|
||||
func (p *Progress) CompleteItem(item string, action archiver.ItemAction, s archiver.ItemStats, d time.Duration) {
|
||||
if action.IsZero() {
|
||||
// file reading completed but not fully saved, tell the status display to remove the line
|
||||
p.mu.Lock()
|
||||
delete(p.currentFiles, item)
|
||||
p.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
switch current.Type {
|
||||
case data.NodeTypeDir:
|
||||
switch action {
|
||||
case archiver.ActionDirNew, archiver.ActionDirUnchanged, archiver.ActionDirModified:
|
||||
p.mu.Lock()
|
||||
p.addProcessed(Counter{Dirs: 1})
|
||||
p.mu.Unlock()
|
||||
p.printer.CompleteItem(string(action), item, s, d)
|
||||
|
||||
switch {
|
||||
case previous == nil:
|
||||
p.printer.CompleteItem("dir new", item, s, d)
|
||||
case previous.Equals(*current):
|
||||
p.printer.CompleteItem("dir unchanged", item, s, d)
|
||||
default:
|
||||
p.printer.CompleteItem("dir modified", item, s, d)
|
||||
}
|
||||
|
||||
case data.NodeTypeFile:
|
||||
case archiver.ActionFileNew, archiver.ActionFileUnchanged, archiver.ActionFileModified:
|
||||
p.mu.Lock()
|
||||
p.addProcessed(Counter{Files: 1})
|
||||
delete(p.currentFiles, item)
|
||||
p.mu.Unlock()
|
||||
|
||||
switch {
|
||||
case previous == nil:
|
||||
p.printer.CompleteItem("file new", item, s, d)
|
||||
case previous.Equals(*current):
|
||||
p.printer.CompleteItem("file unchanged", item, s, d)
|
||||
default:
|
||||
p.printer.CompleteItem("file modified", item, s, d)
|
||||
}
|
||||
p.printer.CompleteItem(string(action), item, s, d)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/restic/restic/internal/archiver"
|
||||
"github.com/restic/restic/internal/data"
|
||||
"github.com/restic/restic/internal/restic"
|
||||
)
|
||||
|
||||
@@ -54,11 +53,9 @@ func TestProgress(t *testing.T) {
|
||||
prog.CompleteBlob(1024)
|
||||
|
||||
// "dir unchanged"
|
||||
node := data.Node{Type: data.NodeTypeDir}
|
||||
prog.CompleteItem("foo", &node, &node, archiver.ItemStats{}, 0)
|
||||
prog.CompleteItem("foo", archiver.ActionDirUnchanged, archiver.ItemStats{}, 0)
|
||||
// "file new"
|
||||
node.Type = data.NodeTypeFile
|
||||
prog.CompleteItem("foo", nil, &node, archiver.ItemStats{}, 0)
|
||||
prog.CompleteItem("foo", archiver.ActionFileNew, archiver.ItemStats{}, 0)
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
id := restic.NewRandomID()
|
||||
|
||||
Reference in New Issue
Block a user