Browse Source

vendor: upgrade "gopkg.in/cheggaaa/pb.v1"

Signed-off-by: Gyuho Lee <gyuhox@gmail.com>
Gyuho Lee 7 years ago
parent
commit
f9084d5d69

+ 2 - 2
Gopkg.lock

@@ -358,8 +358,8 @@
 [[projects]]
   name = "gopkg.in/cheggaaa/pb.v1"
   packages = ["."]
-  revision = "226d21d43a305fac52b3a104ef83e721b15275e0"
-  version = "v1.0.2"
+  revision = "2af8bbdea9e99e83b3ac400d8f6b6d1b8cbbf338"
+  version = "v1.0.25"
 
 [[projects]]
   name = "gopkg.in/yaml.v2"

+ 61 - 23
vendor/gopkg.in/cheggaaa/pb.v1/format.go

@@ -2,7 +2,6 @@ package pb
 
 import (
 	"fmt"
-	"strings"
 	"time"
 )
 
@@ -11,12 +10,26 @@ type Units int
 const (
 	// U_NO are default units, they represent a simple value and are not formatted at all.
 	U_NO Units = iota
-	// U_BYTES units are formatted in a human readable way (b, Bb, Mb, ...)
+	// U_BYTES units are formatted in a human readable way (B, KiB, MiB, ...)
 	U_BYTES
+	// U_BYTES_DEC units are like U_BYTES, but base 10 (B, KB, MB, ...)
+	U_BYTES_DEC
 	// U_DURATION units are formatted in a human readable way (3h14m15s)
 	U_DURATION
 )
 
+const (
+	KiB = 1024
+	MiB = 1048576
+	GiB = 1073741824
+	TiB = 1099511627776
+
+	KB = 1e3
+	MB = 1e6
+	GB = 1e9
+	TB = 1e12
+)
+
 func Format(i int64) *formatter {
 	return &formatter{n: i}
 }
@@ -28,11 +41,6 @@ type formatter struct {
 	perSec bool
 }
 
-func (f *formatter) Value(n int64) *formatter {
-	f.n = n
-	return f
-}
-
 func (f *formatter) To(unit Units) *formatter {
 	f.unit = unit
 	return f
@@ -52,13 +60,10 @@ func (f *formatter) String() (out string) {
 	switch f.unit {
 	case U_BYTES:
 		out = formatBytes(f.n)
+	case U_BYTES_DEC:
+		out = formatBytesDec(f.n)
 	case U_DURATION:
-		d := time.Duration(f.n)
-		if d > time.Hour*24 {
-			out = fmt.Sprintf("%dd", d/24/time.Hour)
-			d -= (d / time.Hour / 24) * (time.Hour * 24)
-		}
-		out = fmt.Sprintf("%s%v", out, d)
+		out = formatDuration(f.n)
 	default:
 		out = fmt.Sprintf(fmt.Sprintf("%%%dd", f.width), f.n)
 	}
@@ -68,20 +73,53 @@ func (f *formatter) String() (out string) {
 	return
 }
 
-// Convert bytes to human readable string. Like a 2 MB, 64.2 KB, 52 B
+// Convert bytes to human readable string. Like 2 MiB, 64.2 KiB, 52 B
 func formatBytes(i int64) (result string) {
 	switch {
-	case i > (1024 * 1024 * 1024 * 1024):
-		result = fmt.Sprintf("%.02f TB", float64(i)/1024/1024/1024/1024)
-	case i > (1024 * 1024 * 1024):
-		result = fmt.Sprintf("%.02f GB", float64(i)/1024/1024/1024)
-	case i > (1024 * 1024):
-		result = fmt.Sprintf("%.02f MB", float64(i)/1024/1024)
-	case i > 1024:
-		result = fmt.Sprintf("%.02f KB", float64(i)/1024)
+	case i >= TiB:
+		result = fmt.Sprintf("%.02f TiB", float64(i)/TiB)
+	case i >= GiB:
+		result = fmt.Sprintf("%.02f GiB", float64(i)/GiB)
+	case i >= MiB:
+		result = fmt.Sprintf("%.02f MiB", float64(i)/MiB)
+	case i >= KiB:
+		result = fmt.Sprintf("%.02f KiB", float64(i)/KiB)
 	default:
 		result = fmt.Sprintf("%d B", i)
 	}
-	result = strings.Trim(result, " ")
+	return
+}
+
+// Convert bytes to base-10 human readable string. Like 2 MB, 64.2 KB, 52 B
+func formatBytesDec(i int64) (result string) {
+	switch {
+	case i >= TB:
+		result = fmt.Sprintf("%.02f TB", float64(i)/TB)
+	case i >= GB:
+		result = fmt.Sprintf("%.02f GB", float64(i)/GB)
+	case i >= MB:
+		result = fmt.Sprintf("%.02f MB", float64(i)/MB)
+	case i >= KB:
+		result = fmt.Sprintf("%.02f KB", float64(i)/KB)
+	default:
+		result = fmt.Sprintf("%d B", i)
+	}
+	return
+}
+
+func formatDuration(n int64) (result string) {
+	d := time.Duration(n)
+	if d > time.Hour*24 {
+		result = fmt.Sprintf("%dd", d/24/time.Hour)
+		d -= (d / time.Hour / 24) * (time.Hour * 24)
+	}
+	if d > time.Hour {
+		result = fmt.Sprintf("%s%dh", result, d/time.Hour)
+		d -= d / time.Hour * time.Hour
+	}
+	m := d / time.Minute
+	d -= m * time.Minute
+	s := d / time.Second
+	result = fmt.Sprintf("%s%02dm%02ds", result, m, s)
 	return
 }

+ 149 - 73
vendor/gopkg.in/cheggaaa/pb.v1/pb.go

@@ -13,7 +13,7 @@ import (
 )
 
 // Current version
-const Version = "1.0.2"
+const Version = "1.0.25"
 
 const (
 	// Default refresh rate - 200ms
@@ -37,18 +37,17 @@ func New(total int) *ProgressBar {
 // Create new progress bar object using int64 as total
 func New64(total int64) *ProgressBar {
 	pb := &ProgressBar{
-		Total:         total,
-		RefreshRate:   DEFAULT_REFRESH_RATE,
-		ShowPercent:   true,
-		ShowCounters:  true,
-		ShowBar:       true,
-		ShowTimeLeft:  true,
-		ShowFinalTime: true,
-		Units:         U_NO,
-		ManualUpdate:  false,
-		finish:        make(chan struct{}),
-		currentValue:  -1,
-		mu:            new(sync.Mutex),
+		Total:           total,
+		RefreshRate:     DEFAULT_REFRESH_RATE,
+		ShowPercent:     true,
+		ShowCounters:    true,
+		ShowBar:         true,
+		ShowTimeLeft:    true,
+		ShowElapsedTime: false,
+		ShowFinalTime:   true,
+		Units:           U_NO,
+		ManualUpdate:    false,
+		finish:          make(chan struct{}),
 	}
 	return pb.Format(FORMAT)
 }
@@ -67,13 +66,14 @@ func StartNew(total int) *ProgressBar {
 type Callback func(out string)
 
 type ProgressBar struct {
-	current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278)
+	current  int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278)
+	previous int64
 
 	Total                            int64
 	RefreshRate                      time.Duration
 	ShowPercent, ShowCounters        bool
 	ShowSpeed, ShowTimeLeft, ShowBar bool
-	ShowFinalTime                    bool
+	ShowFinalTime, ShowElapsedTime   bool
 	Output                           io.Writer
 	Callback                         Callback
 	NotPrint                         bool
@@ -81,6 +81,7 @@ type ProgressBar struct {
 	Width                            int
 	ForceWidth                       bool
 	ManualUpdate                     bool
+	AutoStat                         bool
 
 	// Default width for the time box.
 	UnitsWidth   int
@@ -90,13 +91,14 @@ type ProgressBar struct {
 	finish     chan struct{}
 	isFinish   bool
 
-	startTime    time.Time
-	startValue   int64
-	currentValue int64
+	startTime  time.Time
+	startValue int64
+
+	changeTime time.Time
 
 	prefix, postfix string
 
-	mu        *sync.Mutex
+	mu        sync.Mutex
 	lastPrint string
 
 	BarStart string
@@ -111,10 +113,11 @@ type ProgressBar struct {
 // Start print
 func (pb *ProgressBar) Start() *ProgressBar {
 	pb.startTime = time.Now()
-	pb.startValue = pb.current
-	if pb.Total == 0 {
+	pb.startValue = atomic.LoadInt64(&pb.current)
+	if atomic.LoadInt64(&pb.Total) == 0 {
 		pb.ShowTimeLeft = false
 		pb.ShowPercent = false
+		pb.AutoStat = false
 	}
 	if !pb.ManualUpdate {
 		pb.Update() // Initial printing of the bar before running the bar refresher.
@@ -128,6 +131,12 @@ func (pb *ProgressBar) Increment() int {
 	return pb.Add(1)
 }
 
+// Get current value
+func (pb *ProgressBar) Get() int64 {
+	c := atomic.LoadInt64(&pb.current)
+	return c
+}
+
 // Set current value
 func (pb *ProgressBar) Set(current int) *ProgressBar {
 	return pb.Set64(int64(current))
@@ -165,7 +174,7 @@ func (pb *ProgressBar) Postfix(postfix string) *ProgressBar {
 // Example: bar.Format("[\x00=\x00>\x00-\x00]") // \x00 is the delimiter
 func (pb *ProgressBar) Format(format string) *ProgressBar {
 	var formatEntries []string
-	if len(format) == 5 {
+	if utf8.RuneCountInString(format) == 5 {
 		formatEntries = strings.Split(format, "")
 	} else {
 		formatEntries = strings.Split(format, "\x00")
@@ -213,18 +222,34 @@ func (pb *ProgressBar) Finish() {
 	//Protect multiple calls
 	pb.finishOnce.Do(func() {
 		close(pb.finish)
-		pb.write(atomic.LoadInt64(&pb.current))
-		if !pb.NotPrint {
+		pb.write(atomic.LoadInt64(&pb.Total), atomic.LoadInt64(&pb.current))
+		pb.mu.Lock()
+		defer pb.mu.Unlock()
+		switch {
+		case pb.Output != nil:
+			fmt.Fprintln(pb.Output)
+		case !pb.NotPrint:
 			fmt.Println()
 		}
 		pb.isFinish = true
 	})
 }
 
+// IsFinished return boolean
+func (pb *ProgressBar) IsFinished() bool {
+	pb.mu.Lock()
+	defer pb.mu.Unlock()
+	return pb.isFinish
+}
+
 // End print and write string 'str'
 func (pb *ProgressBar) FinishPrint(str string) {
 	pb.Finish()
-	fmt.Println(str)
+	if pb.Output != nil {
+		fmt.Fprintln(pb.Output, str)
+	} else {
+		fmt.Println(str)
+	}
 }
 
 // implement io.Writer
@@ -242,20 +267,21 @@ func (pb *ProgressBar) Read(p []byte) (n int, err error) {
 }
 
 // Create new proxy reader over bar
+// Takes io.Reader or io.ReadCloser
 func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader {
 	return &Reader{r, pb}
 }
 
-func (pb *ProgressBar) write(current int64) {
+func (pb *ProgressBar) write(total, current int64) {
 	width := pb.GetWidth()
 
-	var percentBox, countersBox, timeLeftBox, speedBox, barBox, end, out string
+	var percentBox, countersBox, timeLeftBox, timeSpentBox, speedBox, barBox, end, out string
 
 	// percents
 	if pb.ShowPercent {
 		var percent float64
-		if pb.Total > 0 {
-			percent = float64(current) / (float64(pb.Total) / float64(100))
+		if total > 0 {
+			percent = float64(current) / (float64(total) / float64(100))
 		} else {
 			percent = float64(current) / float64(100)
 		}
@@ -265,41 +291,49 @@ func (pb *ProgressBar) write(current int64) {
 	// counters
 	if pb.ShowCounters {
 		current := Format(current).To(pb.Units).Width(pb.UnitsWidth)
-		if pb.Total > 0 {
-			total := Format(pb.Total).To(pb.Units).Width(pb.UnitsWidth)
-			countersBox = fmt.Sprintf(" %s / %s ", current, total)
+		if total > 0 {
+			totalS := Format(total).To(pb.Units).Width(pb.UnitsWidth)
+			countersBox = fmt.Sprintf(" %s / %s ", current, totalS)
 		} else {
 			countersBox = fmt.Sprintf(" %s / ? ", current)
 		}
 	}
 
 	// time left
-	fromStart := time.Now().Sub(pb.startTime)
+	pb.mu.Lock()
 	currentFromStart := current - pb.startValue
+	fromStart := time.Now().Sub(pb.startTime)
+	lastChangeTime := pb.changeTime
+	fromChange := lastChangeTime.Sub(pb.startTime)
+	pb.mu.Unlock()
+
+	if pb.ShowElapsedTime {
+		timeSpentBox = fmt.Sprintf(" %s ", (fromStart/time.Second)*time.Second)
+	}
+
 	select {
 	case <-pb.finish:
 		if pb.ShowFinalTime {
 			var left time.Duration
-			if pb.Total > 0 {
-				left = (fromStart / time.Second) * time.Second
-			} else {
-				left = (time.Duration(currentFromStart) / time.Second) * time.Second
-			}
-			timeLeftBox = left.String()
+			left = (fromStart / time.Second) * time.Second
+			timeLeftBox = fmt.Sprintf(" %s", left.String())
 		}
 	default:
 		if pb.ShowTimeLeft && currentFromStart > 0 {
-			perEntry := fromStart / time.Duration(currentFromStart)
+			perEntry := fromChange / time.Duration(currentFromStart)
 			var left time.Duration
-			if pb.Total > 0 {
-				left = time.Duration(pb.Total-currentFromStart) * perEntry
+			if total > 0 {
+				left = time.Duration(total-currentFromStart) * perEntry
+				left -= time.Since(lastChangeTime)
 				left = (left / time.Second) * time.Second
 			} else {
 				left = time.Duration(currentFromStart) * perEntry
 				left = (left / time.Second) * time.Second
 			}
-			timeLeft := Format(int64(left)).To(U_DURATION).String()
-			timeLeftBox = fmt.Sprintf(" %s", timeLeft)
+			if left > 0 {
+				timeLeft := Format(int64(left)).To(U_DURATION).String()
+				timeLeftBox = fmt.Sprintf(" %s", timeLeft)
+			}
 		}
 	}
 
@@ -314,30 +348,38 @@ func (pb *ProgressBar) write(current int64) {
 		speedBox = " " + Format(int64(speed)).To(pb.Units).Width(pb.UnitsWidth).PerSec().String()
 	}
 
-	barWidth := escapeAwareRuneCountInString(countersBox + pb.BarStart + pb.BarEnd + percentBox + timeLeftBox + speedBox + pb.prefix + pb.postfix)
+	barWidth := escapeAwareRuneCountInString(countersBox + pb.BarStart + pb.BarEnd + percentBox + timeSpentBox + timeLeftBox + speedBox + pb.prefix + pb.postfix)
 	// bar
 	if pb.ShowBar {
 		size := width - barWidth
 		if size > 0 {
-			if pb.Total > 0 {
-				curCount := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size)))
-				emptCount := size - curCount
+			if total > 0 {
+				curSize := int(math.Ceil((float64(current) / float64(total)) * float64(size)))
+				emptySize := size - curSize
 				barBox = pb.BarStart
-				if emptCount < 0 {
-					emptCount = 0
+				if emptySize < 0 {
+					emptySize = 0
 				}
-				if curCount > size {
-					curCount = size
+				if curSize > size {
+					curSize = size
 				}
-				if emptCount <= 0 {
-					barBox += strings.Repeat(pb.Current, curCount)
-				} else if curCount > 0 {
-					barBox += strings.Repeat(pb.Current, curCount-1) + pb.CurrentN
+
+				cursorLen := escapeAwareRuneCountInString(pb.Current)
+				if emptySize <= 0 {
+					barBox += strings.Repeat(pb.Current, curSize/cursorLen)
+				} else if curSize > 0 {
+					cursorEndLen := escapeAwareRuneCountInString(pb.CurrentN)
+					cursorRepetitions := (curSize - cursorEndLen) / cursorLen
+					barBox += strings.Repeat(pb.Current, cursorRepetitions)
+					barBox += pb.CurrentN
 				}
-				barBox += strings.Repeat(pb.Empty, emptCount) + pb.BarEnd
+
+				emptyLen := escapeAwareRuneCountInString(pb.Empty)
+				barBox += strings.Repeat(pb.Empty, emptySize/emptyLen)
+				barBox += pb.BarEnd
 			} else {
-				barBox = pb.BarStart
 				pos := size - int(current)%int(size)
+				barBox = pb.BarStart
 				if pos-1 > 0 {
 					barBox += strings.Repeat(pb.Empty, pos-1)
 				}
@@ -351,17 +393,19 @@ func (pb *ProgressBar) write(current int64) {
 	}
 
 	// check len
-	out = pb.prefix + countersBox + barBox + percentBox + speedBox + timeLeftBox + pb.postfix
-	if escapeAwareRuneCountInString(out) < width {
-		end = strings.Repeat(" ", width-utf8.RuneCountInString(out))
+	out = pb.prefix + timeSpentBox + countersBox + barBox + percentBox + speedBox + timeLeftBox + pb.postfix
+	if cl := escapeAwareRuneCountInString(out); cl < width {
+		end = strings.Repeat(" ", width-cl)
 	}
 
 	// and print!
 	pb.mu.Lock()
+	defer pb.mu.Unlock()
 	pb.lastPrint = out + end
-	pb.mu.Unlock()
+	isFinish := pb.isFinish
+
 	switch {
-	case pb.isFinish:
+	case isFinish:
 		return
 	case pb.Output != nil:
 		fmt.Fprint(pb.Output, "\r"+out+end)
@@ -394,16 +438,55 @@ func (pb *ProgressBar) GetWidth() int {
 // Write the current state of the progressbar
 func (pb *ProgressBar) Update() {
 	c := atomic.LoadInt64(&pb.current)
-	if pb.AlwaysUpdate || c != pb.currentValue {
-		pb.write(c)
-		pb.currentValue = c
+	p := atomic.LoadInt64(&pb.previous)
+	t := atomic.LoadInt64(&pb.Total)
+	if p != c {
+		pb.mu.Lock()
+		pb.changeTime = time.Now()
+		pb.mu.Unlock()
+		atomic.StoreInt64(&pb.previous, c)
+	}
+	pb.write(t, c)
+	if pb.AutoStat {
+		if c == 0 {
+			pb.startTime = time.Now()
+			pb.startValue = 0
+		} else if c >= t && pb.isFinish != true {
+			pb.Finish()
+		}
 	}
 }
 
+// String return the last bar print
 func (pb *ProgressBar) String() string {
+	pb.mu.Lock()
+	defer pb.mu.Unlock()
 	return pb.lastPrint
 }
 
+// SetTotal atomically sets new total count
+func (pb *ProgressBar) SetTotal(total int) *ProgressBar {
+	return pb.SetTotal64(int64(total))
+}
+
+// SetTotal64 atomically sets new total count
+func (pb *ProgressBar) SetTotal64(total int64) *ProgressBar {
+	atomic.StoreInt64(&pb.Total, total)
+	return pb
+}
+
+// Reset bar and set new total count
+// Does effect only on finished bar
+func (pb *ProgressBar) Reset(total int) *ProgressBar {
+	pb.mu.Lock()
+	defer pb.mu.Unlock()
+	if pb.isFinish {
+		pb.SetTotal(total).Set(0)
+		atomic.StoreInt64(&pb.previous, 0)
+	}
+	return pb
+}
+
 // Internal loop for refreshing the progressbar
 func (pb *ProgressBar) refresher() {
 	for {
@@ -415,10 +498,3 @@ func (pb *ProgressBar) refresher() {
 		}
 	}
 }
-
-type window struct {
-	Row    uint16
-	Col    uint16
-	Xpixel uint16
-	Ypixel uint16
-}

+ 0 - 8
vendor/gopkg.in/cheggaaa/pb.v1/pb_nix.go

@@ -1,8 +0,0 @@
-// +build linux darwin freebsd netbsd openbsd dragonfly
-// +build !appengine
-
-package pb
-
-import "syscall"
-
-const sysIoctl = syscall.SYS_IOCTL

+ 0 - 6
vendor/gopkg.in/cheggaaa/pb.v1/pb_solaris.go

@@ -1,6 +0,0 @@
-// +build solaris
-// +build !appengine
-
-package pb
-
-const sysIoctl = 54

+ 4 - 2
vendor/gopkg.in/cheggaaa/pb.v1/pb_win.go

@@ -75,7 +75,7 @@ func terminalWidth() (width int, err error) {
 	if e != 0 {
 		return 0, error(e)
 	}
-	return int(info.dwSize.X), nil
+	return int(info.dwSize.X) - 1, nil
 }
 
 func getCursorPos() (pos coordinates, err error) {
@@ -102,7 +102,7 @@ var echoLockMutex sync.Mutex
 
 var oldState word
 
-func lockEcho() (quit chan int, err error) {
+func lockEcho() (shutdownCh chan struct{}, err error) {
 	echoLockMutex.Lock()
 	defer echoLockMutex.Unlock()
 	if echoLocked {
@@ -124,6 +124,8 @@ func lockEcho() (quit chan int, err error) {
 		err = fmt.Errorf("Can't set terminal settings: %v", e)
 		return
 	}
+
+	shutdownCh = make(chan struct{})
 	return
 }
 

+ 50 - 52
vendor/gopkg.in/cheggaaa/pb.v1/pb_x.go

@@ -8,25 +8,24 @@ import (
 	"fmt"
 	"os"
 	"os/signal"
-	"runtime"
 	"sync"
 	"syscall"
-	"unsafe"
-)
 
-const (
-	TIOCGWINSZ     = 0x5413
-	TIOCGWINSZ_OSX = 1074295912
+	"golang.org/x/sys/unix"
 )
 
-var tty *os.File
-
 var ErrPoolWasStarted = errors.New("Bar pool was started")
 
-var echoLocked bool
-var echoLockMutex sync.Mutex
+var (
+	echoLockMutex    sync.Mutex
+	origTermStatePtr *unix.Termios
+	tty              *os.File
+)
 
 func init() {
+	echoLockMutex.Lock()
+	defer echoLockMutex.Unlock()
+
 	var err error
 	tty, err = os.Open("/dev/tty")
 	if err != nil {
@@ -36,73 +35,72 @@ func init() {
 
 // terminalWidth returns width of the terminal.
 func terminalWidth() (int, error) {
-	w := new(window)
-	tio := syscall.TIOCGWINSZ
-	if runtime.GOOS == "darwin" {
-		tio = TIOCGWINSZ_OSX
-	}
-	res, _, err := syscall.Syscall(sysIoctl,
-		tty.Fd(),
-		uintptr(tio),
-		uintptr(unsafe.Pointer(w)),
-	)
-	if int(res) == -1 {
+	echoLockMutex.Lock()
+	defer echoLockMutex.Unlock()
+
+	fd := int(tty.Fd())
+
+	ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
+	if err != nil {
 		return 0, err
 	}
-	return int(w.Col), nil
-}
 
-var oldState syscall.Termios
+	return int(ws.Col), nil
+}
 
-func lockEcho() (quit chan int, err error) {
+func lockEcho() (shutdownCh chan struct{}, err error) {
 	echoLockMutex.Lock()
 	defer echoLockMutex.Unlock()
-	if echoLocked {
-		err = ErrPoolWasStarted
-		return
+	if origTermStatePtr != nil {
+		return shutdownCh, ErrPoolWasStarted
 	}
-	echoLocked = true
 
-	fd := tty.Fd()
-	if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); e != 0 {
-		err = fmt.Errorf("Can't get terminal settings: %v", e)
-		return
+	fd := int(tty.Fd())
+
+	origTermStatePtr, err = unix.IoctlGetTermios(fd, ioctlReadTermios)
+	if err != nil {
+		return nil, fmt.Errorf("Can't get terminal settings: %v", err)
 	}
 
-	newState := oldState
-	newState.Lflag &^= syscall.ECHO
-	newState.Lflag |= syscall.ICANON | syscall.ISIG
-	newState.Iflag |= syscall.ICRNL
-	if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); e != 0 {
-		err = fmt.Errorf("Can't set terminal settings: %v", e)
-		return
+	oldTermios := *origTermStatePtr
+	newTermios := oldTermios
+	newTermios.Lflag &^= syscall.ECHO
+	newTermios.Lflag |= syscall.ICANON | syscall.ISIG
+	newTermios.Iflag |= syscall.ICRNL
+	if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newTermios); err != nil {
+		return nil, fmt.Errorf("Can't set terminal settings: %v", err)
 	}
-	quit = make(chan int, 1)
-	go catchTerminate(quit)
+
+	shutdownCh = make(chan struct{})
+	go catchTerminate(shutdownCh)
 	return
 }
 
-func unlockEcho() (err error) {
+func unlockEcho() error {
 	echoLockMutex.Lock()
 	defer echoLockMutex.Unlock()
-	if !echoLocked {
-		return
+	if origTermStatePtr == nil {
+		return nil
 	}
-	echoLocked = false
-	fd := tty.Fd()
-	if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); e != 0 {
-		err = fmt.Errorf("Can't set terminal settings")
+
+	fd := int(tty.Fd())
+
+	if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, origTermStatePtr); err != nil {
+		return fmt.Errorf("Can't set terminal settings: %v", err)
 	}
-	return
+
+	origTermStatePtr = nil
+
+	return nil
 }
 
 // listen exit signals and restore terminal state
-func catchTerminate(quit chan int) {
+func catchTerminate(shutdownCh chan struct{}) {
 	sig := make(chan os.Signal, 1)
 	signal.Notify(sig, os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGKILL)
 	defer signal.Stop(sig)
 	select {
-	case <-quit:
+	case <-shutdownCh:
 		unlockEcho()
 	case <-sig:
 		unlockEcho()

+ 46 - 19
vendor/gopkg.in/cheggaaa/pb.v1/pool.go

@@ -3,6 +3,7 @@
 package pb
 
 import (
+	"io"
 	"sync"
 	"time"
 )
@@ -11,21 +12,36 @@ import (
 // You need call pool.Stop() after work
 func StartPool(pbs ...*ProgressBar) (pool *Pool, err error) {
 	pool = new(Pool)
-	if err = pool.start(); err != nil {
+	if err = pool.Start(); err != nil {
 		return
 	}
-	pool.add(pbs...)
+	pool.Add(pbs...)
+	return
+}
+
+// NewPool initialises a pool with progress bars, but
+// doesn't start it. You need to call Start manually
+func NewPool(pbs ...*ProgressBar) (pool *Pool) {
+	pool = new(Pool)
+	pool.Add(pbs...)
 	return
 }
 
 type Pool struct {
-	RefreshRate time.Duration
-	bars        []*ProgressBar
-	quit        chan int
-	finishOnce  sync.Once
+	Output        io.Writer
+	RefreshRate   time.Duration
+	bars          []*ProgressBar
+	lastBarsCount int
+	shutdownCh    chan struct{}
+	workerCh      chan struct{}
+	m             sync.Mutex
+	finishOnce    sync.Once
 }
 
-func (p *Pool) add(pbs ...*ProgressBar) {
+// Add progress bars.
+func (p *Pool) Add(pbs ...*ProgressBar) {
+	p.m.Lock()
+	defer p.m.Unlock()
 	for _, bar := range pbs {
 		bar.ManualUpdate = true
 		bar.NotPrint = true
@@ -34,30 +50,38 @@ func (p *Pool) add(pbs ...*ProgressBar) {
 	}
 }
 
-func (p *Pool) start() (err error) {
+func (p *Pool) Start() (err error) {
 	p.RefreshRate = DefaultRefreshRate
-	quit, err := lockEcho()
+	p.shutdownCh, err = lockEcho()
 	if err != nil {
 		return
 	}
-	p.quit = make(chan int)
-	go p.writer(quit)
+	p.workerCh = make(chan struct{})
+	go p.writer()
 	return
 }
 
-func (p *Pool) writer(finish chan int) {
+func (p *Pool) writer() {
 	var first = true
+	defer func() {
+		if first == false {
+			p.print(false)
+		} else {
+			p.print(true)
+			p.print(false)
+		}
+		close(p.workerCh)
+	}()
+
 	for {
 		select {
 		case <-time.After(p.RefreshRate):
 			if p.print(first) {
 				p.print(false)
-				finish <- 1
 				return
 			}
 			first = false
-		case <-p.quit:
-			finish <- 1
+		case <-p.shutdownCh:
 			return
 		}
 	}
@@ -65,11 +89,14 @@ func (p *Pool) writer(finish chan int) {
 
 // Restore terminal state and close pool
 func (p *Pool) Stop() error {
-	// Wait until one final refresh has passed.
-	time.Sleep(p.RefreshRate)
-
 	p.finishOnce.Do(func() {
-		close(p.quit)
+		close(p.shutdownCh)
 	})
+
+	// Wait for the worker to complete
+	select {
+	case <-p.workerCh:
+	}
+
 	return unlockEcho()
 }

+ 13 - 3
vendor/gopkg.in/cheggaaa/pb.v1/pool_win.go

@@ -8,13 +8,18 @@ import (
 )
 
 func (p *Pool) print(first bool) bool {
+	p.m.Lock()
+	defer p.m.Unlock()
 	var out string
 	if !first {
 		coords, err := getCursorPos()
 		if err != nil {
 			log.Panic(err)
 		}
-		coords.Y -= int16(len(p.bars))
+		coords.Y -= int16(p.lastBarsCount)
+		if coords.Y < 0 {
+			coords.Y = 0
+		}
 		coords.X = 0
 
 		err = setCursorPos(coords)
@@ -24,12 +29,17 @@ func (p *Pool) print(first bool) bool {
 	}
 	isFinished := true
 	for _, bar := range p.bars {
-		if !bar.isFinish {
+		if !bar.IsFinished() {
 			isFinished = false
 		}
 		bar.Update()
 		out += fmt.Sprintf("\r%s\n", bar.String())
 	}
-	fmt.Print(out)
+	if p.Output != nil {
+		fmt.Fprint(p.Output, out)
+	} else {
+		fmt.Print(out)
+	}
+	p.lastBarsCount = len(p.bars)
 	return isFinished
 }

+ 10 - 3
vendor/gopkg.in/cheggaaa/pb.v1/pool_x.go

@@ -5,18 +5,25 @@ package pb
 import "fmt"
 
 func (p *Pool) print(first bool) bool {
+	p.m.Lock()
+	defer p.m.Unlock()
 	var out string
 	if !first {
-		out = fmt.Sprintf("\033[%dA", len(p.bars))
+		out = fmt.Sprintf("\033[%dA", p.lastBarsCount)
 	}
 	isFinished := true
 	for _, bar := range p.bars {
-		if !bar.isFinish {
+		if !bar.IsFinished() {
 			isFinished = false
 		}
 		bar.Update()
 		out += fmt.Sprintf("\r%s\n", bar.String())
 	}
-	fmt.Print(out)
+	if p.Output != nil {
+		fmt.Fprint(p.Output, out)
+	} else {
+		fmt.Print(out)
+	}
+	p.lastBarsCount = len(p.bars)
 	return isFinished
 }

+ 8 - 0
vendor/gopkg.in/cheggaaa/pb.v1/reader.go

@@ -15,3 +15,11 @@ func (r *Reader) Read(p []byte) (n int, err error) {
 	r.bar.Add(n)
 	return
 }
+
+// Close the reader when it implements io.Closer
+func (r *Reader) Close() (err error) {
+	if closer, ok := r.Reader.(io.Closer); ok {
+		return closer.Close()
+	}
+	return
+}

+ 3 - 3
vendor/gopkg.in/cheggaaa/pb.v1/runecount.go

@@ -1,17 +1,17 @@
 package pb
 
 import (
+	"github.com/mattn/go-runewidth"
 	"regexp"
-	"unicode/utf8"
 )
 
 // Finds the control character sequences (like colors)
 var ctrlFinder = regexp.MustCompile("\x1b\x5b[0-9]+\x6d")
 
 func escapeAwareRuneCountInString(s string) int {
-	n := utf8.RuneCountInString(s)
+	n := runewidth.StringWidth(s)
 	for _, sm := range ctrlFinder.FindAllString(s, -1) {
-		n -= len(sm)
+		n -= runewidth.StringWidth(sm)
 	}
 	return n
 }

+ 0 - 7
vendor/gopkg.in/cheggaaa/pb.v1/termios_nix.go

@@ -1,7 +0,0 @@
-// +build linux solaris
-// +build !appengine
-
-package pb
-
-const ioctlReadTermios = 0x5401  // syscall.TCGETS
-const ioctlWriteTermios = 0x5402 // syscall.TCSETS

+ 13 - 0
vendor/gopkg.in/cheggaaa/pb.v1/termios_sysv.go

@@ -0,0 +1,13 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux solaris
+// +build !appengine
+
+package pb
+
+import "golang.org/x/sys/unix"
+
+const ioctlReadTermios = unix.TCGETS
+const ioctlWriteTermios = unix.TCSETS