internal/restorer: invert dependency direction to ui/restorer

The restorer imported ui/restorer which leaks ui logic into the restorer
core. Swap the direction by letting the restorer use a ProgressReporter
interface + associated constants.
This commit is contained in:
Michael Eischer
2026-06-14 14:11:00 +02:00
parent 5cd39d01c1
commit 2f31cde517
12 changed files with 189 additions and 116 deletions
+8 -7
View File
@@ -4,6 +4,7 @@ import (
"time"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/restorer"
"github.com/restic/restic/internal/ui"
"github.com/restic/restic/internal/ui/progress"
)
@@ -61,24 +62,24 @@ func (t *jsonPrinter) Error(item string, err error) error {
return nil
}
func (t *jsonPrinter) CompleteItem(messageType ItemAction, item string, size uint64) {
func (t *jsonPrinter) CompleteItem(messageType restorer.ItemAction, item string, size uint64) {
if t.verbosity < 3 {
return
}
var action string
switch messageType {
case ActionDirRestored:
case restorer.ActionDirRestored:
action = "restored"
case ActionFileRestored:
case restorer.ActionFileRestored:
action = "restored"
case ActionOtherRestored:
case restorer.ActionOtherRestored:
action = "restored"
case ActionFileUpdated:
case restorer.ActionFileUpdated:
action = "updated"
case ActionFileUnchanged:
case restorer.ActionFileUnchanged:
action = "unchanged"
case ActionDeleted:
case restorer.ActionDeleted:
action = "deleted"
default:
panic("unknown message type")
+7 -6
View File
@@ -5,6 +5,7 @@ import (
"time"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/restorer"
"github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui"
)
@@ -47,15 +48,15 @@ func TestJSONPrintSummaryOnSuccessWithSkipped(t *testing.T) {
func TestJSONPrintCompleteItem(t *testing.T) {
for _, data := range []struct {
action ItemAction
action restorer.ItemAction
size uint64
expected string
}{
{ActionDirRestored, 0, "{\"message_type\":\"verbose_status\",\"action\":\"restored\",\"item\":\"test\",\"size\":0}\n"},
{ActionFileRestored, 123, "{\"message_type\":\"verbose_status\",\"action\":\"restored\",\"item\":\"test\",\"size\":123}\n"},
{ActionFileUpdated, 123, "{\"message_type\":\"verbose_status\",\"action\":\"updated\",\"item\":\"test\",\"size\":123}\n"},
{ActionFileUnchanged, 123, "{\"message_type\":\"verbose_status\",\"action\":\"unchanged\",\"item\":\"test\",\"size\":123}\n"},
{ActionDeleted, 0, "{\"message_type\":\"verbose_status\",\"action\":\"deleted\",\"item\":\"test\",\"size\":0}\n"},
{restorer.ActionDirRestored, 0, "{\"message_type\":\"verbose_status\",\"action\":\"restored\",\"item\":\"test\",\"size\":0}\n"},
{restorer.ActionFileRestored, 123, "{\"message_type\":\"verbose_status\",\"action\":\"restored\",\"item\":\"test\",\"size\":123}\n"},
{restorer.ActionFileUpdated, 123, "{\"message_type\":\"verbose_status\",\"action\":\"updated\",\"item\":\"test\",\"size\":123}\n"},
{restorer.ActionFileUnchanged, 123, "{\"message_type\":\"verbose_status\",\"action\":\"unchanged\",\"item\":\"test\",\"size\":123}\n"},
{restorer.ActionDeleted, 0, "{\"message_type\":\"verbose_status\",\"action\":\"deleted\",\"item\":\"test\",\"size\":0}\n"},
} {
term, printer := createJSONProgress()
printer.CompleteItem(data.action, "test", data.size)
+8 -15
View File
@@ -5,6 +5,7 @@ import (
"time"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/restorer"
"github.com/restic/restic/internal/ui/progress"
)
@@ -29,6 +30,8 @@ type Progress struct {
printer ProgressPrinter
}
var _ restorer.ProgressReporter = (*Progress)(nil)
type progressInfoEntry struct {
bytesWritten uint64
bytesTotal uint64
@@ -37,22 +40,12 @@ type progressInfoEntry struct {
type ProgressPrinter interface {
Update(progress State, duration time.Duration)
Error(item string, err error) error
CompleteItem(action ItemAction, item string, size uint64)
CompleteItem(action restorer.ItemAction, item string, size uint64)
Finish(progress State, duration time.Duration)
restic.Printer
}
type ItemAction string
// Constants for the different CompleteItem actions.
const (
ActionDirRestored ItemAction = "dir restored"
ActionFileRestored ItemAction = "file restored"
ActionFileUpdated ItemAction = "file updated"
ActionFileUnchanged ItemAction = "file unchanged"
ActionOtherRestored ItemAction = "other restored"
ActionDeleted ItemAction = "deleted"
)
var _ restorer.ProgressReporter = (*Progress)(nil)
func NewProgress(printer ProgressPrinter, quiet, json, canUpdateStatus bool) *Progress {
return newProgress(printer, progress.CalculateProgressInterval(!quiet, json, canUpdateStatus))
@@ -93,7 +86,7 @@ func (p *Progress) AddFile(size uint64) {
}
// AddProgress accumulates the number of bytes written for a file
func (p *Progress) AddProgress(name string, action ItemAction, bytesWrittenPortion uint64, bytesTotal uint64) {
func (p *Progress) AddProgress(name string, action restorer.ItemAction, bytesWrittenPortion uint64, bytesTotal uint64) {
if p == nil {
return
}
@@ -128,7 +121,7 @@ func (p *Progress) AddSkippedFile(name string, size uint64) {
p.s.FilesSkipped++
p.s.AllBytesSkipped += size
p.printer.CompleteItem(ActionFileUnchanged, name, size)
p.printer.CompleteItem(restorer.ActionFileUnchanged, name, size)
}
func (p *Progress) ReportDeletion(name string) {
@@ -141,7 +134,7 @@ func (p *Progress) ReportDeletion(name string) {
p.s.FilesDeleted++
p.printer.CompleteItem(ActionDeleted, name, 0)
p.printer.CompleteItem(restorer.ActionDeleted, name, 0)
}
func (p *Progress) Error(item string, err error) error {
+23 -22
View File
@@ -6,6 +6,7 @@ import (
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/restorer"
"github.com/restic/restic/internal/test"
)
@@ -19,7 +20,7 @@ type printerTraceEntry struct {
type printerTrace []printerTraceEntry
type itemTraceEntry struct {
action ItemAction
action restorer.ItemAction
item string
size uint64
}
@@ -49,7 +50,7 @@ func (p *mockPrinter) Error(item string, err error) error {
p.errors = append(p.errors, errorTraceEntry{item, err})
return nil
}
func (p *mockPrinter) CompleteItem(action ItemAction, item string, size uint64) {
func (p *mockPrinter) CompleteItem(action restorer.ItemAction, item string, size uint64) {
p.items = append(p.items, itemTraceEntry{action, item, size})
}
func (p *mockPrinter) Finish(progress State, _ time.Duration) {
@@ -98,7 +99,7 @@ func TestFirstProgressOnAFile(t *testing.T) {
result, items, _ := testProgress(func(progress *Progress) bool {
progress.AddFile(expectedBytesTotal)
progress.AddProgress("test", ActionFileUpdated, expectedBytesWritten, expectedBytesTotal)
progress.AddProgress("test", restorer.ActionFileUpdated, expectedBytesWritten, expectedBytesTotal)
return false
})
test.Equals(t, printerTrace{
@@ -112,16 +113,16 @@ func TestLastProgressOnAFile(t *testing.T) {
result, items, _ := testProgress(func(progress *Progress) bool {
progress.AddFile(fileSize)
progress.AddProgress("test", ActionFileUpdated, 30, fileSize)
progress.AddProgress("test", ActionFileUpdated, 35, fileSize)
progress.AddProgress("test", ActionFileUpdated, 35, fileSize)
progress.AddProgress("test", restorer.ActionFileUpdated, 30, fileSize)
progress.AddProgress("test", restorer.ActionFileUpdated, 35, fileSize)
progress.AddProgress("test", restorer.ActionFileUpdated, 35, fileSize)
return false
})
test.Equals(t, printerTrace{
printerTraceEntry{State{1, 1, 0, 0, fileSize, fileSize, 0}, 0, false},
}, result)
test.Equals(t, itemTrace{
itemTraceEntry{action: ActionFileUpdated, item: "test", size: fileSize},
itemTraceEntry{action: restorer.ActionFileUpdated, item: "test", size: fileSize},
}, items)
}
@@ -131,17 +132,17 @@ func TestLastProgressOnLastFile(t *testing.T) {
result, items, _ := testProgress(func(progress *Progress) bool {
progress.AddFile(fileSize)
progress.AddFile(50)
progress.AddProgress("test1", ActionFileUpdated, 50, 50)
progress.AddProgress("test2", ActionFileUpdated, 50, fileSize)
progress.AddProgress("test2", ActionFileUpdated, 50, fileSize)
progress.AddProgress("test1", restorer.ActionFileUpdated, 50, 50)
progress.AddProgress("test2", restorer.ActionFileUpdated, 50, fileSize)
progress.AddProgress("test2", restorer.ActionFileUpdated, 50, fileSize)
return false
})
test.Equals(t, printerTrace{
printerTraceEntry{State{2, 2, 0, 0, 50 + fileSize, 50 + fileSize, 0}, 0, false},
}, result)
test.Equals(t, itemTrace{
itemTraceEntry{action: ActionFileUpdated, item: "test1", size: 50},
itemTraceEntry{action: ActionFileUpdated, item: "test2", size: fileSize},
itemTraceEntry{action: restorer.ActionFileUpdated, item: "test1", size: 50},
itemTraceEntry{action: restorer.ActionFileUpdated, item: "test2", size: fileSize},
}, items)
}
@@ -151,8 +152,8 @@ func TestSummaryOnSuccess(t *testing.T) {
result, _, _ := testProgress(func(progress *Progress) bool {
progress.AddFile(fileSize)
progress.AddFile(50)
progress.AddProgress("test1", ActionFileUpdated, 50, 50)
progress.AddProgress("test2", ActionFileUpdated, fileSize, fileSize)
progress.AddProgress("test1", restorer.ActionFileUpdated, 50, 50)
progress.AddProgress("test2", restorer.ActionFileUpdated, fileSize, fileSize)
return true
})
test.Equals(t, printerTrace{
@@ -166,8 +167,8 @@ func TestSummaryOnErrors(t *testing.T) {
result, _, _ := testProgress(func(progress *Progress) bool {
progress.AddFile(fileSize)
progress.AddFile(50)
progress.AddProgress("test1", ActionFileUpdated, 50, 50)
progress.AddProgress("test2", ActionFileUpdated, fileSize/2, fileSize)
progress.AddProgress("test1", restorer.ActionFileUpdated, 50, 50)
progress.AddProgress("test2", restorer.ActionFileUpdated, fileSize/2, fileSize)
return true
})
test.Equals(t, printerTrace{
@@ -186,7 +187,7 @@ func TestSkipFile(t *testing.T) {
printerTraceEntry{State{0, 0, 1, 0, 0, 0, fileSize}, mockFinishDuration, true},
}, result)
test.Equals(t, itemTrace{
itemTraceEntry{ActionFileUnchanged, "test", fileSize},
itemTraceEntry{restorer.ActionFileUnchanged, "test", fileSize},
}, items)
}
@@ -196,15 +197,15 @@ func TestProgressTypes(t *testing.T) {
_, items, _ := testProgress(func(progress *Progress) bool {
progress.AddFile(fileSize)
progress.AddFile(0)
progress.AddProgress("dir", ActionDirRestored, fileSize, fileSize)
progress.AddProgress("new", ActionFileRestored, 0, 0)
progress.AddProgress("dir", restorer.ActionDirRestored, fileSize, fileSize)
progress.AddProgress("new", restorer.ActionFileRestored, 0, 0)
progress.ReportDeletion("del")
return true
})
test.Equals(t, itemTrace{
itemTraceEntry{ActionDirRestored, "dir", fileSize},
itemTraceEntry{ActionFileRestored, "new", 0},
itemTraceEntry{ActionDeleted, "del", 0},
itemTraceEntry{restorer.ActionDirRestored, "dir", fileSize},
itemTraceEntry{restorer.ActionFileRestored, "new", 0},
itemTraceEntry{restorer.ActionDeleted, "del", 0},
}, items)
}
+9 -8
View File
@@ -5,6 +5,7 @@ import (
"time"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/restorer"
"github.com/restic/restic/internal/ui"
"github.com/restic/restic/internal/ui/progress"
)
@@ -44,26 +45,26 @@ func (t *textPrinter) Error(item string, err error) error {
return nil
}
func (t *textPrinter) CompleteItem(messageType ItemAction, item string, size uint64) {
func (t *textPrinter) CompleteItem(messageType restorer.ItemAction, item string, size uint64) {
var action string
switch messageType {
case ActionDirRestored:
case restorer.ActionDirRestored:
action = "restored"
case ActionFileRestored:
case restorer.ActionFileRestored:
action = "restored"
case ActionOtherRestored:
case restorer.ActionOtherRestored:
action = "restored"
case ActionFileUpdated:
case restorer.ActionFileUpdated:
action = "updated"
case ActionFileUnchanged:
case restorer.ActionFileUnchanged:
action = "unchanged"
case ActionDeleted:
case restorer.ActionDeleted:
action = "deleted"
default:
panic("unknown message type")
}
if messageType == ActionDirRestored || messageType == ActionOtherRestored || messageType == ActionDeleted {
if messageType == restorer.ActionDirRestored || messageType == restorer.ActionOtherRestored || messageType == restorer.ActionDeleted {
t.VV("%-9v %v", action, item)
} else {
t.VV("%-9v %v with size %v", action, item, ui.FormatBytes(size))
+8 -7
View File
@@ -5,6 +5,7 @@ import (
"time"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/restorer"
"github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui"
)
@@ -47,16 +48,16 @@ func TestPrintSummaryOnSuccessWithSkipped(t *testing.T) {
func TestPrintCompleteItem(t *testing.T) {
for _, data := range []struct {
action ItemAction
action restorer.ItemAction
size uint64
expected string
}{
{ActionDirRestored, 0, "restored test"},
{ActionFileRestored, 123, "restored test with size 123 B"},
{ActionOtherRestored, 0, "restored test"},
{ActionFileUpdated, 123, "updated test with size 123 B"},
{ActionFileUnchanged, 123, "unchanged test with size 123 B"},
{ActionDeleted, 0, "deleted test"},
{restorer.ActionDirRestored, 0, "restored test"},
{restorer.ActionFileRestored, 123, "restored test with size 123 B"},
{restorer.ActionOtherRestored, 0, "restored test"},
{restorer.ActionFileUpdated, 123, "updated test with size 123 B"},
{restorer.ActionFileUnchanged, 123, "unchanged test with size 123 B"},
{restorer.ActionDeleted, 0, "deleted test"},
} {
term, printer := createTextProgress()
printer.CompleteItem(data.action, "test", data.size)