Hoarder dragons were undead dragons who were so thoroughly greedy, they refused to leave their hoards after death, haunting them somewhat similarly to ghosts.

Cartouche

Champ Valeur
Auteur·e Élise
Édition 2024-09-06
Durée 2 semaines
Taille des équipes 2 personnes
Rendu via git, dépôt $YEAR_hoarder_dragon, droits en lecture à delivery_collector

Règlement

Prenez connaissance du règlement ici

L’intégralité de la bibliothèque standard est autorisée. Vous êtes encouragés à vous servir des outils qu’elle vous propose s’ils résolvent un de vos problèmes. Votre objectif c’est d’éviter de ré-inventer la roue quand ça n’est pas nécessaire.

Certains crates sont proposés dans le sujet. Vous avez le droit de vous servir de toutes leurs fonctionnalités.

Vous pouvez rechercher des alternatives à ces crates, voir des crates qui vous proposent des fonctionnalités complètement différentes. Si ces crates affectent l’écriture de votre algorithme ou l’architecture de votre programme, vous devez les faire valider en amont.

Règles d’évaluation spécifiques

Introduction

Vous allez choisir entre un des deux projets suivants dont le but est de vous aider à faire des tâches répétitives. On parle de QoL, Quality of Life.

  • Sujet 1 : déduplication
    • recherche de fichiers doublons
    • proposer leur suppression
  • Sujet 2 : nettoyage des dépôts de projets
    • recherche de répertoires de projets
    • suppression des fichiers temporaires et des exécutables

Plusieurs crates vont nous aider :

  • walkdir/jwalk pour récursivement parcourir un dosser ;
  • clap pour les arguments du programme ,
  • inquire pour poser des questions à l’utilisateur lors de l’exécution.

Pour les deux sujets

Vous devez designer votre interface en ligne de commande et à la façon dont votre programme va présenter les informations qu’il affiche sur la sortie standard. Assurez-vous de la cohérence de l’affichage d’une fonction à l’autre et de la facilité de lecture.

À chaque fois que votre programme fait une suppression il doit l’afficher.

À la fin de leur exécution, vos programme doivent afficher :

  • le nombre de fichiers/dossiers considérés
  • le nombre correspondances (doublons ou dossiers de projets) ;
  • le nombre d’actions réussies et échouées (suppressions, commandes).

Gestion d’erreur

Une simple erreur d’accès à un dossier, de consultation de métadonnées, d’ouverture de fichier, de lecture ou de suppression ne doit pas arrêter votre programme. Vous devez afficher l’erreur qui s’est produite sur la sortie standard et dans quel situation s’est-elle produite.

Vous devez aussi implémenter un moyen de compter les erreurs et réussites pour afficher les statistiques à la fin du programme.

Sujet 1 : déduplication

Si vous êtes quelque peu comme moi, vous avez un dossier téléchargement sur votre ordinateur avec quelques fichiers. Pasted image 20240910134158.png

Tous très probablement TRÈS important. Mais le réel problème, c’est les fichiers qui sont en double.

L’objectif : écrire un programme qui repère les fichiers avec le même contenu, et propose de les supprimer.

Logique générale

La logique générale d’un tel programme serait :

  • parcourir un dossier donné de façon récursive :
    • à l’aide de walkdir/jwalk ;
  • noter la taille de chaque fichier ;
  • relever les fichiers qui font la même taille ;
  • lire leur contenu et le comparer ;
  • si aucune différence n’est rencontrée entre deux fichiers ils faut les afficher sur la sortie standard en demandant à l’utilisateur s’il veut les supprimer.

Dossiers à ignorer

Il est inutile de parcourir certains dossiers comme :

  • node_modules dans les projets NodeJS ;
  • .git ;
  • les dossiers cachés de façon générale.

En réalité un tel programme est inadapté aux dépôts de code source et est plus utile avec des documents, des archives, des images, des fichiers téléchargés.

Arguments

Votre programme doit fonctionner avec les arguments suivants :

  • une liste de repertoires à parcourir ;
  • un drapeau pour forcer la suppression sans demander ;
  • un drapeau pour ignorer les dépôts git (les dossiers qui contiennent un .git).

Outil : poser une question à l’utilisateur

Il existe plusieurs façon de demander quelque chose à l’utilisateur. Un exemple de crate qui vous permet de le faire c’est inquire.

Outil : suppression

Pour supprimer un fichier on peut utiliser std::fs::remove_file et pour supprimer un dossier ainsi que tout son contenu, de façon récursive on peut utiliser std::fs::remove_dir_all.

Dans le cadre de ce projet, lorsque vous supprimez un dossier ou un fichier, affichez-le systématiquement sur la sortie standard de la même façon que rm -v example.txt.

Sujet 2 : nettoyage de projets

Si vous êtes quelque peu comme moi, vous avez quelques dépôts git sur votre machine.

Pasted image 20240910140154.png

De même, ça vous arrive de les compiler pour les tester, ou travailler dessus, et ensuite de les laisser à jamais. Pour gagner de la place sur votre disque vous les supprimeriez bien mais tout ces projets sont extrêmement importants.

L’objectif : écrire un programme qui repère les dossiers de projet, l’outil de gestion de projet utilisé (cargo, composer, make, yarn, npm, etc.), et propose à l’utilisateur de les nettoyer.

Arguments

Votre programme doit fonctionner avec les arguments suivants :

  • une liste de repertoires à parcourir ;
  • un drapeau pour forcer la suppression sans demander.

Différents gestionnaires de projets

Pour certains gestionnaires de projets il suffit de lancer une commande pour nettoyer le dépôt (comme cargo clean). Pour d’autres, il faut supprimer un dossier (comme node_modules avec npm ou yarn quand on est pas en mode plug and play). Et enfin avec les projets en C/C++ sur Linux, avec un Makefile, on a pas de garantie qu’il y ait des recettes clean et fclean fonctionnelles (en particulier sur des rendus étudiants), donc la meilleure stratégie c’est de repérer tous les fichiers ELF et de les supprimer.

C’est un peu risqué dans certaines situation où on se sert d’un .a, d’un .so ou que l’on a ramené d’autre part dont on a besoin, c’est pourquoi il vaut mieux lister les fichiers que l’on veut supprimer, et demander à l’utilisateur si ça lui convient avant avant de le faire.

Sur Linux on ne repère pas un fichier exécutable ou un objet grace son extension, mais on le repère grace à son contenu. Les exécutables, les bibliothèques partagées et les objets sont appelés des fichiers ELF (Executable and Linkable Format). Ils commencent tous par une constante magique sur 4 octets : 0x7F, 'E', 'L', 'F'.

Comme nous n’avons pas fait de C ou de C++ sur Windows à l’école, nous n’allons pas les gérer pour ce projet, sauf si vous voulez le faire en bonus.

Outils : commande

Si le nettoyage passe par une commande, on va pouvoir utiliser std::process::Command :

let mut cmd = std::process::Command::new("ls");
cmd.arg("-l").arg("-a").arg("/home").current_dir(path);
if let Ok(output) = cmd.output() {
    use std::io::Write;
    std::io::stderr().write_all(&output.stdout).unwrap();
    std::io::stderr().write_all(&output.stderr).unwrap();
    if !output.status.success() {
	eprintln!("failed command");
	eprintln!(
	    "{} exited with status: {}",
	    cmd.get_program().to_str().unwrap_or("?"),
	    output.status
	);
    }
} else {
     eprintln!("failed to spawn command");
}

Si on se moque de la sortie d’une commande, on peut appeler .spawn() au lieu de .output(). Allez voir la documentation de Command pour plus d’appels.

Bonus pour les deux sujets

Le spin baudelairien

Certaines tâches prennent du temps et afficher juste une ligne du genre processing machin... dans le terminal, c’est pas toujours très agréable pour l’utilisateur.

Heureusement les dieux nous ont gracié avec les ✨ spinners ✨. Un exemple de crate qui permet de générer des spinners : spinoff.

Grâce à un spinner, vous pouvez associer un message d’attente à une animation, rassurant l’utilisateur quant au fait que votre programme tourne toujours.