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

Add support for ignoring parse errors #662

Merged
merged 1 commit into from
Mar 31, 2018
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import (
flag "github.com/spf13/pflag"
)

// FParseErrWhitelist configures Flag parse errors to be ignored
type FParseErrWhitelist flag.ParseErrorsWhitelist

// Command is just that, a command for your application.
// E.g. 'go run ...' - 'run' is the command. Cobra requires
// you to define the usage and description as part of your command
Expand Down Expand Up @@ -137,6 +140,9 @@ type Command struct {
// TraverseChildren parses flags on all parents before executing child command.
TraverseChildren bool

//FParseErrWhitelist flag parse errors to be ignored
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A minor style suggestion. There should be a space after the //, since this is a normal comment for humans (like the one above).

See https://dmitri.shuralyov.com/idiomatic-go#comments-for-humans-always-have-a-single-space-after-the-slashes for full rationale.

FParseErrWhitelist FParseErrWhitelist

// commands is the list of commands supported by this program.
commands []*Command
// parent is a parent command for this command.
Expand Down Expand Up @@ -1463,6 +1469,10 @@ func (c *Command) ParseFlags(args []string) error {
}
beforeErrorBufLen := c.flagErrorBuf.Len()
c.mergePersistentFlags()

//do it here after merging all flags and just before parse
c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)

err := c.Flags().Parse(args)
// Print warnings if they occurred (e.g. deprecated flag messages).
if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil {
Expand Down
105 changes: 105 additions & 0 deletions command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1626,3 +1626,108 @@ func TestCalledAs(t *testing.T) {
t.Run(name, tc.test)
}
}

func TestFParseErrWhitelistBackwardCompatibility(t *testing.T) {
c := &Command{Use: "c", Run: emptyRun}
c.Flags().BoolP("boola", "a", false, "a boolean flag")

output, err := executeCommand(c, "c", "-a", "--unknown", "flag")
if err == nil {
t.Error("expected unknown flag error")
}
checkStringContains(t, output, "unknown flag: --unknown")
}

func TestFParseErrWhitelistSameCommand(t *testing.T) {
c := &Command{
Use: "c",
Run: emptyRun,
FParseErrWhitelist: FParseErrWhitelist{
UnknownFlags: true,
},
}
c.Flags().BoolP("boola", "a", false, "a boolean flag")

_, err := executeCommand(c, "c", "-a", "--unknown", "flag")
if err != nil {
t.Error("unexpected error: ", err)
}
}

func TestFParseErrWhitelistParentCommand(t *testing.T) {
root := &Command{
Use: "root",
Run: emptyRun,
FParseErrWhitelist: FParseErrWhitelist{
UnknownFlags: true,
},
}

c := &Command{
Use: "child",
Run: emptyRun,
}
c.Flags().BoolP("boola", "a", false, "a boolean flag")

root.AddCommand(c)

output, err := executeCommand(root, "child", "-a", "--unknown", "flag")
if err == nil {
t.Error("expected unknown flag error")
}
checkStringContains(t, output, "unknown flag: --unknown")
}

func TestFParseErrWhitelistChildCommand(t *testing.T) {
root := &Command{
Use: "root",
Run: emptyRun,
}

c := &Command{
Use: "child",
Run: emptyRun,
FParseErrWhitelist: FParseErrWhitelist{
UnknownFlags: true,
},
}
c.Flags().BoolP("boola", "a", false, "a boolean flag")

root.AddCommand(c)

_, err := executeCommand(root, "child", "-a", "--unknown", "flag")
if err != nil {
t.Error("unexpected error: ", err.Error())
}
}

func TestFParseErrWhitelistSiblingCommand(t *testing.T) {
root := &Command{
Use: "root",
Run: emptyRun,
}

c := &Command{
Use: "child",
Run: emptyRun,
FParseErrWhitelist: FParseErrWhitelist{
UnknownFlags: true,
},
}
c.Flags().BoolP("boola", "a", false, "a boolean flag")

s := &Command{
Use: "sibling",
Run: emptyRun,
}
s.Flags().BoolP("boolb", "b", false, "a boolean flag")

root.AddCommand(c)
root.AddCommand(s)

output, err := executeCommand(root, "sibling", "-b", "--unknown", "flag")
if err == nil {
t.Error("expected unknown flag error")
}
checkStringContains(t, output, "unknown flag: --unknown")
}