fix(deps): update module github.com/containers/image/v5 to v5.33.0

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
renovate[bot]
2024-11-12 18:34:08 +00:00
committed by Miloslav Trmač
parent 15f69ac611
commit fa1762f52b
546 changed files with 26538 additions and 10856 deletions

View File

@@ -19,40 +19,38 @@ type Bar struct {
priority int // used by heap
frameCh chan *renderFrame
operateState chan func(*bState)
done chan struct{}
container *Progress
bs *bState
bsOk chan struct{}
ctx context.Context
cancel func()
}
type syncTable [2][]chan int
type extenderFunc func([]io.Reader, decor.Statistics) ([]io.Reader, error)
type extenderFunc func(decor.Statistics, ...io.Reader) ([]io.Reader, error)
// bState is actual bar's state.
type bState struct {
id int
priority int
reqWidth int
shutdown int
total int64
current int64
refill int64
trimSpace bool
completed bool
aborted bool
triggerComplete bool
rmOnComplete bool
noPop bool
autoRefresh bool
buffers [3]*bytes.Buffer
decorators [2][]decor.Decorator
averageDecorators []decor.AverageDecorator
ewmaDecorators []decor.EwmaDecorator
shutdownListeners []decor.ShutdownListener
filler BarFiller
extender extenderFunc
renderReq chan<- time.Time
waitBar *Bar // key for (*pState).queueBars
id int
priority int
reqWidth int
shutdown int
total int64
current int64
refill int64
trimSpace bool
aborted bool
triggerComplete bool
rmOnComplete bool
noPop bool
autoRefresh bool
buffers [3]*bytes.Buffer
decorators [2][]decor.Decorator
ewmaDecorators []decor.EwmaDecorator
filler BarFiller
extender extenderFunc
renderReq chan<- time.Time
waitBar *Bar // key for (*pState).queueBars
}
type renderFrame struct {
@@ -70,13 +68,14 @@ func newBar(ctx context.Context, container *Progress, bs *bState) *Bar {
priority: bs.priority,
frameCh: make(chan *renderFrame, 1),
operateState: make(chan func(*bState)),
done: make(chan struct{}),
bsOk: make(chan struct{}),
container: container,
ctx: ctx,
cancel: cancel,
}
container.bwg.Add(1)
go bar.serve(ctx, bs)
go bar.serve(bs)
return bar
}
@@ -89,11 +88,13 @@ func (b *Bar) ProxyReader(r io.Reader) io.ReadCloser {
if r == nil {
panic("expected non nil io.Reader")
}
result := make(chan bool)
result := make(chan io.ReadCloser)
select {
case b.operateState <- func(s *bState) { result <- len(s.ewmaDecorators) != 0 }:
return newProxyReader(r, b, <-result)
case <-b.done:
case b.operateState <- func(s *bState) {
result <- newProxyReader(r, b, len(s.ewmaDecorators) != 0)
}:
return <-result
case <-b.ctx.Done():
return nil
}
}
@@ -105,11 +106,13 @@ func (b *Bar) ProxyWriter(w io.Writer) io.WriteCloser {
if w == nil {
panic("expected non nil io.Writer")
}
result := make(chan bool)
result := make(chan io.WriteCloser)
select {
case b.operateState <- func(s *bState) { result <- len(s.ewmaDecorators) != 0 }:
return newProxyWriter(w, b, <-result)
case <-b.done:
case b.operateState <- func(s *bState) {
result <- newProxyWriter(w, b, len(s.ewmaDecorators) != 0)
}:
return <-result
case <-b.ctx.Done():
return nil
}
}
@@ -120,7 +123,7 @@ func (b *Bar) ID() int {
select {
case b.operateState <- func(s *bState) { result <- s.id }:
return <-result
case <-b.done:
case <-b.bsOk:
return b.bs.id
}
}
@@ -131,7 +134,7 @@ func (b *Bar) Current() int64 {
select {
case b.operateState <- func(s *bState) { result <- s.current }:
return <-result
case <-b.done:
case <-b.bsOk:
return b.bs.current
}
}
@@ -149,26 +152,30 @@ func (b *Bar) SetRefill(amount int64) {
s.refill = s.current
}
}:
case <-b.done:
case <-b.ctx.Done():
}
}
// TraverseDecorators traverses all available decorators and calls cb func on each.
// TraverseDecorators traverses available decorators and calls cb func
// on each in a new goroutine. Decorators implementing decor.Wrapper
// interface are unwrapped first.
func (b *Bar) TraverseDecorators(cb func(decor.Decorator)) {
iter := make(chan decor.Decorator)
select {
case b.operateState <- func(s *bState) {
var wg sync.WaitGroup
for _, decorators := range s.decorators {
wg.Add(len(decorators))
for _, d := range decorators {
iter <- d
d := d
go func() {
cb(unwrap(d))
wg.Done()
}()
}
}
close(iter)
wg.Wait()
}:
for d := range iter {
cb(unwrap(d))
}
case <-b.done:
case <-b.ctx.Done():
}
}
@@ -183,13 +190,12 @@ func (b *Bar) EnableTriggerComplete() {
}
if s.current >= s.total {
s.current = s.total
s.completed = true
b.triggerCompletion(s)
s.triggerCompletion(b)
} else {
s.triggerComplete = true
}
}:
case <-b.done:
case <-b.ctx.Done():
}
}
@@ -211,11 +217,10 @@ func (b *Bar) SetTotal(total int64, complete bool) {
}
if complete {
s.current = s.total
s.completed = true
b.triggerCompletion(s)
s.triggerCompletion(b)
}
}:
case <-b.done:
case <-b.ctx.Done():
}
}
@@ -229,31 +234,10 @@ func (b *Bar) SetCurrent(current int64) {
s.current = current
if s.triggerComplete && s.current >= s.total {
s.current = s.total
s.completed = true
b.triggerCompletion(s)
s.triggerCompletion(b)
}
}:
case <-b.done:
}
}
// EwmaSetCurrent sets progress' current to an arbitrary value and updates
// EWMA based decorators by dur of a single iteration.
func (b *Bar) EwmaSetCurrent(current int64, iterDur time.Duration) {
if current < 0 {
return
}
select {
case b.operateState <- func(s *bState) {
s.decoratorEwmaUpdate(current-s.current, iterDur)
s.current = current
if s.triggerComplete && s.current >= s.total {
s.current = s.total
s.completed = true
b.triggerCompletion(s)
}
}:
case <-b.done:
case <-b.ctx.Done():
}
}
@@ -269,19 +253,15 @@ func (b *Bar) IncrBy(n int) {
// IncrInt64 increments progress by amount of n.
func (b *Bar) IncrInt64(n int64) {
if n <= 0 {
return
}
select {
case b.operateState <- func(s *bState) {
s.current += n
if s.triggerComplete && s.current >= s.total {
s.current = s.total
s.completed = true
b.triggerCompletion(s)
s.triggerCompletion(b)
}
}:
case <-b.done:
case <-b.ctx.Done():
}
}
@@ -300,26 +280,63 @@ func (b *Bar) EwmaIncrBy(n int, iterDur time.Duration) {
func (b *Bar) EwmaIncrInt64(n int64, iterDur time.Duration) {
select {
case b.operateState <- func(s *bState) {
s.decoratorEwmaUpdate(n, iterDur)
var wg sync.WaitGroup
wg.Add(len(s.ewmaDecorators))
for _, d := range s.ewmaDecorators {
d := d
go func() {
d.EwmaUpdate(n, iterDur)
wg.Done()
}()
}
s.current += n
if s.triggerComplete && s.current >= s.total {
s.current = s.total
s.completed = true
b.triggerCompletion(s)
s.triggerCompletion(b)
}
wg.Wait()
}:
case <-b.done:
case <-b.ctx.Done():
}
}
// DecoratorAverageAdjust adjusts all average based decorators. Call
// if you need to adjust start time of all average based decorators
// or after progress resume.
func (b *Bar) DecoratorAverageAdjust(start time.Time) {
select {
case b.operateState <- func(s *bState) { s.decoratorAverageAdjust(start) }:
case <-b.done:
// EwmaSetCurrent sets progress' current to an arbitrary value and updates
// EWMA based decorators by dur of a single iteration.
func (b *Bar) EwmaSetCurrent(current int64, iterDur time.Duration) {
if current < 0 {
return
}
select {
case b.operateState <- func(s *bState) {
n := current - s.current
var wg sync.WaitGroup
wg.Add(len(s.ewmaDecorators))
for _, d := range s.ewmaDecorators {
d := d
go func() {
d.EwmaUpdate(n, iterDur)
wg.Done()
}()
}
s.current = current
if s.triggerComplete && s.current >= s.total {
s.current = s.total
s.triggerCompletion(b)
}
wg.Wait()
}:
case <-b.ctx.Done():
}
}
// DecoratorAverageAdjust adjusts decorators implementing decor.AverageDecorator interface.
// Call if there is need to set start time after decorators have been constructed.
func (b *Bar) DecoratorAverageAdjust(start time.Time) {
b.TraverseDecorators(func(d decor.Decorator) {
if d, ok := d.(decor.AverageDecorator); ok {
d.AverageAdjust(start)
}
})
}
// SetPriority changes bar's order among multiple bars. Zero is highest
@@ -336,14 +353,14 @@ func (b *Bar) SetPriority(priority int) {
func (b *Bar) Abort(drop bool) {
select {
case b.operateState <- func(s *bState) {
if s.completed || s.aborted {
if s.aborted || s.completed() {
return
}
s.aborted = true
s.rmOnComplete = drop
b.triggerCompletion(s)
s.triggerCompletion(b)
}:
case <-b.done:
case <-b.ctx.Done():
}
}
@@ -353,7 +370,7 @@ func (b *Bar) Aborted() bool {
select {
case b.operateState <- func(s *bState) { result <- s.aborted }:
return <-result
case <-b.done:
case <-b.bsOk:
return b.bs.aborted
}
}
@@ -362,41 +379,52 @@ func (b *Bar) Aborted() bool {
func (b *Bar) Completed() bool {
result := make(chan bool)
select {
case b.operateState <- func(s *bState) { result <- s.completed }:
case b.operateState <- func(s *bState) { result <- s.completed() }:
return <-result
case <-b.done:
return b.bs.completed
case <-b.bsOk:
return b.bs.completed()
}
}
// IsRunning reports whether the bar is running, i.e. not yet completed
// and not yet aborted.
// IsRunning reports whether the bar is in running state.
func (b *Bar) IsRunning() bool {
result := make(chan bool)
select {
case b.operateState <- func(s *bState) { result <- !s.completed && !s.aborted }:
return <-result
case <-b.done:
case <-b.ctx.Done():
return false
default:
return true
}
}
// Wait blocks until bar is completed or aborted.
func (b *Bar) Wait() {
<-b.done
<-b.bsOk
}
func (b *Bar) serve(ctx context.Context, bs *bState) {
defer b.container.bwg.Done()
func (b *Bar) serve(bs *bState) {
decoratorsOnShutdown := func(decorators []decor.Decorator) {
for _, d := range decorators {
if d, ok := unwrap(d).(decor.ShutdownListener); ok {
b.container.bwg.Add(1)
go func() {
d.OnShutdown()
b.container.bwg.Done()
}()
}
}
}
for {
select {
case op := <-b.operateState:
op(bs)
case <-ctx.Done():
bs.aborted = !bs.completed
bs.decoratorShutdownNotify()
case <-b.ctx.Done():
decoratorsOnShutdown(bs.decorators[0])
decoratorsOnShutdown(bs.decorators[1])
// bar can be aborted by canceling parent ctx without calling b.Abort
bs.aborted = !bs.completed()
b.bs = bs
close(b.done)
close(b.bsOk)
b.container.bwg.Done()
return
}
}
@@ -405,7 +433,7 @@ func (b *Bar) serve(ctx context.Context, bs *bState) {
func (b *Bar) render(tw int) {
fn := func(s *bState) {
frame := new(renderFrame)
stat := newStatistics(tw, s)
stat := s.newStatistics(tw)
r, err := s.draw(stat)
if err != nil {
for _, buf := range s.buffers {
@@ -415,11 +443,8 @@ func (b *Bar) render(tw int) {
b.frameCh <- frame
return
}
frame.rows = append(frame.rows, r)
if s.extender != nil {
frame.rows, frame.err = s.extender(frame.rows, stat)
}
if s.completed || s.aborted {
frame.rows, frame.err = s.extender(stat, r)
if s.aborted || s.completed() {
frame.shutdown = s.shutdown
frame.rmOnComplete = s.rmOnComplete
frame.noPop = s.noPop
@@ -430,22 +455,11 @@ func (b *Bar) render(tw int) {
}
select {
case b.operateState <- fn:
case <-b.done:
case <-b.bsOk:
fn(b.bs)
}
}
func (b *Bar) triggerCompletion(s *bState) {
if s.autoRefresh {
// Technically this call isn't required, but if refresh rate is set to
// one hour for example and bar completes within a few minutes p.Wait()
// will wait for one hour. This call helps to avoid unnecessary waiting.
go b.tryEarlyRefresh(s.renderReq)
} else {
b.cancel()
}
}
func (b *Bar) tryEarlyRefresh(renderReq chan<- time.Time) {
var otherRunning int
b.container.traverseBars(func(bar *Bar) bool {
@@ -459,7 +473,7 @@ func (b *Bar) tryEarlyRefresh(renderReq chan<- time.Time) {
for {
select {
case renderReq <- time.Now():
case <-b.done:
case <-b.ctx.Done():
return
}
}
@@ -471,7 +485,7 @@ func (b *Bar) wSyncTable() syncTable {
select {
case b.operateState <- func(s *bState) { result <- s.wSyncTable() }:
return <-result
case <-b.done:
case <-b.bsOk:
return b.bs.wSyncTable()
}
}
@@ -551,58 +565,31 @@ func (s *bState) wSyncTable() (table syncTable) {
return table
}
func (s bState) decoratorEwmaUpdate(n int64, dur time.Duration) {
var wg sync.WaitGroup
for i := 0; i < len(s.ewmaDecorators); i++ {
switch d := s.ewmaDecorators[i]; i {
case len(s.ewmaDecorators) - 1:
d.EwmaUpdate(n, dur)
default:
wg.Add(1)
go func() {
d.EwmaUpdate(n, dur)
wg.Done()
}()
func (s *bState) populateEwmaDecorators(decorators []decor.Decorator) {
for _, d := range decorators {
if d, ok := unwrap(d).(decor.EwmaDecorator); ok {
s.ewmaDecorators = append(s.ewmaDecorators, d)
}
}
wg.Wait()
}
func (s bState) decoratorAverageAdjust(start time.Time) {
var wg sync.WaitGroup
for i := 0; i < len(s.averageDecorators); i++ {
switch d := s.averageDecorators[i]; i {
case len(s.averageDecorators) - 1:
d.AverageAdjust(start)
default:
wg.Add(1)
go func() {
d.AverageAdjust(start)
wg.Done()
}()
}
func (s *bState) triggerCompletion(b *Bar) {
s.triggerComplete = true
if s.autoRefresh {
// Technically this call isn't required, but if refresh rate is set to
// one hour for example and bar completes within a few minutes p.Wait()
// will wait for one hour. This call helps to avoid unnecessary waiting.
go b.tryEarlyRefresh(s.renderReq)
} else {
b.cancel()
}
wg.Wait()
}
func (s bState) decoratorShutdownNotify() {
var wg sync.WaitGroup
for i := 0; i < len(s.shutdownListeners); i++ {
switch d := s.shutdownListeners[i]; i {
case len(s.shutdownListeners) - 1:
d.OnShutdown()
default:
wg.Add(1)
go func() {
d.OnShutdown()
wg.Done()
}()
}
}
wg.Wait()
func (s bState) completed() bool {
return s.triggerComplete && s.current == s.total
}
func newStatistics(tw int, s *bState) decor.Statistics {
func (s bState) newStatistics(tw int) decor.Statistics {
return decor.Statistics{
AvailableWidth: tw,
RequestedWidth: s.reqWidth,
@@ -610,7 +597,7 @@ func newStatistics(tw int, s *bState) decor.Statistics {
Total: s.total,
Current: s.current,
Refill: s.refill,
Completed: s.completed,
Completed: s.completed(),
Aborted: s.aborted,
}
}

View File

@@ -50,13 +50,13 @@ type flushSection struct {
}
type bFiller struct {
components [components]component
meta [components]func(io.Writer, []byte) error
flush func(io.Writer, ...flushSection) error
tipOnComplete bool
tip struct {
frames []component
count uint
components [components]component
meta [components]func(io.Writer, []byte) error
flush func(io.Writer, ...flushSection) error
tip struct {
onComplete bool
count uint
frames []component
}
}
@@ -155,8 +155,7 @@ func (s barStyle) Reverse() BarStyleComposer {
func (s barStyle) Build() BarFiller {
bf := &bFiller{
meta: s.metaFuncs,
tipOnComplete: s.tipOnComplete,
meta: s.metaFuncs,
}
bf.components[iLbound] = component{
width: runewidth.StringWidth(s.style[iLbound]),
@@ -178,6 +177,7 @@ func (s barStyle) Build() BarFiller {
width: runewidth.StringWidth(s.style[iPadding]),
bytes: []byte(s.style[iPadding]),
}
bf.tip.onComplete = s.tipOnComplete
bf.tip.frames = make([]component, len(s.tipFrames))
for i, t := range s.tipFrames {
bf.tip.frames[i] = component{
@@ -233,17 +233,17 @@ func (s *bFiller) Fill(w io.Writer, stat decor.Statistics) error {
var tip component
var refilling, filling, padding []byte
var fillCount int
curWidth := int(internal.PercentageRound(stat.Total, stat.Current, int64(width)))
curWidth := int(internal.PercentageRound(stat.Total, stat.Current, uint(width)))
if curWidth != 0 {
if !stat.Completed || s.tipOnComplete {
if !stat.Completed || s.tip.onComplete {
tip = s.tip.frames[s.tip.count%uint(len(s.tip.frames))]
s.tip.count++
fillCount += tip.width
}
switch refWidth := 0; {
case stat.Refill != 0:
refWidth = int(internal.PercentageRound(stat.Total, stat.Refill, int64(width)))
refWidth = int(internal.PercentageRound(stat.Total, stat.Refill, uint(width)))
curWidth -= refWidth
refWidth += curWidth
fallthrough

View File

@@ -24,6 +24,7 @@ func inspect(decorators []decor.Decorator) (dest []decor.Decorator) {
func PrependDecorators(decorators ...decor.Decorator) BarOption {
decorators = inspect(decorators)
return func(s *bState) {
s.populateEwmaDecorators(decorators)
s.decorators[0] = decorators
}
}
@@ -32,6 +33,7 @@ func PrependDecorators(decorators ...decor.Decorator) BarOption {
func AppendDecorators(decorators ...decor.Decorator) BarOption {
decorators = inspect(decorators)
return func(s *bState) {
s.populateEwmaDecorators(decorators)
s.decorators[1] = decorators
}
}
@@ -112,6 +114,9 @@ func BarExtender(filler BarFiller, rev bool) BarOption {
if filler == nil {
return nil
}
if f, ok := filler.(BarFillerFunc); ok && f == nil {
return nil
}
fn := makeExtenderFunc(filler, rev)
return func(s *bState) {
s.extender = fn
@@ -120,28 +125,27 @@ func BarExtender(filler BarFiller, rev bool) BarOption {
func makeExtenderFunc(filler BarFiller, rev bool) extenderFunc {
buf := new(bytes.Buffer)
base := func(rows []io.Reader, stat decor.Statistics) ([]io.Reader, error) {
base := func(stat decor.Statistics, rows ...io.Reader) ([]io.Reader, error) {
err := filler.Fill(buf, stat)
if err != nil {
buf.Reset()
return rows, err
}
for {
b, err := buf.ReadBytes('\n')
line, err := buf.ReadBytes('\n')
if err != nil {
buf.Reset()
break
}
rows = append(rows, bytes.NewReader(b))
rows = append(rows, bytes.NewReader(line))
}
return rows, err
}
if !rev {
return base
}
return func(rows []io.Reader, stat decor.Statistics) ([]io.Reader, error) {
rows, err := base(rows, stat)
return func(stat decor.Statistics, rows ...io.Reader) ([]io.Reader, error) {
rows, err := base(stat, rows...)
if err != nil {
return rows, err
}

View File

@@ -17,15 +17,15 @@ func Elapsed(style TimeStyle, wcc ...WC) Decorator {
//
// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS]
//
// `startTime` start time
// `start` start time
//
// `wcc` optional WC config
func NewElapsed(style TimeStyle, startTime time.Time, wcc ...WC) Decorator {
func NewElapsed(style TimeStyle, start time.Time, wcc ...WC) Decorator {
var msg string
producer := chooseTimeProducer(style)
fn := func(s Statistics) string {
if !s.Completed {
msg = producer(time.Since(startTime))
if !s.Completed && !s.Aborted {
msg = producer(time.Since(start))
}
return msg
}

View File

@@ -33,13 +33,18 @@ func (f TimeNormalizerFunc) Normalize(src time.Duration) time.Duration {
// decorator to work correctly you have to measure each iteration's duration
// and pass it to one of the (*Bar).EwmaIncr... family methods.
func EwmaETA(style TimeStyle, age float64, wcc ...WC) Decorator {
return EwmaNormalizedETA(style, age, nil, wcc...)
}
// EwmaNormalizedETA same as EwmaETA but with TimeNormalizer option.
func EwmaNormalizedETA(style TimeStyle, age float64, normalizer TimeNormalizer, wcc ...WC) Decorator {
var average ewma.MovingAverage
if age == 0 {
average = ewma.NewMovingAverage()
} else {
average = ewma.NewMovingAverage(age)
}
return MovingAverageETA(style, average, nil, wcc...)
return MovingAverageETA(style, average, normalizer, wcc...)
}
// MovingAverageETA decorator relies on MovingAverage implementation to calculate its average.
@@ -52,6 +57,9 @@ func EwmaETA(style TimeStyle, age float64, wcc ...WC) Decorator {
//
// `wcc` optional WC config
func MovingAverageETA(style TimeStyle, average ewma.MovingAverage, normalizer TimeNormalizer, wcc ...WC) Decorator {
if average == nil {
average = NewMedian()
}
d := &movingAverageETA{
WC: initWC(wcc...),
producer: chooseTimeProducer(style),
@@ -105,15 +113,15 @@ func AverageETA(style TimeStyle, wcc ...WC) Decorator {
//
// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS]
//
// `startTime` start time
// `start` start time
//
// `normalizer` available implementations are [FixedIntervalTimeNormalizer|MaxTolerateTimeNormalizer]
//
// `wcc` optional WC config
func NewAverageETA(style TimeStyle, startTime time.Time, normalizer TimeNormalizer, wcc ...WC) Decorator {
func NewAverageETA(style TimeStyle, start time.Time, normalizer TimeNormalizer, wcc ...WC) Decorator {
d := &averageETA{
WC: initWC(wcc...),
startTime: startTime,
start: start,
normalizer: normalizer,
producer: chooseTimeProducer(style),
}
@@ -122,7 +130,7 @@ func NewAverageETA(style TimeStyle, startTime time.Time, normalizer TimeNormaliz
type averageETA struct {
WC
startTime time.Time
start time.Time
normalizer TimeNormalizer
producer func(time.Duration) string
}
@@ -130,7 +138,7 @@ type averageETA struct {
func (d *averageETA) Decor(s Statistics) (string, int) {
var remaining time.Duration
if s.Current != 0 {
durPerItem := float64(time.Since(d.startTime)) / float64(s.Current)
durPerItem := float64(time.Since(d.start)) / float64(s.Current)
durPerItem = math.Round(durPerItem)
remaining = time.Duration((s.Total - s.Current) * int64(durPerItem))
if d.normalizer != nil {
@@ -140,8 +148,8 @@ func (d *averageETA) Decor(s Statistics) (string, int) {
return d.Format(d.producer(remaining))
}
func (d *averageETA) AverageAdjust(startTime time.Time) {
d.startTime = startTime
func (d *averageETA) AverageAdjust(start time.Time) {
d.start = start
}
// MaxTolerateTimeNormalizer returns implementation of TimeNormalizer.
@@ -156,7 +164,10 @@ func MaxTolerateTimeNormalizer(maxTolerate time.Duration) TimeNormalizer {
}
normalized -= time.Since(lastCall)
lastCall = time.Now()
return normalized
if normalized > 0 {
return normalized
}
return remaining
})
}
@@ -175,7 +186,10 @@ func FixedIntervalTimeNormalizer(updInterval int) TimeNormalizer {
count--
normalized -= time.Since(lastCall)
lastCall = time.Now()
return normalized
if normalized > 0 {
return normalized
}
return remaining
})
}

View File

@@ -61,7 +61,7 @@ func NewPercentage(format string, wcc ...WC) Decorator {
format = "% d"
}
f := func(s Statistics) string {
p := internal.PercentageRound(s.Total, s.Current, 100)
p := internal.Percentage(uint(s.Total), uint(s.Current), 100)
return fmt.Sprintf(format, percentageType(p))
}
return Any(f, wcc...)

View File

@@ -21,15 +21,15 @@ var (
//
// fmt.Printf("%.1f", FmtAsSpeed(SizeB1024(2048)))
func FmtAsSpeed(input fmt.Formatter) fmt.Formatter {
return speedFormatter{input}
return &speedFormatter{input}
}
type speedFormatter struct {
fmt.Formatter
}
func (self speedFormatter) Format(st fmt.State, verb rune) {
self.Formatter.Format(st, verb)
func (s *speedFormatter) Format(st fmt.State, verb rune) {
s.Formatter.Format(st, verb)
_, err := io.WriteString(st, "/s")
if err != nil {
panic(err)
@@ -120,7 +120,7 @@ func AverageSpeed(unit interface{}, format string, wcc ...WC) Decorator {
//
// `format` printf compatible verb for value, like "%f" or "%d"
//
// `startTime` start time
// `start` start time
//
// `wcc` optional WC config
//
@@ -130,32 +130,32 @@ func AverageSpeed(unit interface{}, format string, wcc ...WC) Decorator {
// unit=SizeB1024(0), format="% .1f" output: "1.0 MiB/s"
// unit=SizeB1000(0), format="%.1f" output: "1.0MB/s"
// unit=SizeB1000(0), format="% .1f" output: "1.0 MB/s"
func NewAverageSpeed(unit interface{}, format string, startTime time.Time, wcc ...WC) Decorator {
func NewAverageSpeed(unit interface{}, format string, start time.Time, wcc ...WC) Decorator {
d := &averageSpeed{
WC: initWC(wcc...),
startTime: startTime,
producer: chooseSpeedProducer(unit, format),
WC: initWC(wcc...),
start: start,
producer: chooseSpeedProducer(unit, format),
}
return d
}
type averageSpeed struct {
WC
startTime time.Time
producer func(float64) string
msg string
start time.Time
producer func(float64) string
msg string
}
func (d *averageSpeed) Decor(s Statistics) (string, int) {
if !s.Completed {
speed := float64(s.Current) / float64(time.Since(d.startTime))
speed := float64(s.Current) / float64(time.Since(d.start))
d.msg = d.producer(speed * 1e9)
}
return d.Format(d.msg)
}
func (d *averageSpeed) AverageAdjust(startTime time.Time) {
d.startTime = startTime
func (d *averageSpeed) AverageAdjust(start time.Time) {
d.start = start
}
func chooseSpeedProducer(unit interface{}, format string) func(float64) string {

View File

@@ -14,9 +14,9 @@ func Percentage(total, current, width uint) float64 {
}
// PercentageRound same as Percentage but with math.Round.
func PercentageRound(total, current, width int64) float64 {
if total < 0 || current < 0 || width < 0 {
func PercentageRound(total, current int64, width uint) float64 {
if total < 0 || current < 0 {
return 0
}
return math.Round(Percentage(uint(total), uint(current), uint(width)))
return math.Round(Percentage(uint(total), uint(current), width))
}

View File

@@ -126,6 +126,9 @@ func (p *Progress) AddSpinner(total int64, options ...BarOption) *Bar {
// New creates a bar by calling `Build` method on provided `BarFillerBuilder`.
func (p *Progress) New(total int64, builder BarFillerBuilder, options ...BarOption) *Bar {
if builder == nil {
return p.MustAdd(total, nil, options...)
}
return p.MustAdd(total, builder.Build(), options...)
}
@@ -147,12 +150,10 @@ func (p *Progress) MustAdd(total int64, filler BarFiller, options ...BarOption)
func (p *Progress) Add(total int64, filler BarFiller, options ...BarOption) (*Bar, error) {
if filler == nil {
filler = NopStyle().Build()
} else if f, ok := filler.(BarFillerFunc); ok && f == nil {
filler = NopStyle().Build()
}
type result struct {
bar *Bar
bs *bState
}
ch := make(chan result)
ch := make(chan *Bar)
select {
case p.operateState <- func(ps *pState) {
bs := ps.makeBarState(total, filler, options...)
@@ -163,22 +164,9 @@ func (p *Progress) Add(total int64, filler BarFiller, options ...BarOption) (*Ba
ps.hm.push(bar, true)
}
ps.idCount++
ch <- result{bar, bs}
ch <- bar
}:
res := <-ch
bar, bs := res.bar, res.bs
bar.TraverseDecorators(func(d decor.Decorator) {
if d, ok := d.(decor.AverageDecorator); ok {
bs.averageDecorators = append(bs.averageDecorators, d)
}
if d, ok := d.(decor.EwmaDecorator); ok {
bs.ewmaDecorators = append(bs.ewmaDecorators, d)
}
if d, ok := d.(decor.ShutdownListener); ok {
bs.shutdownListeners = append(bs.shutdownListeners, d)
}
})
return bar, nil
return <-ch, nil
case <-p.done:
return nil, DoneError
}
@@ -237,13 +225,12 @@ func (p *Progress) Write(b []byte) (int, error) {
// Wait waits for all bars to complete and finally shutdowns container. After
// this method has been called, there is no way to reuse `*Progress` instance.
func (p *Progress) Wait() {
p.bwg.Wait()
p.Shutdown()
// wait for user wg, if any
if p.uwg != nil {
p.uwg.Wait()
}
p.bwg.Wait()
p.Shutdown()
}
// Shutdown cancels any running bar immediately and then shutdowns `*Progress`
@@ -453,6 +440,9 @@ func (s pState) makeBarState(total int64, filler BarFiller, options ...BarOption
filler: filler,
renderReq: s.renderReq,
autoRefresh: s.autoRefresh,
extender: func(_ decor.Statistics, rows ...io.Reader) ([]io.Reader, error) {
return rows, nil
},
}
if total > 0 {

View File

@@ -69,28 +69,5 @@ func toReadCloser(r io.Reader) io.ReadCloser {
if rc, ok := r.(io.ReadCloser); ok {
return rc
}
return toNopReadCloser(r)
}
func toNopReadCloser(r io.Reader) io.ReadCloser {
if _, ok := r.(io.WriterTo); ok {
return nopReadCloserWriterTo{r}
}
return nopReadCloser{r}
}
type nopReadCloser struct {
io.Reader
}
func (nopReadCloser) Close() error { return nil }
type nopReadCloserWriterTo struct {
io.Reader
}
func (nopReadCloserWriterTo) Close() error { return nil }
func (c nopReadCloserWriterTo) WriteTo(w io.Writer) (int64, error) {
return c.Reader.(io.WriterTo).WriteTo(w)
return io.NopCloser(r)
}