package fr.monlouyan.bakefile; import java.io.File; import java.io.IOException; public class CommandExecutor { private boolean debug; private boolean needsUpdate = false; // Pour tracker si quelque chose doit être mis à jour private boolean isCircular = false; // Pour tracker si un cycle a été détecté private boolean futureTimestampDetected = false; // Pour détecter les timestamps dans le futur public CommandExecutor(boolean debug, boolean isCircular) { this.debug = debug; this.isCircular = isCircular; } public void execute(Rule rule) { // On vérifie d'abord si cette règle a besoin d'être mise à jour boolean ruleNeedsUpdate = rule.needsUpdate(); if (ruleNeedsUpdate) { needsUpdate = true; // Au moins une règle doit être mise à jour // Vérifier les timestamps des dépendances pour détecter ceux dans le futur for (String dependency : rule.getDependencies()) { if (dependency.startsWith("~")) { continue; } File depFile = new File(dependency); if (depFile.exists() && TimestampManager.getTimestamp(depFile) > System.currentTimeMillis()) { futureTimestampDetected = true; } } } // Si la règle a besoin d'être mise à jour et qu'il n'y a pas de commandes if (ruleNeedsUpdate && rule.getCommands().isEmpty()) { return; // On ne fait rien mais on ne montre pas de message } for (String command : rule.getCommands()) { if (isCircular){ System.out.println(command); } // On n'exécute que si nécessaire if (ruleNeedsUpdate) { try { if(!isCircular){ System.out.println(command); } if (debug) System.out.println("Debug: Executing " + command); ProcessBuilder pb = new ProcessBuilder("sh", "-c", command); pb.inheritIO(); Process process = pb.start(); // Attendre la fin du processus int exitCode = process.waitFor(); if (exitCode != 0) { System.err.println("bake: *** [" + rule.getName() + "] Error " + exitCode); System.exit(exitCode); } } catch (IOException | InterruptedException e) { e.printStackTrace(); System.exit(1); } } } // Si on a détecté des timestamps dans le futur, afficher un avertissement à la fin (comme make) if (futureTimestampDetected && !isCircular) { System.out.println("bake: warning: Clock skew detected. Your build may be incomplete."); } // Vérifier si cette règle est une cible directement demandée par l'utilisateur boolean isRequestedTarget = BakeCLI.getTargets().contains(rule.getName()) || (BakeCLI.getTargets().isEmpty() && rule.getName().equals(BakefileParser.getFirstTarget())); if (!isRequestedTarget || needsUpdate) { // Si ce n'est pas une cible demandée ou si une mise à jour a été nécessaire, // ne pas afficher de message return; } // Vérifier si la cible existe en tant que fichier File targetFile = new File(rule.getName()); boolean fileExists = targetFile.exists(); if (!rule.getCommands().isEmpty() && fileExists) { // Si la cible a des commandes et existe en tant que fichier, // afficher "up to date" System.out.println("bake: `" + rule.getName() + "' is up to date."); } else { // Si la cible n'a pas de commandes ou n'existe pas en tant que fichier, // afficher "Nothing to be done" System.out.println("bake: Nothing to be done for `" + rule.getName() + "'."); } } }