summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildstream/_pipeline.py28
-rw-r--r--buildstream/element.py42
2 files changed, 35 insertions, 35 deletions
diff --git a/buildstream/_pipeline.py b/buildstream/_pipeline.py
index febadbcc7..9820880f6 100644
--- a/buildstream/_pipeline.py
+++ b/buildstream/_pipeline.py
@@ -195,24 +195,16 @@ class Pipeline():
# also iterate over sources.
#
def dependencies(self, scope, include_sources=False):
- # Create a dummy element (can't use namedtuple because of the
- # '__' prefix).
- class DummyElement(object):
- def __init__(self, build_dependencies, runtime_dependencies):
- self.name = ''
- self._Element__build_dependencies = build_dependencies
- self._Element__runtime_dependencies = runtime_dependencies
- dummy = DummyElement(self.targets, self.targets)
-
- for element in Element.dependencies(dummy, scope):
- # We don't actually want to find the dummy element
- if isinstance(element, DummyElement):
- continue
-
- if include_sources:
- for source in element.sources():
- yield source
- yield element
+ # Keep track of 'visited' in this scope, so that all targets
+ # share the same context.
+ visited = {}
+
+ for target in self.targets:
+ for element in target.dependencies(scope, visited=visited):
+ if include_sources:
+ for source in element.sources():
+ yield source
+ yield element
# Asserts that the pipeline is in a consistent state, that
# is to say that all sources are consistent and can at least
diff --git a/buildstream/element.py b/buildstream/element.py
index 22a2ebdbb..b76ef688f 100644
--- a/buildstream/element.py
+++ b/buildstream/element.py
@@ -179,7 +179,7 @@ class Element(Plugin):
for source in self.__sources:
yield source
- def dependencies(self, scope, recurse=True, visited=None):
+ def dependencies(self, scope, recurse=True, visited=None, recursed=False):
"""dependencies(scope, recurse=True)
A generator function which yields the dependencies of the given element.
@@ -197,36 +197,44 @@ class Element(Plugin):
Yields:
(:class:`.Element`): The dependencies in `scope`, in deterministic staging order
"""
- did_recurse = False
if visited is None:
- visited = []
- else:
- did_recurse = True
+ visited = {}
+
+ scope_set = set((Scope.BUILD, Scope.RUN)) if scope == Scope.ALL else set((scope,))
- if self.name in visited:
+ if self.name in visited and scope_set.issubset(visited[self.name]):
return
- visited.append(self.name)
- if recurse or not did_recurse:
+ should_yield = False
+ if self.name not in visited:
+ visited[self.name] = scope_set
+ should_yield = True
+ else:
+ visited[self.name] |= scope_set
+
+ if recurse or not recursed:
if scope == Scope.ALL:
for dep in self.__build_dependencies:
- for elt in dep.dependencies(Scope.ALL, recurse=recurse, visited=visited):
- yield elt
+ yield from dep.dependencies(Scope.ALL, recurse=recurse,
+ visited=visited, recursed=True)
+
for dep in self.__runtime_dependencies:
if dep not in self.__build_dependencies:
- for elt in dep.dependencies(Scope.ALL, recurse=recurse, visited=visited):
- yield elt
+ yield from dep.dependencies(Scope.ALL, recurse=recurse,
+ visited=visited, recursed=True)
+
elif scope == Scope.BUILD:
for dep in self.__build_dependencies:
- for elt in dep.dependencies(Scope.RUN, recurse=recurse, visited=visited):
- yield elt
+ yield from dep.dependencies(Scope.RUN, recurse=recurse,
+ visited=visited, recursed=True)
+
elif scope == Scope.RUN:
for dep in self.__runtime_dependencies:
- for elt in dep.dependencies(Scope.RUN, recurse=recurse, visited=visited):
- yield elt
+ yield from dep.dependencies(Scope.RUN, recurse=recurse,
+ visited=visited, recursed=True)
# Yeild self only at the end, after anything needed has been traversed
- if (recurse or did_recurse) and (scope == Scope.ALL or scope == Scope.RUN):
+ if should_yield and (recurse or recursed) and (scope == Scope.ALL or scope == Scope.RUN):
yield self
def search(self, scope, name):