Amélioration de la gestion des dépendances circulaires
This commit is contained in:
@@ -20,7 +20,7 @@ public class BakeCLI {
|
||||
/*
|
||||
* Liste des arguments passés en ligne de commande
|
||||
*/
|
||||
private List<String> targets;
|
||||
private static List<String> targets;
|
||||
|
||||
/**
|
||||
* Constructeur de la classe BakeCLI
|
||||
@@ -31,7 +31,7 @@ public class BakeCLI {
|
||||
*/
|
||||
public BakeCLI(String[] args){
|
||||
debug = false;
|
||||
this.targets = new ArrayList<>();
|
||||
targets = new ArrayList<>();
|
||||
parseArgs(args);
|
||||
}
|
||||
|
||||
@@ -60,5 +60,5 @@ public class BakeCLI {
|
||||
* Permet de récupérer les arguments autres que "-d" passés en ligne de commande
|
||||
* @return
|
||||
*/
|
||||
public List<String> getTargets(){ return targets; }
|
||||
public static List<String> getTargets(){ return targets; }
|
||||
}
|
||||
|
@@ -3,13 +3,11 @@ package fr.monlouyan.bakefile;
|
||||
import java.util.List;
|
||||
|
||||
public class BakeEngine {
|
||||
private BakeCLI cli;
|
||||
private BakefileParser parser;
|
||||
private DependencyResolver resolver;
|
||||
private CommandExecutor executor;
|
||||
|
||||
public BakeEngine(BakeCLI cli) {
|
||||
this.cli = cli;
|
||||
public BakeEngine() {
|
||||
this.parser = new BakefileParser("Bakefile");
|
||||
this.resolver = new DependencyResolver(BakeCLI.isDebug());
|
||||
this.executor = new CommandExecutor(BakeCLI.isDebug());
|
||||
@@ -17,7 +15,7 @@ public class BakeEngine {
|
||||
|
||||
public void run() {
|
||||
List<Rule> rules = parser.parse();
|
||||
List<Rule> rulesToBuild = resolver.resolve(rules, cli.getTargets());
|
||||
List<Rule> rulesToBuild = resolver.resolve(rules, BakeCLI.getTargets());
|
||||
|
||||
for (Rule rule : rulesToBuild) {
|
||||
executor.execute(rule);
|
||||
|
@@ -8,6 +8,9 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class BakefileParser {
|
||||
/**
|
||||
* Nom du fichier Bakefile à parser (donc Bakefile...).
|
||||
*/
|
||||
private String filename;
|
||||
|
||||
/**
|
||||
@@ -22,8 +25,15 @@ public class BakefileParser {
|
||||
*/
|
||||
private static final Pattern COMMAND_PATTERN = Pattern.compile("^\\s+(.+)$");
|
||||
|
||||
/**
|
||||
* Première cible trouvée dans le fichier Bakefile.
|
||||
*/
|
||||
private static String firstTarget;
|
||||
|
||||
|
||||
public BakefileParser(String filename) {
|
||||
this.filename = filename;
|
||||
firstTarget = null;
|
||||
}
|
||||
|
||||
public List<Rule> parse() {
|
||||
@@ -46,6 +56,10 @@ public class BakefileParser {
|
||||
Matcher commandMatcher = COMMAND_PATTERN.matcher(line);
|
||||
|
||||
if (targetMatcher.matches()) {
|
||||
if (firstTarget == null) {
|
||||
firstTarget = targetMatcher.group(1);
|
||||
}
|
||||
|
||||
// Sauvegarde de la règle précédente si elle existe
|
||||
if (currentTarget != null) {
|
||||
rules.add(new Rule(currentTarget, dependencies, commands, phonyTargets.contains(currentTarget)));
|
||||
@@ -71,4 +85,10 @@ public class BakefileParser {
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de récupérer la première cible trouvée dans le fichier Bakefile.
|
||||
* @return La première cible trouvée
|
||||
*/
|
||||
public static String getFirstTarget() { return firstTarget; }
|
||||
}
|
||||
|
@@ -15,11 +15,14 @@ public class CommandExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rule.needsUpdate()){
|
||||
System.out.println("bake: '" + rule.getName() + "' is up to date.");
|
||||
if (!rule.needsUpdate()) {
|
||||
if (rule.getName().equals(BakefileParser.getFirstTarget())) {
|
||||
System.out.println("bake: '" + rule.getName() + "' is up to date.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
for (String command : rule.getCommands()) {
|
||||
System.out.println(command); // Affichage de la commande executée
|
||||
|
@@ -1,26 +1,80 @@
|
||||
package fr.monlouyan.bakefile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class DependencyResolver {
|
||||
private boolean debug;
|
||||
|
||||
private Map<String, Rule> ruleMap;
|
||||
|
||||
public DependencyResolver(boolean debug) {
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
public List<Rule> resolve(List<Rule> allRules, List<String> requestedRules) {
|
||||
List<Rule> rulesToBuild = new ArrayList<>();
|
||||
ruleMap = new HashMap<>();
|
||||
Set<String> builtRules = new HashSet<>(); // Éviter d'ajouter des règles déjà vérifiées
|
||||
|
||||
for (Rule rule : allRules) {
|
||||
if (requestedRules.isEmpty() || requestedRules.contains(rule.getName()) || rule.isPhony()) {
|
||||
if (debug){
|
||||
System.out.println("Rule " + rule.getName() + " is requested");
|
||||
}
|
||||
rulesToBuild.add(rule);
|
||||
ruleMap.put(rule.getName(), rule);
|
||||
}
|
||||
|
||||
Set<String> visited = new HashSet<>();
|
||||
Set<String> stack = new HashSet<>();
|
||||
|
||||
for (String ruleName : requestedRules.isEmpty() ? ruleMap.keySet() : requestedRules) {
|
||||
if (ruleMap.containsKey(ruleName)) {
|
||||
detectCycle(ruleName, visited, stack);
|
||||
collectDependencies(ruleName, rulesToBuild, builtRules);
|
||||
} else if (debug) {
|
||||
System.out.println("Warning: Rule '" + ruleName + "' not found.");
|
||||
}
|
||||
}
|
||||
|
||||
return rulesToBuild;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Détection des cycles avec DFS
|
||||
*/
|
||||
private void detectCycle(String ruleName, Set<String> visited, Set<String> stack) {
|
||||
if (stack.contains(ruleName)) {
|
||||
throw new RuntimeException("Dependency cycle detected involving rule: " + ruleName);
|
||||
}
|
||||
|
||||
if (!visited.contains(ruleName)) {
|
||||
visited.add(ruleName);
|
||||
stack.add(ruleName);
|
||||
|
||||
Rule rule = ruleMap.get(ruleName);
|
||||
if (rule != null) {
|
||||
for (String dependency : rule.getDependencies()) {
|
||||
if (ruleMap.containsKey(dependency)) {
|
||||
detectCycle(dependency, visited, stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
stack.remove(ruleName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collecte récursive des règles à construire en évitant les doublons
|
||||
*/
|
||||
private void collectDependencies(String ruleName, List<Rule> rulesToBuild, Set<String> builtRules) {
|
||||
if (builtRules.contains(ruleName)) {
|
||||
return; // Évite d'ajouter une règle plusieurs fois
|
||||
}
|
||||
|
||||
Rule rule = ruleMap.get(ruleName);
|
||||
if (rule != null) {
|
||||
for (String dependency : rule.getDependencies()) {
|
||||
if (ruleMap.containsKey(dependency)) {
|
||||
collectDependencies(dependency, rulesToBuild, builtRules);
|
||||
}
|
||||
}
|
||||
rulesToBuild.add(rule);
|
||||
builtRules.add(ruleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,8 +16,9 @@ public class Main{
|
||||
* @return void
|
||||
*/
|
||||
public static void main(String[] args){
|
||||
@SuppressWarnings("unused")
|
||||
BakeCLI cli = new BakeCLI(args);
|
||||
BakeEngine engine = new BakeEngine(cli);
|
||||
BakeEngine engine = new BakeEngine();
|
||||
engine.run();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user