| Index: gclient.py
|
| diff --git a/gclient.py b/gclient.py
|
| index d86c3663e2d17a50f9b2c8e2b11bb698eeebce4e..e2257724e535cc6c646f84f6ab637851dac89b43 100644
|
| --- a/gclient.py
|
| +++ b/gclient.py
|
| @@ -141,6 +141,9 @@ class Dependency(GClientKeywords, gclient_utils.WorkItem):
|
|
|
| def __init__(self, parent, name, url, safesync_url, custom_deps,
|
| custom_vars, deps_file, should_process):
|
| + # Warning: this function can be called from any thread. Both
|
| + # self.dependencies and self.requirements are read and modified from
|
| + # multiple threads at the same time. Sad.
|
| GClientKeywords.__init__(self)
|
| gclient_utils.WorkItem.__init__(self)
|
| self.parent = parent
|
| @@ -167,11 +170,9 @@ class Dependency(GClientKeywords, gclient_utils.WorkItem):
|
| # This dependency had its hook run
|
| self.hooks_ran = False
|
| # Required dependencies to run before running this one:
|
| - self.requirements = []
|
| - if self.parent and self.parent.name:
|
| - self.requirements.append(self.parent.name)
|
| - if isinstance(self.url, self.FromImpl):
|
| - self.requirements.append(self.url.module_name)
|
| + self.requirements = set()
|
| +
|
| + self._FindDependencies()
|
|
|
| # Sanity checks
|
| if not self.name and self.parent:
|
| @@ -185,6 +186,54 @@ class Dependency(GClientKeywords, gclient_utils.WorkItem):
|
| raise gclient_utils.Error('deps_file name must not be a path, just a '
|
| 'filename. %s' % self.deps_file)
|
|
|
| + def _FindDependencies(self):
|
| + """Setup self.requirements and find any other dependency who would have self
|
| + as a requirement.
|
| + """
|
| + # self.parent is implicitly a requirement. This will be recursive by
|
| + # definition.
|
| + if self.parent and self.parent.name:
|
| + self.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.
|
| + # This becomes messy for >2 depth as the DEPS file format is a dictionary,
|
| + # thus unsorted, while the .gclient format is a list thus sorted.
|
| + #
|
| + # * _recursion_limit is hard coded 2 and there is no hope to change this
|
| + # value.
|
| + #
|
| + # 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.
|
| + if self.parent in self.root_parent().dependencies:
|
| + root_deps = self.root_parent().dependencies
|
| + for i in range(0, root_deps.index(self.parent)):
|
| + value = root_deps[i]
|
| + if value.name:
|
| + self.requirements.add(value.name)
|
| +
|
| + if isinstance(self.url, self.FromImpl):
|
| + self.requirements.add(self.url.module_name)
|
| +
|
| + if self.name:
|
| + def yield_full_tree(root):
|
| + """Depth-first recursion."""
|
| + yield root
|
| + for i in root.dependencies:
|
| + for j in yield_full_tree(i):
|
| + yield j
|
| +
|
| + for obj in yield_full_tree(self.root_parent()):
|
| + 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.requirements.add(obj.name)
|
| + # Step 2: Find any requirements self may impose.
|
| + if obj.name.startswith(posixpath.join(self.name, '')):
|
| + obj.requirements.add(self.name)
|
| +
|
| def LateOverride(self, url):
|
| """Resolves the parsed url from url.
|
|
|
| @@ -406,16 +455,6 @@ class Dependency(GClientKeywords, gclient_utils.WorkItem):
|
| if self.recursion_limit() > 0:
|
| # Then we can parse the DEPS file.
|
| self.ParseDepsFile()
|
| - # Adjust the implicit dependency requirement; e.g. if a DEPS file contains
|
| - # both src/foo and src/foo/bar, src/foo/bar is implicitly dependent of
|
| - # src/foo. Yes, it's O(n^2)... It's important to do that before
|
| - # enqueueing them.
|
| - for s in self.dependencies:
|
| - for s2 in self.dependencies:
|
| - if s is s2:
|
| - continue
|
| - if s.name.startswith(posixpath.join(s2.name, '')):
|
| - s.requirements.append(s2.name)
|
|
|
| # Parse the dependencies of this dependency.
|
| for s in self.dependencies:
|
|
|