summaryrefslogtreecommitdiff
path: root/vendor/github.com/vbauerster
diff options
context:
space:
mode:
authorValentin Rothberg <rothberg@redhat.com>2019-02-21 11:54:04 +0100
committerValentin Rothberg <rothberg@redhat.com>2019-02-21 11:54:04 +0100
commitc069d117594d72159157aa48d0693d8571be45c5 (patch)
tree19b8af7cb8eb967154f162bde56bb6b599aad4cf /vendor/github.com/vbauerster
parent4934bf23272f185fa9f08d0ba890c5a0eb4ed14d (diff)
downloadpodman-c069d117594d72159157aa48d0693d8571be45c5.tar.gz
podman-c069d117594d72159157aa48d0693d8571be45c5.tar.bz2
podman-c069d117594d72159157aa48d0693d8571be45c5.zip
vendor containers/image v1.4
This requires some additional changes to the dependencies since the progress-bar library has been changed to github.com/vbauerster/mpb. Please refer to the following link for the release notes: https://github.com/containers/image/releases/tag/v1.4 Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
Diffstat (limited to 'vendor/github.com/vbauerster')
-rw-r--r--vendor/github.com/vbauerster/mpb/LICENSE29
-rw-r--r--vendor/github.com/vbauerster/mpb/README.md117
-rw-r--r--vendor/github.com/vbauerster/mpb/bar.go455
-rw-r--r--vendor/github.com/vbauerster/mpb/bar_option.go124
-rw-r--r--vendor/github.com/vbauerster/mpb/cwriter/writer.go78
-rw-r--r--vendor/github.com/vbauerster/mpb/cwriter/writer_posix.go13
-rw-r--r--vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go77
-rw-r--r--vendor/github.com/vbauerster/mpb/decor/counters.go206
-rw-r--r--vendor/github.com/vbauerster/mpb/decor/decorator.go144
-rw-r--r--vendor/github.com/vbauerster/mpb/decor/doc.go25
-rw-r--r--vendor/github.com/vbauerster/mpb/decor/elapsed.go68
-rw-r--r--vendor/github.com/vbauerster/mpb/decor/eta.go207
-rw-r--r--vendor/github.com/vbauerster/mpb/decor/moving-average.go66
-rw-r--r--vendor/github.com/vbauerster/mpb/decor/name.go45
-rw-r--r--vendor/github.com/vbauerster/mpb/decor/percentage.go39
-rw-r--r--vendor/github.com/vbauerster/mpb/decor/speed.go270
-rw-r--r--vendor/github.com/vbauerster/mpb/doc.go6
-rw-r--r--vendor/github.com/vbauerster/mpb/internal/percentage.go10
-rw-r--r--vendor/github.com/vbauerster/mpb/internal/round.go49
-rw-r--r--vendor/github.com/vbauerster/mpb/options.go95
-rw-r--r--vendor/github.com/vbauerster/mpb/options_go1.7.go15
-rw-r--r--vendor/github.com/vbauerster/mpb/priority_queue.go40
-rw-r--r--vendor/github.com/vbauerster/mpb/progress.go251
-rw-r--r--vendor/github.com/vbauerster/mpb/progress_posix.go70
-rw-r--r--vendor/github.com/vbauerster/mpb/progress_windows.go43
-rw-r--r--vendor/github.com/vbauerster/mpb/proxyreader.go22
26 files changed, 2564 insertions, 0 deletions
diff --git a/vendor/github.com/vbauerster/mpb/LICENSE b/vendor/github.com/vbauerster/mpb/LICENSE
new file mode 100644
index 000000000..5e68ed21e
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (C) 2016-2018 Vladimir Bauer
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/vbauerster/mpb/README.md b/vendor/github.com/vbauerster/mpb/README.md
new file mode 100644
index 000000000..9b760647e
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/README.md
@@ -0,0 +1,117 @@
+# Multi Progress Bar
+
+[![GoDoc](https://godoc.org/github.com/vbauerster/mpb?status.svg)](https://godoc.org/github.com/vbauerster/mpb)
+[![Build Status](https://travis-ci.org/vbauerster/mpb.svg?branch=master)](https://travis-ci.org/vbauerster/mpb)
+[![Go Report Card](https://goreportcard.com/badge/github.com/vbauerster/mpb)](https://goreportcard.com/report/github.com/vbauerster/mpb)
+[![codecov](https://codecov.io/gh/vbauerster/mpb/branch/master/graph/badge.svg)](https://codecov.io/gh/vbauerster/mpb)
+
+**mpb** is a Go lib for rendering progress bars in terminal applications.
+
+## Features
+
+* __Multiple Bars__: Multiple progress bars are supported
+* __Dynamic Total__: [Set total](https://github.com/vbauerster/mpb/issues/9#issuecomment-344448984) while bar is running
+* __Dynamic Add/Remove__: Dynamically add or remove bars
+* __Cancellation__: Cancel whole rendering process
+* __Predefined Decorators__: Elapsed time, [ewma](https://github.com/VividCortex/ewma) based ETA, Percentage, Bytes counter
+* __Decorator's width sync__: Synchronized decorator's width among multiple bars
+
+## Installation
+
+```sh
+go get github.com/vbauerster/mpb
+```
+
+_Note:_ it is preferable to go get from github.com, rather than gopkg.in. See issue [#11](https://github.com/vbauerster/mpb/issues/11).
+
+## Usage
+
+#### [Rendering single bar](examples/singleBar/main.go)
+```go
+ p := mpb.New(
+ // override default (80) width
+ mpb.WithWidth(64),
+ // override default "[=>-]" format
+ mpb.WithFormat("╢▌▌░╟"),
+ // override default 120ms refresh rate
+ mpb.WithRefreshRate(180*time.Millisecond),
+ )
+
+ total := 100
+ name := "Single Bar:"
+ // adding a single bar
+ bar := p.AddBar(int64(total),
+ mpb.PrependDecorators(
+ // display our name with one space on the right
+ decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight}),
+ // replace ETA decorator with "done" message, OnComplete event
+ decor.OnComplete(
+ // ETA decorator with ewma age of 60, and width reservation of 4
+ decor.EwmaETA(decor.ET_STYLE_GO, 60, decor.WC{W: 4}), "done",
+ ),
+ ),
+ mpb.AppendDecorators(decor.Percentage()),
+ )
+ // simulating some work
+ max := 100 * time.Millisecond
+ for i := 0; i < total; i++ {
+ start := time.Now()
+ time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10)
+ // ewma based decorators require work duration measurement
+ bar.IncrBy(1, time.Since(start))
+ }
+ // wait for our bar to complete and flush
+ p.Wait()
+```
+
+#### [Rendering multiple bars](examples/simple/main.go)
+```go
+ var wg sync.WaitGroup
+ p := mpb.New(mpb.WithWaitGroup(&wg))
+ total, numBars := 100, 3
+ wg.Add(numBars)
+
+ for i := 0; i < numBars; i++ {
+ name := fmt.Sprintf("Bar#%d:", i)
+ bar := p.AddBar(int64(total),
+ mpb.PrependDecorators(
+ // simple name decorator
+ decor.Name(name),
+ // decor.DSyncWidth bit enables column width synchronization
+ decor.Percentage(decor.WCSyncSpace),
+ ),
+ mpb.AppendDecorators(
+ // replace ETA decorator with "done" message, OnComplete event
+ decor.OnComplete(
+ // ETA decorator with ewma age of 60
+ decor.EwmaETA(decor.ET_STYLE_GO, 60), "done",
+ ),
+ ),
+ )
+ // simulating some work
+ go func() {
+ defer wg.Done()
+ max := 100 * time.Millisecond
+ for i := 0; i < total; i++ {
+ start := time.Now()
+ time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10)
+ // ewma based decorators require work duration measurement
+ bar.IncrBy(1, time.Since(start))
+ }
+ }()
+ }
+ // wait for all bars to complete and flush
+ p.Wait()
+```
+
+#### [Dynamic total](examples/dynTotal/main.go)
+
+![dynamic total](examples/gifs/godEMrCZmJkHYH1X9dN4Nm0U7.svg)
+
+#### [Complex example](examples/complex/main.go)
+
+![complex](examples/gifs/wHzf1M7sd7B3zVa2scBMnjqRf.svg)
+
+#### [Bytes counters](examples/io/single/main.go)
+
+![byte counters](examples/gifs/hIpTa3A5rQz65ssiVuRJu87X6.svg)
diff --git a/vendor/github.com/vbauerster/mpb/bar.go b/vendor/github.com/vbauerster/mpb/bar.go
new file mode 100644
index 000000000..5a506fc84
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/bar.go
@@ -0,0 +1,455 @@
+package mpb
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "strings"
+ "sync"
+ "time"
+ "unicode/utf8"
+
+ "github.com/vbauerster/mpb/decor"
+ "github.com/vbauerster/mpb/internal"
+)
+
+const (
+ rLeft = iota
+ rFill
+ rTip
+ rEmpty
+ rRight
+)
+
+const formatLen = 5
+
+type barRunes [formatLen]rune
+
+// Bar represents a progress Bar
+type Bar struct {
+ priority int
+ index int
+
+ runningBar *Bar
+ cacheState *bState
+ operateState chan func(*bState)
+ int64Ch chan int64
+ boolCh chan bool
+ frameReaderCh chan *frameReader
+ syncTableCh chan [][]chan int
+
+ // done is closed by Bar's goroutine, after cacheState is written
+ done chan struct{}
+ // shutdown is closed from master Progress goroutine only
+ shutdown chan struct{}
+}
+
+type (
+ bState struct {
+ id int
+ width int
+ total int64
+ current int64
+ runes barRunes
+ trimLeftSpace bool
+ trimRightSpace bool
+ toComplete bool
+ removeOnComplete bool
+ barClearOnComplete bool
+ completeFlushed bool
+ aDecorators []decor.Decorator
+ pDecorators []decor.Decorator
+ amountReceivers []decor.AmountReceiver
+ shutdownListeners []decor.ShutdownListener
+ refill *refill
+ bufP, bufB, bufA *bytes.Buffer
+ bufNL *bytes.Buffer
+ panicMsg string
+ newLineExtendFn func(io.Writer, *decor.Statistics)
+
+ // following options are assigned to the *Bar
+ priority int
+ runningBar *Bar
+ }
+ refill struct {
+ char rune
+ till int64
+ }
+ frameReader struct {
+ io.Reader
+ extendedLines int
+ toShutdown bool
+ removeOnComplete bool
+ }
+)
+
+func newBar(wg *sync.WaitGroup, id int, total int64, cancel <-chan struct{}, options ...BarOption) *Bar {
+ if total <= 0 {
+ total = time.Now().Unix()
+ }
+
+ s := &bState{
+ id: id,
+ priority: id,
+ total: total,
+ }
+
+ for _, opt := range options {
+ if opt != nil {
+ opt(s)
+ }
+ }
+
+ s.bufP = bytes.NewBuffer(make([]byte, 0, s.width))
+ s.bufB = bytes.NewBuffer(make([]byte, 0, s.width))
+ s.bufA = bytes.NewBuffer(make([]byte, 0, s.width))
+
+ b := &Bar{
+ priority: s.priority,
+ runningBar: s.runningBar,
+ operateState: make(chan func(*bState)),
+ int64Ch: make(chan int64),
+ boolCh: make(chan bool),
+ frameReaderCh: make(chan *frameReader, 1),
+ syncTableCh: make(chan [][]chan int),
+ done: make(chan struct{}),
+ shutdown: make(chan struct{}),
+ }
+
+ if b.runningBar != nil {
+ b.priority = b.runningBar.priority
+ }
+
+ if s.newLineExtendFn != nil {
+ s.bufNL = bytes.NewBuffer(make([]byte, 0, s.width))
+ }
+
+ go b.serve(wg, s, cancel)
+ return b
+}
+
+// RemoveAllPrependers removes all prepend functions.
+func (b *Bar) RemoveAllPrependers() {
+ select {
+ case b.operateState <- func(s *bState) { s.pDecorators = nil }:
+ case <-b.done:
+ }
+}
+
+// RemoveAllAppenders removes all append functions.
+func (b *Bar) RemoveAllAppenders() {
+ select {
+ case b.operateState <- func(s *bState) { s.aDecorators = nil }:
+ case <-b.done:
+ }
+}
+
+// ProxyReader wraps r with metrics required for progress tracking.
+func (b *Bar) ProxyReader(r io.Reader) io.ReadCloser {
+ if r == nil {
+ panic("expect io.Reader, got nil")
+ }
+ rc, ok := r.(io.ReadCloser)
+ if !ok {
+ rc = ioutil.NopCloser(r)
+ }
+ return &proxyReader{rc, b, time.Now()}
+}
+
+// ID returs id of the bar.
+func (b *Bar) ID() int {
+ select {
+ case b.operateState <- func(s *bState) { b.int64Ch <- int64(s.id) }:
+ return int(<-b.int64Ch)
+ case <-b.done:
+ return b.cacheState.id
+ }
+}
+
+// Current returns bar's current number, in other words sum of all increments.
+func (b *Bar) Current() int64 {
+ select {
+ case b.operateState <- func(s *bState) { b.int64Ch <- s.current }:
+ return <-b.int64Ch
+ case <-b.done:
+ return b.cacheState.current
+ }
+}
+
+// SetTotal sets total dynamically.
+// Set final to true, when total is known, it will trigger bar complete event.
+func (b *Bar) SetTotal(total int64, final bool) bool {
+ select {
+ case b.operateState <- func(s *bState) {
+ if total > 0 {
+ s.total = total
+ }
+ if final {
+ s.current = s.total
+ s.toComplete = true
+ }
+ }:
+ return true
+ case <-b.done:
+ return false
+ }
+}
+
+// SetRefill sets fill rune to r, up until n.
+func (b *Bar) SetRefill(n int, r rune) {
+ if n <= 0 {
+ return
+ }
+ b.operateState <- func(s *bState) {
+ s.refill = &refill{r, int64(n)}
+ }
+}
+
+// RefillBy is deprecated, use SetRefill
+func (b *Bar) RefillBy(n int, r rune) {
+ b.SetRefill(n, r)
+}
+
+// Increment is a shorthand for b.IncrBy(1).
+func (b *Bar) Increment() {
+ b.IncrBy(1)
+}
+
+// IncrBy increments progress bar by amount of n.
+// wdd is optional work duration i.e. time.Since(start),
+// which expected to be provided, if any ewma based decorator is used.
+func (b *Bar) IncrBy(n int, wdd ...time.Duration) {
+ select {
+ case b.operateState <- func(s *bState) {
+ s.current += int64(n)
+ if s.current >= s.total {
+ s.current = s.total
+ s.toComplete = true
+ }
+ for _, ar := range s.amountReceivers {
+ ar.NextAmount(n, wdd...)
+ }
+ }:
+ case <-b.done:
+ }
+}
+
+// Completed reports whether the bar is in completed state.
+func (b *Bar) Completed() bool {
+ // omit select here, because primary usage of the method is for loop
+ // condition, like for !bar.Completed() {...}
+ // so when toComplete=true it is called once (at which time, the bar is still alive),
+ // then quits the loop and never suppose to be called afterwards.
+ return <-b.boolCh
+}
+
+func (b *Bar) wSyncTable() [][]chan int {
+ select {
+ case b.operateState <- func(s *bState) { b.syncTableCh <- s.wSyncTable() }:
+ return <-b.syncTableCh
+ case <-b.done:
+ return b.cacheState.wSyncTable()
+ }
+}
+
+func (b *Bar) serve(wg *sync.WaitGroup, s *bState, cancel <-chan struct{}) {
+ defer wg.Done()
+ for {
+ select {
+ case op := <-b.operateState:
+ op(s)
+ case b.boolCh <- s.toComplete:
+ case <-cancel:
+ s.toComplete = true
+ cancel = nil
+ case <-b.shutdown:
+ b.cacheState = s
+ close(b.done)
+ for _, sl := range s.shutdownListeners {
+ sl.Shutdown()
+ }
+ return
+ }
+ }
+}
+
+func (b *Bar) render(debugOut io.Writer, tw int) {
+ select {
+ case b.operateState <- func(s *bState) {
+ defer func() {
+ // recovering if user defined decorator panics for example
+ if p := recover(); p != nil {
+ s.panicMsg = fmt.Sprintf("panic: %v", p)
+ fmt.Fprintf(debugOut, "%s %s bar id %02d %v\n", "[mpb]", time.Now(), s.id, s.panicMsg)
+ b.frameReaderCh <- &frameReader{
+ Reader: strings.NewReader(fmt.Sprintf(fmt.Sprintf("%%.%ds\n", tw), s.panicMsg)),
+ toShutdown: true,
+ }
+ }
+ }()
+ r := s.draw(tw)
+ var extendedLines int
+ if s.newLineExtendFn != nil {
+ s.bufNL.Reset()
+ s.newLineExtendFn(s.bufNL, newStatistics(s))
+ extendedLines = countLines(s.bufNL.Bytes())
+ r = io.MultiReader(r, s.bufNL)
+ }
+ b.frameReaderCh <- &frameReader{
+ Reader: r,
+ extendedLines: extendedLines,
+ toShutdown: s.toComplete && !s.completeFlushed,
+ removeOnComplete: s.removeOnComplete,
+ }
+ s.completeFlushed = s.toComplete
+ }:
+ case <-b.done:
+ s := b.cacheState
+ r := s.draw(tw)
+ var extendedLines int
+ if s.newLineExtendFn != nil {
+ s.bufNL.Reset()
+ s.newLineExtendFn(s.bufNL, newStatistics(s))
+ extendedLines = countLines(s.bufNL.Bytes())
+ r = io.MultiReader(r, s.bufNL)
+ }
+ b.frameReaderCh <- &frameReader{
+ Reader: r,
+ extendedLines: extendedLines,
+ }
+ }
+}
+
+func (s *bState) draw(termWidth int) io.Reader {
+ defer s.bufA.WriteByte('\n')
+
+ if s.panicMsg != "" {
+ return strings.NewReader(fmt.Sprintf(fmt.Sprintf("%%.%ds\n", termWidth), s.panicMsg))
+ }
+
+ stat := newStatistics(s)
+
+ for _, d := range s.pDecorators {
+ s.bufP.WriteString(d.Decor(stat))
+ }
+
+ for _, d := range s.aDecorators {
+ s.bufA.WriteString(d.Decor(stat))
+ }
+
+ prependCount := utf8.RuneCount(s.bufP.Bytes())
+ appendCount := utf8.RuneCount(s.bufA.Bytes())
+
+ if s.barClearOnComplete && s.completeFlushed {
+ return io.MultiReader(s.bufP, s.bufA)
+ }
+
+ s.fillBar(s.width)
+ barCount := utf8.RuneCount(s.bufB.Bytes())
+ totalCount := prependCount + barCount + appendCount
+ if spaceCount := 0; totalCount > termWidth {
+ if !s.trimLeftSpace {
+ spaceCount++
+ }
+ if !s.trimRightSpace {
+ spaceCount++
+ }
+ s.fillBar(termWidth - prependCount - appendCount - spaceCount)
+ }
+
+ return io.MultiReader(s.bufP, s.bufB, s.bufA)
+}
+
+func (s *bState) fillBar(width int) {
+ defer func() {
+ s.bufB.WriteRune(s.runes[rRight])
+ if !s.trimRightSpace {
+ s.bufB.WriteByte(' ')
+ }
+ }()
+
+ s.bufB.Reset()
+ if !s.trimLeftSpace {
+ s.bufB.WriteByte(' ')
+ }
+ s.bufB.WriteRune(s.runes[rLeft])
+ if width <= 2 {
+ return
+ }
+
+ // bar s.width without leftEnd and rightEnd runes
+ barWidth := width - 2
+
+ completedWidth := internal.Percentage(s.total, s.current, int64(barWidth))
+
+ if s.refill != nil {
+ till := internal.Percentage(s.total, s.refill.till, int64(barWidth))
+ // append refill rune
+ var i int64
+ for i = 0; i < till; i++ {
+ s.bufB.WriteRune(s.refill.char)
+ }
+ for i = till; i < completedWidth; i++ {
+ s.bufB.WriteRune(s.runes[rFill])
+ }
+ } else {
+ var i int64
+ for i = 0; i < completedWidth; i++ {
+ s.bufB.WriteRune(s.runes[rFill])
+ }
+ }
+
+ if completedWidth < int64(barWidth) && completedWidth > 0 {
+ _, size := utf8.DecodeLastRune(s.bufB.Bytes())
+ s.bufB.Truncate(s.bufB.Len() - size)
+ s.bufB.WriteRune(s.runes[rTip])
+ }
+
+ for i := completedWidth; i < int64(barWidth); i++ {
+ s.bufB.WriteRune(s.runes[rEmpty])
+ }
+}
+
+func (s *bState) wSyncTable() [][]chan int {
+ columns := make([]chan int, 0, len(s.pDecorators)+len(s.aDecorators))
+ var pCount int
+ for _, d := range s.pDecorators {
+ if ok, ch := d.Syncable(); ok {
+ columns = append(columns, ch)
+ pCount++
+ }
+ }
+ var aCount int
+ for _, d := range s.aDecorators {
+ if ok, ch := d.Syncable(); ok {
+ columns = append(columns, ch)
+ aCount++
+ }
+ }
+ table := make([][]chan int, 2)
+ table[0] = columns[0:pCount]
+ table[1] = columns[pCount : pCount+aCount : pCount+aCount]
+ return table
+}
+
+func newStatistics(s *bState) *decor.Statistics {
+ return &decor.Statistics{
+ ID: s.id,
+ Completed: s.completeFlushed,
+ Total: s.total,
+ Current: s.current,
+ }
+}
+
+func strToBarRunes(format string) (array barRunes) {
+ for i, n := 0, 0; len(format) > 0; i++ {
+ array[i], n = utf8.DecodeRuneInString(format)
+ format = format[n:]
+ }
+ return
+}
+
+func countLines(b []byte) int {
+ return bytes.Count(b, []byte("\n"))
+}
diff --git a/vendor/github.com/vbauerster/mpb/bar_option.go b/vendor/github.com/vbauerster/mpb/bar_option.go
new file mode 100644
index 000000000..e33bce4da
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/bar_option.go
@@ -0,0 +1,124 @@
+package mpb
+
+import (
+ "io"
+
+ "github.com/vbauerster/mpb/decor"
+)
+
+// BarOption is a function option which changes the default behavior of a bar,
+// if passed to p.AddBar(int64, ...BarOption)
+type BarOption func(*bState)
+
+// AppendDecorators let you inject decorators to the bar's right side
+func AppendDecorators(appenders ...decor.Decorator) BarOption {
+ return func(s *bState) {
+ for _, decorator := range appenders {
+ if ar, ok := decorator.(decor.AmountReceiver); ok {
+ s.amountReceivers = append(s.amountReceivers, ar)
+ }
+ if sl, ok := decorator.(decor.ShutdownListener); ok {
+ s.shutdownListeners = append(s.shutdownListeners, sl)
+ }
+ s.aDecorators = append(s.aDecorators, decorator)
+ }
+ }
+}
+
+// PrependDecorators let you inject decorators to the bar's left side
+func PrependDecorators(prependers ...decor.Decorator) BarOption {
+ return func(s *bState) {
+ for _, decorator := range prependers {
+ if ar, ok := decorator.(decor.AmountReceiver); ok {
+ s.amountReceivers = append(s.amountReceivers, ar)
+ }
+ if sl, ok := decorator.(decor.ShutdownListener); ok {
+ s.shutdownListeners = append(s.shutdownListeners, sl)
+ }
+ s.pDecorators = append(s.pDecorators, decorator)
+ }
+ }
+}
+
+// BarTrimLeft trims left side space of the bar
+func BarTrimLeft() BarOption {
+ return func(s *bState) {
+ s.trimLeftSpace = true
+ }
+}
+
+// BarTrimRight trims right space of the bar
+func BarTrimRight() BarOption {
+ return func(s *bState) {
+ s.trimRightSpace = true
+ }
+}
+
+// BarTrim trims both left and right spaces of the bar
+func BarTrim() BarOption {
+ return func(s *bState) {
+ s.trimLeftSpace = true
+ s.trimRightSpace = true
+ }
+}
+
+// BarID overwrites internal bar id
+func BarID(id int) BarOption {
+ return func(s *bState) {
+ s.id = id
+ }
+}
+
+// BarRemoveOnComplete is a flag, if set whole bar line will be removed on complete event.
+// If both BarRemoveOnComplete and BarClearOnComplete are set, first bar section gets cleared
+// and then whole bar line gets removed completely.
+func BarRemoveOnComplete() BarOption {
+ return func(s *bState) {
+ s.removeOnComplete = true
+ }
+}
+
+// BarReplaceOnComplete is indicator for delayed bar start, after the `runningBar` is complete.
+// To achieve bar replacement effect, `runningBar` should has its `BarRemoveOnComplete` option set.
+func BarReplaceOnComplete(runningBar *Bar) BarOption {
+ return func(s *bState) {
+ s.runningBar = runningBar
+ }
+}
+
+// BarClearOnComplete is a flag, if set will clear bar section on complete event.
+// If you need to remove a whole bar line, refer to BarRemoveOnComplete.
+func BarClearOnComplete() BarOption {
+ return func(s *bState) {
+ s.barClearOnComplete = true
+ }
+}
+
+// BarPriority sets bar's priority.
+// Zero is highest priority, i.e. bar will be on top.
+// If `BarReplaceOnComplete` option is supplied, this option is ignored.
+func BarPriority(priority int) BarOption {
+ return func(s *bState) {
+ s.priority = priority
+ }
+}
+
+// BarNewLineExtend takes user defined efn, which gets called each render cycle.
+// Any write to provided writer of efn, will appear on new line of respective bar.
+func BarNewLineExtend(efn func(io.Writer, *decor.Statistics)) BarOption {
+ return func(s *bState) {
+ s.newLineExtendFn = efn
+ }
+}
+
+func barWidth(w int) BarOption {
+ return func(s *bState) {
+ s.width = w
+ }
+}
+
+func barFormat(format string) BarOption {
+ return func(s *bState) {
+ s.runes = strToBarRunes(format)
+ }
+}
diff --git a/vendor/github.com/vbauerster/mpb/cwriter/writer.go b/vendor/github.com/vbauerster/mpb/cwriter/writer.go
new file mode 100644
index 000000000..0b1470d4c
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/cwriter/writer.go
@@ -0,0 +1,78 @@
+package cwriter
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+
+ isatty "github.com/mattn/go-isatty"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+// ESC is the ASCII code for escape character
+const ESC = 27
+
+var NotATTY = errors.New("not a terminal")
+
+var (
+ cursorUp = fmt.Sprintf("%c[%dA", ESC, 1)
+ clearLine = fmt.Sprintf("%c[2K\r", ESC)
+ clearCursorAndLine = cursorUp + clearLine
+)
+
+// Writer is a buffered the writer that updates the terminal.
+// The contents of writer will be flushed when Flush is called.
+type Writer struct {
+ out io.Writer
+ buf bytes.Buffer
+ isTerminal bool
+ fd int
+ lineCount int
+}
+
+// New returns a new Writer with defaults
+func New(out io.Writer) *Writer {
+ w := &Writer{out: out}
+ if f, ok := out.(*os.File); ok {
+ fd := f.Fd()
+ w.isTerminal = isatty.IsTerminal(fd)
+ w.fd = int(fd)
+ }
+ return w
+}
+
+// Flush flushes the underlying buffer
+func (w *Writer) Flush(lineCount int) error {
+ err := w.clearLines()
+ w.lineCount = lineCount
+ // WriteTo takes care of w.buf.Reset
+ if _, e := w.buf.WriteTo(w.out); err == nil {
+ err = e
+ }
+ return err
+}
+
+// Write appends the contents of p to the underlying buffer
+func (w *Writer) Write(p []byte) (n int, err error) {
+ return w.buf.Write(p)
+}
+
+// WriteString writes string to the underlying buffer
+func (w *Writer) WriteString(s string) (n int, err error) {
+ return w.buf.WriteString(s)
+}
+
+// ReadFrom reads from the provided io.Reader and writes to the underlying buffer.
+func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) {
+ return w.buf.ReadFrom(r)
+}
+
+func (w *Writer) GetWidth() (int, error) {
+ if w.isTerminal {
+ tw, _, err := terminal.GetSize(w.fd)
+ return tw, err
+ }
+ return -1, NotATTY
+}
diff --git a/vendor/github.com/vbauerster/mpb/cwriter/writer_posix.go b/vendor/github.com/vbauerster/mpb/cwriter/writer_posix.go
new file mode 100644
index 000000000..05e31c480
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/cwriter/writer_posix.go
@@ -0,0 +1,13 @@
+// +build !windows
+
+package cwriter
+
+import (
+ "io"
+ "strings"
+)
+
+func (w *Writer) clearLines() error {
+ _, err := io.WriteString(w.out, strings.Repeat(clearCursorAndLine, w.lineCount))
+ return err
+}
diff --git a/vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go b/vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go
new file mode 100644
index 000000000..dad7f50b2
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go
@@ -0,0 +1,77 @@
+// +build windows
+
+package cwriter
+
+import (
+ "io"
+ "strings"
+ "syscall"
+ "unsafe"
+
+ "github.com/mattn/go-isatty"
+)
+
+var kernel32 = syscall.NewLazyDLL("kernel32.dll")
+
+var (
+ procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
+ procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition")
+ procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
+ procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
+)
+
+type (
+ short int16
+ word uint16
+ dword uint32
+
+ coord struct {
+ x short
+ y short
+ }
+ smallRect struct {
+ left short
+ top short
+ right short
+ bottom short
+ }
+ consoleScreenBufferInfo struct {
+ size coord
+ cursorPosition coord
+ attributes word
+ window smallRect
+ maximumWindowSize coord
+ }
+)
+
+// FdWriter is a writer with a file descriptor.
+type FdWriter interface {
+ io.Writer
+ Fd() uintptr
+}
+
+func (w *Writer) clearLines() error {
+ f, ok := w.out.(FdWriter)
+ if ok && !isatty.IsTerminal(f.Fd()) {
+ _, err := io.WriteString(w.out, strings.Repeat(clearCursorAndLine, w.lineCount))
+ return err
+ }
+ fd := f.Fd()
+ var info consoleScreenBufferInfo
+ procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&info)))
+
+ for i := 0; i < w.lineCount; i++ {
+ // move the cursor up
+ info.cursorPosition.y--
+ procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&info.cursorPosition))))
+ // clear the line
+ cursor := coord{
+ x: info.window.left,
+ y: info.window.top + info.cursorPosition.y,
+ }
+ var count, w dword
+ count = dword(info.size.x)
+ procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w)))
+ }
+ return nil
+}
diff --git a/vendor/github.com/vbauerster/mpb/decor/counters.go b/vendor/github.com/vbauerster/mpb/decor/counters.go
new file mode 100644
index 000000000..e4161dc4b
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/decor/counters.go
@@ -0,0 +1,206 @@
+package decor
+
+import (
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+)
+
+const (
+ _ = iota
+ KiB = 1 << (iota * 10)
+ MiB
+ GiB
+ TiB
+)
+
+const (
+ KB = 1000
+ MB = KB * 1000
+ GB = MB * 1000
+ TB = GB * 1000
+)
+
+const (
+ _ = iota
+ UnitKiB
+ UnitKB
+)
+
+type CounterKiB int64
+
+func (c CounterKiB) Format(st fmt.State, verb rune) {
+ prec, ok := st.Precision()
+
+ if verb == 'd' || !ok {
+ prec = 0
+ }
+ if verb == 'f' && !ok {
+ prec = 6
+ }
+ // retain old beahavior if s verb used
+ if verb == 's' {
+ prec = 1
+ }
+
+ var res, unit string
+ switch {
+ case c >= TiB:
+ unit = "TiB"
+ res = strconv.FormatFloat(float64(c)/TiB, 'f', prec, 64)
+ case c >= GiB:
+ unit = "GiB"
+ res = strconv.FormatFloat(float64(c)/GiB, 'f', prec, 64)
+ case c >= MiB:
+ unit = "MiB"
+ res = strconv.FormatFloat(float64(c)/MiB, 'f', prec, 64)
+ case c >= KiB:
+ unit = "KiB"
+ res = strconv.FormatFloat(float64(c)/KiB, 'f', prec, 64)
+ default:
+ unit = "b"
+ res = strconv.FormatInt(int64(c), 10)
+ }
+
+ if st.Flag(' ') {
+ res += " "
+ }
+ res += unit
+
+ if w, ok := st.Width(); ok {
+ if len(res) < w {
+ pad := strings.Repeat(" ", w-len(res))
+ if st.Flag(int('-')) {
+ res += pad
+ } else {
+ res = pad + res
+ }
+ }
+ }
+
+ io.WriteString(st, res)
+}
+
+type CounterKB int64
+
+func (c CounterKB) Format(st fmt.State, verb rune) {
+ prec, ok := st.Precision()
+
+ if verb == 'd' || !ok {
+ prec = 0
+ }
+ if verb == 'f' && !ok {
+ prec = 6
+ }
+ // retain old beahavior if s verb used
+ if verb == 's' {
+ prec = 1
+ }
+
+ var res, unit string
+ switch {
+ case c >= TB:
+ unit = "TB"
+ res = strconv.FormatFloat(float64(c)/TB, 'f', prec, 64)
+ case c >= GB:
+ unit = "GB"
+ res = strconv.FormatFloat(float64(c)/GB, 'f', prec, 64)
+ case c >= MB:
+ unit = "MB"
+ res = strconv.FormatFloat(float64(c)/MB, 'f', prec, 64)
+ case c >= KB:
+ unit = "kB"
+ res = strconv.FormatFloat(float64(c)/KB, 'f', prec, 64)
+ default:
+ unit = "b"
+ res = strconv.FormatInt(int64(c), 10)
+ }
+
+ if st.Flag(' ') {
+ res += " "
+ }
+ res += unit
+
+ if w, ok := st.Width(); ok {
+ if len(res) < w {
+ pad := strings.Repeat(" ", w-len(res))
+ if st.Flag(int('-')) {
+ res += pad
+ } else {
+ res = pad + res
+ }
+ }
+ }
+
+ io.WriteString(st, res)
+}
+
+// CountersNoUnit is a wrapper around Counters with no unit param.
+func CountersNoUnit(pairFormat string, wcc ...WC) Decorator {
+ return Counters(0, pairFormat, wcc...)
+}
+
+// CountersKibiByte is a wrapper around Counters with predefined unit UnitKiB (bytes/1024).
+func CountersKibiByte(pairFormat string, wcc ...WC) Decorator {
+ return Counters(UnitKiB, pairFormat, wcc...)
+}
+
+// CountersKiloByte is a wrapper around Counters with predefined unit UnitKB (bytes/1000).
+func CountersKiloByte(pairFormat string, wcc ...WC) Decorator {
+ return Counters(UnitKB, pairFormat, wcc...)
+}
+
+// Counters decorator with dynamic unit measure adjustment.
+//
+// `unit` one of [0|UnitKiB|UnitKB] zero for no unit
+//
+// `pairFormat` printf compatible verbs for current and total, like "%f" or "%d"
+//
+// `wcc` optional WC config
+//
+// pairFormat example if UnitKB is chosen:
+//
+// "%.1f / %.1f" = "1.0MB / 12.0MB" or "% .1f / % .1f" = "1.0 MB / 12.0 MB"
+func Counters(unit int, pairFormat string, wcc ...WC) Decorator {
+ var wc WC
+ for _, widthConf := range wcc {
+ wc = widthConf
+ }
+ wc.Init()
+ d := &countersDecorator{
+ WC: wc,
+ unit: unit,
+ pairFormat: pairFormat,
+ }
+ return d
+}
+
+type countersDecorator struct {
+ WC
+ unit int
+ pairFormat string
+ completeMsg *string
+}
+
+func (d *countersDecorator) Decor(st *Statistics) string {
+ if st.Completed && d.completeMsg != nil {
+ return d.FormatMsg(*d.completeMsg)
+ }
+
+ var str string
+ switch d.unit {
+ case UnitKiB:
+ str = fmt.Sprintf(d.pairFormat, CounterKiB(st.Current), CounterKiB(st.Total))
+ case UnitKB:
+ str = fmt.Sprintf(d.pairFormat, CounterKB(st.Current), CounterKB(st.Total))
+ default:
+ str = fmt.Sprintf(d.pairFormat, st.Current, st.Total)
+ }
+
+ return d.FormatMsg(str)
+}
+
+func (d *countersDecorator) OnCompleteMessage(msg string) {
+ d.completeMsg = &msg
+}
diff --git a/vendor/github.com/vbauerster/mpb/decor/decorator.go b/vendor/github.com/vbauerster/mpb/decor/decorator.go
new file mode 100644
index 000000000..6aaf6c830
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/decor/decorator.go
@@ -0,0 +1,144 @@
+package decor
+
+import (
+ "fmt"
+ "time"
+ "unicode/utf8"
+)
+
+const (
+ // DidentRight bit specifies identation direction.
+ // |foo |b | With DidentRight
+ // | foo| b| Without DidentRight
+ DidentRight = 1 << iota
+
+ // DextraSpace bit adds extra space, makes sense with DSyncWidth only.
+ // When DidentRight bit set, the space will be added to the right,
+ // otherwise to the left.
+ DextraSpace
+
+ // DSyncWidth bit enables same column width synchronization.
+ // Effective with multiple bars only.
+ DSyncWidth
+
+ // DSyncWidthR is shortcut for DSyncWidth|DidentRight
+ DSyncWidthR = DSyncWidth | DidentRight
+
+ // DSyncSpace is shortcut for DSyncWidth|DextraSpace
+ DSyncSpace = DSyncWidth | DextraSpace
+
+ // DSyncSpaceR is shortcut for DSyncWidth|DextraSpace|DidentRight
+ DSyncSpaceR = DSyncWidth | DextraSpace | DidentRight
+)
+
+const (
+ ET_STYLE_GO = iota
+ ET_STYLE_HHMMSS
+ ET_STYLE_HHMM
+ ET_STYLE_MMSS
+)
+
+// Statistics is a struct, which gets passed to a Decorator.
+type Statistics struct {
+ ID int
+ Completed bool
+ Total int64
+ Current int64
+}
+
+// Decorator interface.
+// A decorator must implement this interface, in order to be used with mpb library.
+type Decorator interface {
+ Decor(*Statistics) string
+ Syncable
+}
+
+// Syncable interface.
+// All decorators implement this interface implicitly.
+// Its Syncable method exposes width sync channel, if sync is enabled.
+type Syncable interface {
+ Syncable() (bool, chan int)
+}
+
+// OnCompleteMessenger interface.
+// Decorators implementing this interface suppose to return provided string on complete event.
+type OnCompleteMessenger interface {
+ OnCompleteMessage(string)
+}
+
+// AmountReceiver interface.
+// If decorator needs to receive increment amount,
+// so this is the right interface to implement.
+type AmountReceiver interface {
+ NextAmount(int, ...time.Duration)
+}
+
+// ShutdownListener interface.
+// If decorator needs to be notified once upon bar shutdown event,
+// so this is the right interface to implement.
+type ShutdownListener interface {
+ Shutdown()
+}
+
+// Global convenience shortcuts
+var (
+ WCSyncWidth = WC{C: DSyncWidth}
+ WCSyncWidthR = WC{C: DSyncWidthR}
+ WCSyncSpace = WC{C: DSyncSpace}
+ WCSyncSpaceR = WC{C: DSyncSpaceR}
+)
+
+// WC is a struct with two public fields W and C, both of int type.
+// W represents width and C represents bit set of width related config.
+type WC struct {
+ W int
+ C int
+ format string
+ wsync chan int
+}
+
+// FormatMsg formats final message according to WC.W and WC.C.
+// Should be called by any Decorator implementation.
+func (wc WC) FormatMsg(msg string) string {
+ if (wc.C & DSyncWidth) != 0 {
+ wc.wsync <- utf8.RuneCountInString(msg)
+ max := <-wc.wsync
+ if max == 0 {
+ max = wc.W
+ }
+ if (wc.C & DextraSpace) != 0 {
+ max++
+ }
+ return fmt.Sprintf(fmt.Sprintf(wc.format, max), msg)
+ }
+ return fmt.Sprintf(fmt.Sprintf(wc.format, wc.W), msg)
+}
+
+// Init initializes width related config.
+func (wc *WC) Init() {
+ wc.format = "%%"
+ if (wc.C & DidentRight) != 0 {
+ wc.format += "-"
+ }
+ wc.format += "%ds"
+ if (wc.C & DSyncWidth) != 0 {
+ wc.wsync = make(chan int)
+ }
+}
+
+func (wc *WC) Syncable() (bool, chan int) {
+ return (wc.C & DSyncWidth) != 0, wc.wsync
+}
+
+// OnComplete returns decorator, which wraps provided decorator, with sole
+// purpose to display provided message on complete event.
+//
+// `decorator` Decorator to wrap
+//
+// `message` message to display on complete event
+func OnComplete(decorator Decorator, message string) Decorator {
+ if d, ok := decorator.(OnCompleteMessenger); ok {
+ d.OnCompleteMessage(message)
+ }
+ return decorator
+}
diff --git a/vendor/github.com/vbauerster/mpb/decor/doc.go b/vendor/github.com/vbauerster/mpb/decor/doc.go
new file mode 100644
index 000000000..561a8677c
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/decor/doc.go
@@ -0,0 +1,25 @@
+// Copyright (C) 2016-2018 Vladimir Bauer
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+ Package decor contains common decorators used by "github.com/vbauerster/mpb" package.
+
+ Some decorators returned by this package might have a closure state. It is ok to use
+ decorators concurrently, unless you share the same decorator among multiple
+ *mpb.Bar instances. To avoid data races, create new decorator per *mpb.Bar instance.
+
+ Don't:
+
+ p := mpb.New()
+ name := decor.Name("bar")
+ p.AddBar(100, mpb.AppendDecorators(name))
+ p.AddBar(100, mpb.AppendDecorators(name))
+
+ Do:
+
+ p := mpb.New()
+ p.AddBar(100, mpb.AppendDecorators(decor.Name("bar1")))
+ p.AddBar(100, mpb.AppendDecorators(decor.Name("bar2")))
+*/
+package decor
diff --git a/vendor/github.com/vbauerster/mpb/decor/elapsed.go b/vendor/github.com/vbauerster/mpb/decor/elapsed.go
new file mode 100644
index 000000000..649d40a30
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/decor/elapsed.go
@@ -0,0 +1,68 @@
+package decor
+
+import (
+ "fmt"
+ "time"
+)
+
+// Elapsed returns elapsed time decorator.
+//
+// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS]
+//
+// `wcc` optional WC config
+func Elapsed(style int, wcc ...WC) Decorator {
+ var wc WC
+ for _, widthConf := range wcc {
+ wc = widthConf
+ }
+ wc.Init()
+ d := &elapsedDecorator{
+ WC: wc,
+ style: style,
+ startTime: time.Now(),
+ }
+ return d
+}
+
+type elapsedDecorator struct {
+ WC
+ style int
+ startTime time.Time
+ msg string
+ completeMsg *string
+}
+
+func (d *elapsedDecorator) Decor(st *Statistics) string {
+ if st.Completed {
+ if d.completeMsg != nil {
+ return d.FormatMsg(*d.completeMsg)
+ }
+ return d.FormatMsg(d.msg)
+ }
+
+ timeElapsed := time.Since(d.startTime)
+ hours := int64((timeElapsed / time.Hour) % 60)
+ minutes := int64((timeElapsed / time.Minute) % 60)
+ seconds := int64((timeElapsed / time.Second) % 60)
+
+ switch d.style {
+ case ET_STYLE_GO:
+ d.msg = fmt.Sprint(time.Duration(timeElapsed.Seconds()) * time.Second)
+ case ET_STYLE_HHMMSS:
+ d.msg = fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
+ case ET_STYLE_HHMM:
+ d.msg = fmt.Sprintf("%02d:%02d", hours, minutes)
+ case ET_STYLE_MMSS:
+ if hours > 0 {
+ d.msg = fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
+ } else {
+ d.msg = fmt.Sprintf("%02d:%02d", minutes, seconds)
+ }
+ }
+
+ return d.FormatMsg(d.msg)
+}
+
+func (d *elapsedDecorator) OnCompleteMessage(msg string) {
+ d.completeMsg = &msg
+}
diff --git a/vendor/github.com/vbauerster/mpb/decor/eta.go b/vendor/github.com/vbauerster/mpb/decor/eta.go
new file mode 100644
index 000000000..44a1f03ea
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/decor/eta.go
@@ -0,0 +1,207 @@
+package decor
+
+import (
+ "fmt"
+ "math"
+ "time"
+
+ "github.com/VividCortex/ewma"
+ "github.com/vbauerster/mpb/internal"
+)
+
+type TimeNormalizer func(time.Duration) time.Duration
+
+// EwmaETA exponential-weighted-moving-average based ETA decorator.
+//
+// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS]
+//
+// `age` is the previous N samples to average over.
+//
+// `wcc` optional WC config
+func EwmaETA(style int, age float64, wcc ...WC) Decorator {
+ return MovingAverageETA(style, ewma.NewMovingAverage(age), NopNormalizer(), wcc...)
+}
+
+// MovingAverageETA decorator relies on MovingAverage implementation to calculate its average.
+//
+// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS]
+//
+// `average` available implementations of MovingAverage [ewma.MovingAverage|NewMedian|NewMedianEwma]
+//
+// `normalizer` available implementations are [NopNormalizer|FixedIntervalTimeNormalizer|MaxTolerateTimeNormalizer]
+//
+// `wcc` optional WC config
+func MovingAverageETA(style int, average MovingAverage, normalizer TimeNormalizer, wcc ...WC) Decorator {
+ var wc WC
+ for _, widthConf := range wcc {
+ wc = widthConf
+ }
+ wc.Init()
+ d := &movingAverageETA{
+ WC: wc,
+ style: style,
+ average: average,
+ normalizer: normalizer,
+ }
+ return d
+}
+
+type movingAverageETA struct {
+ WC
+ style int
+ average ewma.MovingAverage
+ completeMsg *string
+ normalizer TimeNormalizer
+}
+
+func (d *movingAverageETA) Decor(st *Statistics) string {
+ if st.Completed && d.completeMsg != nil {
+ return d.FormatMsg(*d.completeMsg)
+ }
+
+ v := internal.Round(d.average.Value())
+ remaining := d.normalizer(time.Duration((st.Total - st.Current) * int64(v)))
+ hours := int64((remaining / time.Hour) % 60)
+ minutes := int64((remaining / time.Minute) % 60)
+ seconds := int64((remaining / time.Second) % 60)
+
+ var str string
+ switch d.style {
+ case ET_STYLE_GO:
+ str = fmt.Sprint(time.Duration(remaining.Seconds()) * time.Second)
+ case ET_STYLE_HHMMSS:
+ str = fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
+ case ET_STYLE_HHMM:
+ str = fmt.Sprintf("%02d:%02d", hours, minutes)
+ case ET_STYLE_MMSS:
+ if hours > 0 {
+ str = fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
+ } else {
+ str = fmt.Sprintf("%02d:%02d", minutes, seconds)
+ }
+ }
+
+ return d.FormatMsg(str)
+}
+
+func (d *movingAverageETA) NextAmount(n int, wdd ...time.Duration) {
+ var workDuration time.Duration
+ for _, wd := range wdd {
+ workDuration = wd
+ }
+ lastItemEstimate := float64(workDuration) / float64(n)
+ if math.IsInf(lastItemEstimate, 0) || math.IsNaN(lastItemEstimate) {
+ return
+ }
+ d.average.Add(lastItemEstimate)
+}
+
+func (d *movingAverageETA) OnCompleteMessage(msg string) {
+ d.completeMsg = &msg
+}
+
+// AverageETA decorator.
+//
+// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS]
+//
+// `wcc` optional WC config
+func AverageETA(style int, wcc ...WC) Decorator {
+ var wc WC
+ for _, widthConf := range wcc {
+ wc = widthConf
+ }
+ wc.Init()
+ d := &averageETA{
+ WC: wc,
+ style: style,
+ startTime: time.Now(),
+ }
+ return d
+}
+
+type averageETA struct {
+ WC
+ style int
+ startTime time.Time
+ completeMsg *string
+}
+
+func (d *averageETA) Decor(st *Statistics) string {
+ if st.Completed && d.completeMsg != nil {
+ return d.FormatMsg(*d.completeMsg)
+ }
+
+ var str string
+ timeElapsed := time.Since(d.startTime)
+ v := internal.Round(float64(timeElapsed) / float64(st.Current))
+ if math.IsInf(v, 0) || math.IsNaN(v) {
+ v = 0
+ }
+ remaining := time.Duration((st.Total - st.Current) * int64(v))
+ hours := int64((remaining / time.Hour) % 60)
+ minutes := int64((remaining / time.Minute) % 60)
+ seconds := int64((remaining / time.Second) % 60)
+
+ switch d.style {
+ case ET_STYLE_GO:
+ str = fmt.Sprint(time.Duration(remaining.Seconds()) * time.Second)
+ case ET_STYLE_HHMMSS:
+ str = fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
+ case ET_STYLE_HHMM:
+ str = fmt.Sprintf("%02d:%02d", hours, minutes)
+ case ET_STYLE_MMSS:
+ if hours > 0 {
+ str = fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
+ } else {
+ str = fmt.Sprintf("%02d:%02d", minutes, seconds)
+ }
+ }
+
+ return d.FormatMsg(str)
+}
+
+func (d *averageETA) OnCompleteMessage(msg string) {
+ d.completeMsg = &msg
+}
+
+func MaxTolerateTimeNormalizer(maxTolerate time.Duration) TimeNormalizer {
+ var normalized time.Duration
+ var lastCall time.Time
+ return func(remaining time.Duration) time.Duration {
+ if diff := normalized - remaining; diff <= 0 || diff > maxTolerate || remaining < maxTolerate/2 {
+ normalized = remaining
+ lastCall = time.Now()
+ return remaining
+ }
+ normalized -= time.Since(lastCall)
+ lastCall = time.Now()
+ return normalized
+ }
+}
+
+func FixedIntervalTimeNormalizer(updInterval int) TimeNormalizer {
+ var normalized time.Duration
+ var lastCall time.Time
+ var count int
+ return func(remaining time.Duration) time.Duration {
+ if count == 0 || remaining <= time.Duration(15*time.Second) {
+ count = updInterval
+ normalized = remaining
+ lastCall = time.Now()
+ return remaining
+ }
+ count--
+ normalized -= time.Since(lastCall)
+ lastCall = time.Now()
+ if normalized > 0 {
+ return normalized
+ }
+ return remaining
+ }
+}
+
+func NopNormalizer() TimeNormalizer {
+ return func(remaining time.Duration) time.Duration {
+ return remaining
+ }
+}
diff --git a/vendor/github.com/vbauerster/mpb/decor/moving-average.go b/vendor/github.com/vbauerster/mpb/decor/moving-average.go
new file mode 100644
index 000000000..f9596a27f
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/decor/moving-average.go
@@ -0,0 +1,66 @@
+package decor
+
+import (
+ "sort"
+
+ "github.com/VividCortex/ewma"
+)
+
+// MovingAverage is the interface that computes a moving average over a time-
+// series stream of numbers. The average may be over a window or exponentially
+// decaying.
+type MovingAverage interface {
+ Add(float64)
+ Value() float64
+ Set(float64)
+}
+
+type medianWindow [3]float64
+
+func (s *medianWindow) Len() int { return len(s) }
+func (s *medianWindow) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s *medianWindow) Less(i, j int) bool { return s[i] < s[j] }
+
+func (s *medianWindow) Add(value float64) {
+ s[0], s[1] = s[1], s[2]
+ s[2] = value
+}
+
+func (s *medianWindow) Value() float64 {
+ tmp := *s
+ sort.Sort(&tmp)
+ return tmp[1]
+}
+
+func (s *medianWindow) Set(value float64) {
+ for i := 0; i < len(s); i++ {
+ s[i] = value
+ }
+}
+
+// NewMedian is fixed last 3 samples median MovingAverage.
+func NewMedian() MovingAverage {
+ return new(medianWindow)
+}
+
+type medianEwma struct {
+ count uint
+ median MovingAverage
+ MovingAverage
+}
+
+func (s *medianEwma) Add(v float64) {
+ s.median.Add(v)
+ if s.count >= 2 {
+ s.MovingAverage.Add(s.median.Value())
+ }
+ s.count++
+}
+
+// NewMedianEwma is ewma based MovingAverage, which gets its values from median MovingAverage.
+func NewMedianEwma(age ...float64) MovingAverage {
+ return &medianEwma{
+ MovingAverage: ewma.NewMovingAverage(age...),
+ median: NewMedian(),
+ }
+}
diff --git a/vendor/github.com/vbauerster/mpb/decor/name.go b/vendor/github.com/vbauerster/mpb/decor/name.go
new file mode 100644
index 000000000..a5a5d1469
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/decor/name.go
@@ -0,0 +1,45 @@
+package decor
+
+// StaticName returns name decorator.
+//
+// `name` string to display
+//
+// `wcc` optional WC config
+func StaticName(name string, wcc ...WC) Decorator {
+ return Name(name, wcc...)
+}
+
+// Name returns name decorator.
+//
+// `name` string to display
+//
+// `wcc` optional WC config
+func Name(name string, wcc ...WC) Decorator {
+ var wc WC
+ for _, widthConf := range wcc {
+ wc = widthConf
+ }
+ wc.Init()
+ d := &nameDecorator{
+ WC: wc,
+ msg: name,
+ }
+ return d
+}
+
+type nameDecorator struct {
+ WC
+ msg string
+ complete *string
+}
+
+func (d *nameDecorator) Decor(st *Statistics) string {
+ if st.Completed && d.complete != nil {
+ return d.FormatMsg(*d.complete)
+ }
+ return d.FormatMsg(d.msg)
+}
+
+func (d *nameDecorator) OnCompleteMessage(msg string) {
+ d.complete = &msg
+}
diff --git a/vendor/github.com/vbauerster/mpb/decor/percentage.go b/vendor/github.com/vbauerster/mpb/decor/percentage.go
new file mode 100644
index 000000000..078fbcf89
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/decor/percentage.go
@@ -0,0 +1,39 @@
+package decor
+
+import (
+ "fmt"
+
+ "github.com/vbauerster/mpb/internal"
+)
+
+// Percentage returns percentage decorator.
+//
+// `wcc` optional WC config
+func Percentage(wcc ...WC) Decorator {
+ var wc WC
+ for _, widthConf := range wcc {
+ wc = widthConf
+ }
+ wc.Init()
+ d := &percentageDecorator{
+ WC: wc,
+ }
+ return d
+}
+
+type percentageDecorator struct {
+ WC
+ completeMsg *string
+}
+
+func (d *percentageDecorator) Decor(st *Statistics) string {
+ if st.Completed && d.completeMsg != nil {
+ return d.FormatMsg(*d.completeMsg)
+ }
+ str := fmt.Sprintf("%d %%", internal.Percentage(st.Total, st.Current, 100))
+ return d.FormatMsg(str)
+}
+
+func (d *percentageDecorator) OnCompleteMessage(msg string) {
+ d.completeMsg = &msg
+}
diff --git a/vendor/github.com/vbauerster/mpb/decor/speed.go b/vendor/github.com/vbauerster/mpb/decor/speed.go
new file mode 100644
index 000000000..395e5d04d
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/decor/speed.go
@@ -0,0 +1,270 @@
+package decor
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/VividCortex/ewma"
+)
+
+type SpeedKiB float64
+
+func (s SpeedKiB) Format(st fmt.State, verb rune) {
+ prec, ok := st.Precision()
+
+ if verb == 'd' || !ok {
+ prec = 0
+ }
+ if verb == 'f' && !ok {
+ prec = 6
+ }
+ // retain old beahavior if s verb used
+ if verb == 's' {
+ prec = 1
+ }
+
+ var res, unit string
+ switch {
+ case s >= TiB:
+ unit = "TiB/s"
+ res = strconv.FormatFloat(float64(s)/TiB, 'f', prec, 64)
+ case s >= GiB:
+ unit = "GiB/s"
+ res = strconv.FormatFloat(float64(s)/GiB, 'f', prec, 64)
+ case s >= MiB:
+ unit = "MiB/s"
+ res = strconv.FormatFloat(float64(s)/MiB, 'f', prec, 64)
+ case s >= KiB:
+ unit = "KiB/s"
+ res = strconv.FormatFloat(float64(s)/KiB, 'f', prec, 64)
+ default:
+ unit = "b/s"
+ res = strconv.FormatInt(int64(s), 10)
+ }
+
+ if st.Flag(' ') {
+ res += " "
+ }
+ res += unit
+
+ if w, ok := st.Width(); ok {
+ if len(res) < w {
+ pad := strings.Repeat(" ", w-len(res))
+ if st.Flag(int('-')) {
+ res += pad
+ } else {
+ res = pad + res
+ }
+ }
+ }
+
+ io.WriteString(st, res)
+}
+
+type SpeedKB float64
+
+func (s SpeedKB) Format(st fmt.State, verb rune) {
+ prec, ok := st.Precision()
+
+ if verb == 'd' || !ok {
+ prec = 0
+ }
+ if verb == 'f' && !ok {
+ prec = 6
+ }
+ // retain old beahavior if s verb used
+ if verb == 's' {
+ prec = 1
+ }
+
+ var res, unit string
+ switch {
+ case s >= TB:
+ unit = "TB/s"
+ res = strconv.FormatFloat(float64(s)/TB, 'f', prec, 64)
+ case s >= GB:
+ unit = "GB/s"
+ res = strconv.FormatFloat(float64(s)/GB, 'f', prec, 64)
+ case s >= MB:
+ unit = "MB/s"
+ res = strconv.FormatFloat(float64(s)/MB, 'f', prec, 64)
+ case s >= KB:
+ unit = "kB/s"
+ res = strconv.FormatFloat(float64(s)/KB, 'f', prec, 64)
+ default:
+ unit = "b/s"
+ res = strconv.FormatInt(int64(s), 10)
+ }
+
+ if st.Flag(' ') {
+ res += " "
+ }
+ res += unit
+
+ if w, ok := st.Width(); ok {
+ if len(res) < w {
+ pad := strings.Repeat(" ", w-len(res))
+ if st.Flag(int('-')) {
+ res += pad
+ } else {
+ res = pad + res
+ }
+ }
+ }
+
+ io.WriteString(st, res)
+}
+
+// EwmaSpeed exponential-weighted-moving-average based speed decorator,
+// with dynamic unit measure adjustment.
+//
+// `unit` one of [0|UnitKiB|UnitKB] zero for no unit
+//
+// `unitFormat` printf compatible verb for value, like "%f" or "%d"
+//
+// `average` MovingAverage implementation
+//
+// `wcc` optional WC config
+//
+// unitFormat example if UnitKiB is chosen:
+//
+// "%.1f" = "1.0MiB/s" or "% .1f" = "1.0 MiB/s"
+func EwmaSpeed(unit int, unitFormat string, age float64, wcc ...WC) Decorator {
+ return MovingAverageSpeed(unit, unitFormat, ewma.NewMovingAverage(age), wcc...)
+}
+
+// MovingAverageSpeed decorator relies on MovingAverage implementation to calculate its average.
+//
+// `unit` one of [0|UnitKiB|UnitKB] zero for no unit
+//
+// `unitFormat` printf compatible verb for value, like "%f" or "%d"
+//
+// `average` MovingAverage implementation
+//
+// `wcc` optional WC config
+func MovingAverageSpeed(unit int, unitFormat string, average MovingAverage, wcc ...WC) Decorator {
+ var wc WC
+ for _, widthConf := range wcc {
+ wc = widthConf
+ }
+ wc.Init()
+ d := &movingAverageSpeed{
+ WC: wc,
+ unit: unit,
+ unitFormat: unitFormat,
+ average: average,
+ }
+ return d
+}
+
+type movingAverageSpeed struct {
+ WC
+ unit int
+ unitFormat string
+ average ewma.MovingAverage
+ msg string
+ completeMsg *string
+}
+
+func (d *movingAverageSpeed) Decor(st *Statistics) string {
+ if st.Completed {
+ if d.completeMsg != nil {
+ return d.FormatMsg(*d.completeMsg)
+ }
+ return d.FormatMsg(d.msg)
+ }
+
+ speed := d.average.Value()
+ switch d.unit {
+ case UnitKiB:
+ d.msg = fmt.Sprintf(d.unitFormat, SpeedKiB(speed))
+ case UnitKB:
+ d.msg = fmt.Sprintf(d.unitFormat, SpeedKB(speed))
+ default:
+ d.msg = fmt.Sprintf(d.unitFormat, speed)
+ }
+
+ return d.FormatMsg(d.msg)
+}
+
+func (s *movingAverageSpeed) NextAmount(n int, wdd ...time.Duration) {
+ var workDuration time.Duration
+ for _, wd := range wdd {
+ workDuration = wd
+ }
+ speed := float64(n) / workDuration.Seconds() / 1000
+ if math.IsInf(speed, 0) || math.IsNaN(speed) {
+ return
+ }
+ s.average.Add(speed)
+}
+
+func (d *movingAverageSpeed) OnCompleteMessage(msg string) {
+ d.completeMsg = &msg
+}
+
+// AverageSpeed decorator with dynamic unit measure adjustment.
+//
+// `unit` one of [0|UnitKiB|UnitKB] zero for no unit
+//
+// `unitFormat` printf compatible verb for value, like "%f" or "%d"
+//
+// `wcc` optional WC config
+//
+// unitFormat example if UnitKiB is chosen:
+//
+// "%.1f" = "1.0MiB/s" or "% .1f" = "1.0 MiB/s"
+func AverageSpeed(unit int, unitFormat string, wcc ...WC) Decorator {
+ var wc WC
+ for _, widthConf := range wcc {
+ wc = widthConf
+ }
+ wc.Init()
+ d := &averageSpeed{
+ WC: wc,
+ unit: unit,
+ unitFormat: unitFormat,
+ startTime: time.Now(),
+ }
+ return d
+}
+
+type averageSpeed struct {
+ WC
+ unit int
+ unitFormat string
+ startTime time.Time
+ msg string
+ completeMsg *string
+}
+
+func (d *averageSpeed) Decor(st *Statistics) string {
+ if st.Completed {
+ if d.completeMsg != nil {
+ return d.FormatMsg(*d.completeMsg)
+ }
+ return d.FormatMsg(d.msg)
+ }
+
+ timeElapsed := time.Since(d.startTime)
+ speed := float64(st.Current) / timeElapsed.Seconds()
+
+ switch d.unit {
+ case UnitKiB:
+ d.msg = fmt.Sprintf(d.unitFormat, SpeedKiB(speed))
+ case UnitKB:
+ d.msg = fmt.Sprintf(d.unitFormat, SpeedKB(speed))
+ default:
+ d.msg = fmt.Sprintf(d.unitFormat, speed)
+ }
+
+ return d.FormatMsg(d.msg)
+}
+
+func (d *averageSpeed) OnCompleteMessage(msg string) {
+ d.completeMsg = &msg
+}
diff --git a/vendor/github.com/vbauerster/mpb/doc.go b/vendor/github.com/vbauerster/mpb/doc.go
new file mode 100644
index 000000000..16245956a
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/doc.go
@@ -0,0 +1,6 @@
+// Copyright (C) 2016-2018 Vladimir Bauer
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package mpb is a library for rendering progress bars in terminal applications.
+package mpb
diff --git a/vendor/github.com/vbauerster/mpb/internal/percentage.go b/vendor/github.com/vbauerster/mpb/internal/percentage.go
new file mode 100644
index 000000000..3c8defb7d
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/internal/percentage.go
@@ -0,0 +1,10 @@
+package internal
+
+// Percentage is a helper function, to calculate percentage.
+func Percentage(total, current, width int64) int64 {
+ if total <= 0 {
+ return 0
+ }
+ p := float64(width*current) / float64(total)
+ return int64(Round(p))
+}
diff --git a/vendor/github.com/vbauerster/mpb/internal/round.go b/vendor/github.com/vbauerster/mpb/internal/round.go
new file mode 100644
index 000000000..c54a789d2
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/internal/round.go
@@ -0,0 +1,49 @@
+package internal
+
+import "math"
+
+const (
+ uvone = 0x3FF0000000000000
+ mask = 0x7FF
+ shift = 64 - 11 - 1
+ bias = 1023
+ signMask = 1 << 63
+ fracMask = 1<<shift - 1
+)
+
+// Round returns the nearest integer, rounding half away from zero.
+//
+// Special cases are:
+// Round(±0) = ±0
+// Round(±Inf) = ±Inf
+// Round(NaN) = NaN
+func Round(x float64) float64 {
+ // Round is a faster implementation of:
+ //
+ // func Round(x float64) float64 {
+ // t := Trunc(x)
+ // if Abs(x-t) >= 0.5 {
+ // return t + Copysign(1, x)
+ // }
+ // return t
+ // }
+ bits := math.Float64bits(x)
+ e := uint(bits>>shift) & mask
+ if e < bias {
+ // Round abs(x) < 1 including denormals.
+ bits &= signMask // +-0
+ if e == bias-1 {
+ bits |= uvone // +-1
+ }
+ } else if e < bias+shift {
+ // Round any abs(x) >= 1 containing a fractional component [0,1).
+ //
+ // Numbers with larger exponents are returned unchanged since they
+ // must be either an integer, infinity, or NaN.
+ const half = 1 << (shift - 1)
+ e -= bias
+ bits += half >> e
+ bits &^= fracMask >> e
+ }
+ return math.Float64frombits(bits)
+}
diff --git a/vendor/github.com/vbauerster/mpb/options.go b/vendor/github.com/vbauerster/mpb/options.go
new file mode 100644
index 000000000..05d2ecf1f
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/options.go
@@ -0,0 +1,95 @@
+package mpb
+
+import (
+ "io"
+ "sync"
+ "time"
+ "unicode/utf8"
+
+ "github.com/vbauerster/mpb/cwriter"
+)
+
+// ProgressOption is a function option which changes the default behavior of
+// progress pool, if passed to mpb.New(...ProgressOption)
+type ProgressOption func(*pState)
+
+// WithWaitGroup provides means to have a single joint point.
+// If *sync.WaitGroup is provided, you can safely call just p.Wait()
+// without calling Wait() on provided *sync.WaitGroup.
+// Makes sense when there are more than one bar to render.
+func WithWaitGroup(wg *sync.WaitGroup) ProgressOption {
+ return func(s *pState) {
+ s.uwg = wg
+ }
+}
+
+// WithWidth overrides default width 80
+func WithWidth(w int) ProgressOption {
+ return func(s *pState) {
+ if w >= 0 {
+ s.width = w
+ }
+ }
+}
+
+// WithFormat overrides default bar format "[=>-]"
+func WithFormat(format string) ProgressOption {
+ return func(s *pState) {
+ if utf8.RuneCountInString(format) == formatLen {
+ s.format = format
+ }
+ }
+}
+
+// WithRefreshRate overrides default 120ms refresh rate
+func WithRefreshRate(d time.Duration) ProgressOption {
+ return func(s *pState) {
+ if d < 10*time.Millisecond {
+ return
+ }
+ s.rr = d
+ }
+}
+
+// WithManualRefresh disables internal auto refresh time.Ticker.
+// Refresh will occur upon receive value from provided ch.
+func WithManualRefresh(ch <-chan time.Time) ProgressOption {
+ return func(s *pState) {
+ s.manualRefreshCh = ch
+ }
+}
+
+// WithCancel provide your cancel channel,
+// which you plan to close at some point.
+func WithCancel(ch <-chan struct{}) ProgressOption {
+ return func(s *pState) {
+ s.cancel = ch
+ }
+}
+
+// WithShutdownNotifier provided chanel will be closed, after all bars have been rendered.
+func WithShutdownNotifier(ch chan struct{}) ProgressOption {
+ return func(s *pState) {
+ s.shutdownNotifier = ch
+ }
+}
+
+// WithOutput overrides default output os.Stdout
+func WithOutput(w io.Writer) ProgressOption {
+ return func(s *pState) {
+ if w == nil {
+ return
+ }
+ s.cw = cwriter.New(w)
+ }
+}
+
+// WithDebugOutput sets debug output.
+func WithDebugOutput(w io.Writer) ProgressOption {
+ return func(s *pState) {
+ if w == nil {
+ return
+ }
+ s.debugOut = w
+ }
+}
diff --git a/vendor/github.com/vbauerster/mpb/options_go1.7.go b/vendor/github.com/vbauerster/mpb/options_go1.7.go
new file mode 100644
index 000000000..ca9a5bad8
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/options_go1.7.go
@@ -0,0 +1,15 @@
+//+build go1.7
+
+package mpb
+
+import "context"
+
+// WithContext provided context will be used for cancellation purposes
+func WithContext(ctx context.Context) ProgressOption {
+ return func(s *pState) {
+ if ctx == nil {
+ panic("ctx must not be nil")
+ }
+ s.cancel = ctx.Done()
+ }
+}
diff --git a/vendor/github.com/vbauerster/mpb/priority_queue.go b/vendor/github.com/vbauerster/mpb/priority_queue.go
new file mode 100644
index 000000000..7bc588c29
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/priority_queue.go
@@ -0,0 +1,40 @@
+package mpb
+
+import "container/heap"
+
+// A priorityQueue implements heap.Interface
+type priorityQueue []*Bar
+
+func (pq priorityQueue) Len() int { return len(pq) }
+
+func (pq priorityQueue) Less(i, j int) bool {
+ return pq[i].priority < pq[j].priority
+}
+
+func (pq priorityQueue) Swap(i, j int) {
+ pq[i], pq[j] = pq[j], pq[i]
+ pq[i].index = i
+ pq[j].index = j
+}
+
+func (pq *priorityQueue) Push(x interface{}) {
+ n := len(*pq)
+ bar := x.(*Bar)
+ bar.index = n
+ *pq = append(*pq, bar)
+}
+
+func (pq *priorityQueue) Pop() interface{} {
+ old := *pq
+ n := len(old)
+ bar := old[n-1]
+ bar.index = -1 // for safety
+ *pq = old[0 : n-1]
+ return bar
+}
+
+// update modifies the priority of a Bar in the queue.
+func (pq *priorityQueue) update(bar *Bar, priority int) {
+ bar.priority = priority
+ heap.Fix(pq, bar.index)
+}
diff --git a/vendor/github.com/vbauerster/mpb/progress.go b/vendor/github.com/vbauerster/mpb/progress.go
new file mode 100644
index 000000000..d95fe45b7
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/progress.go
@@ -0,0 +1,251 @@
+package mpb
+
+import (
+ "container/heap"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "sync"
+ "time"
+
+ "github.com/vbauerster/mpb/cwriter"
+)
+
+const (
+ // default RefreshRate
+ prr = 120 * time.Millisecond
+ // default width
+ pwidth = 80
+ // default format
+ pformat = "[=>-]"
+)
+
+// Progress represents the container that renders Progress bars
+type Progress struct {
+ wg *sync.WaitGroup
+ uwg *sync.WaitGroup
+ operateState chan func(*pState)
+ done chan struct{}
+}
+
+type pState struct {
+ bHeap *priorityQueue
+ shutdownPending []*Bar
+ heapUpdated bool
+ zeroWait bool
+ idCounter int
+ width int
+ format string
+ rr time.Duration
+ cw *cwriter.Writer
+ pMatrix map[int][]chan int
+ aMatrix map[int][]chan int
+
+ // following are provided by user
+ uwg *sync.WaitGroup
+ manualRefreshCh <-chan time.Time
+ cancel <-chan struct{}
+ shutdownNotifier chan struct{}
+ waitBars map[*Bar]*Bar
+ debugOut io.Writer
+}
+
+// New creates new Progress instance, which orchestrates bars rendering process.
+// Accepts mpb.ProgressOption funcs for customization.
+func New(options ...ProgressOption) *Progress {
+ pq := make(priorityQueue, 0)
+ heap.Init(&pq)
+ s := &pState{
+ bHeap: &pq,
+ width: pwidth,
+ format: pformat,
+ cw: cwriter.New(os.Stdout),
+ rr: prr,
+ waitBars: make(map[*Bar]*Bar),
+ debugOut: ioutil.Discard,
+ }
+
+ for _, opt := range options {
+ if opt != nil {
+ opt(s)
+ }
+ }
+
+ p := &Progress{
+ uwg: s.uwg,
+ wg: new(sync.WaitGroup),
+ operateState: make(chan func(*pState)),
+ done: make(chan struct{}),
+ }
+ go p.serve(s)
+ return p
+}
+
+// AddBar creates a new progress bar and adds to the container.
+func (p *Progress) AddBar(total int64, options ...BarOption) *Bar {
+ p.wg.Add(1)
+ result := make(chan *Bar)
+ select {
+ case p.operateState <- func(s *pState) {
+ options = append(options, barWidth(s.width), barFormat(s.format))
+ b := newBar(p.wg, s.idCounter, total, s.cancel, options...)
+ if b.runningBar != nil {
+ s.waitBars[b.runningBar] = b
+ } else {
+ heap.Push(s.bHeap, b)
+ s.heapUpdated = true
+ }
+ s.idCounter++
+ result <- b
+ }:
+ return <-result
+ case <-p.done:
+ p.wg.Done()
+ return nil
+ }
+}
+
+// Abort is only effective while bar progress is running,
+// it means remove bar now without waiting for its completion.
+// If bar is already completed, there is nothing to abort.
+// If you need to remove bar after completion, use BarRemoveOnComplete BarOption.
+func (p *Progress) Abort(b *Bar, remove bool) {
+ select {
+ case p.operateState <- func(s *pState) {
+ if b.index < 0 {
+ return
+ }
+ if remove {
+ s.heapUpdated = heap.Remove(s.bHeap, b.index) != nil
+ }
+ s.shutdownPending = append(s.shutdownPending, b)
+ }:
+ case <-p.done:
+ }
+}
+
+// UpdateBarPriority provides a way to change bar's order position.
+// Zero is highest priority, i.e. bar will be on top.
+func (p *Progress) UpdateBarPriority(b *Bar, priority int) {
+ select {
+ case p.operateState <- func(s *pState) { s.bHeap.update(b, priority) }:
+ case <-p.done:
+ }
+}
+
+// BarCount returns bars count
+func (p *Progress) BarCount() int {
+ result := make(chan int, 1)
+ select {
+ case p.operateState <- func(s *pState) { result <- s.bHeap.Len() }:
+ return <-result
+ case <-p.done:
+ return 0
+ }
+}
+
+// Wait first waits for user provided *sync.WaitGroup, if any,
+// then waits far all bars to complete and finally shutdowns master goroutine.
+// After this method has been called, there is no way to reuse *Progress instance.
+func (p *Progress) Wait() {
+ if p.uwg != nil {
+ p.uwg.Wait()
+ }
+
+ p.wg.Wait()
+
+ select {
+ case p.operateState <- func(s *pState) { s.zeroWait = true }:
+ <-p.done
+ case <-p.done:
+ }
+}
+
+func (s *pState) updateSyncMatrix() {
+ s.pMatrix = make(map[int][]chan int)
+ s.aMatrix = make(map[int][]chan int)
+ for i := 0; i < s.bHeap.Len(); i++ {
+ bar := (*s.bHeap)[i]
+ table := bar.wSyncTable()
+ pRow, aRow := table[0], table[1]
+
+ for i, ch := range pRow {
+ s.pMatrix[i] = append(s.pMatrix[i], ch)
+ }
+
+ for i, ch := range aRow {
+ s.aMatrix[i] = append(s.aMatrix[i], ch)
+ }
+ }
+}
+
+func (s *pState) render(tw int) {
+ if s.heapUpdated {
+ s.updateSyncMatrix()
+ s.heapUpdated = false
+ }
+ syncWidth(s.pMatrix)
+ syncWidth(s.aMatrix)
+
+ for i := 0; i < s.bHeap.Len(); i++ {
+ bar := (*s.bHeap)[i]
+ go bar.render(s.debugOut, tw)
+ }
+
+ if err := s.flush(s.bHeap.Len()); err != nil {
+ fmt.Fprintf(s.debugOut, "%s %s %v\n", "[mpb]", time.Now(), err)
+ }
+}
+
+func (s *pState) flush(lineCount int) error {
+ for s.bHeap.Len() > 0 {
+ bar := heap.Pop(s.bHeap).(*Bar)
+ frameReader := <-bar.frameReaderCh
+ defer func() {
+ if frameReader.toShutdown {
+ // shutdown at next flush, in other words decrement underlying WaitGroup
+ // only after the bar with completed state has been flushed.
+ // this ensures no bar ends up with less than 100% rendered.
+ s.shutdownPending = append(s.shutdownPending, bar)
+ if replacementBar, ok := s.waitBars[bar]; ok {
+ heap.Push(s.bHeap, replacementBar)
+ s.heapUpdated = true
+ delete(s.waitBars, bar)
+ }
+ if frameReader.removeOnComplete {
+ s.heapUpdated = true
+ return
+ }
+ }
+ heap.Push(s.bHeap, bar)
+ }()
+ s.cw.ReadFrom(frameReader)
+ lineCount += frameReader.extendedLines
+ }
+
+ for i := len(s.shutdownPending) - 1; i >= 0; i-- {
+ close(s.shutdownPending[i].shutdown)
+ s.shutdownPending = s.shutdownPending[:i]
+ }
+
+ return s.cw.Flush(lineCount)
+}
+
+func syncWidth(matrix map[int][]chan int) {
+ for _, column := range matrix {
+ column := column
+ go func() {
+ var maxWidth int
+ for _, ch := range column {
+ w := <-ch
+ if w > maxWidth {
+ maxWidth = w
+ }
+ }
+ for _, ch := range column {
+ ch <- maxWidth
+ }
+ }()
+ }
+}
diff --git a/vendor/github.com/vbauerster/mpb/progress_posix.go b/vendor/github.com/vbauerster/mpb/progress_posix.go
new file mode 100644
index 000000000..545245a42
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/progress_posix.go
@@ -0,0 +1,70 @@
+// +build !windows
+
+package mpb
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+)
+
+func (p *Progress) serve(s *pState) {
+
+ var ticker *time.Ticker
+ var refreshCh <-chan time.Time
+ var winch chan os.Signal
+ var resumeTimer *time.Timer
+ var resumeEvent <-chan time.Time
+ winchIdleDur := s.rr * 2
+
+ if s.manualRefreshCh == nil {
+ ticker = time.NewTicker(s.rr)
+ refreshCh = ticker.C
+ winch = make(chan os.Signal, 2)
+ signal.Notify(winch, syscall.SIGWINCH)
+ } else {
+ refreshCh = s.manualRefreshCh
+ }
+
+ for {
+ select {
+ case op := <-p.operateState:
+ op(s)
+ case <-refreshCh:
+ if s.zeroWait {
+ if s.manualRefreshCh == nil {
+ signal.Stop(winch)
+ ticker.Stop()
+ }
+ if s.shutdownNotifier != nil {
+ close(s.shutdownNotifier)
+ }
+ close(p.done)
+ return
+ }
+ tw, err := s.cw.GetWidth()
+ if err != nil {
+ tw = s.width
+ }
+ s.render(tw)
+ case <-winch:
+ tw, err := s.cw.GetWidth()
+ if err != nil {
+ tw = s.width
+ }
+ s.render(tw - tw/8)
+ if resumeTimer != nil && resumeTimer.Reset(winchIdleDur) {
+ break
+ }
+ ticker.Stop()
+ resumeTimer = time.NewTimer(winchIdleDur)
+ resumeEvent = resumeTimer.C
+ case <-resumeEvent:
+ ticker = time.NewTicker(s.rr)
+ refreshCh = ticker.C
+ resumeEvent = nil
+ resumeTimer = nil
+ }
+ }
+}
diff --git a/vendor/github.com/vbauerster/mpb/progress_windows.go b/vendor/github.com/vbauerster/mpb/progress_windows.go
new file mode 100644
index 000000000..cab03d36c
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/progress_windows.go
@@ -0,0 +1,43 @@
+// +build windows
+
+package mpb
+
+import (
+ "time"
+)
+
+func (p *Progress) serve(s *pState) {
+
+ var ticker *time.Ticker
+ var refreshCh <-chan time.Time
+
+ if s.manualRefreshCh == nil {
+ ticker = time.NewTicker(s.rr)
+ refreshCh = ticker.C
+ } else {
+ refreshCh = s.manualRefreshCh
+ }
+
+ for {
+ select {
+ case op := <-p.operateState:
+ op(s)
+ case <-refreshCh:
+ if s.zeroWait {
+ if s.manualRefreshCh == nil {
+ ticker.Stop()
+ }
+ if s.shutdownNotifier != nil {
+ close(s.shutdownNotifier)
+ }
+ close(p.done)
+ return
+ }
+ tw, err := s.cw.GetWidth()
+ if err != nil {
+ tw = s.width
+ }
+ s.render(tw)
+ }
+ }
+}
diff --git a/vendor/github.com/vbauerster/mpb/proxyreader.go b/vendor/github.com/vbauerster/mpb/proxyreader.go
new file mode 100644
index 000000000..d2692ccf4
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/proxyreader.go
@@ -0,0 +1,22 @@
+package mpb
+
+import (
+ "io"
+ "time"
+)
+
+// proxyReader is io.Reader wrapper, for proxy read bytes
+type proxyReader struct {
+ io.ReadCloser
+ bar *Bar
+ iT time.Time
+}
+
+func (pr *proxyReader) Read(p []byte) (n int, err error) {
+ n, err = pr.ReadCloser.Read(p)
+ if n > 0 {
+ pr.bar.IncrBy(n, time.Since(pr.iT))
+ pr.iT = time.Now()
+ }
+ return
+}