Skip to content

Commit ddcd28c

Browse files
committed
Replace golang.org/x/term with golang.org/x/sys/unix
A subsequent commit will use this to ensure that the user can still interact with the image download prompt while 'skopeo inspect' fetches the image size from the remote registry. To do this, at some point, the terminal device will be put into non-canonical mode input and the echoing of input characters will be disabled to retain full control of the cursor position. Unfortunately, this will require access to the full termios(3) struct that isn't given by golang.org/x/term, and, hence, the code needs to be written using the underlying termios(3) API. This future code will have enough overlap with the IsTerminal API from golang.org/x/term that it doesn't make sense to use a separate module (ie., golang.org/x/term) for it. #752 #1263
1 parent 2149609 commit ddcd28c

File tree

8 files changed

+96
-27
lines changed

8 files changed

+96
-27
lines changed

src/cmd/create.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ import (
2828
"github.com/containers/toolbox/pkg/podman"
2929
"github.com/containers/toolbox/pkg/shell"
3030
"github.com/containers/toolbox/pkg/skopeo"
31+
"github.com/containers/toolbox/pkg/term"
3132
"github.com/containers/toolbox/pkg/utils"
3233
"github.com/docker/go-units"
3334
"github.com/godbus/dbus/v5"
3435
"github.com/sirupsen/logrus"
3536
"github.com/spf13/cobra"
36-
"golang.org/x/term"
3737
)
3838

3939
const (
@@ -449,10 +449,7 @@ func createContainer(container, image, release, authFile string, showCommandToEn
449449
}
450450

451451
s := spinner.New(spinner.CharSets[9], 500*time.Millisecond)
452-
453-
stdoutFd := os.Stdout.Fd()
454-
stdoutFdInt := int(stdoutFd)
455-
if logLevel := logrus.GetLevel(); logLevel < logrus.DebugLevel && term.IsTerminal(stdoutFdInt) {
452+
if logLevel := logrus.GetLevel(); logLevel < logrus.DebugLevel && term.IsTerminal(os.Stdout) {
456453
s.Prefix = fmt.Sprintf("Creating container %s: ", container)
457454
s.Writer = os.Stdout
458455
s.Start()
@@ -731,9 +728,7 @@ func pullImage(image, release, authFile string) (bool, error) {
731728

732729
logrus.Debugf("Pulling image %s", imageFull)
733730

734-
stdoutFd := os.Stdout.Fd()
735-
stdoutFdInt := int(stdoutFd)
736-
if logLevel := logrus.GetLevel(); logLevel < logrus.DebugLevel && term.IsTerminal(stdoutFdInt) {
731+
if logLevel := logrus.GetLevel(); logLevel < logrus.DebugLevel && term.IsTerminal(os.Stdout) {
737732
s := spinner.New(spinner.CharSets[9], 500*time.Millisecond)
738733
s.Prefix = fmt.Sprintf("Pulling %s: ", imageFull)
739734
s.Writer = os.Stdout

src/cmd/list.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright © 2019 – 2022 Red Hat Inc.
2+
* Copyright © 2019 – 2023 Red Hat Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,10 +25,10 @@ import (
2525
"text/tabwriter"
2626

2727
"github.com/containers/toolbox/pkg/podman"
28+
"github.com/containers/toolbox/pkg/term"
2829
"github.com/containers/toolbox/pkg/utils"
2930
"github.com/sirupsen/logrus"
3031
"github.com/spf13/cobra"
31-
"golang.org/x/term"
3232
)
3333

3434
type toolboxContainer struct {
@@ -247,11 +247,9 @@ func listOutput(images []podman.Image, containers []toolboxContainer) {
247247
const defaultColor = "\033[0;00m" // identical to resetColor, but same length as boldGreenColor
248248
const resetColor = "\033[0m"
249249

250-
stdoutFd := os.Stdout.Fd()
251-
stdoutFdInt := int(stdoutFd)
252250
writer := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
253251

254-
if term.IsTerminal(stdoutFdInt) {
252+
if term.IsTerminal(os.Stdout) {
255253
fmt.Fprintf(writer, "%s", defaultColor)
256254
}
257255

@@ -263,7 +261,7 @@ func listOutput(images []podman.Image, containers []toolboxContainer) {
263261
"STATUS",
264262
"IMAGE NAME")
265263

266-
if term.IsTerminal(stdoutFdInt) {
264+
if term.IsTerminal(os.Stdout) {
267265
fmt.Fprintf(writer, "%s", resetColor)
268266
}
269267

@@ -275,7 +273,7 @@ func listOutput(images []podman.Image, containers []toolboxContainer) {
275273
isRunning = container.Status == "running"
276274
}
277275

278-
if term.IsTerminal(stdoutFdInt) {
276+
if term.IsTerminal(os.Stdout) {
279277
var color string
280278
if isRunning {
281279
color = boldGreenColor
@@ -293,7 +291,7 @@ func listOutput(images []podman.Image, containers []toolboxContainer) {
293291
container.Status,
294292
container.Image)
295293

296-
if term.IsTerminal(stdoutFdInt) {
294+
if term.IsTerminal(os.Stdout) {
297295
fmt.Fprintf(writer, "%s", resetColor)
298296
}
299297

src/cmd/run.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ import (
2626

2727
"github.com/containers/toolbox/pkg/podman"
2828
"github.com/containers/toolbox/pkg/shell"
29+
"github.com/containers/toolbox/pkg/term"
2930
"github.com/containers/toolbox/pkg/utils"
3031
"github.com/sirupsen/logrus"
3132
"github.com/spf13/cobra"
32-
"golang.org/x/term"
3333
)
3434

3535
var (
@@ -317,13 +317,7 @@ func runCommandWithFallbacks(container string,
317317
var stderr io.Writer
318318
var ttyNeeded bool
319319

320-
stdinFd := os.Stdin.Fd()
321-
stdinFdInt := int(stdinFd)
322-
323-
stdoutFd := os.Stdout.Fd()
324-
stdoutFdInt := int(stdoutFd)
325-
326-
if term.IsTerminal(stdinFdInt) && term.IsTerminal(stdoutFdInt) {
320+
if term.IsTerminal(os.Stdin) && term.IsTerminal(os.Stdout) {
327321
ttyNeeded = true
328322
if logLevel := logrus.GetLevel(); logLevel >= logrus.DebugLevel {
329323
stderr = os.Stderr

src/go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,4 @@ require (
1414
github.com/spf13/viper v1.10.1
1515
github.com/stretchr/testify v1.7.0
1616
golang.org/x/sys v0.1.0
17-
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
1817
)

src/go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,8 +555,6 @@ golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBc
555555
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
556556
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
557557
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
558-
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
559-
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
560558
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
561559
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
562560
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

src/meson.build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ sources = files(
2424
'pkg/shell/shell.go',
2525
'pkg/shell/shell_test.go',
2626
'pkg/skopeo/skopeo.go',
27+
'pkg/term/term.go',
28+
'pkg/term/term_test.go',
2729
'pkg/utils/libsubid-wrappers.c',
2830
'pkg/utils/errors.go',
2931
'pkg/utils/utils.go',

src/pkg/term/term.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright © 2023 Red Hat Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package term
18+
19+
import (
20+
"os"
21+
22+
"golang.org/x/sys/unix"
23+
)
24+
25+
func GetState(file *os.File) (*unix.Termios, error) {
26+
fileFD := file.Fd()
27+
fileFDInt := int(fileFD)
28+
state, err := unix.IoctlGetTermios(fileFDInt, unix.TCGETS)
29+
return state, err
30+
}
31+
32+
func IsTerminal(file *os.File) bool {
33+
if _, err := GetState(file); err != nil {
34+
return false
35+
}
36+
37+
return true
38+
}

src/pkg/term/term_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright © 2023 Red Hat Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package term
18+
19+
import (
20+
"os"
21+
"testing"
22+
23+
"github.com/stretchr/testify/assert"
24+
)
25+
26+
func TestIsTerminalTemporaryFile(t *testing.T) {
27+
dir := t.TempDir()
28+
file, err := os.CreateTemp(dir, "TestIsTerminalTempFile")
29+
assert.NoError(t, err)
30+
fileName := file.Name()
31+
defer os.Remove(fileName)
32+
defer file.Close()
33+
34+
ok := IsTerminal(file)
35+
assert.False(t, ok)
36+
}
37+
38+
func TestIsTerminalTerminal(t *testing.T) {
39+
file, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
40+
assert.NoError(t, err)
41+
defer file.Close()
42+
43+
ok := IsTerminal(file)
44+
assert.True(t, ok)
45+
}

0 commit comments

Comments
 (0)