diff --git a/os/gcmd/gcmd_command.go b/os/gcmd/gcmd_command.go index 50ac66b98..a7d018786 100644 --- a/os/gcmd/gcmd_command.go +++ b/os/gcmd/gcmd_command.go @@ -10,6 +10,7 @@ package gcmd import ( "context" + "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/text/gstr" ) @@ -70,16 +71,35 @@ func CommandFromCtx(ctx context.Context) *Command { // AddCommand adds one or more sub-commands to current command. func (c *Command) AddCommand(commands ...*Command) error { for _, cmd := range commands { - cmd.Name = gstr.Trim(cmd.Name) - if cmd.Name == "" { - return gerror.New("command name should not be empty") + if err := c.doAddCommand(cmd); err != nil { + return err } - cmd.parent = c - c.commands = append(c.commands, cmd) } return nil } +// doAddCommand adds one sub-command to current command. +func (c *Command) doAddCommand(command *Command) error { + command.Name = gstr.Trim(command.Name) + if command.Name == "" { + return gerror.New("command name should not be empty") + } + // Repeated check. + var ( + commandNameSet = gset.NewStrSet() + ) + for _, cmd := range c.commands { + commandNameSet.Add(cmd.Name) + } + if commandNameSet.Contains(command.Name) { + return gerror.Newf(`command "%s" is already added to command "%s"`, command.Name, c.Name) + } + // Add the given command to its sub-commands array. + command.parent = c + c.commands = append(c.commands, command) + return nil +} + // AddObject adds one or more sub-commands to current command using struct object. func (c *Command) AddObject(objects ...interface{}) error { var ( diff --git a/os/gcmd/gcmd_command_object.go b/os/gcmd/gcmd_command_object.go index da33741f5..9308bf8d7 100644 --- a/os/gcmd/gcmd_command_object.go +++ b/os/gcmd/gcmd_command_object.go @@ -308,7 +308,9 @@ func newCommandFromMethod(object interface{}, method reflect.Value) (command *Co func newArgumentsFromInput(object interface{}) (args []Argument, err error) { var ( - fields []gstructs.Field + fields []gstructs.Field + nameSet = gset.NewStrSet() + shortSet = gset.NewStrSet() ) fields, err = gstructs.Fields(gstructs.FieldsInput{ Pointer: object, @@ -340,8 +342,27 @@ func newArgumentsFromInput(object interface{}) (args []Argument, err error) { if v, ok := metaData[tagNameArg]; ok { arg.IsArg = gconv.Bool(v) } + if nameSet.Contains(arg.Name) { + return nil, gerror.Newf( + `argument name "%s" defined in "%s.%s" is already token by other argument`, + arg.Name, reflect.TypeOf(object).String(), field.Name(), + ) + } + nameSet.Add(arg.Name) + + if arg.Short != "" { + if shortSet.Contains(arg.Short) { + return nil, gerror.Newf( + `short argument name "%s" defined in "%s.%s" is already token by other argument`, + arg.Short, reflect.TypeOf(object).String(), field.Name(), + ) + } + shortSet.Add(arg.Short) + } + args = append(args, arg) } + return }