1
0
mirror of https://github.com/restic/restic.git synced 2024-07-27 12:37:40 +02:00
restic/internal/ui/restore/progress.go

145 lines
2.8 KiB
Go
Raw Permalink Normal View History

package restore
import (
"sync"
"time"
"github.com/restic/restic/internal/ui/progress"
)
2024-05-31 13:43:57 +02:00
type State struct {
FilesFinished uint64
FilesTotal uint64
FilesSkipped uint64
2024-05-31 13:43:57 +02:00
AllBytesWritten uint64
AllBytesTotal uint64
AllBytesSkipped uint64
2024-05-31 13:43:57 +02:00
}
type Progress struct {
updater progress.Updater
m sync.Mutex
progressInfoMap map[string]progressInfoEntry
2024-05-31 13:43:57 +02:00
s State
started time.Time
printer ProgressPrinter
}
type progressInfoEntry struct {
bytesWritten uint64
bytesTotal uint64
}
type term interface {
Print(line string)
SetStatus(lines []string)
}
type ProgressPrinter interface {
2024-05-31 13:43:57 +02:00
Update(progress State, duration time.Duration)
CompleteItem(action ItemAction, item string, size uint64)
2024-05-31 13:43:57 +02:00
Finish(progress State, duration time.Duration)
}
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"
)
func NewProgress(printer ProgressPrinter, interval time.Duration) *Progress {
p := &Progress{
progressInfoMap: make(map[string]progressInfoEntry),
started: time.Now(),
printer: printer,
}
p.updater = *progress.NewUpdater(interval, p.update)
return p
}
func (p *Progress) update(runtime time.Duration, final bool) {
p.m.Lock()
defer p.m.Unlock()
if !final {
2024-05-31 13:43:57 +02:00
p.printer.Update(p.s, runtime)
} else {
2024-05-31 13:43:57 +02:00
p.printer.Finish(p.s, runtime)
}
}
// AddFile starts tracking a new file with the given size
func (p *Progress) AddFile(size uint64) {
if p == nil {
return
}
p.m.Lock()
defer p.m.Unlock()
2024-05-31 13:43:57 +02:00
p.s.FilesTotal++
p.s.AllBytesTotal += size
}
// AddProgress accumulates the number of bytes written for a file
func (p *Progress) AddProgress(name string, action ItemAction, bytesWrittenPortion uint64, bytesTotal uint64) {
if p == nil {
return
}
p.m.Lock()
defer p.m.Unlock()
entry, exists := p.progressInfoMap[name]
if !exists {
entry.bytesTotal = bytesTotal
}
entry.bytesWritten += bytesWrittenPortion
p.progressInfoMap[name] = entry
2024-05-31 13:43:57 +02:00
p.s.AllBytesWritten += bytesWrittenPortion
if entry.bytesWritten == entry.bytesTotal {
delete(p.progressInfoMap, name)
2024-05-31 13:43:57 +02:00
p.s.FilesFinished++
p.printer.CompleteItem(action, name, bytesTotal)
}
}
func (p *Progress) AddSkippedFile(name string, size uint64) {
if p == nil {
return
}
p.m.Lock()
defer p.m.Unlock()
p.s.FilesSkipped++
p.s.AllBytesSkipped += size
p.printer.CompleteItem(ActionFileUnchanged, name, size)
}
func (p *Progress) ReportDeletedFile(name string) {
if p == nil {
return
}
p.m.Lock()
defer p.m.Unlock()
p.printer.CompleteItem(ActionDeleted, name, 0)
}
func (p *Progress) Finish() {
p.updater.Done()
}