| Index: gclient.py
 | 
| diff --git a/gclient.py b/gclient.py
 | 
| index ed64354f1b1043007f442bc4428b3e5e996e4e22..5f40f4ed997e851c1fd9bb85fb85a23082db6852 100644
 | 
| --- a/gclient.py
 | 
| +++ b/gclient.py
 | 
| @@ -258,8 +258,31 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
 | 
|      # This dependency had its hook run
 | 
|      self._hooks_ran = False
 | 
|  
 | 
| -    # Setup self.requirements and find any other dependency who would have self
 | 
| -    # as a requirement.
 | 
| +    if not self.name and self.parent:
 | 
| +      raise gclient_utils.Error('Dependency without name')
 | 
| +
 | 
| +  def setup_requirements(self):
 | 
| +    """Setup self.requirements and find any other dependency who would have self
 | 
| +    as a requirement.
 | 
| +
 | 
| +    Returns True if this entry should be added, False if it is a duplicate of
 | 
| +    another entry.
 | 
| +    """
 | 
| +    if self.name in [s.name for s in self.parent.dependencies]:
 | 
| +      raise gclient_utils.Error(
 | 
| +          'The same name "%s" appears multiple times in the deps section' %
 | 
| +              self.name)
 | 
| +    if self.should_process:
 | 
| +      siblings = [d for d in self.root.subtree(False) if d.name == self.name]
 | 
| +      for sibling in siblings:
 | 
| +        if self.url != sibling.url:
 | 
| +          raise gclient_utils.Error(
 | 
| +              'Dependency %s specified more than once:\n  %s\nvs\n  %s' %
 | 
| +              (self.name, sibling.hierarchy(), self.hierarchy()))
 | 
| +        # In theory we could keep it as a shadow of the other one. In
 | 
| +        # practice, simply ignore it.
 | 
| +        logging.warn('Won\'t process duplicate dependency %s' % sibling)
 | 
| +        return False
 | 
|  
 | 
|      # self.parent is implicitly a requirement. This will be recursive by
 | 
|      # definition.
 | 
| @@ -298,9 +321,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
 | 
|          # Step 2: Find any requirements self may impose.
 | 
|          if obj.name.startswith(posixpath.join(self.name, '')):
 | 
|            obj.add_requirement(self.name)
 | 
| -
 | 
| -    if not self.name and self.parent:
 | 
| -      raise gclient_utils.Error('Dependency without name')
 | 
| +    return True
 | 
|  
 | 
|    def LateOverride(self, url):
 | 
|      """Resolves the parsed url from url.
 | 
| @@ -416,8 +437,6 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
 | 
|          else:
 | 
|            deps.update(os_deps)
 | 
|  
 | 
| -    self._deps_hooks.extend(local_scope.get('hooks', []))
 | 
| -
 | 
|      # If a line is in custom_deps, but not in the solution, we want to append
 | 
|      # this line to the solution.
 | 
|      for d in self.custom_deps:
 | 
| @@ -437,31 +456,21 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
 | 
|        deps = rel_deps
 | 
|  
 | 
|      # Convert the deps into real Dependency.
 | 
| +    deps_to_add = []
 | 
|      for name, url in deps.iteritems():
 | 
| -      if name in [s.name for s in self._dependencies]:
 | 
| -        raise gclient_utils.Error(
 | 
| -            'The same name "%s" appears multiple times in the deps section' %
 | 
| -                name)
 | 
|        should_process = self.recursion_limit and self.should_process
 | 
| -      if should_process:
 | 
| -        tree = dict((d.name, d) for d in self.root.subtree(False))
 | 
| -        if name in tree:
 | 
| -          if url == tree[name].url:
 | 
| -            logging.info('Won\'t process duplicate dependency %s' % tree[name])
 | 
| -            # In theory we could keep it as a shadow of the other one. In
 | 
| -            # practice, simply ignore it.
 | 
| -            #should_process = False
 | 
| -            continue
 | 
| -          else:
 | 
| -            raise gclient_utils.Error(
 | 
| -                'Dependency %s specified more than once:\n  %s\nvs\n  %s' %
 | 
| -                (name, tree[name].hierarchy(), self.hierarchy()))
 | 
| -      self._dependencies.append(
 | 
| -          Dependency(
 | 
| -            self, name, url, None, None, None, None,
 | 
| -            self.deps_file, should_process))
 | 
| -    self._deps_parsed = True
 | 
| -    logging.debug('Loaded: %s' % str(self))
 | 
| +      deps_to_add.append(Dependency(
 | 
| +          self, name, url, None, None, None, None,
 | 
| +          self.deps_file, should_process))
 | 
| +    self.add_dependencies_and_close(deps_to_add, local_scope.get('hooks', []))
 | 
| +    logging.info('ParseDepsFile(%s) done' % self.name)
 | 
| +
 | 
| +  def add_dependencies_and_close(self, deps_to_add, hooks):
 | 
| +    """Adds the dependencies, hooks and mark the parsing as done."""
 | 
| +    for dep in deps_to_add:
 | 
| +      if dep.setup_requirements():
 | 
| +        self.add_dependency(dep)
 | 
| +    self._mark_as_parsed(hooks)
 | 
|  
 | 
|    # Arguments number differs from overridden method
 | 
|    # pylint: disable=W0221
 | 
| @@ -632,7 +641,17 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
 | 
|          if j.should_process:
 | 
|            yield j
 | 
|  
 | 
| +  @gclient_utils.lockedmethod
 | 
| +  def add_dependency(self, new_dep):
 | 
| +    self._dependencies.append(new_dep)
 | 
| +
 | 
| +  @gclient_utils.lockedmethod
 | 
| +  def _mark_as_parsed(self, new_hooks):
 | 
| +    self._deps_hooks.extend(new_hooks)
 | 
| +    self._deps_parsed = True
 | 
| +
 | 
|    @property
 | 
| +  @gclient_utils.lockedmethod
 | 
|    def dependencies(self):
 | 
|      return tuple(self._dependencies)
 | 
|  
 | 
| @@ -765,13 +784,11 @@ solutions = [
 | 
|        exec(content, config_dict)
 | 
|      except SyntaxError, e:
 | 
|        gclient_utils.SyntaxErrorToError('.gclient', e)
 | 
| +
 | 
| +    deps_to_add = []
 | 
|      for s in config_dict.get('solutions', []):
 | 
|        try:
 | 
| -        tree = dict((d.name, d) for d in self.root.subtree(False))
 | 
| -        if s['name'] in tree:
 | 
| -          raise gclient_utils.Error(
 | 
| -              'Dependency %s specified more than once in .gclient' % s['name'])
 | 
| -        self._dependencies.append(Dependency(
 | 
| +        deps_to_add.append(Dependency(
 | 
|              self, s['name'], s['url'],
 | 
|              s.get('safesync_url', None),
 | 
|              s.get('managed', True),
 | 
| @@ -782,9 +799,8 @@ solutions = [
 | 
|        except KeyError:
 | 
|          raise gclient_utils.Error('Invalid .gclient file. Solution is '
 | 
|                                    'incomplete: %s' % s)
 | 
| -    # .gclient can have hooks.
 | 
| -    self._deps_hooks = config_dict.get('hooks', [])
 | 
| -    self._deps_parsed = True
 | 
| +    self.add_dependencies_and_close(deps_to_add, config_dict.get('hooks', []))
 | 
| +    logging.info('SetConfig() done')
 | 
|  
 | 
|    def SaveConfig(self):
 | 
|      gclient_utils.FileWrite(os.path.join(self.root_dir,
 | 
| 
 |