async def find_owners(owners_request: OwnersRequest) -> Owners: sources_set = FrozenOrderedSet(owners_request.sources) dirs_set = FrozenOrderedSet( os.path.dirname(source) for source in sources_set) # Walk up the buildroot looking for targets that would conceivably claim changed sources. candidate_specs = tuple(AscendantAddresses(directory=d) for d in dirs_set) candidate_targets = await Get[HydratedTargets]( AddressSpecs(candidate_specs)) # Match the source globs against the expanded candidate targets. def owns_any_source(legacy_target: HydratedTarget) -> bool: """Given a `HydratedTarget` instance, check if it owns the given source file.""" target_kwargs = legacy_target.adaptor.kwargs() # Handle `sources`-declaring targets. # NB: Deleted files can only be matched against the 'filespec' (ie, `PathGlobs`) for a target, # so we don't actually call `fileset.matches` here. # TODO: This matching logic should be implemented using the rust `fs` crate for two reasons: # 1) having two implementations isn't great # 2) we're expanding sources via HydratedTarget, but it isn't necessary to do that to match target_sources = target_kwargs.get("sources", None) return target_sources and any_matches_filespec( paths=sources_set, spec=target_sources.filespec) build_file_addresses = await MultiGet( Get[BuildFileAddress](Address, ht.adaptor.address) for ht in candidate_targets) owners = Addresses( ht.adaptor.address for ht, bfa in zip(candidate_targets, build_file_addresses) if LegacyAddressMapper.any_is_declaring_file(bfa, sources_set) or owns_any_source(ht)) return Owners(owners)
async def find_owners(build_configuration: BuildConfiguration, address_mapper: AddressMapper, owners_request: OwnersRequest) -> BuildFileAddresses: sources_set = OrderedSet(owners_request.sources) dirs_set = OrderedSet(dirname(source) for source in sources_set) # Walk up the buildroot looking for targets that would conceivably claim changed sources. candidate_specs = tuple(AscendantAddresses(directory=d) for d in dirs_set) candidate_targets = await Get(HydratedTargets, Specs(candidate_specs)) # Match the source globs against the expanded candidate targets. def owns_any_source(legacy_target): """Given a `HydratedTarget` instance, check if it owns the given source file.""" target_kwargs = legacy_target.adaptor.kwargs() # Handle `sources`-declaring targets. # NB: Deleted files can only be matched against the 'filespec' (ie, `PathGlobs`) for a target, # so we don't actually call `fileset.matches` here. # TODO: This matching logic should be implemented using the rust `fs` crate for two reasons: # 1) having two implementations isn't great # 2) we're expanding sources via HydratedTarget, but it isn't necessary to do that to match target_sources = target_kwargs.get('sources', None) if target_sources and any_matches_filespec(sources_set, target_sources.filespec): return True return False direct_owners = tuple( ht.adaptor.address for ht in candidate_targets if LegacyAddressMapper.any_is_declaring_file( ht.adaptor.address, sources_set) or owns_any_source(ht)) # If the OwnersRequest does not require dependees, then we're done. if owners_request.include_dependees == 'none': return BuildFileAddresses(direct_owners) else: # Otherwise: find dependees. all_addresses = await Get(BuildFileAddresses, Specs((DescendantAddresses(''), ))) all_hydrated_structs = await MultiGet( Get(HydratedStruct, Address, a.to_address()) for a in all_addresses) all_structs = [hs.value for hs in all_hydrated_structs] bfa = build_configuration.registered_aliases() graph = _DependentGraph.from_iterable( target_types_from_build_file_aliases(bfa), address_mapper, all_structs) if owners_request.include_dependees == 'direct': return BuildFileAddresses( tuple(graph.dependents_of_addresses(direct_owners))) else: assert owners_request.include_dependees == 'transitive' return BuildFileAddresses( tuple(graph.transitive_dependents_of_addresses(direct_owners)))
def find_owners(build_configuration, address_mapper, owners_request): sources_set = OrderedSet(owners_request.sources) dirs_set = OrderedSet(dirname(source) for source in sources_set) # Walk up the buildroot looking for targets that would conceivably claim changed sources. candidate_specs = tuple(AscendantAddresses(directory=d) for d in dirs_set) candidate_targets = yield Get(HydratedTargets, Specs(candidate_specs)) # Match the source globs against the expanded candidate targets. def owns_any_source(legacy_target): """Given a `HydratedTarget` instance, check if it owns the given source file.""" target_kwargs = legacy_target.adaptor.kwargs() # Handle `sources`-declaring targets. # NB: Deleted files can only be matched against the 'filespec' (ie, `PathGlobs`) for a target, # so we don't actually call `fileset.matches` here. # TODO: This matching logic should be implemented using the rust `fs` crate for two reasons: # 1) having two implementations isn't great # 2) we're expanding sources via HydratedTarget, but it isn't necessary to do that to match target_sources = target_kwargs.get('sources', None) if target_sources and any_matches_filespec(sources_set, target_sources.filespec): return True return False direct_owners = tuple(ht.adaptor.address for ht in candidate_targets if LegacyAddressMapper.any_is_declaring_file(ht.adaptor.address, sources_set) or owns_any_source(ht)) # If the OwnersRequest does not require dependees, then we're done. if owners_request.include_dependees == 'none': yield BuildFileAddresses(direct_owners) else: # Otherwise: find dependees. all_addresses = yield Get(BuildFileAddresses, Specs((DescendantAddresses(''),))) all_structs = yield [Get(HydratedStruct, Address, a.to_address()) for a in all_addresses] all_structs = [s.value for s in all_structs] bfa = build_configuration.registered_aliases() graph = _DependentGraph.from_iterable(target_types_from_build_file_aliases(bfa), address_mapper, all_structs) if owners_request.include_dependees == 'direct': yield BuildFileAddresses(tuple(graph.dependents_of_addresses(direct_owners))) else: assert owners_request.include_dependees == 'transitive' yield BuildFileAddresses(tuple(graph.transitive_dependents_of_addresses(direct_owners)))
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