from typing import Set
from typing import Callable
from typing import List
import collections


def add_subrepositories_depending_on(
    changed: Set[str], all_subrepos: Set[str], requirement_getter: Callable[[str], List[str]]
) -> Set[str]:
    """
    Augments "changed" with other members of "all_subrepos" that directly or indirectly depend on the
    members of "changed", as listed in their internal_requirements.txt files.
    """
    if not changed:
        return changed  # pragma: no cover
    # Mapping from subrepo names to subrepos that directly depend on them.
    dependency_graph = collections.defaultdict(list)
    for name in all_subrepos:
        deps = requirement_getter(name)
        for dep in deps:
            if dep in all_subrepos:
                dependency_graph[dep].append(name)
    result = changed.copy()
    while True:
        additional = set()
        for name in result:
            additional.update(dependency_graph[name])
        additional.difference_update(result)
        if not additional:
            break  # we've converged
        result.update(additional)
    return result