2. Le manifeste
Tout ce que fait haw part d’un seul fichier : haw.toml, le manifeste. C’est ton intention — quels dépôts existent, où ils vivent, quelle révision tu veux, et comment ils se composent en stacks. Dans ce chapitre, tu vas en écrire un vrai, de haut en bas, et construire le modèle mental. On ne synchronisera pas encore — c’est pour le prochain chapitre. Ici, on soigne d’abord la déclaration.
Un stack, ce ne sont que des blocs de construction — des dépôts emboîtés sous un seul nom, déclarés dans le manifeste.
🎯 Dans ce chapitre, tu vas apprendre à…
- Déclarer un remote une fois et le réutiliser sur tous les dépôts.
- Ajouter des dépôts, chacun avec un
rev(branche, tag ou SHA) et desgroupslibres. - Composer les dépôts en stacks nommées — partagées, jamais copiées.
- Recourir aux overlays quand un dépôt a besoin de surcharges par variante.
- Lire un
haw.tomlentier et savoir exactement ce qu’il va faire.
🛠️ 1. Crée un espace de travail
Crée un répertoire vide et dépose-y un manifeste. Nous utiliserons de petits dépôts publics réels, issus du compte octocat de GitHub — les mêmes que ceux de l’exemple livré examples/quickstart — pour que dès le prochain chapitre tu puisses réellement faire haw sync dessus via HTTPS, sans authentification.
mkdir my-first-stack && cd my-first-stack
Crée maintenant haw.toml avec ce contenu :
[remote.gh]
url = "https://github.com/octocat"
forge = "github"
[repo.hello-world]
remote = "gh"
repo = "Hello-World.git"
rev = "master"
groups = ["core"]
[repo.spoon-knife]
remote = "gh"
repo = "Spoon-Knife.git"
rev = "main"
groups = ["web"]
# `site` composes the two repos into one named stack.
[stack.site]
repos = ["hello-world", "spoon-knife"]
description = "A shared core repo plus the fork-demo front end."
Lis-le de haut en bas, car il est le modèle mental. Prenons-le un bloc à la fois.
🌐 2. Le remote — nomme une URL de base une seule fois
[remote.gh]
url = "https://github.com/octocat"
forge = "github"
Un [remote.NAME] nomme une URL de base une seule fois, pour ne pas la répéter sur chaque dépôt. forge indique à haw quelle API parler plus tard (pour les PR, la CI, etc.) — github, gitlab, ou bitbucket. Tu peux déclarer plusieurs remotes ; une flotte peut s’étendre sur plusieurs forges, et plus tard un changeset peut ouvrir une PR sur l’une et une MR sur l’autre depuis une seule commande.
📦 3. Les dépôts — une déclaration chacun
[repo.hello-world]
remote = "gh"
repo = "Hello-World.git"
rev = "master"
groups = ["core"]
Chaque [repo.NAME] déclare un dépôt :
remote+repo— sur quel remote il vit et son chemin là-bas. Combinés, ils se résolvent enhttps://github.com/octocat/Hello-World.git.rev— la révision que tu veux : une branche (master), un tag (v6.1.2), ou un SHA exact.hawdétecte automatiquement de quel type il s’agit. C’est ton intention — une branche mouvante jusqu’à ce que le lockfile la fige (prochain chapitre).groups— des étiquettes libres par lesquelles tu filtreras des commandes plus tard (ex.haw status --group core). Un dépôt peut appartenir à plusieurs groupes.
rev est une intention, pas un ancrage. Écrire rev = "master" signifie « suivre master ». Rien n’est figé tant que tu ne synchronises pas et qu’un lockfile n’enregistre pas le commit exact — c’est toute l’histoire de la reproductibilité, et c’est l’objet entier du chapitre 3.
🧱 4. Les stacks — compose des dépôts sous un nom
[stack.site]
repos = ["hello-world", "spoon-knife"]
description = "A shared core repo plus the fork-demo front end."
Un stack est une composition nommée de dépôts. Il ne copie rien — il dit simplement « ces dépôts, ensemble, sous ce nom ». Un même manifeste peut définir plusieurs stacks qui partagent les mêmes dépôts :
[stack.site]
repos = ["hello-world", "spoon-knife"]
[stack.core-only]
repos = ["hello-world"]
hello-world apparaît dans les deux stacks, mais il n’y a jamais qu’un seul clone de lui sur le disque. Les stacks sont la façon dont tu découpes une grande flotte en jeux de travail que tu builds et testes réellement ensemble — tu feras haw switch <stack> pour passer de l’un à l’autre, et tu limiteras la portée d’une commande à l’un avec --stack.
🧬 5. Les overlays — des surcharges par variante (quand tu en as besoin)
La plupart des dépôts n’ont besoin de rien de plus que les champs ci-dessus. Mais parfois un dépôt doit être légèrement différent dans une composition particulière — une branche différente pour une variante de release, par exemple. C’est un overlay : un ensemble nommé de surcharges par dépôt, appliquées au moment du lock.
[repo.app-mqtt]
remote = "gh"
repo = "app-mqtt.git"
rev = "main"
# Override app-mqtt's rev only when the `release` overlay is active.
[overlay.release.app-mqtt]
rev = "release/2.x"
Avec l’overlay release actif, app-mqtt se verrouille sur release/2.x au lieu de main ; tout le reste ne bouge pas. Ne recours aux overlays que lorsqu’un dépôt doit vraiment varier selon la variante — pour le reste de ce cours, nous n’en aurons pas besoin. Voir CLI design pour la sémantique complète des overlays.
Astuce : Tu n’es pas obligé d’écrire chaque dépôt à la main. haw repo add et haw stack add éditent le manifeste à ta place, et haw import convertit un west.yml existant ou un default.xml de Google-repo directement en un haw.toml.
🗺️ 6. La vue d’ensemble
Voici le manifeste sous forme de schéma — l’intention qui s’écoule vers les stacks :
haw.toml
├─ [remote.gh] base URL + forge, named once
├─ [repo.hello-world] remote + repo + rev + groups ┐
├─ [repo.spoon-knife] remote + repo + rev + groups ├─ the repos (your intent)
│ ┘
└─ [stack.site] repos = [hello-world, spoon-knife] ← a named composition
Voilà le modèle mental complet du manifeste : les remotes nomment où, les repos déclarent quoi et quelle rev, les groups les découpent, les stacks les composent, et les overlays les ajustent par variante. Rien ici n’a encore touché le réseau ni le disque — c’est de la pure déclaration.
Tu viens de déclarer une flotte. Un remote, deux dépôts et un stack — c’est un haw.toml réel et synchronisable. Il passe à l’échelle de la même façon jusqu’à une centaine de dépôts et une douzaine de stacks.
🙌 À toi de jouer
Approprie-toi le manifeste — aucune synchro nécessaire, ce n’est que de la déclaration :
- Ajoute un troisième dépôt à
haw.toml— essaieoctocat/git-consortium.gitsur le remotegh— donne-lui unrevet mets-le dans un nouveau groupe. - Ajoute-le à la liste
reposde la stacksite, puis ajoute une deuxième stack,core-only, qui ne liste quehello-world. Remarque que le dépôt est partagé, pas copié. - Esquisse sur papier ce que tu attends sur le disque après une synchro : combien de clones ? (Indice : un par dépôt, peu importe le nombre de stacks qui le référencent.)
✅ Récapitulatif
- Le manifeste (
haw.toml) est ton intention — rien n’est cloné ni figé tant que tu ne synchronises pas. [remote.NAME]nomme une URL de base + une forge une seule fois ; les dépôts y font référence.[repo.NAME]déclare un dépôt avec unerev(branche/tag/SHA, détectée automatiquement) et desgroupslibres.[stack.NAME]compose des dépôts sous un nom — partagés, jamais copiés ; un dépôt peut appartenir à plusieurs stacks et groupes.[overlay.…]applique des surcharges par variante au moment du lock, pour le rare dépôt qui doit varier.
👉 La suite
Tu as déclaré la flotte. Maintenant, rendons-la réelle — clonons-la, figeons-la dans un lockfile, et regardons haw détecter la dérive → 3. La synchro et le lockfile.