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

Fix:(issue_1930) Fix for invalid bool counts #1941

Merged
merged 3 commits into from
Jul 1, 2024
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
6 changes: 0 additions & 6 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -800,12 +800,6 @@ func (cmd *Command) parseFlags(args Args) (Args, error) {
return cmd.Args(), err
}

tracef("normalizing flags (cmd=%[1]q)", cmd.Name)

if err := normalizeFlags(cmd.Flags, cmd.flagSet); err != nil {
return cmd.Args(), err
}

tracef("done parsing flags (cmd=%[1]q)", cmd.Name)

return cmd.Args(), nil
Expand Down
63 changes: 53 additions & 10 deletions command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3204,17 +3204,60 @@ func TestCommand_Bool(t *testing.T) {
}

func TestCommand_Value(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int("myflag", 12, "doc")
parentSet := flag.NewFlagSet("test", 0)
parentSet.Int("top-flag", 13, "doc")
pCmd := &Command{flagSet: parentSet}
cmd := &Command{flagSet: set, parent: pCmd}
subCmd := &Command{
Name: "test",
Flags: []Flag{
&IntFlag{
Name: "myflag",
Usage: "doc",
Aliases: []string{"m", "mf"},
},
},
Action: func(ctx context.Context, c *Command) error {
return nil
},
}

r := require.New(t)
r.Equal(12, cmd.Value("myflag"))
r.Equal(13, cmd.Value("top-flag"))
r.Nil(cmd.Value("unknown-flag"))
cmd := &Command{
Flags: []Flag{
&IntFlag{
Name: "top-flag",
Usage: "doc",
Aliases: []string{"t", "tf"},
},
},
Commands: []*Command{
subCmd,
},
}
t.Run("flag name", func(t *testing.T) {
r := require.New(t)
err := cmd.Run(buildTestContext(t), []string{"main", "--top-flag", "13", "test", "--myflag", "14"})

r.NoError(err)
r.Equal(int64(13), cmd.Value("top-flag"))
r.Equal(int64(13), cmd.Value("t"))
r.Equal(int64(13), cmd.Value("tf"))

r.Equal(int64(14), subCmd.Value("myflag"))
r.Equal(int64(14), subCmd.Value("m"))
r.Equal(int64(14), subCmd.Value("mf"))
})

t.Run("flag aliases", func(t *testing.T) {
r := require.New(t)
err := cmd.Run(buildTestContext(t), []string{"main", "-tf", "15", "test", "-m", "16"})

r.NoError(err)
r.Equal(int64(15), cmd.Value("top-flag"))
r.Equal(int64(15), cmd.Value("t"))
r.Equal(int64(15), cmd.Value("tf"))

r.Equal(int64(16), subCmd.Value("myflag"))
r.Equal(int64(16), subCmd.Value("m"))
r.Equal(int64(16), subCmd.Value("mf"))
r.Nil(cmd.Value("unknown-flag"))
})
}

func TestCommand_Value_InvalidFlagAccessHandler(t *testing.T) {
Expand Down
43 changes: 0 additions & 43 deletions flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package cli

import (
"context"
"errors"
"flag"
"fmt"
"io"
Expand Down Expand Up @@ -198,48 +197,6 @@ func newFlagSet(name string, flags []Flag) (*flag.FlagSet, error) {
return set, nil
}

func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
switch ff.Value.(type) {
case Serializer:
_ = set.Set(name, ff.Value.(Serializer).Serialize())
default:
_ = set.Set(name, ff.Value.String())
}
}

func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
visited := make(map[string]bool)
set.Visit(func(f *flag.Flag) {
visited[f.Name] = true
})
for _, f := range flags {
parts := f.Names()
if len(parts) == 1 {
continue
}
var ff *flag.Flag
for _, name := range parts {
name = strings.Trim(name, " ")
if visited[name] {
if ff != nil {
return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
}
ff = set.Lookup(name)
}
}
if ff == nil {
continue
}
for _, name := range parts {
name = strings.Trim(name, " ")
if !visited[name] {
copyFlag(name, ff, set)
}
}
}
return nil
}

func visibleFlags(fl []Flag) []Flag {
var visible []Flag
for _, f := range fl {
Expand Down
28 changes: 19 additions & 9 deletions flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,28 +83,38 @@ func TestBoolFlagCountFromCommand(t *testing.T) {
expectedCount int
}{
{
input: []string{"-tf", "-w", "-huh"},
input: []string{"main", "-tf", "-w", "-huh"},
expectedVal: true,
expectedCount: 3,
},
{
input: []string{},
input: []string{"main", "-huh"},
expectedVal: true,
expectedCount: 1,
},
{
input: []string{"main"},
expectedVal: false,
expectedCount: 0,
},
}

bf := &BoolFlag{Name: "tf", Aliases: []string{"w", "huh"}}
for _, bct := range boolCountTests {
set := flag.NewFlagSet("test", 0)
cmd := &Command{flagSet: set}
tf := &BoolFlag{Name: "tf", Aliases: []string{"w", "huh"}}
cmd := &Command{
Flags: []Flag{
bf,
},
}
r := require.New(t)

r.NoError(tf.Apply(set))
r.NoError(set.Parse(bct.input))
r.NoError(cmd.Run(buildTestContext(t), bct.input))

r.Equal(bct.expectedVal, tf.Get(cmd))
r.Equal(bct.expectedCount, cmd.Count("tf"))
r.Equal(bct.expectedVal, cmd.Value(bf.Name))
r.Equal(bct.expectedCount, cmd.Count(bf.Name))
for _, alias := range bf.Aliases {
r.Equal(bct.expectedCount, cmd.Count(alias))
}
}
}

Expand Down
Loading