mirror of
https://github.com/containers/podman.git
synced 2025-09-10 15:46:07 +08:00
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>
This commit is contained in:
29
vendor/github.com/vbauerster/mpb/LICENSE
generated
vendored
Normal file
29
vendor/github.com/vbauerster/mpb/LICENSE
generated
vendored
Normal file
@ -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.
|
117
vendor/github.com/vbauerster/mpb/README.md
generated
vendored
Normal file
117
vendor/github.com/vbauerster/mpb/README.md
generated
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
# Multi Progress Bar
|
||||
|
||||
[](https://godoc.org/github.com/vbauerster/mpb)
|
||||
[](https://travis-ci.org/vbauerster/mpb)
|
||||
[](https://goreportcard.com/report/github.com/vbauerster/mpb)
|
||||
[](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)
|
||||
|
||||

|
||||
|
||||
#### [Complex example](examples/complex/main.go)
|
||||
|
||||

|
||||
|
||||
#### [Bytes counters](examples/io/single/main.go)
|
||||
|
||||

|
455
vendor/github.com/vbauerster/mpb/bar.go
generated
vendored
Normal file
455
vendor/github.com/vbauerster/mpb/bar.go
generated
vendored
Normal file
@ -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"))
|
||||
}
|
124
vendor/github.com/vbauerster/mpb/bar_option.go
generated
vendored
Normal file
124
vendor/github.com/vbauerster/mpb/bar_option.go
generated
vendored
Normal file
@ -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)
|
||||
}
|
||||
}
|
78
vendor/github.com/vbauerster/mpb/cwriter/writer.go
generated
vendored
Normal file
78
vendor/github.com/vbauerster/mpb/cwriter/writer.go
generated
vendored
Normal file
@ -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
|
||||
}
|
13
vendor/github.com/vbauerster/mpb/cwriter/writer_posix.go
generated
vendored
Normal file
13
vendor/github.com/vbauerster/mpb/cwriter/writer_posix.go
generated
vendored
Normal file
@ -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
|
||||
}
|
77
vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go
generated
vendored
Normal file
77
vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go
generated
vendored
Normal file
@ -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
|
||||
}
|
206
vendor/github.com/vbauerster/mpb/decor/counters.go
generated
vendored
Normal file
206
vendor/github.com/vbauerster/mpb/decor/counters.go
generated
vendored
Normal file
@ -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
|
||||
}
|
144
vendor/github.com/vbauerster/mpb/decor/decorator.go
generated
vendored
Normal file
144
vendor/github.com/vbauerster/mpb/decor/decorator.go
generated
vendored
Normal file
@ -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
|
||||
}
|
25
vendor/github.com/vbauerster/mpb/decor/doc.go
generated
vendored
Normal file
25
vendor/github.com/vbauerster/mpb/decor/doc.go
generated
vendored
Normal file
@ -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
|
68
vendor/github.com/vbauerster/mpb/decor/elapsed.go
generated
vendored
Normal file
68
vendor/github.com/vbauerster/mpb/decor/elapsed.go
generated
vendored
Normal file
@ -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
|
||||
}
|
207
vendor/github.com/vbauerster/mpb/decor/eta.go
generated
vendored
Normal file
207
vendor/github.com/vbauerster/mpb/decor/eta.go
generated
vendored
Normal file
@ -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
|
||||
}
|
||||
}
|
66
vendor/github.com/vbauerster/mpb/decor/moving-average.go
generated
vendored
Normal file
66
vendor/github.com/vbauerster/mpb/decor/moving-average.go
generated
vendored
Normal file
@ -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(),
|
||||
}
|
||||
}
|
45
vendor/github.com/vbauerster/mpb/decor/name.go
generated
vendored
Normal file
45
vendor/github.com/vbauerster/mpb/decor/name.go
generated
vendored
Normal file
@ -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
|
||||
}
|
39
vendor/github.com/vbauerster/mpb/decor/percentage.go
generated
vendored
Normal file
39
vendor/github.com/vbauerster/mpb/decor/percentage.go
generated
vendored
Normal file
@ -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
|
||||
}
|
270
vendor/github.com/vbauerster/mpb/decor/speed.go
generated
vendored
Normal file
270
vendor/github.com/vbauerster/mpb/decor/speed.go
generated
vendored
Normal file
@ -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
|
||||
}
|
6
vendor/github.com/vbauerster/mpb/doc.go
generated
vendored
Normal file
6
vendor/github.com/vbauerster/mpb/doc.go
generated
vendored
Normal file
@ -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
|
10
vendor/github.com/vbauerster/mpb/internal/percentage.go
generated
vendored
Normal file
10
vendor/github.com/vbauerster/mpb/internal/percentage.go
generated
vendored
Normal file
@ -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))
|
||||
}
|
49
vendor/github.com/vbauerster/mpb/internal/round.go
generated
vendored
Normal file
49
vendor/github.com/vbauerster/mpb/internal/round.go
generated
vendored
Normal file
@ -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)
|
||||
}
|
95
vendor/github.com/vbauerster/mpb/options.go
generated
vendored
Normal file
95
vendor/github.com/vbauerster/mpb/options.go
generated
vendored
Normal file
@ -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
|
||||
}
|
||||
}
|
15
vendor/github.com/vbauerster/mpb/options_go1.7.go
generated
vendored
Normal file
15
vendor/github.com/vbauerster/mpb/options_go1.7.go
generated
vendored
Normal file
@ -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()
|
||||
}
|
||||
}
|
40
vendor/github.com/vbauerster/mpb/priority_queue.go
generated
vendored
Normal file
40
vendor/github.com/vbauerster/mpb/priority_queue.go
generated
vendored
Normal file
@ -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)
|
||||
}
|
251
vendor/github.com/vbauerster/mpb/progress.go
generated
vendored
Normal file
251
vendor/github.com/vbauerster/mpb/progress.go
generated
vendored
Normal file
@ -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
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
70
vendor/github.com/vbauerster/mpb/progress_posix.go
generated
vendored
Normal file
70
vendor/github.com/vbauerster/mpb/progress_posix.go
generated
vendored
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
}
|
43
vendor/github.com/vbauerster/mpb/progress_windows.go
generated
vendored
Normal file
43
vendor/github.com/vbauerster/mpb/progress_windows.go
generated
vendored
Normal file
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
22
vendor/github.com/vbauerster/mpb/proxyreader.go
generated
vendored
Normal file
22
vendor/github.com/vbauerster/mpb/proxyreader.go
generated
vendored
Normal file
@ -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
|
||||
}
|
Reference in New Issue
Block a user