mirror of
https://github.com/kopia/kopia.git
synced 2026-04-04 14:23:21 -04:00
revamped progress bar by including hashing and uploading part separately
This commit is contained in:
123
cli/cli_progress.go
Normal file
123
cli/cli_progress.go
Normal file
@@ -0,0 +1,123 @@
|
||||
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{}
|
||||
Reference in New Issue
Block a user