| Index: gclient.py
|
| diff --git a/gclient.py b/gclient.py
|
| index 22e5f990a635b2da696922bf41862c2fa6c1fc6d..cbba142e60ab1c16d1519fdd68f7be49b50942ae 100644
|
| --- a/gclient.py
|
| +++ b/gclient.py
|
| @@ -261,33 +261,14 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
| 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
|
| -
|
| + @property
|
| + def requirements(self):
|
| + """Calculate the list of requirements."""
|
| + requirements = set()
|
| # self.parent is implicitly a requirement. This will be recursive by
|
| # definition.
|
| if self.parent and self.parent.name:
|
| - self.add_requirement(self.parent.name)
|
| + requirements.add(self.parent.name)
|
|
|
| # For a tree with at least 2 levels*, the leaf node needs to depend
|
| # on the level higher up in an orderly way.
|
| @@ -300,27 +281,48 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
| # Interestingly enough, the following condition only works in the case we
|
| # want: self is a 2nd level node. 3nd level node wouldn't need this since
|
| # they already have their parent as a requirement.
|
| - root_deps = self.root.dependencies
|
| - if self.parent in root_deps:
|
| - for i in root_deps:
|
| - if i is self.parent:
|
| - break
|
| - if i.name:
|
| - self.add_requirement(i.name)
|
| + if self.parent and self.parent.parent and not self.parent.parent.parent:
|
| + requirements |= set(i.name for i in self.root.dependencies if i.name)
|
|
|
| if isinstance(self.url, self.FromImpl):
|
| - self.add_requirement(self.url.module_name)
|
| + requirements.add(self.url.module_name)
|
|
|
| - if self.name and self.should_process:
|
| - for obj in self.root.depth_first_tree():
|
| - if obj is self or not obj.name:
|
| - continue
|
| - # Step 1: Find any requirements self may need.
|
| - if self.name.startswith(posixpath.join(obj.name, '')):
|
| - self.add_requirement(obj.name)
|
| - # Step 2: Find any requirements self may impose.
|
| - if obj.name.startswith(posixpath.join(self.name, '')):
|
| - obj.add_requirement(self.name)
|
| + if self.name:
|
| + requirements |= set(
|
| + obj.name for obj in self.root.subtree(False)
|
| + if (obj is not self
|
| + and obj.name and
|
| + self.name.startswith(posixpath.join(obj.name, ''))))
|
| + requirements = tuple(sorted(requirements))
|
| + logging.info('Dependency(%s).requirements = %s' % (self.name, requirements))
|
| + return requirements
|
| +
|
| + def verify_validity(self):
|
| + """Verifies that this Dependency is fine to add as a child of another one.
|
| +
|
| + Returns True if this entry should be added, False if it is a duplicate of
|
| + another entry.
|
| + """
|
| + logging.info('Dependency(%s).verify_validity()' % self.name)
|
| + 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 not self.should_process:
|
| + # Return early, no need to set requirements.
|
| + return True
|
| +
|
| + # This require a full tree traversal with locks.
|
| + 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
|
| return True
|
|
|
| def LateOverride(self, url):
|
| @@ -331,10 +333,13 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
| assert self.parsed_url == None or not self.should_process, self.parsed_url
|
| parsed_url = self.get_custom_deps(self.name, url)
|
| if parsed_url != url:
|
| - logging.info('LateOverride(%s, %s) -> %s' % (self.name, url, parsed_url))
|
| + logging.info(
|
| + 'Dependency(%s).LateOverride(%s) -> %s' %
|
| + (self.name, url, parsed_url))
|
| return parsed_url
|
|
|
| if isinstance(url, self.FromImpl):
|
| + # Requires tree traversal.
|
| ref = [
|
| dep for dep in self.root.subtree(True) if url.module_name == dep.name
|
| ]
|
| @@ -355,7 +360,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
| found_dep = found_deps[0]
|
| parsed_url = found_dep.LateOverride(found_dep.url)
|
| logging.info(
|
| - 'LateOverride(%s, %s) -> %s (From)' % (self.name, url, parsed_url))
|
| + 'Dependency(%s).LateOverride(%s) -> %s (From)' %
|
| + (self.name, url, parsed_url))
|
| return parsed_url
|
|
|
| if isinstance(url, basestring):
|
| @@ -374,15 +380,20 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
| parsed_url = scm.FullUrlForRelativeUrl(url)
|
| else:
|
| parsed_url = url
|
| - logging.info('LateOverride(%s, %s) -> %s' % (self.name, url, parsed_url))
|
| + logging.info(
|
| + 'Dependency(%s).LateOverride(%s) -> %s' %
|
| + (self.name, url, parsed_url))
|
| return parsed_url
|
|
|
| if isinstance(url, self.FileImpl):
|
| - logging.info('LateOverride(%s, %s) -> %s (File)' % (self.name, url, url))
|
| + logging.info(
|
| + 'Dependency(%s).LateOverride(%s) -> %s (File)' %
|
| + (self.name, url, url))
|
| return url
|
|
|
| if url is None:
|
| - logging.info('LateOverride(%s, %s) -> %s' % (self.name, url, url))
|
| + logging.info(
|
| + 'Dependency(%s).LateOverride(%s) -> %s' % (self.name, url, url))
|
| return url
|
|
|
| raise gclient_utils.Error('Unknown url type')
|
| @@ -459,8 +470,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
|
|
| 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():
|
| + for dep in sorted(deps_to_add, key=lambda x: x.name):
|
| + if dep.verify_validity():
|
| self.add_dependency(dep)
|
| self._mark_as_parsed(hooks)
|
|
|
| @@ -505,6 +516,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
| # pylint: disable=W0221
|
| def run(self, revision_overrides, command, args, work_queue, options):
|
| """Runs |command| then parse the DEPS file."""
|
| + logging.info('Dependency(%s).run()' % self.name)
|
| assert self._file_list == []
|
| if not self.should_process:
|
| return
|
|
|