Description
Hi,
First, a little bit of context. I am trying to programatically generate nix derivation using scala. It turned out that I need to calculate nix-store path in order to put the drv file into the nix-store (which is a requirement for realizing it).
Because of that I started to implement minimialistic version of hnix-store in scala, so that I can calculate the nix-store output path. I tried reading The Purely Functional Software
Deployment Model and the code in this repository (though I don't know much haskell), however it was enough for me to get started. Then I also found https://web.archive.org/web/20221001050043/https://comono.id/posts/2020-03-20-how-nix-instantiation-works/ which was an invaluable help.
I am at the point where I can calculate nix-store path correctly for some real derivations like "/nix/store/dsn6vl7x1hbn1akgpxync19gpx2dzy8w-bootstrap-tools"
or more complex /nix/store/32lr8w57frc1ij5wzc3hb9ks8vzs2ms1-libffi-3.4.4.drv
.
However, for some reason I cannot calculate correctly nix-store path for "/nix/store/h8z4rypl78kwais0yim76czxjnd55dsm-python3-minimal-3.10.12"
There must be something different about this package/its inputDrvs but I fail to spot anything.
I wonder if you know any better resources about the algorithm used to calculate nix-store paths.
I will list steps that I do, in the hope that maybe someone will be able to spot a mistake:
(fixed hash derivation are left out for brevity)
- replace each inputDrv with its descriptor hash and sort that list lexicographical
- mask outputs (all outputs are set to "", environment variables that refer to outputs are also set to "")
- calculate hash of such modified serialized derivation
- concatenate the hash with metadata and hash it again:
sha256("output:out:sha256:${sha256(d)}:/nix/store:${d.env("name")}")
- truncate to 160 bits and convert to base32 nix-variant
descriptor hashes are calculated as follows:
- if this is a fixed hash derivation then calculate
sha256("fixed:out:${d.hashAlgo}:${d.hash}:${d.path.get}")
- otherwise replace each inputDrv with its descriptor hash and sort that list lexicographical
- calculate hash of such modified serialized derivation -
sha256(derivation)
If anything I think that I might be handling multiple outputs incorrectly.
If there is a derivation A
that defines several outputs:
"outputs": {
"dev": {
"path": "/nix/store/8qg5ralh4c1m2pas6lbi572qykxxsxdn-libffi-3.4.4-dev"
},
"info": {
"path": "/nix/store/v5j3cysbnah4m265wlm57gjmln18qq7a-libffi-3.4.4-info"
},
"man": {
"path": "/nix/store/x92j3f8v85h216avky5rdi5xizx12j6h-libffi-3.4.4-man"
},
"out": {
"path": "/nix/store/ksz7in14b8si5f107w3ay3ph79f67i68-libffi-3.4.4"
}
},
and then we depend on such derivation in B
:
inputDrvs=[
"/nix/store/32lr8w57frc1ij5wzc3hb9ks8vzs2ms1-libffi-3.4.4.drv" -> ("dev", "out"),
...
]
I don't change my logic for calculating B
descriptor in terms of A
and I do it the same way as if there was only a single output out
both defined in B
and used in A
.
Thanks in advance 🙇♂️