133 lines
4.7 KiB
Java
Raw Normal View History

package fr.monlouyan.bakefile;
import java.io.File;
import java.io.IOException;
2025-03-07 22:13:57 +01:00
/**
* Exécuteur des commandes définies dans les règles.
* Cette classe est responsable de l'exécution des commandes définies dans les règles
* du fichier Bakefile.
*
* @author Moncef STITI, Yanis HAMOUDI, Louay DARDOURI
* @version 1.0
*/
public class CommandExecutor {
2025-03-07 22:13:57 +01:00
/**
* true si le mode debug est activé, false sinon
*/
private boolean debug;
2025-03-07 22:13:57 +01:00
/**
* Pour tracker si quelque chose doit être mis à jour
*/
private boolean needsUpdate = false;
/**
* Pour tracker si un cycle a été détecté
*/
private boolean isCircular = false;
/**
* Pour détecter les timestamps dans le futur
*/
private boolean futureTimestampDetected = false;
/**
* Constructeur de la classe CommandExecutor.
* @param debug true si le mode debug est activé, false sinon
* @param isCircular true si on est en mode circulaire, false sinon
*/
public CommandExecutor(boolean debug, boolean isCircular) {
this.debug = debug;
this.isCircular = isCircular;
}
2025-03-07 22:13:57 +01:00
/**
* Exécute les commandes d'une règle.
* @param rule La règle à exécuter
*/
2025-02-04 17:31:25 +01:00
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;
}
}
2025-02-04 17:31:25 +01:00
}
// 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(2);
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
System.exit(2);
2025-02-04 17:31:25 +01:00
}
}
}
// 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() + "'.");
}
}
}