Skip to content

Commit 9e0f443

Browse files
committed
chore: convert to creack/pty
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
1 parent df5bf33 commit 9e0f443

File tree

5 files changed

+65
-43
lines changed

5 files changed

+65
-43
lines changed

cmd/oras/internal/display/status/console/console.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ package console
1818
import (
1919
"os"
2020

21-
containerd "github.com/containerd/console"
21+
"github.com/creack/pty"
2222
"github.com/morikuni/aec"
23+
"golang.org/x/term"
2324
)
2425

2526
const (
@@ -33,27 +34,47 @@ const (
3334
Restore = "\0338"
3435
)
3536

36-
// Console is a wrapper around containerd's Console and ANSI escape codes.
37+
// Console is a wrapper around PTY and ANSI escape codes.
3738
type Console interface {
38-
containerd.Console
39+
Write(p []byte) (n int, err error)
40+
Size() (*WinSize, error)
3941
GetHeightWidth() (height, width int)
4042
Save()
4143
NewRow()
4244
OutputTo(upCnt uint, str string)
4345
Restore()
4446
}
4547

48+
// WinSize represents the size of a terminal window.
49+
type WinSize struct {
50+
Height uint16
51+
Width uint16
52+
}
53+
4654
type console struct {
47-
containerd.Console
55+
file *os.File
4856
}
4957

5058
// NewConsole generates a console from a file.
5159
func NewConsole(f *os.File) (Console, error) {
52-
c, err := containerd.ConsoleFromFile(f)
60+
if !term.IsTerminal(int(f.Fd())) {
61+
return nil, os.ErrInvalid
62+
}
63+
return &console{file: f}, nil
64+
}
65+
66+
// Write writes data to the console.
67+
func (c *console) Write(p []byte) (n int, err error) {
68+
return c.file.Write(p)
69+
}
70+
71+
// Size returns the size of the console.
72+
func (c *console) Size() (*WinSize, error) {
73+
rows, cols, err := pty.Getsize(c.file)
5374
if err != nil {
5475
return nil, err
5576
}
56-
return &console{c}, nil
77+
return &WinSize{Height: uint16(rows), Width: uint16(cols)}, nil
5778
}
5879

5980
// GetHeightWidth returns the width and height of the console.

cmd/oras/internal/display/status/console/console_test.go

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,30 @@ import (
2121
"os"
2222
"testing"
2323

24-
containerd "github.com/containerd/console"
24+
"github.com/creack/pty"
2525
"oras.land/oras/internal/testutils"
2626
)
2727

28-
func givenConsole(t *testing.T) (c Console, pty containerd.Console) {
29-
pty, _, err := containerd.NewPty()
28+
func givenConsole(t *testing.T) (c Console, ptmx *os.File) {
29+
ptmx, pts, err := pty.Open()
3030
if err != nil {
3131
t.Fatal(err)
3232
}
33+
defer func() { _ = pts.Close() }()
3334

3435
c = &console{
35-
Console: pty,
36+
file: ptmx,
3637
}
37-
return c, pty
38+
return c, ptmx
3839
}
3940

40-
func givenTestConsole(t *testing.T) (c Console, pty containerd.Console, tty *os.File) {
41+
func givenTestConsole(t *testing.T) (c Console, ptmx *os.File, pts *os.File) {
4142
var err error
42-
pty, tty, err = testutils.NewPty()
43+
ptmx, pts, err = testutils.NewPty()
4344
if err != nil {
4445
t.Fatal(err)
4546
}
46-
c, err = NewConsole(tty)
47+
c, err = NewConsole(pts)
4748
if err != nil {
4849
t.Fatal(err)
4950
}
@@ -68,68 +69,73 @@ func TestNewConsole(t *testing.T) {
6869
}
6970

7071
func TestConsole_GetHeightWidth(t *testing.T) {
71-
c, pty := givenConsole(t)
72+
c, ptmx := givenConsole(t)
73+
defer func() { _ = ptmx.Close() }()
7274

7375
// minimal width and height
7476
gotHeight, gotWidth := c.GetHeightWidth()
7577
validateSize(t, gotWidth, gotHeight, MinWidth, MinHeight)
7678

7779
// zero width
78-
_ = pty.Resize(containerd.WinSize{Width: 0, Height: MinHeight})
80+
_ = pty.Setsize(ptmx, &pty.Winsize{Rows: MinHeight, Cols: 0})
7981
gotHeight, gotWidth = c.GetHeightWidth()
8082
validateSize(t, gotWidth, gotHeight, MinWidth, MinHeight)
8183

8284
// zero height
83-
_ = pty.Resize(containerd.WinSize{Width: MinWidth, Height: 0})
85+
_ = pty.Setsize(ptmx, &pty.Winsize{Rows: 0, Cols: MinWidth})
8486
gotHeight, gotWidth = c.GetHeightWidth()
8587
validateSize(t, gotWidth, gotHeight, MinWidth, MinHeight)
8688

87-
// valid zero and height
88-
_ = pty.Resize(containerd.WinSize{Width: 200, Height: 100})
89+
// valid width and height
90+
_ = pty.Setsize(ptmx, &pty.Winsize{Rows: 100, Cols: 200})
8991
gotHeight, gotWidth = c.GetHeightWidth()
9092
validateSize(t, gotWidth, gotHeight, 200, 100)
9193

9294
}
9395

9496
func TestConsole_NewRow(t *testing.T) {
95-
c, pty, tty := givenTestConsole(t)
97+
c, ptmx, pts := givenTestConsole(t)
98+
defer func() { _ = ptmx.Close() }()
9699

97100
c.NewRow()
98101

99-
err := testutils.MatchPty(pty, tty, "\x1b8\r\n\x1b7")
102+
err := testutils.MatchPty(ptmx, pts, "\x1b8\r\n\x1b7")
100103
if err != nil {
101104
t.Fatalf("NewRow output error: %v", err)
102105
}
103106
}
104107

105108
func TestConsole_OutputTo(t *testing.T) {
106-
c, pty, tty := givenTestConsole(t)
109+
c, ptmx, pts := givenTestConsole(t)
110+
defer func() { _ = ptmx.Close() }()
107111

108112
c.OutputTo(1, "test string")
109113

110-
err := testutils.MatchPty(pty, tty, "\x1b8\x1b[1Ftest string\x1b[0m\r\n\x1b[0K")
114+
err := testutils.MatchPty(ptmx, pts, "\x1b8\x1b[1Ftest string\x1b[0m\r\n\x1b[0K")
111115
if err != nil {
112116
t.Fatalf("OutputTo output error: %v", err)
113117
}
114118
}
115119

116120
func TestConsole_Restore(t *testing.T) {
117-
c, pty, tty := givenTestConsole(t)
121+
c, ptmx, pts := givenTestConsole(t)
122+
defer ptmx.Close()
118123

119124
c.Restore()
120125

121-
err := testutils.MatchPty(pty, tty, "\x1b8\x1b[0G\x1b[2K\x1b[?25h")
126+
err := testutils.MatchPty(ptmx, pts, "\x1b8\x1b[0G\x1b[2K\x1b[?25h")
122127
if err != nil {
123128
t.Fatalf("Restore output error: %v", err)
124129
}
125130
}
126131

127132
func TestConsole_Save(t *testing.T) {
128-
c, pty, tty := givenTestConsole(t)
133+
c, ptmx, pts := givenTestConsole(t)
134+
defer ptmx.Close()
129135

130136
c.Save()
131137

132-
err := testutils.MatchPty(pty, tty, "\x1b[?25l\x1b7\x1b[0m")
138+
err := testutils.MatchPty(ptmx, pts, "\x1b[?25l\x1b7\x1b[0m")
133139
if err != nil {
134140
t.Fatalf("Save output error: %v", err)
135141
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.25.0
44

55
require (
66
github.com/Masterminds/sprig/v3 v3.3.0
7-
github.com/containerd/console v1.0.5
7+
github.com/creack/pty v1.1.24
88
github.com/morikuni/aec v1.0.0
99
github.com/opencontainers/go-digest v1.0.0
1010
github.com/opencontainers/image-spec v1.1.1

go.sum

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1
66
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
77
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
88
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
9-
github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=
10-
github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
119
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
10+
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
11+
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
1212
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1313
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1414
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -60,7 +60,6 @@ golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+Zdx
6060
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
6161
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
6262
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
63-
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
6463
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
6564
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
6665
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=

internal/testutils/console.go

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,34 +25,30 @@ import (
2525
"strings"
2626
"sync"
2727

28-
containerd "github.com/containerd/console"
28+
"github.com/creack/pty"
2929
)
3030

3131
// NewPty creates a new pty pair for testing, caller is responsible for closing
32-
// the returned device file if err is not nil.
33-
func NewPty() (containerd.Console, *os.File, error) {
34-
pty, devicePath, err := containerd.NewPty()
32+
// the returned files if err is not nil.
33+
func NewPty() (*os.File, *os.File, error) {
34+
ptmx, pts, err := pty.Open()
3535
if err != nil {
3636
return nil, nil, err
3737
}
38-
device, err := os.OpenFile(devicePath, os.O_RDWR, 0)
39-
if err != nil {
40-
return nil, nil, err
41-
}
42-
return pty, device, nil
38+
return ptmx, pts, nil
4339
}
4440

4541
// MatchPty checks that the output matches the expected strings in specified
4642
// order.
47-
func MatchPty(pty containerd.Console, device *os.File, expected ...string) error {
43+
func MatchPty(ptmx *os.File, pts *os.File, expected ...string) error {
4844
var wg sync.WaitGroup
4945
wg.Add(1)
5046
var buffer bytes.Buffer
5147
go func() {
5248
defer wg.Done()
53-
_, _ = io.Copy(&buffer, pty)
49+
_, _ = io.Copy(&buffer, ptmx)
5450
}()
55-
_ = device.Close()
51+
_ = pts.Close()
5652
wg.Wait()
5753

5854
return OrderedMatch(buffer.String(), expected...)

0 commit comments

Comments
 (0)