Skip to content

Commit a5d4fb1

Browse files
authored
Merge pull request #4153 from thaJeztah/streams_cleanup
cli/streams: minor refactoring and docs touch-ups
2 parents 9ce269f + 8080326 commit a5d4fb1

3 files changed

Lines changed: 42 additions & 28 deletions

File tree

cli/streams/in.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,42 @@ import (
99
"github.com/moby/term"
1010
)
1111

12-
// In is an input stream used by the DockerCli to read user input
12+
// In is an input stream to read user input. It implements [io.ReadCloser]
13+
// with additional utilities, such as putting the terminal in raw mode.
1314
type In struct {
1415
commonStream
1516
in io.ReadCloser
1617
}
1718

19+
// Read implements the [io.Reader] interface.
1820
func (i *In) Read(p []byte) (int, error) {
1921
return i.in.Read(p)
2022
}
2123

22-
// Close implements the Closer interface
24+
// Close implements the [io.Closer] interface.
2325
func (i *In) Close() error {
2426
return i.in.Close()
2527
}
2628

27-
// SetRawTerminal sets raw mode on the input terminal
29+
// SetRawTerminal sets raw mode on the input terminal. It is a no-op if In
30+
// is not a TTY, or if the "NORAW" environment variable is set to a non-empty
31+
// value.
2832
func (i *In) SetRawTerminal() (err error) {
29-
if os.Getenv("NORAW") != "" || !i.commonStream.isTerminal {
33+
if !i.isTerminal || os.Getenv("NORAW") != "" {
3034
return nil
3135
}
32-
i.commonStream.state, err = term.SetRawTerminal(i.commonStream.fd)
36+
i.state, err = term.SetRawTerminal(i.fd)
3337
return err
3438
}
3539

36-
// CheckTty checks if we are trying to attach to a container tty
37-
// from a non-tty client input stream, and if so, returns an error.
40+
// CheckTty checks if we are trying to attach to a container TTY
41+
// from a non-TTY client input stream, and if so, returns an error.
3842
func (i *In) CheckTty(attachStdin, ttyMode bool) error {
3943
// In order to attach to a container tty, input stream for the client must
4044
// be a tty itself: redirecting or piping the client standard input is
4145
// incompatible with `docker run -t`, `docker exec -t` or `docker attach`.
4246
if ttyMode && attachStdin && !i.isTerminal {
43-
eText := "the input device is not a TTY"
47+
const eText = "the input device is not a TTY"
4448
if runtime.GOOS == "windows" {
4549
return errors.New(eText + ". If you are using mintty, try prefixing the command with 'winpty'")
4650
}
@@ -49,8 +53,9 @@ func (i *In) CheckTty(attachStdin, ttyMode bool) error {
4953
return nil
5054
}
5155

52-
// NewIn returns a new In object from a ReadCloser
56+
// NewIn returns a new [In] from an [io.ReadCloser].
5357
func NewIn(in io.ReadCloser) *In {
54-
fd, isTerminal := term.GetFdInfo(in)
55-
return &In{commonStream: commonStream{fd: fd, isTerminal: isTerminal}, in: in}
58+
i := &In{in: in}
59+
i.fd, i.isTerminal = term.GetFdInfo(in)
60+
return i
5661
}

cli/streams/out.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import (
88
"github.com/sirupsen/logrus"
99
)
1010

11-
// Out is an output stream used by the DockerCli to write normal program
12-
// output.
11+
// Out is an output stream to write normal program output. It implements
12+
// an [io.Writer], with additional utilities for detecting whether a terminal
13+
// is connected, getting the TTY size, and putting the terminal in raw mode.
1314
type Out struct {
1415
commonStream
1516
out io.Writer
@@ -19,32 +20,39 @@ func (o *Out) Write(p []byte) (int, error) {
1920
return o.out.Write(p)
2021
}
2122

22-
// SetRawTerminal sets raw mode on the input terminal
23+
// SetRawTerminal puts the output of the terminal connected to the stream
24+
// into raw mode.
25+
//
26+
// On UNIX, this does nothing. On Windows, it disables LF -> CRLF/ translation.
27+
// It is a no-op if Out is not a TTY, or if the "NORAW" environment variable is
28+
// set to a non-empty value.
2329
func (o *Out) SetRawTerminal() (err error) {
24-
if os.Getenv("NORAW") != "" || !o.commonStream.isTerminal {
30+
if !o.isTerminal || os.Getenv("NORAW") != "" {
2531
return nil
2632
}
27-
o.commonStream.state, err = term.SetRawTerminalOutput(o.commonStream.fd)
33+
o.state, err = term.SetRawTerminalOutput(o.fd)
2834
return err
2935
}
3036

31-
// GetTtySize returns the height and width in characters of the tty
32-
func (o *Out) GetTtySize() (uint, uint) {
37+
// GetTtySize returns the height and width in characters of the TTY, or
38+
// zero for both if no TTY is connected.
39+
func (o *Out) GetTtySize() (height uint, width uint) {
3340
if !o.isTerminal {
3441
return 0, 0
3542
}
3643
ws, err := term.GetWinsize(o.fd)
3744
if err != nil {
38-
logrus.Debugf("Error getting size: %s", err)
45+
logrus.WithError(err).Debug("Error getting TTY size")
3946
if ws == nil {
4047
return 0, 0
4148
}
4249
}
4350
return uint(ws.Height), uint(ws.Width)
4451
}
4552

46-
// NewOut returns a new Out object from a Writer
53+
// NewOut returns a new [Out] from an [io.Writer].
4754
func NewOut(out io.Writer) *Out {
48-
fd, isTerminal := term.GetFdInfo(out)
49-
return &Out{commonStream: commonStream{fd: fd, isTerminal: isTerminal}, out: out}
55+
o := &Out{out: out}
56+
o.fd, o.isTerminal = term.GetFdInfo(out)
57+
return o
5058
}

cli/streams/stream.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,32 @@ import (
44
"github.com/moby/term"
55
)
66

7-
// commonStream is an input stream used by the DockerCli to read user input
87
type commonStream struct {
98
fd uintptr
109
isTerminal bool
1110
state *term.State
1211
}
1312

14-
// FD returns the file descriptor number for this stream
13+
// FD returns the file descriptor number for this stream.
1514
func (s *commonStream) FD() uintptr {
1615
return s.fd
1716
}
1817

19-
// IsTerminal returns true if this stream is connected to a terminal
18+
// IsTerminal returns true if this stream is connected to a terminal.
2019
func (s *commonStream) IsTerminal() bool {
2120
return s.isTerminal
2221
}
2322

24-
// RestoreTerminal restores normal mode to the terminal
23+
// RestoreTerminal restores normal mode to the terminal.
2524
func (s *commonStream) RestoreTerminal() {
2625
if s.state != nil {
27-
term.RestoreTerminal(s.fd, s.state)
26+
_ = term.RestoreTerminal(s.fd, s.state)
2827
}
2928
}
3029

31-
// SetIsTerminal sets the boolean used for isTerminal
30+
// SetIsTerminal overrides whether a terminal is connected. It is used to
31+
// override this property in unit-tests, and should not be depended on for
32+
// other purposes.
3233
func (s *commonStream) SetIsTerminal(isTerminal bool) {
3334
s.isTerminal = isTerminal
3435
}

0 commit comments

Comments
 (0)