mirror of
https://github.com/kopia/kopia.git
synced 2026-01-07 22:17:50 -05:00
124 lines
2.5 KiB
Go
124 lines
2.5 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/kopia/kopia/internal/units"
|
|
"github.com/kopia/kopia/snapshot"
|
|
)
|
|
|
|
type singleProgress struct {
|
|
desc string
|
|
startTime time.Time
|
|
progress int64
|
|
total int64
|
|
}
|
|
|
|
func (p *singleProgress) update(progress int64, total int64) {
|
|
p.total = total
|
|
p.progress = progress
|
|
}
|
|
|
|
func (p *singleProgress) toString(details bool) string {
|
|
if p.total == 0 {
|
|
return fmt.Sprintf("empty %v", p.desc)
|
|
}
|
|
|
|
dur := time.Since(p.startTime)
|
|
extraInfo := ""
|
|
if dur > 1*time.Second && details {
|
|
extraInfo = " " + units.BitsPerSecondsString(8*float64(p.progress)/time.Since(p.startTime).Seconds())
|
|
}
|
|
|
|
if p.progress == p.total {
|
|
return fmt.Sprintf("completed %v %v",
|
|
p.desc,
|
|
units.BytesStringBase10(p.progress),
|
|
)
|
|
}
|
|
|
|
return fmt.Sprintf("processing %v %v of %v (%v%%)%v",
|
|
p.desc,
|
|
units.BytesStringBase10(p.progress),
|
|
units.BytesStringBase10(p.total),
|
|
100*p.progress/p.total,
|
|
extraInfo,
|
|
)
|
|
}
|
|
|
|
type multiProgress struct {
|
|
mu sync.Mutex
|
|
items []*singleProgress
|
|
}
|
|
|
|
func (mp *multiProgress) findLocked(desc string) (*singleProgress, int) {
|
|
for i, p := range mp.items {
|
|
if p.desc == desc {
|
|
return p, i
|
|
}
|
|
}
|
|
|
|
return nil, 0
|
|
}
|
|
|
|
func (mp *multiProgress) Report(desc string, progress int64, total int64) {
|
|
mp.mu.Lock()
|
|
defer mp.mu.Unlock()
|
|
|
|
found, foundPos := mp.findLocked(desc)
|
|
|
|
if found != nil && found.progress == progress && found.total == total {
|
|
// do not print redundant progress
|
|
return
|
|
}
|
|
|
|
if found == nil {
|
|
found = &singleProgress{
|
|
desc: desc,
|
|
startTime: time.Now(),
|
|
}
|
|
foundPos = len(mp.items)
|
|
mp.items = append(mp.items, found)
|
|
}
|
|
|
|
found.update(progress, total)
|
|
|
|
var segments []string
|
|
for i, p := range mp.items {
|
|
segments = append(segments, p.toString(i > 0))
|
|
}
|
|
if found.progress >= found.total && foundPos == len(segments)-1 {
|
|
mp.items = append(mp.items[0:foundPos], mp.items[foundPos+1:]...)
|
|
if len(segments) > 0 {
|
|
log.Notice(segments[len(segments)-1])
|
|
}
|
|
} else {
|
|
if len(segments) > 0 {
|
|
log.Info(segments[len(segments)-1])
|
|
}
|
|
}
|
|
}
|
|
|
|
func (mp *multiProgress) Progress(path string, numFiles int, dirCompleted, dirTotal int64, stats *snapshot.Stats) {
|
|
mp.Report(
|
|
fmt.Sprintf("directory '%v' (%v files)", shortenPath(strings.TrimPrefix(path, "./")), numFiles),
|
|
dirCompleted,
|
|
dirTotal)
|
|
}
|
|
|
|
func (mp *multiProgress) UploadFinished() {
|
|
}
|
|
|
|
func shortenPath(s string) string {
|
|
if len(s) < 60 {
|
|
return s
|
|
}
|
|
|
|
return s[0:30] + "..." + s[len(s)-27:]
|
|
}
|
|
|
|
var cliProgress = &multiProgress{}
|