diff options
-rw-r--r-- | buildstream/_pipeline.py | 28 | ||||
-rw-r--r-- | buildstream/element.py | 42 |
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): |