Skip to content

Commit 3a02c88

Browse files
refactor: move --no-tty out of option.Common (#1699)
Signed-off-by: Xiaoxuan Wang <xiaoxuanwang@microsoft.com>
1 parent 16e4682 commit 3a02c88

File tree

16 files changed

+200
-164
lines changed

16 files changed

+200
-164
lines changed

cmd/oras/internal/option/common.go

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,55 +16,24 @@ limitations under the License.
1616
package option
1717

1818
import (
19-
"os"
20-
2119
"github.com/spf13/cobra"
2220
"github.com/spf13/pflag"
23-
"golang.org/x/term"
2421
"oras.land/oras/cmd/oras/internal/output"
2522
)
2623

27-
const NoTTYFlag = "no-tty"
28-
2924
// Common option struct.
3025
type Common struct {
3126
Printer *output.Printer
32-
TTY *os.File
3327
Debug bool
34-
35-
noTTY bool
3628
}
3729

3830
// ApplyFlags applies flags to a command flag set.
3931
func (opts *Common) ApplyFlags(fs *pflag.FlagSet) {
4032
fs.BoolVarP(&opts.Debug, "debug", "d", false, "output debug logs (implies --no-tty)")
41-
fs.BoolVarP(&opts.noTTY, NoTTYFlag, "", false, "[Preview] do not show progress output")
4233
}
4334

4435
// Parse gets target options from user input.
4536
func (opts *Common) Parse(cmd *cobra.Command) error {
4637
opts.Printer = output.NewPrinter(cmd.OutOrStdout(), cmd.OutOrStderr())
47-
// use STDERR as TTY output since STDOUT is reserved for pipeable output
48-
return opts.parseTTY(os.Stderr)
49-
}
50-
51-
// parseTTY gets target options from user input.
52-
func (opts *Common) parseTTY(f *os.File) error {
53-
if !opts.noTTY {
54-
if opts.Debug {
55-
opts.noTTY = true
56-
} else if term.IsTerminal(int(f.Fd())) {
57-
opts.TTY = f
58-
}
59-
}
6038
return nil
6139
}
62-
63-
// UpdateTTY updates the TTY value, given the status of --no-tty flag and output
64-
// path value.
65-
func (opts *Common) UpdateTTY(flagPresent bool, toSTDOUT bool) {
66-
ttyEnforced := flagPresent && !opts.noTTY
67-
if opts.noTTY || (toSTDOUT && !ttyEnforced) {
68-
opts.TTY = nil
69-
}
70-
}

cmd/oras/internal/option/common_test.go

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

cmd/oras/internal/option/common_unix_test.go

Lines changed: 0 additions & 47 deletions
This file was deleted.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
Copyright The ORAS Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
16+
package option
17+
18+
import (
19+
"os"
20+
21+
"github.com/spf13/cobra"
22+
"github.com/spf13/pflag"
23+
"golang.org/x/term"
24+
)
25+
26+
const NoTTYFlag = "no-tty"
27+
28+
// Terminal option struct.
29+
type Terminal struct {
30+
TTY *os.File
31+
32+
noTTY bool
33+
ttyEnforced bool
34+
}
35+
36+
// ApplyFlags applies flags to a command flag set.
37+
func (opts *Terminal) ApplyFlags(fs *pflag.FlagSet) {
38+
fs.BoolVarP(&opts.noTTY, NoTTYFlag, "", false, "[Preview] disable progress bars")
39+
}
40+
41+
// Parse parses the input notty flag.
42+
func (opts *Terminal) Parse(cmd *cobra.Command) error {
43+
opts.ttyEnforced = cmd.Flags().Changed(NoTTYFlag) && !opts.noTTY
44+
// use STDERR as TTY output since STDOUT is reserved for pipeable output
45+
if !opts.noTTY {
46+
f := os.Stderr
47+
if term.IsTerminal(int(f.Fd())) {
48+
opts.TTY = f
49+
}
50+
}
51+
return nil
52+
}
53+
54+
// DisableTTY updates the TTY value, given the status of --debug flag, --no-tty flag and output
55+
// path value.TTY value is set to nil if
56+
// 1. --no-tty flag is set to true
57+
// 2. --debug flag is used
58+
// 3. output path is set to stdout and --no-tty flag is not explicitly set to false
59+
// (i.e. not --no-tty=false)
60+
func (opts *Terminal) DisableTTY(debugEnabled, toSTDOUT bool) {
61+
if debugEnabled || opts.noTTY || (toSTDOUT && !opts.ttyEnforced) {
62+
opts.TTY = nil
63+
}
64+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//go:build freebsd || linux || netbsd || openbsd || solaris
2+
3+
/*
4+
Copyright The ORAS Authors.
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
package option
19+
20+
import (
21+
"os"
22+
"reflect"
23+
"testing"
24+
25+
"github.com/spf13/cobra"
26+
"oras.land/oras/internal/testutils"
27+
)
28+
29+
func TestTerminal_Parse(t *testing.T) {
30+
_, device, err := testutils.NewPty()
31+
if err != nil {
32+
t.Fatal(err)
33+
}
34+
defer device.Close()
35+
opts := Terminal{
36+
noTTY: false,
37+
TTY: device,
38+
}
39+
// TTY output
40+
if err := opts.Parse(&cobra.Command{}); err != nil {
41+
t.Errorf("unexpected error with TTY output: %v", err)
42+
}
43+
}
44+
45+
func TestTerminal_DisableTTY(t *testing.T) {
46+
testTTY := &os.File{}
47+
tests := []struct {
48+
name string
49+
debug bool
50+
toSTDOUT bool
51+
noTTY bool
52+
ttyEnforced bool
53+
expectedTTY *os.File
54+
}{
55+
{
56+
"output to STDOUT, --no-tty flag not used, reset TTY", false, false, true, false, nil,
57+
},
58+
{
59+
"output to STDOUT, --no-tty set to true, reset TTY", false, true, true, true, nil,
60+
},
61+
{
62+
"output to STDOUT, --no-tty set to false", false, true, false, true, testTTY,
63+
},
64+
{
65+
"not output to STDOUT, --no-tty flag not used", false, false, false, false, testTTY,
66+
},
67+
{
68+
"not output to STDOUT, --no-tty set to true, reset TTY", false, false, true, false, nil,
69+
},
70+
{
71+
"not output to STDOUT, --no-tty set to false", false, false, false, true, testTTY,
72+
},
73+
{
74+
"debug enabled, --no-tty flag is not used", true, false, false, false, nil,
75+
},
76+
}
77+
for _, tt := range tests {
78+
t.Run(tt.name, func(t *testing.T) {
79+
opts := &Terminal{
80+
TTY: testTTY,
81+
noTTY: tt.noTTY,
82+
ttyEnforced: tt.ttyEnforced,
83+
}
84+
opts.DisableTTY(tt.debug, tt.toSTDOUT)
85+
if !reflect.DeepEqual(opts.TTY, tt.expectedTTY) {
86+
t.Fatalf("tt.TTY got %v, want %v", opts.TTY, tt.expectedTTY)
87+
}
88+
})
89+
}
90+
}

cmd/oras/root/attach.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type attachOptions struct {
4141
option.Target
4242
option.Format
4343
option.Platform
44+
option.Terminal
4445

4546
artifactType string
4647
concurrency int
@@ -97,6 +98,7 @@ Example - Attach file to the manifest tagged 'v1' in an OCI image layout folder
9798
opts.FileRefs = args[1:]
9899
err := option.Parse(cmd, &opts)
99100
if err == nil {
101+
opts.DisableTTY(opts.Debug, false)
100102
if err = opts.EnsureReferenceNotEmpty(cmd, true); err == nil {
101103
return nil
102104
}

cmd/oras/root/blob/fetch.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type fetchBlobOptions struct {
4040
option.Descriptor
4141
option.Pretty
4242
option.Target
43+
option.Terminal
4344

4445
outputPath string
4546
}
@@ -79,11 +80,11 @@ Example - Fetch and print a blob from OCI image layout archive file 'layout.tar'
7980
return errors.New("`--output -` cannot be used with `--descriptor` at the same time")
8081
}
8182
opts.RawReference = args[0]
82-
err := option.Parse(cmd, &opts)
83-
if err == nil {
84-
opts.UpdateTTY(cmd.Flags().Changed(option.NoTTYFlag), opts.outputPath == "-")
83+
if err := option.Parse(cmd, &opts); err != nil {
84+
return err
8585
}
86-
return err
86+
opts.DisableTTY(opts.Debug, opts.outputPath == "-")
87+
return nil
8788
},
8889
Aliases: []string{"get"},
8990
RunE: func(cmd *cobra.Command, args []string) error {

cmd/oras/root/blob/fetch_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func Test_fetchBlobOptions_doFetch(t *testing.T) {
5353
}
5454
var opts fetchBlobOptions
5555
opts.Reference = tag
56-
opts.Common.TTY = device
56+
opts.TTY = device
5757
opts.outputPath = t.TempDir() + "/test"
5858
// test
5959
_, err = opts.doFetch(ctx, src)

0 commit comments

Comments
 (0)