8000 Merge pull request #38398 from RaviTezu/replace_gotty_with_aec · moby/moby@0cde75e · GitHub
[go: up one dir, main page]

Skip to content

Commit 0cde75e

Browse files
authored
Merge pull request #38398 from RaviTezu/replace_gotty_with_aec
replace gotty with aec, since gotty hasn't been updated since very lo…
2 parents 6351619 + 1990a3e commit 0cde75e

File tree

15 files changed

+1018
-1259
lines changed

15 files changed

+1018
-1259
lines changed

pkg/jsonmessage/jsonmessage.go

Lines changed: 26 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@ import (
44
"encoding/json"
55
"fmt"
66
"io"
7-
"os"
87
"strings"
98
"time"
109

11-
"github.com/Nvveen/Gotty"
1210
"github.com/docker/docker/pkg/term"
1311
"github.com/docker/go-units"
12+
"github.com/morikuni/aec"
1413
)
1514

1615
// RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to
@@ -151,69 +150,32 @@ type JSONMessage struct {
151150
Aux *json.RawMessage `json:"aux,omitempty"`
152151
}
153152

154-
/* Satisfied by gotty.TermInfo as well as noTermInfo from below */
155-
type termInfo interface {
156-
Parse(attr string, params ...interface{}) (string, error)
153+
func clearLine(out io.Writer) {
154+
eraseMode := aec.EraseModes.All
155+
cl := aec.EraseLine(eraseMode)
156+
fmt.Fprint(out, cl)
157157
}
158158

159-
type noTermInfo struct{} // canary used when no terminfo.
160-
161-
func (ti *noTermInfo) Parse(attr string, params ...interface{}) (string, error) {
162-
return "", fmt.Errorf("noTermInfo")
163-
}
164-
165-
func clearLine(out io.Writer, ti termInfo) {
166-
// el2 (clear whole line) is not exposed by terminfo.
167-
168-
// First clear line from beginning to cursor
169-
if attr, err := ti.Parse("el1"); err == nil {
170-
fmt.Fprintf(out, "%s", attr)
171-
} else {
172-
fmt.Fprintf(out, "\x1b[1K")
173-
}
174-
// Then clear line from cursor to end
175-
if attr, err := ti.Parse("el"); err == nil {
176-
fmt.Fprintf(out, "%s", attr)
177-
} else {
178-
fmt.Fprintf(out, "\x1b[K")
179-
}
180-
}
181-
182-
func cursorUp(out io.Writer, ti termInfo, l int) {
183-
if l == 0 { // Should never be the case, but be tolerant
184-
return
185-
}
186-
if attr, err := ti.Parse("cuu", l); err == nil {
187-
fmt.Fprintf(out, "%s", attr)
188-
} else {
189-
fmt.Fprintf(out, "\x1b[%dA", l)
190-
}
159+
func cursorUp(out io.Writer, l uint) {
160+
fmt.Fprint(out, aec.Up(l))
191161
}
192162

193-
func cursorDown(out io.Writer, ti termInfo, l int) {
194-
if l == 0 { // Should never be the case, but be tolerant
195-
return
196-
}
197-
if attr, err := ti.Parse("cud", l); err == nil {
198-
fmt.Fprintf(out, "%s", attr)
199-
} else {
200-
fmt.Fprintf(out, "\x1b[%dB", l)
201-
}
163+
func cursorDown(out io.Writer, l uint) {
164+
fmt.Fprint(out, aec.Down(l))
202165
}
203166

204-
// Display displays the JSONMessage to `out`. `termInfo` is non-nil if `out`
205-
// is a terminal. If this is the case, it will erase the entire current line
206-
// when displaying the progressbar.
207-
func (jm *JSONMessage) Display(out io.Writer, termInfo termInfo) error {
167+
// Display displays the JSONMessage to `out`. If `isTerminal` is true, it will erase the
168+
// entire current line when displaying the progressbar.
169+
func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error {
208170
if jm.Error != nil {
209171
if jm.Error.Code == 401 {
210172
return fmt.Errorf("authentication is required")
211173
}
212174
return jm.Error
213175
}
214176
var endl string
215-
if termInfo != nil && jm.Stream == "" && jm.Progress != nil {
216-
clearLine(out, termInfo)
177+
if isTerminal && jm.Stream == "" && jm.Progress != nil {
178+
clearLine(out)
217179
endl = "\r"
218180
fmt.Fprintf(out, endl)
219181
} else if jm.Progress != nil && jm.Progress.String() != "" { //disable progressbar in non-terminal
@@ -230,7 +192,7 @@ func (jm *JSONMessage) Display(out io.Writer, termInfo termInfo) error {
230192
if jm.From != "" {
231193
fmt.Fprintf(out, "(from %s) ", jm.From)
232194
}
233-
if jm.Progress != nil && termInfo != nil {
195+
if jm.Progress != nil && isTerminal {
234196
fmt.Fprintf(out, "%s %s%s", jm.Status, jm.Progress.String(), endl)
235197
} else if jm.ProgressMessage != "" { //deprecated
236198
fmt.Fprintf(out, "%s %s%s", jm.Status, jm.ProgressMessage, endl)
@@ -248,25 +210,11 @@ func (jm *JSONMessage) Display(out io.Writer, termInfo termInfo) error {
248210
func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(JSONMessage)) error {
249211
var (
250212
dec = json.NewDecoder(in)
251-
ids = make(map[string]int)
213+
ids = make(map[string]uint)
252214
)
253215

254-
var termInfo termInfo
255-
256-
if isTerminal {
257-
term := os.Getenv("TERM")
258-
if term == "" {
259-
term = "vt102"
260-
}
261-
262-
var err error
263-
if termInfo, err = gotty.OpenTermInfo(term); err != nil {
264-
termInfo = &noTermInfo{}
265-
}
266-
}
267-
268216
for {
269-
diff := 0
217+
var diff uint
270218
var jm JSONMessage
271219
if err := dec.Decode(&jm); err != nil {
272220
if err == io.EOF {
@@ -294,27 +242,27 @@ func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr,
294242
// when we output something that's not
295243
// accounted for in the map, such as a line
296244
// with no ID.
297-
line = len(ids)
245+
line = uint(len(ids))
298246
ids[jm.ID] = line
299-
if termInfo != nil {
247+
if isTerminal {
300248
fmt.Fprintf(out, "\n")
301249
}
302250
}
303-
diff = len(ids) - line
304-
if termInfo != nil {
305-
cursorUp(out, termInfo, diff)
251+
diff = uint(len(ids)) - line
252+
if isTerminal {
253+
cursorUp(out, diff)
306254
}
307255
} else {
308256
// When outputting something that isn't progress
309257
// output, clear the history of previous lines. We
310258
// don't want progress entries from some previous
311259
// operation to be updated (for example, pull -a
312260
// with multiple tags).
313-
ids = make(map[string]int)
261+
ids = make(map[string]uint)
314262
}
315-
err := jm.Display(out, termInfo)
316-
if jm.ID != "" && termInfo != nil {
317-
cursorDown(out, termInfo, diff)
263+
err := jm.Display(out, isTerminal)
264+
if jm.ID != "" && isTerminal {
265+
cursorDown(out, diff)
318266
}
319267
if err != nil {
320268
return err

pkg/jsonmessage/jsonmessage_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,23 +180,23 @@ func TestJSONMessageDisplay(t *testing.T) {
180180
Progress: &JSONProgress{Current: 1},
181181
}: {
182182
"",
183-
fmt.Sprintf("%c[1K%c[K\rstatus 1B\r", 27, 27),
183+
fmt.Sprintf("%c[2K\rstatus 1B\r", 27),
184184
},
185185
}
186186

187187
// The tests :)
188188
for jsonMessage, expectedMessages := range messages {
189189
// Without terminal
190190
data := bytes.NewBuffer([]byte{})
191-
if err := jsonMessage.Display(data, nil); err != nil {
191+
if err := jsonMessage.Display(data, false); err != nil {
192192
t.Fatal(err)
193193
}
194194
if data.String() != expectedMessages[0] {
195195
t.Fatalf("Expected %q,got %q", expectedMessages[0], data.String())
196196
}
197197
// With terminal
198198
data = bytes.NewBuffer([]byte{})
199-
if err := jsonMessage.Display(data, &noTermInfo{}); err != nil {
199+
if err := jsonMessage.Display(data, true); err != nil {
200200
t.Fatal(err)
201201
}
202202
if data.String() != expectedMessages[1] {
@@ -210,13 +210,13 @@ func TestJSONMessageDisplayWithJSONError(t *testing.T) {
210210
data := bytes.NewBuffer([]byte{})
211211
jsonMessage := JSONMessage{Error: &JSONError{404, "Can't find it"}}
212212

213-
err := jsonMessage.Display(data, &noTermInfo{})
213+
err := jsonMessage.Display(data, true)
214214
if err == nil || err.Error() != "Can't find it" {
215215
t.Fatalf("Expected a JSONError 404, got %q", err)
216216
}
217217

218218
jsonMessage = JSONMessage{Error: &JSONError{401, "Anything"}}
219-
err = jsonMessage.Display(data, &noTermInfo{})
219+
err = jsonMessage.Display(data, true)
220220
assert.Check(t, is.Error(err, "authentication is required"))
221221
}
222222

@@ -261,7 +261,7 @@ func TestDisplayJSONMessagesStream(t *testing.T) {
261261
// With progressDetail
262262
"{ \"id\": \"ID\", \"status\": \"status\", \"progressDetail\": { \"Current\": 1} }": {
263263
"", // progressbar is disabled in non-terminal
264-
fmt.Sprintf("\n%c[%dA%c[1K%c[K\rID: status 1B\r%c[%dB", 27, 1, 27, 27, 27, 1),
264+
fmt.Sprintf("\n%c[%dA%c[2K\rID: status 1B\r%c[%dB", 27, 1, 27, 27, 1),
265265
},
266266
}
267267

vendor.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
155155
github.com/spf13/cobra v0.0.3
156156
github.com/spf13/pflag v1.0.1
157157
github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 # v1.0
158-
github.com/Nvveen/Gotty a8b993ba6abdb0e0c12b0125c603323a71c7790c https://github.com/ijc25/Gotty
158+
github.com/morikuni/aec 39771216ff4c63d11f5e604076f9c45e8be1067b
159159

160160
# metrics
161161
github.com/docker/go-metrics d466d4f6fd960e01820085bd7e1a24426ee7ef18

vendor/github.com/Nvveen/Gotty/LICENSE

Lines changed: 0 additions & 26 deletions
This file was deleted.

vendor/github.com/Nvveen/Gotty/README

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)
0