Skip to content

Commit

Permalink
Merge 278b0ab into 85fd6a4
Browse files Browse the repository at this point in the history
  • Loading branch information
Stu Hood committed Apr 22, 2015
2 parents 85fd6a4 + 278b0ab commit f87e974
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 10 deletions.
6 changes: 3 additions & 3 deletions src/python/pants/backend/core/tasks/prepare_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def execute(self):
self.context.products.safe_create_data('resources_by_target',
lambda: defaultdict(MultipleRootedProducts))

# `targets` contains the transitive subgraph in pre-order, which is approximately how
# we want them ordered on the classpath. Thus, we preserve ordering here.
# NB: Ordering isn't relevant here, because it is applied during the dep walk to
# consume from the compile_classpath.
targets = self.context.targets()
if len(targets) == 0:
return
Expand Down Expand Up @@ -82,7 +82,7 @@ def compute_target_dir(tgt):
for conf in self.confs:
# TODO(John Sirois): Introduce the notion of RuntimeClasspath and populate that product
# instead of mutating the compile_classpath.
compile_classpath.add_for_targets(targets, [(conf, target_dir)])
compile_classpath.add_for_target(resources_tgt, [(conf, target_dir)])
if resources_by_target is not None:
resources_by_target[resources_tgt].add_rel_paths(
target_dir, resources_tgt.sources_relative_to_source_root())
24 changes: 22 additions & 2 deletions src/python/pants/base/build_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import logging
import traceback
from collections import OrderedDict, defaultdict
from collections import OrderedDict, defaultdict, deque

from twitter.common.collections import OrderedSet

Expand Down Expand Up @@ -183,7 +183,7 @@ def sorted_targets(self):
return sort_targets(self._target_by_address.values())

def walk_transitive_dependency_graph(self, addresses, work, predicate=None, postorder=False):
"""Given a work function, walks the transitive dependency closure of `addresses`.
"""Given a work function, walks the transitive dependency closure of `addresses` using DFS.
:param list<Address> addresses: The closure of `addresses` will be walked.
:param function work: The function that will be called on every target in the closure using
Expand Down Expand Up @@ -263,6 +263,26 @@ def transitive_subgraph_of_addresses(self, addresses, predicate=None, postorder=
postorder=postorder)
return ret

def transitive_subgraph_of_addresses_bfs(self, addresses, predicate=None):
"""Returns the transitive dependency closure of `addresses` using BFS.
:param list<Address> addresses: The closure of `addresses` will be walked.
:param function predicate: If this parameter is not given, no Targets will be filtered
out of the closure. If it is given, any Target which fails the predicate will not be
walked, nor will its dependencies. Thus predicate effectively trims out any subgraph
that would only be reachable through Targets that fail the predicate.
"""
walked = OrderedSet()
to_walk = deque(addresses)
while len(to_walk) > 0:
address = to_walk.popleft()
target = self._target_by_address[address]
if target not in walked:
walked.add(target)
if not predicate or predicate(target):
to_walk.extend(self._target_dependencies_by_address[address])
return walked

def inject_synthetic_target(self,
address,
target_type,
Expand Down
12 changes: 9 additions & 3 deletions src/python/pants/base/target.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,15 @@ def walk(self, work, predicate=None):
raise ValueError('predicate must be callable but was {}'.format(predicate))
self._build_graph.walk_transitive_dependency_graph([self.address], work, predicate)

def closure(self):
"""Returns this target's transitive dependencies, in DFS preorder traversal."""
return self._build_graph.transitive_subgraph_of_addresses([self.address])
def closure(self, bfs=False):
"""Returns this target's transitive dependencies.
The walk will be depth-first in preorder, or breadth first if bfs=True is specified.
"""
if bfs:
return self._build_graph.transitive_subgraph_of_addresses_bfs([self.address])
else:
return self._build_graph.transitive_subgraph_of_addresses([self.address])

# TODO(Eric Ayers) As of 2/5/2015 this call is DEPRECATED and should be removed soon
def add_labels(self, *label):
Expand Down
4 changes: 2 additions & 2 deletions src/python/pants/goal/products.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ def get_for_targets(self, targets):
"""Gets the transitive product deps for the given targets, in order."""
products = OrderedSet()
visited = set()
# Walk the targets transitively to aggregate their products.
# Walk the targets transitively to aggregate their products. We do a breadth-first
for target in targets:
for dep in target.closure():
for dep in target.closure(bfs=True):
if dep not in visited:
products.update(self._products_by_target[dep])
visited.add(dep)
Expand Down

0 comments on commit f87e974

Please sign in to comment.