110 lines
3.6 KiB
Java
110 lines
3.6 KiB
Java
package fr.monlouyan.bakefile;
|
|
|
|
import java.util.*;
|
|
|
|
public class DependencyResolver {
|
|
private boolean debug;
|
|
private Map<String, Rule> ruleMap;
|
|
private boolean isCircular;
|
|
|
|
public DependencyResolver(boolean debug) {
|
|
this.debug = debug;
|
|
this.isCircular = false;
|
|
}
|
|
|
|
public List<Rule> resolve(List<Rule> allRules, List<String> requestedRules) {
|
|
List<Rule> rulesToBuild = new ArrayList<>();
|
|
ruleMap = new HashMap<>();
|
|
|
|
// Construire la map des règles
|
|
for (Rule rule : allRules) {
|
|
ruleMap.put(rule.getName(), rule);
|
|
}
|
|
|
|
// Premier passage : détection et suppression des cycles
|
|
Set<String> visited = new HashSet<>();
|
|
Set<String> stack = new HashSet<>();
|
|
|
|
List<String> targetRules = requestedRules.isEmpty() ?
|
|
Collections.singletonList(BakefileParser.getFirstTarget()) :
|
|
requestedRules;
|
|
|
|
for (String ruleName : targetRules) {
|
|
if (ruleMap.containsKey(ruleName)) {
|
|
detectCycle(ruleName, visited, stack, ruleName);
|
|
} else if (debug) {
|
|
System.out.println("Warning: Rule '" + ruleName + "' not found.");
|
|
}
|
|
}
|
|
|
|
// Deuxième passage : collecte des dépendances dans l'ordre
|
|
Set<String> processed = new HashSet<>();
|
|
List<String> buildOrder = new ArrayList<>();
|
|
|
|
for (String ruleName : targetRules) {
|
|
topologicalSort(ruleName, processed, buildOrder);
|
|
}
|
|
|
|
// Construire la liste finale des règles dans l'ordre
|
|
for (String ruleName : buildOrder) {
|
|
Rule rule = ruleMap.get(ruleName);
|
|
if (rule != null) {
|
|
rulesToBuild.add(rule);
|
|
}
|
|
}
|
|
|
|
return rulesToBuild;
|
|
}
|
|
|
|
private void topologicalSort(String ruleName, Set<String> processed, List<String> buildOrder) {
|
|
if (!ruleMap.containsKey(ruleName) || processed.contains(ruleName)) {
|
|
return;
|
|
}
|
|
|
|
processed.add(ruleName);
|
|
Rule rule = ruleMap.get(ruleName);
|
|
|
|
// D'abord traiter les dépendances
|
|
for (String dep : rule.getDependencies()) {
|
|
topologicalSort(dep, processed, buildOrder);
|
|
}
|
|
|
|
// Puis ajouter la règle courante
|
|
buildOrder.add(ruleName);
|
|
}
|
|
|
|
// La méthode detectCycle reste inchangée
|
|
private void detectCycle(String ruleName, Set<String> visited, Set<String> stack, String parent) {
|
|
if (stack.contains(ruleName)) {
|
|
if (parent != null) {
|
|
System.out.println("bake: Circular " + parent + " <- " + ruleName + " dependency dropped.");
|
|
this.isCircular = true;
|
|
Rule parentRule = ruleMap.get(parent);
|
|
if (parentRule != null) {
|
|
parentRule.getDependencies().remove(ruleName);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!visited.contains(ruleName)) {
|
|
visited.add(ruleName);
|
|
stack.add(ruleName);
|
|
|
|
Rule rule = ruleMap.get(ruleName);
|
|
if (rule != null) {
|
|
List<String> dependenciesCopy = new ArrayList<>(rule.getDependencies());
|
|
for (String dependency : dependenciesCopy) {
|
|
if (ruleMap.containsKey(dependency)) {
|
|
detectCycle(dependency, visited, stack, ruleName);
|
|
}
|
|
}
|
|
}
|
|
stack.remove(ruleName);
|
|
}
|
|
}
|
|
|
|
public boolean isCircular() {
|
|
return isCircular;
|
|
}
|
|
} |