- Pour mieux comprendre la structure interne d’un système de gestion de versions, l’auteur a implémenté lui-même un système similaire à Git
- Il remplace le hachage SHA-1 et la compression zlib de Git par un hachage SHA-256 et la compression zstd, avec un dépôt structuré autour du répertoire
.tvc
- Écrit en Rust, le projet implémente étape par étape les fonctions de hachage de fichiers, compression, commit et checkout
- Les objets de commit incluent le hash de l’arbre, le commit parent, l’auteur et le message, et un même fichier n’est pas réenregistré si son hash existe déjà
- L’expérience met en évidence que Git est un stockage de fichiers adressé par le contenu, et souligne l’importance d’un format de données structuré
Méthodes de hachage et de compression
- Git identifie tous les objets par un hachage SHA-1, mais ce projet utilise SHA-256
- SHA-1 est ancien et présente des faiblesses de sécurité, mais ici la sécurité n’était pas essentielle puisqu’il s’agissait simplement d’identifier le contenu des fichiers
- À la place de zlib, le projet adopte zstd de Facebook comme bibliothèque de compression
- zstd a été jugé plus efficace, et la compatibilité avec Git n’était pas un objectif
- Le projet s’appelle « tvc (Tony’s Version Control) », et utilise les fichiers
.tvc et .tvcignore comme équivalents de la structure Git
Étapes d’implémentation
- La procédure d’implémentation suit l’ordre suivant : lecture des arguments de commande → lecture des règles d’exclusion → affichage de la liste des fichiers → hachage et compression → création des arbres et commits → gestion de HEAD → checkout d’un commit
- Écrit en Rust, la commande
ls applique les règles de .tvcignore, parcourt récursivement les fichiers non ignorés et affiche le hachage SHA-256 de chaque fichier
- Les fonctions de compression et décompression de fichiers ont été implémentées simplement à l’aide de la bibliothèque zstd
Structure des commits
- Un objet de commit contient les informations suivantes
- le type d’objet (« commit »)
- l’état du système de fichiers à cet instant (hash de l’arbre)
- le commit précédent (HEAD)
- l’auteur (
author)
- le message de commit
- Contrairement à Git, le projet ne distingue pas auteur et committer, et n’implémente ni fusion ni rebase
- Lors de la création d’un commit, un objet arbre est généré, haché, compressé puis stocké dans
.tvc/objects/, avant mise à jour du fichier HEAD
- Si deux fichiers ont le même hash, ils ne sont pas stockés une seconde fois, ce qui permet d’éviter les doublons
Objets arbre et checkout
- La fonction
generate_tree() parcourt les répertoires, hache, compresse et stocke chaque fichier, puis construit une chaîne contenant le nom de fichier et son hash
- Les sous-répertoires sont traités récursivement pour former une structure en arbre
- Les objets commit et arbre sont analysés sous forme de structures (
Commit, Tree) afin d’être plus faciles à manipuler en mémoire
- La fonction
generate_fs() reconstruit le système de fichiers à partir de la structure d’arbre et effectue le checkout dans le chemin spécifié
Enseignements du projet
- Le projet permet de constater directement que Git est un stockage de fichiers adressé par le contenu (key-value)
- La partie la plus difficile a été l’analyse du format des objets ; l’auteur prévoit d’utiliser la prochaine fois un format plus explicite comme YAML ou JSON
- Le code complet est publié sur GitHub (tonystr/t-version-control)
Aucun commentaire pour le moment.