🦀 bions-rust vague 1 : 6 briques build-your-own-x — on ne les rebuild plus jamais

Principe RS-7 : « dès qu'on build un truc, plus personne n'a à le rebuild —
la seule chose à faire est l'optimisation. » (nexus/RepoVerse)
- bion-vc      : horloges vectorielles + MvReg fork-visible (LA spec
                 xion-relativiste-v0 enfin codée — CRDT testé par permutations)
- bion-triplet : l'Adressage Génératif (gen_hash BLAKE3, coords, résidu ;
                 résidu vide quand déjà-su ; align décidable au bit)
- bion-tsoinlog: journal append-only rejouable (CRC32 maison, crash-recovery)
- bion-kv      : magasin clé-valeur bitcask (compaction atomique, tombstones)
- bion-regex   : moteur Thompson NFA linéaire (jamais exponentiel — Russ Cox)
- bion-git     : mini-git content-addressed (SHA-1 maison + vecteurs officiels,
                 branches divergentes = le fork visible)
129 tests verts, clippy 0 warning, doc française = chaque bion est un cours.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
cloudion-labo
2026-08-16 01:07:31 +00:00
commit 2556698dd3
27 changed files with 6518 additions and 0 deletions

116
bion-git/README.md Normal file
View File

@@ -0,0 +1,116 @@
# bion-git — mini-git from scratch, le bion du principe « fork = liberté »
## Quoi
Le noyau conceptuel de git, réimplémenté depuis les principes en **Rust std-only,
zéro dépendance, zéro unsafe** — même le SHA-1 est maison (`src/sha1.rs`, ~90
lignes, vérifié contre les vecteurs officiels du NIST) :
- **magasin d'objets content-addressed** : `blob` / `tree` / `commit`, nommés
par le SHA-1 de leur contenu, stockés dans `.bgit/objects/ab/cdef…`
(2 caractères de répertoire / 38 de fichier, comme git) ;
- **instantanés** : `write_tree` photographie un répertoire, `checkout_tree`
le rematérialise n'importe où ;
- **histoire** : commits chaînés (0, 1 ou N parents — le merge est
représentable), `log` en remontant le premier parent ;
- **branches** : 41 octets dans `refs/heads/<nom>` — forker est gratuit.
Les ids de **blobs et trees sont bit-à-bit ceux du vrai git** (testé contre
`git hash-object` et `git write-tree`, tri des entrées compris).
## Pourquoi
C'est le principe RS-7 fait structure de données : *« dès qu'on build un truc,
plus personne n'a à le rebuild — des blocs, la seule chose à faire est
l'optimisation »*. Le content-addressing garantit exactement ça : un contenu
déjà construit porte un nom absolu, universel, immuable — le rebuild est
impossible par construction, on ne peut que référencer ou optimiser.
**Le lien avec le xerboxion** : une branche est un **chemin** dans l'espace des
états ; un fork une **bifurcation visible**. Deux branches divergentes partagent
tout leur passé commun sans copier un octet — la divergence n'écrase rien, ne
cache rien : elle *existe* dans le graphe, on peut la montrer, la comparer, la
refermer par un merge commit tracé. C'est la sémantique gelée par RS-7
(« divergence = branche, jamais d'écrasement silencieux » — voir `bion-vc`
pour son pendant causal/CRDT) et le socle du nexus/RepoVerse : contribution
= repo, reprise = fork, réplication = pull des ids manquants.
## Exemple
```rust
use bion_git::Repo;
let repo = Repo::init(dir)?; // .bgit/
let tree = repo.write_tree(dir)?; // photographier
let racine = repo.commit(tree, &[], "premier instant", "rs-1")?;
repo.branch("main", racine)?;
repo.branch("fork", racine)?; // forker = 41 octets
// diverger…
let cm = repo.commit(tree2, &[racine], "chemin main", "rs-1")?;
let cf = repo.commit(tree3, &[racine], "bifurcation", "rs-7")?;
repo.branch("main", cm)?;
repo.branch("fork", cf)?;
for c in repo.log(repo.branch_target("fork")?)? { // l'histoire
println!("{} {}{}", c.id, c.author, c.message);
}
repo.checkout_tree(&tree, dest)?; // rematérialiser
```
API complète : `Repo::{init, open, hash_object, cat_object, write_tree,
read_tree, checkout_tree, commit, commit_at, read_commit, log, branch,
branch_target, branches}` + `Id`, `Kind`, `TreeEntry`, `Commit`,
`sha1::{sha1, to_hex}`. Cette API est **stable pour toujours** (dogme des
bions) : on peut lui ajouter, jamais lui retirer.
## Écarts assumés avec le vrai git
| Écart | Pourquoi |
|---|---|
| Objets **non compressés** (pas de zlib) | std-only et lisible ; git compresse en deflate *après* le hash, donc les ids restent identiques — seul l'octet sur disque diffère. C'est LE point d'optimisation invité (voir plus bas). |
| Commits : auteur = chaîne libre, fuseau figé `+0000`, `committer` = copie d'`author` | même format textuel que git, mais sans imposer `Nom <email>` ; les ids de commits ne coïncident avec git que si on reproduit son format exact |
| Pas d'index/staging | `write_tree` photographie le répertoire directement |
| Pas de packfiles, refs non packées | un objet = un fichier, un ref = un fichier |
| Modes `100644` et `40000` seulement | ni exécutables ni symlinks (refus explicite) |
| `log` = premier parent | le graphe complet est dans `Commit::parents`, à l'appelant d'explorer |
## build-your-own-x
Correspond au chapitre **« Build your own Git »** de
[codecrafters-io/build-your-own-x](https://github.com/codecrafters-io/build-your-own-x#build-your-own-git) :
- *Write yourself a Git!* (thblt) — la référence dont ce bion suit le périmètre ;
- *Git Internals — Plumbing and Porcelain* (Pro Git, ch. 10) — le format d'objets ;
- CodeCrafters « Build your own Git » — mêmes étapes (init, hash-object,
cat-file, write-tree, commit-tree).
Et pour le SHA-1 : FIPS 180-1 (NIST, 1995) — l'implémentation suit la spec
pas à pas, commentée en français.
## Comment l'optimiser (l'invitation au fork)
Le contrat est l'API + le format d'objets ; tout le reste est forkable :
1. **zlib/deflate** : compresser les objets à l'écriture (ids inchangés !) —
c'est l'écart n°1 avec git, et un « build your own zlib » pédagogique en soi ;
2. **packfiles + delta-encoding** : regrouper N objets en un fichier, encoder
les versions successives en deltas — le vrai gain d'espace de git ;
3. **SHA-256** : brancher un second hash (git fait sa propre migration) ;
4. **index/staging** : un cache `(chemin, mtime, id)` pour ne pas re-hasher
les fichiers inchangés à chaque `write_tree` ;
5. **transport** : `pull(remote)` = énumérer les ids manquants et les copier —
la réplication pull/apply du xerboxion tombe naturellement du
content-addressing ;
6. **merge de trees** : diff3 entre deux trees et leur ancêtre commun, avec
conflits *visibles* (jamais d'arbitrage silencieux — brancher `bion-vc`).
## Tests
`cargo test -p bion-git` — 15 tests unitaires + 2 doc-tests : vecteurs SHA-1
officiels (dont le million de « a »), ids identiques au vrai git (blobs, tree
vide, tree imbriqué vérifié contre `git write-tree`), roundtrips
blob/tree/commit, log d'une chaîne, **fork de deux branches divergentes depuis
un parent commun**, merge à deux parents, détection de corruption
(le magasin est auto-vérifiant), refus des traversées de chemin et de
l'injection dans le format commit.