Add Dependency.hierarchy() to better visualize the origin of a dependency.

TBR=bradnelson

Review URL: http://codereview.chromium.org/2883035

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@53379 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/gclient.py b/gclient.py
index 9a722f7..d62e77e 100644
--- a/gclient.py
+++ b/gclient.py
@@ -160,9 +160,11 @@
     # Sanity checks
     if not self.name and self.parent:
       raise gclient_utils.Error('Dependency without name')
-    if self.name in [d.name for d in self.tree(False)]:
-      raise gclient_utils.Error('Dependency %s specified more than once' %
-          self.name)
+    tree = dict((d.name, d) for d in self.tree(False))
+    if self.name in tree:
+      raise gclient_utils.Error(
+          'Dependency %s specified more than once:\n  %s\nvs\n  %s' %
+          (self.name, tree[self.name].hierarchy(), self.hierarchy()))
     if not isinstance(self.url,
         (basestring, self.FromImpl, self.FileImpl, None.__class__)):
       raise gclient_utils.Error('dependency url must be either a string, None, '
@@ -436,6 +438,15 @@
   def __repr__(self):
     return '%s: %s' % (self.name, self.url)
 
+  def hierarchy(self):
+    "Returns a human-readable hierarchical reference to a Dependency."
+    out = '%s(%s)' % (self.name, self.url)
+    i = self.parent
+    while i and i.name:
+      out = '%s(%s) -> %s' % (i.name, i.url, out)
+      i = i.parent
+    return out
+
 
 class GClient(Dependency):
   """Object that represent a gclient checkout. A tree of Dependency(), one per