From 5b18844c063b9dc344046a98f30e5f70d05aee0c Mon Sep 17 00:00:00 2001
From: Matt Bell <mappum@gmail.com>
Date: Thu, 9 Oct 2014 13:39:13 -0700
Subject: [PATCH] commands: Check for option name collisions

---
 commands/command.go | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/commands/command.go b/commands/command.go
index d118d780e..66439af9e 100644
--- a/commands/command.go
+++ b/commands/command.go
@@ -19,7 +19,13 @@ func (c *Command) Register(id string, sub *Command) error {
     c.subcommands = make(map[string]*Command)
   }
 
-  // TODO: check for duplicate option names
+  // check for duplicate option names (only checks downwards)
+  names := make(map[string]bool)
+  c.checkOptions(names)
+  err := sub.checkOptions(names)
+  if err != nil {
+    return err
+  }
 
   if _, ok := c.subcommands[id]; ok {
     return fmt.Errorf("There is already a subcommand registered with id '%s'", id)
@@ -83,3 +89,23 @@ func (c *Command) Call(path []string, req *Request) (interface{}, error) {
 func (c *Command) Sub(id string) *Command {
   return c.subcommands[id]
 }
+
+func (c *Command) checkOptions(names map[string]bool) error {
+  for _, opt := range c.Options {
+    for _, name := range opt.Names {
+      if _, ok := names[name]; ok {
+        return fmt.Errorf("Multiple options are using the same name ('%s')", name)
+      }
+      names[name] = true
+    }
+  }
+
+  for _, cmd := range c.subcommands {
+    err := cmd.checkOptions(names)
+    if err != nil {
+      return err
+    }
+  }
+
+  return nil
+}
-- 
GitLab