-
Notifications
You must be signed in to change notification settings - Fork 298
/
progress.go
123 lines (106 loc) · 2.27 KB
/
progress.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Package progress makes it possible to dissplay download progress.
package progress
import (
"fmt"
"io"
"os"
"strings"
"golang.org/x/term"
"github.com/bazelbuild/bazelisk/config"
)
// Progress shows a download progress bar.
type progress struct {
header string
total int64
current int64
lastMessage string
}
func showProgress(config config.Config) bool {
// If stdout is a terminal, don't show progress.
if !term.IsTerminal(int(os.Stdout.Fd())) {
return false
}
// Check the config variable.
showProgress := config.Get("BAZELISK_SHOW_PROGRESS")
if len(showProgress) == 0 {
// Default to showing progress
return true
}
switch strings.ToLower(showProgress) {
case "":
return true // Default to on
case "yes":
return true
case "y":
return true
case "true":
return true
case "1":
return true
case "no":
return false
case "n":
return false
case "false":
return false
case "0":
return false
}
// TODO: default: error
return true
}
func Writer(w io.Writer, header string, total int64, config config.Config) io.Writer {
if !showProgress(config) {
return w
}
prog := &progress{
header: header,
total: total,
}
out := io.MultiWriter(w, prog)
return out
}
func Finish(config config.Config) {
if showProgress(config) {
// Add a newline after the progress bar
fmt.Println()
}
}
func (p *progress) Write(buf []byte) (int, error) {
l := len(buf)
p.current += int64(l)
p.ShowProgress()
return l, nil
}
// Writes the current download progress to stdout.
func (p *progress) ShowProgress() {
var message string
if p.total > 0 {
message = fmt.Sprintf("%s: %s out of %s (%s)",
p.header,
formatMb(p.current),
formatMb(p.total),
formatPercentage(p.current, p.total))
} else {
message = fmt.Sprintf("%s: %s",
p.header,
formatMb(p.current))
}
if message == p.lastMessage {
return
}
// Clear the line.
fmt.Printf("\r%s", strings.Repeat(" ", 39))
// Show a message, don't add a newline
fmt.Printf("\r%s", message)
p.lastMessage = message
}
func formatMb(size int64) string {
// TODO: Use units other than MB
inMb := size / (1024 * 1024)
return fmt.Sprintf("%d MB", inMb)
}
func formatPercentage(current, size int64) string {
percentage := current * 100 / size
return fmt.Sprintf("%d%%", percentage)
}