예제 #1
0
    def _internal_scan_specs(self,
                             specs,
                             fail_fast=True,
                             missing_is_fatal=True):
        # TODO: This should really use `product_request`, but on the other hand, we need to
        # deprecate the entire `AddressMapper` interface anyway. See #4769.
        request = self._scheduler.execution_request([BuildFileAddresses],
                                                    [Specs(tuple(specs))])
        result = self._scheduler.execute(request)
        if result.error:
            raise self.BuildFileScanError(str(result.error))
        (_, state), = result.root_products

        if isinstance(state, Throw):
            if isinstance(state.exc, (AddressLookupError, ResolveError)):
                if missing_is_fatal:
                    raise self.BuildFileScanError(
                        'Spec `{}` does not match any targets.\n{}'.format(
                            self._specs_string(specs), str(state.exc)))
                else:
                    # NB: ignore Throws containing ResolveErrors because they are due to missing targets / files
                    return set()
            else:
                raise self.BuildFileScanError(str(state.exc))
        elif missing_is_fatal and not state.value.dependencies:
            raise self.BuildFileScanError(
                'Spec `{}` does not match any targets.'.format(
                    self._specs_string(specs)))

        return set(state.value.dependencies)
예제 #2
0
    def scan_build_files(self, base_path):
        specs = (DescendantAddresses(base_path), )
        build_files_collection, = self._scheduler.product_request(
            BuildFilesCollection, [Specs(specs)])

        build_files_set = set()
        for build_files in build_files_collection.dependencies:
            build_files_set.update(
                f.path for f in build_files.files_content.dependencies)

        return build_files_set
예제 #3
0
  def _inject_specs(self, subjects):
    """Injects targets into the graph for each of the given `Spec` objects.

    Yields the resulting addresses.
    """
    logger.debug('Injecting specs to %s: %s', self, subjects)
    with self._resolve_context():
      specs = tuple(subjects)
      thts, = self._scheduler.product_request(TransitiveHydratedTargets,
                                              [Specs(specs)])

    self._index(thts.closure)

    for hydrated_target in thts.roots:
      yield hydrated_target.address
예제 #4
0
  def iter_target_addresses_for_sources(self, sources):
    """Bulk, iterable form of `target_addresses_for_source`."""
    # Walk up the buildroot looking for targets that would conceivably claim changed sources.
    sources_set = set(sources)
    specs = tuple(AscendantAddresses(directory=d) for d in self._unique_dirs_for_sources(sources_set))

    # Uniqify all transitive hydrated targets.
    hydrated_target_to_address = {}
    hydrated_targets, = self._scheduler.product_request(HydratedTargets, [Specs(specs)])
    for hydrated_target in hydrated_targets.dependencies:
      if hydrated_target not in hydrated_target_to_address:
        hydrated_target_to_address[hydrated_target] = hydrated_target.adaptor.address

    for hydrated_target, legacy_address in six.iteritems(hydrated_target_to_address):
      # Handle BUILD files.
      if (LegacyAddressMapper.any_is_declaring_file(legacy_address, sources_set) or
          self._owns_any_source(sources_set, hydrated_target)):
        yield legacy_address
예제 #5
0
    def warm_product_graph(self, target_roots):
        """Warm the scheduler's `ProductGraph` with `TransitiveHydratedTargets` products.

    :param TargetRoots target_roots: The targets root of the request.
    """
        logger.debug('warming target_roots for: %r', target_roots)
        if type(target_roots) is ChangedTargetRoots:
            subjects = [BuildFileAddresses(target_roots.addresses)]
        elif type(target_roots) is LiteralTargetRoots:
            subjects = [Specs(tuple(target_roots.specs))]
        else:
            raise ValueError(
                'Unexpected TargetRoots type: `{}`.'.format(target_roots))
        request = self.scheduler.execution_request([TransitiveHydratedTargets],
                                                   subjects)
        result = self.scheduler.execute(request)
        if result.error:
            raise result.error
예제 #6
0
    def iter_changed_target_addresses(self, changed_request):
        """Given a `ChangedRequest`, compute and yield all affected target addresses."""
        changed_files = self.changed_files(changed_request.changes_since,
                                           changed_request.diffspec)
        logger.debug('changed files: %s', changed_files)
        if not changed_files:
            return

        changed_addresses = set(
            address
            for address in self._mapper.iter_target_addresses_for_sources(
                changed_files))
        for address in changed_addresses:
            yield address

        if changed_request.include_dependees not in ('direct', 'transitive'):
            return

        # TODO: For dependee finding, we technically only need to parse all build files to collect target
        # dependencies. But in order to fully validate the graph and account for the fact that deleted
        # targets do not show up as changed roots, we use the `TransitiveHydratedTargets` product.
        #   see https://github.com/pantsbuild/pants/issues/382
        specs = (DescendantAddresses(''), )
        adaptor_iter = (t.adaptor
                        for targets in self._scheduler.product_request(
                            TransitiveHydratedTargets, [Specs(specs)])
                        for t in targets.roots)
        graph = _DependentGraph.from_iterable(
            target_types_from_symbol_table(self._symbol_table), adaptor_iter)

        if changed_request.include_dependees == 'direct':
            for address in graph.dependents_of_addresses(changed_addresses):
                yield address
        elif changed_request.include_dependees == 'transitive':
            for address in graph.transitive_dependents_of_addresses(
                    changed_addresses):
                yield address
예제 #7
0
 def resolve(self, spec):
     uhs, = self.scheduler.product_request(UnhydratedStructs,
                                           [Specs(tuple([spec]))])
     return uhs.dependencies
예제 #8
0
 def parse_specs(self, *specs):
     return Specs(tuple(
         self.spec_parser.parse_spec(spec) for spec in specs))