Transitively rechecks targets based on triggers and the dependency map. Returns a list (module id, path) tuples representing modules that contain a target that needs to be reprocessed but that has not been parsed yet. Processed targets should be appended to processed_targets (used in t
(
manager: BuildManager,
graph: dict[str, State],
deps: dict[str, set[str]],
triggered: set[str],
up_to_date_modules: set[str],
targets_with_errors: set[str],
processed_targets: list[str],
)
| 833 | |
| 834 | |
| 835 | def propagate_changes_using_dependencies( |
| 836 | manager: BuildManager, |
| 837 | graph: dict[str, State], |
| 838 | deps: dict[str, set[str]], |
| 839 | triggered: set[str], |
| 840 | up_to_date_modules: set[str], |
| 841 | targets_with_errors: set[str], |
| 842 | processed_targets: list[str], |
| 843 | ) -> list[tuple[str, str]]: |
| 844 | """Transitively rechecks targets based on triggers and the dependency map. |
| 845 | |
| 846 | Returns a list (module id, path) tuples representing modules that contain |
| 847 | a target that needs to be reprocessed but that has not been parsed yet. |
| 848 | |
| 849 | Processed targets should be appended to processed_targets (used in tests only, |
| 850 | to test the order of processing targets). |
| 851 | """ |
| 852 | |
| 853 | num_iter = 0 |
| 854 | remaining_modules: list[tuple[str, str]] = [] |
| 855 | |
| 856 | # Propagate changes until nothing visible has changed during the last |
| 857 | # iteration. |
| 858 | while triggered or targets_with_errors: |
| 859 | num_iter += 1 |
| 860 | if num_iter > MAX_ITER: |
| 861 | raise RuntimeError("Max number of iterations (%d) reached (endless loop?)" % MAX_ITER) |
| 862 | |
| 863 | todo, unloaded, stale_protos = find_targets_recursive( |
| 864 | manager, graph, triggered, deps, up_to_date_modules |
| 865 | ) |
| 866 | # TODO: we sort to make it deterministic, but this is *incredibly* ad hoc |
| 867 | remaining_modules.extend((id, graph[id].xpath) for id in sorted(unloaded)) |
| 868 | # Also process targets that used to have errors, as otherwise some |
| 869 | # errors might be lost. |
| 870 | for target in targets_with_errors: |
| 871 | id = module_prefix(graph, target) |
| 872 | if id is not None and id not in up_to_date_modules: |
| 873 | if id not in todo: |
| 874 | todo[id] = set() |
| 875 | manager.log_fine_grained(f"process target with error: {target}") |
| 876 | more_nodes, _ = lookup_target(manager, target, id) |
| 877 | todo[id].update(more_nodes) |
| 878 | triggered = set() |
| 879 | # First invalidate subtype caches in all stale protocols. |
| 880 | # We need to do this to avoid false negatives if the protocol itself is |
| 881 | # unchanged, but was marked stale because its sub- (or super-) type changed. |
| 882 | for info in stale_protos: |
| 883 | type_state.reset_subtype_caches_for(info) |
| 884 | # Then fully reprocess all targets. |
| 885 | # TODO: Preserve order (set is not optimal) |
| 886 | for id, nodes in sorted(todo.items(), key=lambda x: x[0]): |
| 887 | assert id not in up_to_date_modules |
| 888 | triggered |= reprocess_nodes(manager, graph, id, nodes, deps, processed_targets) |
| 889 | # Changes elsewhere may require us to reprocess modules that were |
| 890 | # previously considered up to date. For example, there may be a |
| 891 | # dependency loop that loops back to an originally processed module. |
| 892 | up_to_date_modules = set() |
no test coverage detected
searching dependent graphs…