1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-08-06 19:44:01 +08:00

commands: Removed Command#Register and exported Subcommands so subcommands can be defined statically

This commit is contained in:
Matt Bell
2014-10-21 18:05:54 -07:00
parent 6ff98df9c1
commit ca44d0da2c

View File

@ -15,37 +15,17 @@ var log = u.Logger("command")
type Function func(Request, Response) type Function func(Request, Response)
// Command is a runnable command, with input arguments and options (flags). // Command is a runnable command, with input arguments and options (flags).
// It can also have subcommands, to group units of work into sets. // It can also have Subcommands, to group units of work into sets.
type Command struct { type Command struct {
Help string Help string
Options []Option Options []Option
Run Function Run Function
Subcommands map[string]*Command
subcommands map[string]*Command
} }
// ErrNotCallable signals a command that cannot be called. // ErrNotCallable signals a command that cannot be called.
var ErrNotCallable = errors.New("This command can't be called directly. Try one of its subcommands.") var ErrNotCallable = errors.New("This command can't be called directly. Try one of its subcommands.")
// Register adds a subcommand
func (c *Command) Register(id string, sub *Command) error {
if c.subcommands == nil {
c.subcommands = make(map[string]*Command)
}
// check for duplicate option names (only checks downwards)
if err := checkOptionClashes(globalCommand, c, sub); err != nil {
return err
}
if _, found := c.subcommands[id]; found {
return fmt.Errorf("There is already a subcommand registered with id '%s'", id)
}
c.subcommands[id] = sub
return nil
}
// Call invokes the command for the given Request // Call invokes the command for the given Request
func (c *Command) Call(req Request) Response { func (c *Command) Call(req Request) Response {
res := NewResponse(req) res := NewResponse(req)
@ -138,48 +118,5 @@ func (c *Command) GetOptions(path []string) (map[string]Option, error) {
// Subcommand returns the subcommand with the given id // Subcommand returns the subcommand with the given id
func (c *Command) Subcommand(id string) *Command { func (c *Command) Subcommand(id string) *Command {
return c.subcommands[id] return c.Subcommands[id]
}
// AddOptionNames returns a map of all command options names, and the command
// they belong to. Will error if names clash in the command hierarchy.
func AddOptionNames(c *Command, names map[string]*Command) error {
for _, opt := range c.Options {
for _, name := range opt.Names {
if c2, found := names[name]; found {
// option can be reused in same command, but more often than not
// the clash will be across commands so error out with that, as
// commands tell us where the problem is
errstr := "Option name ('%s') used multiple times (%v, %v)"
return fmt.Errorf(errstr, c2, c)
}
// mark the name as in use
names[name] = c
}
}
// for every subcommand, recurse
for _, c2 := range c.subcommands {
if err := AddOptionNames(c2, names); err != nil {
return err
}
}
return nil
}
// checkOptionClashes checks all command option names for clashes
func checkOptionClashes(cmds ...*Command) error {
names := map[string]*Command{}
for _, c := range cmds {
if err := AddOptionNames(c, names); err != nil {
return err
}
}
return nil
} }