[FIX] cache qemu : classer les objets de nix comme immuables

Le classeur ne connaissait pas nix. Un « <empreinte>.narinfo » et les
« nar/<empreinte>.nar.zst » tombaient dans le volatil par défaut, donc
revalidés un par un contre l'amont — relevé sur un déploiement réel :
346 narinfo, 249 nar.zst, 54 nar.xz, tous volatils, pour des fichiers dont
le NOM est l'empreinte du chemin de store et qui ne changeront jamais.

Une dérivation modifiée porte une autre empreinte, donc un autre nom. La
clé écarte l'hôte du même coup : le nom identifie le fichier sur tout
miroir. « nix-cache-info » reste volatile, il décrit le magasin amont.

--- EN ---

The classifier did not know nix. A "<hash>.narinfo" and the
"nar/<hash>.nar.zst" fell into the volatile default, so were revalidated
one by one against upstream — read off a real deployment: 346 narinfo,
249 nar.zst, 54 nar.xz, all volatile, for files whose NAME is the store
path hash and which will never change.

A modified derivation carries another hash, hence another name. The key
drops the host at the same time: the name identifies the file on any
mirror. "nix-cache-info" stays volatile, it describes the upstream store.

Assisted-by: Claude Opus 5
This commit is contained in:
Mathieu Benoit 2026-09-16 07:02:08 -04:00
parent 7c860ff047
commit f34c0d2ded
2 changed files with 41 additions and 0 deletions

View file

@ -60,6 +60,14 @@ var immutableSuffixes = []string{
// d'empreinte. Sans ces suffixes, « .metadata » ne correspond à rien et le
// fichier tombe dans le volatil par défaut, repris à chaque installation.
".whl.metadata", ".tar.gz.metadata", ".zip.metadata",
// nix : le NOM porte l'empreinte du chemin de store, chez cache.nixos.org
// comme sur tout miroir. Un « <empreinte>.narinfo » décrit ce chemin-là et
// rien d'autre ; une dérivation modifiée porte une autre empreinte, donc
// un autre nom. Sans ces suffixes ils tombaient dans le volatil par
// défaut, revalidés un par un contre l'amont : une installation NixOS en
// demande des centaines, et c'est autant d'allers-retours pour des
// fichiers qui ne changeront jamais.
".narinfo", ".nar", ".nar.xz", ".nar.zst", ".nar.bz2",
// images et supports d'installation
".qcow2", ".iso", ".img", ".raw", ".vmdk",
// archives amont

View file

@ -298,3 +298,36 @@ func TestLesMetadonneesPythonSontPortables(t *testing.T) {
}
}
}
// Les objets de nix sont adressés par l'empreinte du chemin de store : leur
// NOM est cette empreinte. Ils tombaient dans le volatil par défaut, donc
// revalidés un par un contre l'amont — une installation NixOS en demande des
// centaines, et aucun ne changera jamais.
func TestLesObjetsDeNixSontImmuables(t *testing.T) {
for _, chemin := range []string{
"/kdb6ag6vg2vfkxy3k47zqy7jm0266dhn.narinfo",
"/nar/1abcd2efgh3ijkl4mnop5qrst6uvwx7y.nar.zst",
"/nar/1abcd2efgh3ijkl4mnop5qrst6uvwx7y.nar.xz",
} {
u, err := url.Parse("https://cache.nixos.org" + chemin)
if err != nil {
t.Fatal(err)
}
if c := Classify(u); c != ClassImmutable {
t.Errorf("%s : classe %v, attendu immuable", chemin, c)
}
// Le nom identifie le fichier sur TOUT miroir : la clé écarte l'hôte.
if !PortableParChemin(u) {
t.Errorf("%s : devrait se ranger sans son hôte", chemin)
}
}
}
// « nix-cache-info » n'est PAS adressé par une empreinte : c'est la
// description du magasin amont, et elle peut changer. Elle reste volatile.
func TestLaDescriptionDuMagasinNixResteVolatile(t *testing.T) {
u, _ := url.Parse("https://cache.nixos.org/nix-cache-info")
if c := Classify(u); c == ClassImmutable {
t.Errorf("nix-cache-info tenu pour immuable : %v", c)
}
}