mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
pkg/jsonmessage: Avoid undefined ANSI escape codes.
The ANSI escape codes \e[0A (cursor up 0 lines) and \e[0B (cursor down 0 lines) are not well defined and are treated differently by different terminals. In particular xterm treats 0 as a missing parameter and therefore defaults to 1, whereas rxvt-unicode treats these escapes as a request to move 0 lines. However the use of these codes is unnecessary and were really just hiding the fact that we were not correctly computing diff when adding a new line. Having added the new line to the ids map and output the corresponding \n we need to then calculate a correct diff of 1 rather than leaving it as the default 0 (which xterm then interprets as 1). The fix is to pull the diff calculation out of the else case and to always do it. With this in place we can then avoid outputting escapes for moving 0 lines. Actually diff should never be 0 to start with any more, but check to be safe. This fixes corruption of `docker pull` seen with rxvt-unicode (and likely other terminals in that family) seen in #28111. Tested with rxvt-unicode ($TERM=rxvt-unicode), xterm ($TERM=xterm), mlterm ($TERM=mlterm) and aterm ($TERM=kterm). The test cases have been updated to match the new behaviour. Signed-off-by: Ian Campbell <ian.campbell@docker.com>
This commit is contained in:
parent
c025049c27
commit
b08b437acc
2 changed files with 6 additions and 13 deletions
|
@ -189,13 +189,9 @@ func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr,
|
||||||
if isTerminal {
|
if isTerminal {
|
||||||
fmt.Fprintf(out, "\n")
|
fmt.Fprintf(out, "\n")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
diff = len(ids) - line
|
|
||||||
}
|
}
|
||||||
if isTerminal {
|
diff = len(ids) - line
|
||||||
// NOTE: this appears to be necessary even if
|
if isTerminal && diff > 0 {
|
||||||
// diff == 0.
|
|
||||||
// <ESC>[{diff}A = move cursor up diff rows
|
|
||||||
fmt.Fprintf(out, "%c[%dA", 27, diff)
|
fmt.Fprintf(out, "%c[%dA", 27, diff)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -207,10 +203,7 @@ func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr,
|
||||||
ids = make(map[string]int)
|
ids = make(map[string]int)
|
||||||
}
|
}
|
||||||
err := jm.Display(out, isTerminal)
|
err := jm.Display(out, isTerminal)
|
||||||
if jm.ID != "" && isTerminal {
|
if jm.ID != "" && isTerminal && diff > 0 {
|
||||||
// NOTE: this appears to be necessary even if
|
|
||||||
// diff == 0.
|
|
||||||
// <ESC>[{diff}B = move cursor down diff rows
|
|
||||||
fmt.Fprintf(out, "%c[%dB", 27, diff)
|
fmt.Fprintf(out, "%c[%dB", 27, diff)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -205,17 +205,17 @@ func TestDisplayJSONMessagesStream(t *testing.T) {
|
||||||
// Without progress, with ID
|
// Without progress, with ID
|
||||||
"{ \"id\": \"ID\",\"status\": \"status\" }": {
|
"{ \"id\": \"ID\",\"status\": \"status\" }": {
|
||||||
"ID: status\n",
|
"ID: status\n",
|
||||||
fmt.Sprintf("ID: status\n%c[%dB", 27, 0),
|
fmt.Sprintf("ID: status\n"),
|
||||||
},
|
},
|
||||||
// With progress
|
// With progress
|
||||||
"{ \"id\": \"ID\", \"status\": \"status\", \"progress\": \"ProgressMessage\" }": {
|
"{ \"id\": \"ID\", \"status\": \"status\", \"progress\": \"ProgressMessage\" }": {
|
||||||
"ID: status ProgressMessage",
|
"ID: status ProgressMessage",
|
||||||
fmt.Sprintf("\n%c[%dAID: status ProgressMessage%c[%dB", 27, 0, 27, 0),
|
fmt.Sprintf("\n%c[%dAID: status ProgressMessage%c[%dB", 27, 1, 27, 1),
|
||||||
},
|
},
|
||||||
// With progressDetail
|
// With progressDetail
|
||||||
"{ \"id\": \"ID\", \"status\": \"status\", \"progressDetail\": { \"Current\": 1} }": {
|
"{ \"id\": \"ID\", \"status\": \"status\", \"progressDetail\": { \"Current\": 1} }": {
|
||||||
"", // progressbar is disabled in non-terminal
|
"", // progressbar is disabled in non-terminal
|
||||||
fmt.Sprintf("\n%c[%dA%c[2K\rID: status 1 B\r%c[%dB", 27, 0, 27, 27, 0),
|
fmt.Sprintf("\n%c[%dA%c[2K\rID: status 1 B\r%c[%dB", 27, 1, 27, 27, 1),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for jsonMessage, expectedMessages := range messages {
|
for jsonMessage, expectedMessages := range messages {
|
||||||
|
|
Loading…
Reference in a new issue