Skip to content

Commit b4cc77b

Browse files
authored
Merge pull request #25379 from hashicorp/alisdair/yes
command/login: Require "yes" to confirm
2 parents f6f707c + 779fe37 commit b4cc77b

File tree

7 files changed

+99
-42
lines changed

7 files changed

+99
-42
lines changed

command/login.go

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/hashicorp/terraform-svchost/disco"
2121
"github.com/hashicorp/terraform/command/cliconfig"
2222
"github.com/hashicorp/terraform/httpclient"
23+
"github.com/hashicorp/terraform/terraform"
2324
"github.com/hashicorp/terraform/tfdiags"
2425

2526
uuid "github.com/hashicorp/go-uuid"
@@ -453,12 +454,19 @@ func (c *LoginCommand) interactiveGetTokenByPassword(hostname svchost.Hostname,
453454
c.Ui.Output("\n---------------------------------------------------------------------------------\n")
454455
c.Ui.Output("Terraform must temporarily use your password to request an API token.\nThis password will NOT be saved locally.\n")
455456

456-
username, err := c.Ui.Ask(fmt.Sprintf("Username for %s:", hostname.ForDisplay()))
457+
username, err := c.UIInput().Input(context.Background(), &terraform.InputOpts{
458+
Id: "username",
459+
Query: fmt.Sprintf("Username for %s:", hostname.ForDisplay()),
460+
})
457461
if err != nil {
458462
diags = diags.Append(fmt.Errorf("Failed to request username: %s", err))
459463
return nil, diags
460464
}
461-
password, err := c.Ui.AskSecret(fmt.Sprintf("Password for %s:", username))
465+
password, err := c.UIInput().Input(context.Background(), &terraform.InputOpts{
466+
Id: "password",
467+
Query: fmt.Sprintf("Password for %s:", hostname.ForDisplay()),
468+
Secret: true,
469+
})
462470
if err != nil {
463471
diags = diags.Append(fmt.Errorf("Failed to request password: %s", err))
464472
return nil, diags
@@ -494,6 +502,8 @@ func (c *LoginCommand) interactiveGetTokenByUI(hostname svchost.Hostname, credsC
494502
return "", diags
495503
}
496504

505+
c.Ui.Output("\n---------------------------------------------------------------------------------\n")
506+
497507
tokensURL := url.URL{
498508
Scheme: "https",
499509
Host: service.Hostname(),
@@ -508,6 +518,7 @@ func (c *LoginCommand) interactiveGetTokenByUI(hostname svchost.Hostname, credsC
508518
c.Ui.Output(fmt.Sprintf("Terraform must now open a web browser to the tokens page for %s.\n", hostname.ForDisplay()))
509519
c.Ui.Output(fmt.Sprintf("If a browser does not open this automatically, open the following URL to proceed:\n %s\n", tokensURL.String()))
510520
} else {
521+
log.Printf("[DEBUG] error opening web browser: %s", err)
511522
// Assume we're on a platform where opening a browser isn't possible.
512523
launchBrowserManually = true
513524
}
@@ -533,7 +544,11 @@ func (c *LoginCommand) interactiveGetTokenByUI(hostname svchost.Hostname, credsC
533544
}
534545
}
535546

536-
token, err := c.Ui.AskSecret(fmt.Sprintf(c.Colorize().Color("Token for [bold]%s[reset]:"), hostname.ForDisplay()))
547+
token, err := c.UIInput().Input(context.Background(), &terraform.InputOpts{
548+
Id: "token",
549+
Query: fmt.Sprintf("Token for %s:", hostname.ForDisplay()),
550+
Secret: true,
551+
})
537552
if err != nil {
538553
diags := diags.Append(fmt.Errorf("Failed to retrieve token: %s", err))
539554
return "", diags
@@ -590,20 +605,19 @@ func (c *LoginCommand) interactiveContextConsent(hostname svchost.Hostname, gran
590605
}
591606
}
592607

593-
v, err := c.Ui.Ask("Do you want to proceed? (y/n)")
608+
v, err := c.UIInput().Input(context.Background(), &terraform.InputOpts{
609+
Id: "approve",
610+
Query: "Do you want to proceed?",
611+
Description: `Only 'yes' will be accepted to confirm.`,
612+
})
594613
if err != nil {
595614
// Should not happen because this command checks that input is enabled
596615
// before we get to this point.
597616
diags = diags.Append(err)
598617
return false, diags
599618
}
600619

601-
switch strings.ToLower(v) {
602-
case "y", "yes":
603-
return true, diags
604-
default:
605-
return false, diags
606-
}
620+
return strings.ToLower(v) == "yes", diags
607621
}
608622

609623
func (c *LoginCommand) listenerForCallback(minPort, maxPort uint16) (net.Listener, string, error) {

command/login_test.go

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package command
22

33
import (
4-
"bytes"
54
"context"
65
"io/ioutil"
76
"net/http/httptest"
@@ -34,7 +33,7 @@ func TestLogin(t *testing.T) {
3433
ts := httptest.NewServer(tfeserver.Handler)
3534
defer ts.Close()
3635

37-
loginTestCase := func(test func(t *testing.T, c *LoginCommand, ui *cli.MockUi, inp func(string))) func(t *testing.T) {
36+
loginTestCase := func(test func(t *testing.T, c *LoginCommand, ui *cli.MockUi)) func(t *testing.T) {
3837
return func(t *testing.T) {
3938
t.Helper()
4039
workDir, err := ioutil.TempDir("", "terraform-test-command-login")
@@ -48,15 +47,15 @@ func TestLogin(t *testing.T) {
4847
ctx, cancel := context.WithCancel(context.Background())
4948
defer cancel()
5049

51-
ui := cli.NewMockUi()
50+
// Do not use the NewMockUi initializer here, as we want to delay
51+
// the call to init until after setting up the input mocks
52+
ui := new(cli.MockUi)
53+
5254
browserLauncher := webbrowser.NewMockLauncher(ctx)
5355
creds := cliconfig.EmptyCredentialsSourceForTests(filepath.Join(workDir, "credentials.tfrc.json"))
5456
svcs := disco.NewWithCredentialsSource(creds)
5557
svcs.SetUserAgent(httpclient.TerraformUserAgent(version.String()))
5658

57-
inputBuf := &bytes.Buffer{}
58-
ui.InputReader = inputBuf
59-
6059
svcs.ForceHostServices(svchost.Hostname("app.terraform.io"), map[string]interface{}{
6160
"login.v1": map[string]interface{}{
6261
// On app.terraform.io we use password-based authorization.
@@ -96,16 +95,16 @@ func TestLogin(t *testing.T) {
9695
},
9796
}
9897

99-
test(t, c, ui, func(data string) {
100-
t.Helper()
101-
inputBuf.WriteString(data)
102-
})
98+
test(t, c, ui)
10399
}
104100
}
105101

106-
t.Run("defaulting to app.terraform.io with password flow", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi, inp func(string)) {
107-
// Enter "yes" at the consent prompt, then a username and then a password.
108-
inp("yes\nfoo\nbar\n")
102+
t.Run("defaulting to app.terraform.io with password flow", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi) {
103+
defer testInputMap(t, map[string]string{
104+
"approve": "yes",
105+
"username": "foo",
106+
"password": "bar",
107+
})()
109108
status := c.Run(nil)
110109
if status != 0 {
111110
t.Fatalf("unexpected error code %d\nstderr:\n%s", status, ui.ErrorWriter.String())
@@ -121,9 +120,11 @@ func TestLogin(t *testing.T) {
121120
}
122121
}))
123122

124-
t.Run("example.com with authorization code flow", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi, inp func(string)) {
123+
t.Run("example.com with authorization code flow", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi) {
125124
// Enter "yes" at the consent prompt.
126-
inp("yes\n")
125+
defer testInputMap(t, map[string]string{
126+
"approve": "yes",
127+
})()
127128
status := c.Run([]string{"example.com"})
128129
if status != 0 {
129130
t.Fatalf("unexpected error code %d\nstderr:\n%s", status, ui.ErrorWriter.String())
@@ -139,10 +140,13 @@ func TestLogin(t *testing.T) {
139140
}
140141
}))
141142

142-
t.Run("TFE host without login support", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi, inp func(string)) {
143+
t.Run("TFE host without login support", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi) {
143144
// Enter "yes" at the consent prompt, then paste a token with some
144145
// accidental whitespace.
145-
inp("yes\n good-token \n")
146+
defer testInputMap(t, map[string]string{
147+
"approve": "yes",
148+
"token": " good-token ",
149+
})()
146150
status := c.Run([]string{"tfe.acme.com"})
147151
if status != 0 {
148152
t.Fatalf("unexpected error code %d\nstderr:\n%s", status, ui.ErrorWriter.String())
@@ -158,9 +162,12 @@ func TestLogin(t *testing.T) {
158162
}
159163
}))
160164

161-
t.Run("TFE host without login support, incorrectly pasted token", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi, inp func(string)) {
165+
t.Run("TFE host without login support, incorrectly pasted token", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi) {
162166
// Enter "yes" at the consent prompt, then paste an invalid token.
163-
inp("yes\ngood-tok\n")
167+
defer testInputMap(t, map[string]string{
168+
"approve": "yes",
169+
"token": "good-tok",
170+
})()
164171
status := c.Run([]string{"tfe.acme.com"})
165172
if status != 1 {
166173
t.Fatalf("unexpected error code %d\nstderr:\n%s", status, ui.ErrorWriter.String())
@@ -176,7 +183,7 @@ func TestLogin(t *testing.T) {
176183
}
177184
}))
178185

179-
t.Run("host without login or TFE API support", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi, inp func(string)) {
186+
t.Run("host without login or TFE API support", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi) {
180187
status := c.Run([]string{"unsupported.example.net"})
181188
if status == 0 {
182189
t.Fatalf("successful exit; want error")
@@ -186,4 +193,34 @@ func TestLogin(t *testing.T) {
186193
t.Fatalf("missing expected error message\nwant: %s\nfull output:\n%s", want, got)
187194
}
188195
}))
196+
197+
t.Run("answering no cancels", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi) {
198+
// Enter "no" at the consent prompt
199+
defer testInputMap(t, map[string]string{
200+
"approve": "no",
201+
})()
202+
status := c.Run(nil)
203+
if status != 1 {
204+
t.Fatalf("unexpected error code %d\nstderr:\n%s", status, ui.ErrorWriter.String())
205+
}
206+
207+
if got, want := ui.ErrorWriter.String(), "Login cancelled"; !strings.Contains(got, want) {
208+
t.Fatalf("missing expected error message\nwant: %s\nfull output:\n%s", want, got)
209+
}
210+
}))
211+
212+
t.Run("answering y cancels", loginTestCase(func(t *testing.T, c *LoginCommand, ui *cli.MockUi) {
213+
// Enter "y" at the consent prompt
214+
defer testInputMap(t, map[string]string{
215+
"approve": "y",
216+
})()
217+
status := c.Run(nil)
218+
if status != 1 {
219+
t.Fatalf("unexpected error code %d\nstderr:\n%s", status, ui.ErrorWriter.String())
220+
}
221+
222+
if got, want := ui.ErrorWriter.String(), "Login cancelled"; !strings.Contains(got, want) {
223+
t.Fatalf("missing expected error message\nwant: %s\nfull output:\n%s", want, got)
224+
}
225+
}))
189226
}

command/ui_input.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ import (
1515
"sync/atomic"
1616
"unicode"
1717

18+
"github.com/bgentry/speakeasy"
1819
"github.com/hashicorp/terraform/terraform"
20+
"github.com/mattn/go-isatty"
1921
"github.com/mitchellh/colorstring"
2022
)
2123

@@ -128,8 +130,14 @@ func (i *UIInput) Input(ctx context.Context, opts *terraform.InputOpts) (string,
128130
}
129131
defer atomic.CompareAndSwapInt32(&i.listening, 1, 0)
130132

131-
buf := bufio.NewReader(r)
132-
line, err := buf.ReadString('\n')
133+
var line string
134+
var err error
135+
if opts.Secret && isatty.IsTerminal(os.Stdin.Fd()) {
136+
line, err = speakeasy.Ask("")
137+
} else {
138+
buf := bufio.NewReader(r)
139+
line, err = buf.ReadString('\n')
140+
}
133141
if err != nil {
134142
log.Printf("[ERR] UIInput scan err: %s", err)
135143
}

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ require (
2121
github.com/armon/go-radix v1.0.0 // indirect
2222
github.com/aws/aws-sdk-go v1.31.9
2323
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
24+
github.com/bgentry/speakeasy v0.1.0
2425
github.com/blang/semver v3.5.1+incompatible
2526
github.com/bmatcuk/doublestar v1.1.5
2627
github.com/boltdb/bolt v1.3.1 // indirect
@@ -90,6 +91,7 @@ require (
9091
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 // indirect
9192
github.com/masterzen/winrm v0.0.0-20200615185753-c42b5136ff88
9293
github.com/mattn/go-colorable v0.1.1
94+
github.com/mattn/go-isatty v0.0.5
9395
github.com/mattn/go-shellwords v1.0.4
9496
github.com/miekg/dns v1.0.8 // indirect
9597
github.com/mitchellh/cli v1.0.0

go.sum

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,6 @@ github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9 h1:SmVbOZFWAly
363363
github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
364364
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 h1:2ZKn+w/BJeL43sCxI2jhPLRv73oVVOjEKZjKkflyqxg=
365365
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
366-
github.com/masterzen/winrm v0.0.0-20190223112901-5e5c9a7fe54b h1:/1RFh2SLCJ+tEnT73+Fh5R2AO89sQqs8ba7o+hx1G0Y=
367-
github.com/masterzen/winrm v0.0.0-20190223112901-5e5c9a7fe54b/go.mod h1:wr1VqkwW0AB5JS0QLy5GpVMS9E3VtRoSYXUYyVk46KY=
368366
github.com/masterzen/winrm v0.0.0-20200615185753-c42b5136ff88 h1:cxuVcCvCLD9yYDbRCWw0jSgh1oT6P6mv3aJDKK5o7X4=
369367
github.com/masterzen/winrm v0.0.0-20200615185753-c42b5136ff88/go.mod h1:a2HXwefeat3evJHxFXSayvRHpYEPJYtErl4uIzfaUqY=
370368
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
@@ -436,8 +434,6 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
436434
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
437435
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
438436
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
439-
github.com/packer-community/winrmcp v0.0.0-20180102160824-81144009af58 h1:m3CEgv3ah1Rhy82L+c0QG/U3VyY1UsvsIdkh0/rU97Y=
440-
github.com/packer-community/winrmcp v0.0.0-20180102160824-81144009af58/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk=
441437
github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db h1:9uViuKtx1jrlXLBW/pMnhOfzn3iSEdLase/But/IZRU=
442438
github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk=
443439
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs=
@@ -549,8 +545,6 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
549545
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
550546
golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
551547
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
552-
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw=
553-
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
554548
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
555549
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
556550
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -587,8 +581,6 @@ golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLL
587581
golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
588582
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
589583
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
590-
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
591-
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
592584
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
593585
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
594586
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -623,8 +615,6 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7w
623615
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
624616
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 h1:ZBzSG/7F4eNKz2L3GE9o300RX0Az1Bw5HF7PDraD+qU=
625617
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
626-
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
627-
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
628618
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
629619
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
630620
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

terraform/ui_input.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,8 @@ type InputOpts struct {
2525

2626
// Default will be the value returned if no data is entered.
2727
Default string
28+
29+
// Secret should be true if we are asking for sensitive input.
30+
// If attached to a TTY, Terraform will disable echo.
31+
Secret bool
2832
}

vendor/modules.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ github.com/aws/aws-sdk-go/service/sts/stsiface
168168
# github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d
169169
github.com/bgentry/go-netrc/netrc
170170
# github.com/bgentry/speakeasy v0.1.0
171+
## explicit
171172
github.com/bgentry/speakeasy
172173
# github.com/blang/semver v3.5.1+incompatible
173174
## explicit
@@ -476,6 +477,7 @@ github.com/masterzen/winrm/soap
476477
## explicit
477478
github.com/mattn/go-colorable
478479
# github.com/mattn/go-isatty v0.0.5
480+
## explicit
479481
github.com/mattn/go-isatty
480482
# github.com/mattn/go-shellwords v1.0.4
481483
## explicit

0 commit comments

Comments
 (0)