We have a new `DerivationBuilder` struct, and `DerivationBuilderParams`
`DerivationBuilderCallbacks` supporting it.
`LocalDerivationGoal` doesn't subclass any of these, so we are ready to
now move them out to a new file!
Now, most of it is in two new functions:
`LocalDerivationGoal::{,un}repareBuild`.
This might seems like a step backwards from coroutines --- now we have
more functions, and are stuck with class vars --- but I don't think it
needs to be.
There's a few options here:
- (Re)introduce coroutines for the isolated building logic. We could use the
same coroutines types, or simpler ones specialized to this use-case.
The `tryLocalBuild` caller can still use `Goal::Co`, and just will
manually "pump" this inner coroutine.
- Return closures from each step. This is sort of like coroutines by
hand, but it still allows us to stop writing down the local variables
in each type.
Being able to fully-use RAII again would be very nice!
- Keep top-level first-order functions like now, but make more
functional. Instead of having one state object (`DerivationBuilder`)
for all steps (setup, run, teardown), we can have separate structs for
the live variables at each point we consume and return.
This at least avoids "are these variables active at this time?"
questions, but doesn't give us the full benefit of RAII as we must
manually ensure FIFO create/destroy orders still.
One thing to note is that by keeping the `outputLock` unlocking in
`tryLocalBuild`, we are arguably uncovering a rebuild scheduling vs
building distinction, as the output locks are pretty squarely a
scheduling concern. It's nice that the builder doesn't need to know
about them at all.
We had fields set to the same values before in our test data. This is
not a problem per-se, but does mean we wouldn't catch certain mixups.
Now, the fields are set to distinct values (where possible), which makes
the test more robust.
This requires that we refer to the `sourceInfo` instead of the
`result`. However, `sourceInfo` does not create a chain of basedir
resolution, so we add that back with `flakeDir`.
Only a much smaller `StructuredAttrs` remains, the rest is is now moved
to `DerivationOptions`.
This gets us quite close to `std::optional<StructuredAttrs>` and
`DerivationOptions` being included in `Derivation` as fields.
Now, both the unit and functional tests relating to derivation options
are tested both ways -- with input addressing and content-addressing
derivations.
This is a small optimization used when we're signing a narinfo for
multiple keys in one go. Using this sign variant, we only compute the
NAR fingerprint once, then sign it with all the keys.
It is just use for adding context to errors, but we have `addTrace` to
do that. Let the callers do that instead.
The callers doing so is a bit duplicated, yes, but this will get better
once `DerivationOptions` is included in `Derivation`.
This fixes evaluation for Windows. There are unfortunately deps that
still don't build, but this can be fixed next.
Flake lock file updates:
• Updated input 'nixpkgs':
'github:NixOS/nixpkgs/52faf482a3889b7619003c0daec593a1912fddc1?narHash=sha256-6hl6L/tRnwubHcA4pfUUtk542wn2Om%2BD4UnDhlDW9BE%3D' (2025-03-30)
→ 'github:NixOS/nixpkgs/f675531bc7e6657c10a18b565cfebd8aa9e24c14?narHash=sha256-gbl9hE39nQRpZaLjhWKmEu5ejtQsgI5TWYrIVVJn30U%3D' (2025-04-09)
The STSProfileCredentialsProviders allows to assume a specific IAM role
when accessing an S3 repository. Sometimes this is needed to obtain the
permissions to operate on the bucket.
Nix shipping with Yet Another Programming Language is often questioned
among beginners. This change highlights distinctive aspects of the Nix
language to ease the learning curve and better orient readers around
what really matters for using Nix.
Since it's on topic, this change also polishes the wording on the motivation for string contexts.
This change follows the definition from aptitude, but using precise notions from Nix:
> package managers deal with packages: collections of files that are
> bundled together and can be installed and removed as a group.
> [...]
> If a package A depends upon another package B, then B is required
> for A to operate properly.
> [...]
> The job of a package manager is to present an interface which assists
> the user in managing the collection of packages installed on his or her system.
>
> -- <https://www.debian.org/doc/manuals/aptitude/pr01s02.en.html>
An interesting addition:
> Packages are abstractions defining the granularity at which users can act
> (add, remove, upgrade, etc.) on available software.
> A distribution is a collection of packages maintained (hopefully) coherently.
>
> -- Package Upgrades in FOSS Distributions: Details and Challenges
> (Roberto Di Cosmo, Stefano Zacchiroli; 2009) <https://arxiv.org/pdf/0902.1610>
Notably these quotes and this change don't say anything about installation,
or what it means for software to be available. In practice, this is
handled downstream, e.g. in NixOS or Home Manager. Nix historically
provides rudimentary facilities for package management such as
`nix-env`, but I claim they are widely agreed upon being discouraged,
with plenty of arguments provided in <https://stop-using-nix-env.privatevoid.net>.
Similarly, the specific structure of packages is determined downstream,
since Nix is policy-free:
> Nix is policy-free; it provides mechanisms to implement various deployment policies, but does not enforce a specific one.
>
> -- The Purely Functional Software Deployment Model (Eelco Dolstra; 2006) <https://edolstra.github.io/pubs/phd-thesis.pdf>
Specifically, Nix mechanisms do not define what a package is supposed to be:
> It's worth noting that the Nix language is intended as a DSL for package and configuration management, but it has no notions of "packages" or "configurations".
>
> -- <https://gist.github.com/edolstra/29ce9d8ea399b703a7023073b0dbc00d>
This is why we say, Nix *allows* denoting packages in a certain way, but
doesn't enforce any particular way.