Skip to content

Commit 0860150

Browse files
author
Bobby
committed
Reject v1-style flag aliases
1 parent fb1c26b commit 0860150

4 files changed

Lines changed: 86 additions & 2 deletions

File tree

app_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,8 @@ func ExampleApp_Run_bashComplete_withLongFlag() {
283283
Aliases: []string{"x"},
284284
},
285285
&StringFlag{
286-
Name: "some-flag,s",
286+
Name: "some-flag",
287+
Aliases: []string{"s"},
287288
},
288289
&StringFlag{
289290
Name: "similar-flag",

context_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ func TestCheckRequiredFlags(t *testing.T) {
626626
expectedAnError: true,
627627
expectedErrorContents: []string{"Required flag \"names\" not set"},
628628
flags: []Flag{
629-
&StringSliceFlag{Name: "names, n", Required: true},
629+
&StringSliceFlag{Name: "names", Aliases: []string{"n"}, Required: true},
630630
},
631631
},
632632
{

flag.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"io"
88
"os"
9+
"reflect"
910
"regexp"
1011
"runtime"
1112
"strings"
@@ -171,6 +172,9 @@ func flagSet(name string, flags []Flag, spec separatorSpec) (*flag.FlagSet, erro
171172
set := flag.NewFlagSet(name, flag.ContinueOnError)
172173

173174
for _, f := range flags {
175+
if err := validateFlagName(f); err != nil {
176+
return nil, err
177+
}
174178
if c, ok := f.(customizedSeparator); ok {
175179
c.WithSeparatorSpec(spec)
176180
}
@@ -182,6 +186,35 @@ func flagSet(name string, flags []Flag, spec separatorSpec) (*flag.FlagSet, erro
182186
return set, nil
183187
}
184188

189+
func validateFlagName(f Flag) error {
190+
name, ok := rawFlagName(f)
191+
if !ok || !commaWhitespace.MatchString(name) {
192+
return nil
193+
}
194+
195+
return fmt.Errorf("invalid flag name %q: use Aliases instead of v1-style comma or space separated names", name)
196+
}
197+
198+
func rawFlagName(f Flag) (string, bool) {
199+
v := reflect.ValueOf(f)
200+
for v.IsValid() && v.Kind() == reflect.Pointer {
201+
if v.IsNil() {
202+
return "", false
203+
}
204+
v = v.Elem()
205+
}
206+
if !v.IsValid() || v.Kind() != reflect.Struct {
207+
return "", false
208+
}
209+
210+
field := v.FieldByName("Name")
211+
if !field.IsValid() || field.Kind() != reflect.String {
212+
return "", false
213+
}
214+
215+
return field.String(), true
216+
}
217+
185218
func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
186219
switch ff.Value.(type) {
187220
case Serializer:

flag_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,56 @@ func TestBoolFlagApply_SetsCount(t *testing.T) {
8888
expect(t, count, 3)
8989
}
9090

91+
func TestAppRunRejectsV1StyleFlagNames(t *testing.T) {
92+
tests := []string{
93+
"config, cfg",
94+
"config cfg",
95+
}
96+
97+
for _, name := range tests {
98+
t.Run(name, func(t *testing.T) {
99+
app := newTestApp()
100+
app.Flags = []Flag{
101+
&StringFlag{Name: name},
102+
}
103+
104+
err := app.Run([]string{"app"})
105+
if err == nil {
106+
t.Fatal("expected invalid flag name error")
107+
}
108+
if !strings.Contains(err.Error(), "invalid flag name") {
109+
t.Fatalf("expected invalid flag name error, got %q", err)
110+
}
111+
if !strings.Contains(err.Error(), name) {
112+
t.Fatalf("expected error to mention %q, got %q", name, err)
113+
}
114+
if !strings.Contains(err.Error(), "Aliases") {
115+
t.Fatalf("expected error to point to Aliases, got %q", err)
116+
}
117+
})
118+
}
119+
}
120+
121+
func TestCommandRunRejectsV1StyleFlagNames(t *testing.T) {
122+
app := newTestApp()
123+
app.Commands = []*Command{
124+
{
125+
Name: "serve",
126+
Flags: []Flag{
127+
&BoolFlag{Name: "verbose, v"},
128+
},
129+
},
130+
}
131+
132+
err := app.Run([]string{"app", "serve"})
133+
if err == nil {
134+
t.Fatal("expected invalid flag name error")
135+
}
136+
if !strings.Contains(err.Error(), "verbose, v") {
137+
t.Fatalf("expected error to mention invalid flag name, got %q", err)
138+
}
139+
}
140+
91141
func TestBoolFlagCountFromContext(t *testing.T) {
92142

93143
boolCountTests := []struct {

0 commit comments

Comments
 (0)