Files
SAE32_2024/src/fr/monlouyan/bakefile/Rule.java

201 lines
7.1 KiB
Java

package fr.monlouyan.bakefile;
import java.io.File;
import java.util.List;
/**
* Représente une règle du fichier Bakefile.
* Chaque règle est composée d'un nom, d'une liste de dépendances et d'une liste de commandes.
* Une règle peut être phony, c'est-à-dire qu'elle n'a pas de fichier cible associé.
*
* @author Moncef STITI, Yanis HAMOUDI, Louay DARDOURI
* @version 1.0
*/
public class Rule {
/*** Nom de la règle */
private String name;
/*** Liste des dépendances de la règle */
private List<String> dependencies;
/*** Liste des commandes */
private List<String> commands;
/*** true si la règle est phony, false sinon */
private boolean isPhony;
/**
* Constructeur de la classe Rule.
* @param name Nom de la règle
* @param dependencies Liste des dépendances
* @param commands Liste des commandes
* @param isPhony true si la règle est phony, false sinon
*/
public Rule(String name, List<String> dependencies, List<String> commands, boolean isPhony) {
this.name = name;
this.dependencies = dependencies;
this.commands = commands;
this.isPhony = isPhony;
}
/**
* Récupère le nom de la règle.
* @return Le nom de la règle
*/
public String getName() { return name; }
/**
* Récupère la liste des dépendances de la règle.
* @return La liste des dépendances
*/
public List<String> getDependencies() { return dependencies; }
/**
* Récupère la liste des commandes de la règle.
* @return La liste des commandes
*/
public List<String> getCommands() { return commands; }
/**
* Vérifie si la règle est phony.
* @return true si la règle est phony, false sinon.
*/
public boolean isPhony() { return isPhony; }
/**
* Vérifie si la règle est vide (sans dépendances ni commandes).
* @return true si la règle est vide, false sinon
*/
public boolean isEmpty() { return dependencies.isEmpty() && commands.isEmpty(); }
/**
* Vérifie si la règle doit être mise à jour.
* @return true si la règle doit être mise à jour, false sinon
*/
public boolean needsUpdate() {
if (BakeCLI.isDebug()){
System.out.println("Debug : Checking if rule " + name + " needs update");
}
// Les règles phony sont toujours mises à jour
if (isPhony) {
if (BakeCLI.isDebug()) {
System.out.println("Debug : Rule " + name + " is phony, always needs update");
}
return true;
}
// Skip targets with tilde in path (home directory) to match make behavior
if (name.startsWith("~")) {
if (BakeCLI.isDebug()) {
System.out.println("Debug : Skipping home directory path: " + name);
}
return false;
}
// Vérifier d'abord toutes les dépendances avant d'exécuter quoi que ce soit
for (String dependency : dependencies) {
// Skip dependencies with tilde in path
if (dependency.startsWith("~")) {
continue;
}
File depFile = new File(dependency);
boolean hasRule = BakeEngine.hasRule(dependency);
if (!depFile.exists() && !dependency.isEmpty() && !hasRule) {
System.out.println("bake: *** No rule to make target `" + dependency + "', needed by `" + name + "'. Stop.");
System.exit(2);
}
}
// Si le fichier cible n'existe pas et qu'il y a des commandes, il doit être mis à jour
File targetFile = new File(name);
if (!targetFile.exists() && !commands.isEmpty()) {
if (BakeCLI.isDebug()) {
System.out.println("Debug : Target file " + name + " does not exist and has commands, needs update");
}
return true;
}
// Si la règle n'a pas de commandes, on vérifie seulement si une dépendance doit être mise à jour
if (commands.isEmpty()) {
for (String dependency : dependencies) {
// Skip dependencies with tilde in path
if (dependency.startsWith("~")) {
continue;
}
Rule depRule = BakeEngine.getRule(dependency);
if (depRule != null && depRule.needsUpdate()) {
if (BakeCLI.isDebug()) {
System.out.println("Debug : Dependency rule " + dependency + " needs update");
}
return true;
}
}
return false;
}
// Pour les règles avec des commandes, on vérifie aussi les timestamps
if (BakeCLI.isDebug()){
System.out.println("Debug : Checking if target file " + name + " exist and is up to date");
}
long targetTimestamp = targetFile.exists() ? TimestampManager.getTimestamp(targetFile) : 0;
if (BakeCLI.isDebug()) {
System.out.println("Debug : Target file '" + name + "' last modified at " + TimestampManager.formatTimestamp(targetTimestamp));
}
long currentTime = System.currentTimeMillis();
for (String dependency : dependencies) {
// Skip dependencies with tilde in path
if (dependency.startsWith("~")) {
continue;
}
File depFile = new File(dependency);
if (!depFile.exists()) {
continue;
}
long depTimestamp = TimestampManager.getTimestamp(depFile);
// Vérifier si le timestamp de la dépendance est dans le futur
if (depTimestamp > currentTime) {
// Avertissement similaire à make
System.out.println("bake: Warning: File '" + dependency + "' has modification time "
+ ((depTimestamp - currentTime) / 1000) + " s in the future");
if (BakeCLI.isDebug()) {
System.out.println("Debug : Dependency " + dependency + " has a timestamp in the future, needs update");
}
return true;
}
if (BakeCLI.isDebug()) {
System.out.println("Debug : Dependency '" + dependency + "' last modified at " + TimestampManager.formatTimestamp(depTimestamp));
}
// Si la dépendance est une règle et qu'elle a besoin d'être mise à jour
Rule depRule = BakeEngine.getRule(dependency);
if (depRule != null && depRule.needsUpdate()) {
if (BakeCLI.isDebug()) {
System.out.println("Debug : Dependency rule " + dependency + " needs update");
}
return true;
}
// Vérifier les timestamps seulement si le fichier existe
if (depTimestamp > targetTimestamp) {
if (BakeCLI.isDebug()) {
System.out.println("Debug : Dependency " + dependency + " is newer than target file " + name + ", needs update");
}
return true;
}
}
return false;
}
}