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 |