Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a small utility method to display a warnings. #16441

Merged
merged 5 commits into from Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog/16441.txt
@@ -0,0 +1,3 @@
```release-note:improvement
cli: CLI commands will print a warning if flags will be ignored because they are passed after positional arguments.
```
16 changes: 13 additions & 3 deletions command/base.go
Expand Up @@ -549,6 +549,7 @@ type FlagSets struct {
mainSet *flag.FlagSet
hiddens map[string]struct{}
completions complete.Flags
ui cli.Ui
}

// NewFlagSets creates a new flag sets.
Expand All @@ -564,6 +565,7 @@ func NewFlagSets(ui cli.Ui) *FlagSets {
mainSet: mainSet,
hiddens: make(map[string]struct{}),
completions: complete.Flags{},
ui: ui,
}
}

Expand All @@ -582,8 +584,16 @@ func (f *FlagSets) Completions() complete.Flags {
}

// Parse parses the given flags, returning any errors.
// Warnings, if any, regarding the arguments format are sent to stdout
func (f *FlagSets) Parse(args []string) error {
return f.mainSet.Parse(args)
err := f.mainSet.Parse(args)

warnings := generateFlagWarnings(f.Args())
if warnings != "" {
f.ui.Warn(warnings)
}

return err
}

// Parsed reports whether the command-line flags have been parsed.
Expand All @@ -603,10 +613,10 @@ func (f *FlagSets) Visit(fn func(*flag.Flag)) {
}

// Help builds custom help for this command, grouping by flag set.
func (fs *FlagSets) Help() string {
func (f *FlagSets) Help() string {
var out bytes.Buffer

for _, set := range fs.flagSets {
for _, set := range f.flagSets {
printFlagTitle(&out, set.name+":")
set.VisitAll(func(f *flag.Flag) {
// Skip any hidden flags
Expand Down
16 changes: 16 additions & 0 deletions command/base_helpers.go
Expand Up @@ -292,3 +292,19 @@ func parseFlagFile(raw string) (string, error) {

return raw, nil
}

func generateFlagWarnings(args []string) string {
var trailingFlags []string
for _, arg := range args {
if strings.HasPrefix(arg, "-") {
trailingFlags = append(trailingFlags, arg)
}
}

if len(trailingFlags) > 0 {
return fmt.Sprintf("Flags must be provided before positional arguments. "+
"The following arguments will not be parsed as flags: [%s]", strings.Join(trailingFlags, ","))
} else {
return ""
}
}
46 changes: 46 additions & 0 deletions command/base_helpers_test.go
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"io/ioutil"
"os"
"strings"
"testing"
"time"
)
Expand Down Expand Up @@ -209,3 +210,48 @@ func TestParseFlagFile(t *testing.T) {
})
}
}

func TestArgWarnings(t *testing.T) {
t.Parallel()

cases := []struct {
args []string
expected string
}{
{
[]string{"a", "b", "c"},
"",
},
{
[]string{"a", "-b"},
"-b",
},
{
[]string{"a", "--b"},
"--b",
},
{
[]string{"a-b", "-c"},
"-c",
},
{
[]string{"a", "-b-c"},
"-b-c",
},
{
[]string{"-a", "b"},
"-a",
},
}

for _, tc := range cases {
tc := tc

t.Run(tc.expected, func(t *testing.T) {
warnings := generateFlagWarnings(tc.args)
if !strings.Contains(warnings, tc.expected) {
t.Fatalf("expected %s to contain %s", warnings, tc.expected)
}
})
}
}