Commit Graph
340 Commits
Author SHA1 Message Date
rootile c64fbcbdb2 f2/command: allow piping stderr to stdout
Change-Id: I280d4888e9dc11cce93bacfddd9b4383a11525e1
2026-05-27 11:49:49 +00:00
rootile 1c81bd926d tests/f2: improve error message for failed in assertions
By default, when one uses `in` assertions, upon failure newlines in any
of the two strings is escaped, and everything is printed in a single
line.

This commit allows one to pass `-vv` to print out the left and righthand
side unescaped, with each line of the output being its own line,
improving readability a lot when dealing with multiline outputs.

Change-Id: Iaf67a20fce57d375e2c62a8e8a0957b14eec26ef
2026-05-18 10:47:00 +00:00
rootile b34f4d7b17 OWNERS: Do not inherit parent owners for f2/testlib
see [lix-weekly of
2026-04-22](https://wiki.lix.systems/link/153#bkmrk-code-ownership-of-f2)

Change-Id: I3e3df0d864a5614bb66a2d756df42c63305a7c8f
2026-05-13 22:32:30 +02:00
piegames 7cdda9c5fa flakes: checkOverlay: Don't check the second argument
It's software archaeology time.

- In 2019 (Nix 2.4), Eelco added `checkOverlays`, which strictly checked
that the overlay must be a function of two arguments, one called `final`
and the other `prev`. (dc3f52a144,
gh#3573)
- In 2024, NofairKing opened an issue about checking the exact name
being a silly idea (gh#10516). Instead of trying to make the check more
sensible, the first fix attempt simply expanded the check to allow
`previous` instead of `prev` (the author's preferred name for the
attribute, supposedly; gh#10553). After some discussion, instead a PR
got merged which simply removed the `prev` check altogether, while
leaving the `final` argument check intact for some reason
(ad65a50a94a97bf1f1a1902f43542d28a2e8206b, gh#10572).
- In 2025, over at Lix and oblivious to the latest change over at
CppNix, I came across this stupid check while trying to improve the
abstractions of the AST in Nixexpr. I spent (wasted, retrospect)
considerable amounts of time removing the exact name checks while also
improving the check overall (making it check for more than two
arguments, and also generally improved error message).
(0928d4d87a,
Id4244171123dd8a228be71ce9f04d8e9f647c111)
- Fast forward to 2026, where I run into this becursed piece of code
once again, and once again during some Lixexpr cleanups. Now that I have
seen how carlessly the issue was handled at CppNix, I can't be arsed to
give a flying fuck anymore. Out the code goes. Bye.

With this commit, all casts on `Expr` subclasses outside of libexpr
itself have been removed. No more violation of abstraction boundaries.
Good riddance.

Change-Id: I939968bb01d461764cfa0f4ea7152b4fcf1acf93
2026-05-06 17:22:19 +02:00
piegames 481fc30ae7 libexpr/flakes: Replace the AST checks with maxCallDepth = 0
Change-Id: I7130cc941b4b7432df76a3995d298edfb28e6a01
2026-05-06 17:22:19 +02:00
eldritch horrorsandpiegames d0a4b55a0e treewide: pour the rpc foundations
pour the foundations for rpc, and let them set. this is very much
unstable and must be opted into with explicit store uris (e.g. by
setting `NIX_REMOTE=daemon?protocol=any`). the daemon sockets are
not enabled by default and must be enabled with the `rpc-sockets`
experimental feature. we will not advertise this just yet because
in the current state it one has to be *very* dedicated to the rpc
cause to deploy this, but once we have some more bits migrated we
may want to add release notes and officially as for beta testing.

Co-Authored-By: piegames <git@piegames.de>
Change-Id: I85a96ccb700b91190c1eb37154bcc6ae1c03401a
2026-05-06 10:55:08 +00:00
eldritch horrors 7edb421e1b treewide: generalize socket handling
this adds the protocol registry. we also extend the systemd unit setup
to allow adding new protocols without much fussing, and we move deamon
instances into protocol-dependent scopes. this will make monitoring or
resource limiting of individual protocol daemon instances much easier.

Change-Id: Ic9da08eb074868b6e57385075c5502b081e8461f
2026-05-05 12:02:16 +00:00
eldritch horrors 4da9a53b66 f2: add test for daemon socket connection
tests both order of sockets tried and that all sockets work as expected.

Change-Id: I5aeb506e159564a0b14b6fbbe5df1e5ccdb437d5
2026-05-05 12:01:58 +00:00
piegames 078bbe6171 libexpr/eval: Fix off by one in maxCallDepth calculation
This isn't really relevant for a setting of 10k, but now that we want to
set it to 0 for Flakes it makes a difference as to whether or not one
top-level function call is allowed or not. (It shouldn't be)

Change-Id: I6bbf99826af0289c232b9d45d172a378b81abe4b
2026-05-03 13:05:46 +02:00
Jade Lovelace d94bb49cf4 fix: structured build logs: bad field types no longer fail builds
Caught by edef's harness. I rewrote the structured build log tests in
f2 and added a test for this one.

Before: it failed the build altogether:
```
building '/tmp/jade/pytest-of-jade/pytest-77/test_invalid_fields_files0_0/nix/store/skhjs5zs082nqiakj69qz32gyywz0v1a-unusual-loggi
ng.drv'...
error: unsupported JSON type 7
```

Now the output is as expected:

```
warning: Unable to handle a JSON message from the derivation builder: error: unsupported log field type number
@nix {"action": "start", "fields": [1.5], "id": 2, "type": 1, "level": 1, "text": "abc"}
```

Change-Id: Idbd28c5a4d4cf15f27207f83b730e7946a6a6964
2026-04-30 17:28:55 +00:00
piegames 076d1aa4cd eval: switch up ExprOpConcatLists error position again
This is a minor adjustment to 2b22dae1ba /
I3e9d7c1c7a6599a8e68302448bbb961d051002b7

Basically having the error point to the operand instead of the operator
kind of makes sense, but it would require error spans to *truly* make
sense, and in the meantime maintaining the logic is more hassle than it
is worth.

Change-Id: Idac98dd77a0f4a6cb386cb74e0d4eb5fd2f503e5
2026-04-30 17:14:43 +02:00
piegamesandeldritch horrors 8782c7533f eval: Improve ExprConcatStrings error messages and positions
"while evaluating a path segment" was just plain wrong

Co-authored-by: eldritch horrors <pennae@lix.systems>
Change-Id: I827374635df2887d17a8ee8b1755c078bf0b506b
2026-04-30 17:14:43 +02:00
rootile 7017def185 f2/testlib: support wrapping commands
It's useful to obtain a fully assembled command and then wrap it to
execute into something else, e.g. gdb, strace or fakeroot.

Change-Id: Ida5928fd001925549eab89edfbf0facada7ef7f1
2026-04-30 16:59:28 +02:00
Jade Lovelaceandrootile e70ae36b3f libexpr/builtins: correctly handle integer edge cases in floor/ceil
We choose to throw an error in the invalid-input space where we *can*
produce a valid (but wrong) result to allow ourselves to, mirroring
CppNix, change the semantics to not corrupt it at all in the future,
while having a middle state where it is an error.

This is a largely-rewritten version of
https://github.com/NixOS/nix/pull/13013.

Co-authored-by: rootile <lix@rootile.de>

Fixes: https://github.com/NixOS/nix/issues/12899
Upstream-PR: https://github.com/NixOS/nix/pull/13013
Change-Id: I6a6a6964cdd1a88714952e80c660d1fa57d1f2d8
2026-04-30 16:10:47 +02:00
skye be34bc0481 testing: migrate and expand import-derivation.sh and warn-import-from-derivation.sh
This started by noticing that the coverage report generated by cl/5489
showed that the error message for when allow-import-from-derivation is
disabled appeared to be not covered by any tests. Since the existing
tests for IFD were in functional, which is deprecated, I migrated those
into functional2 and added a test for erroring when IFD is disabled.

Change-Id: I565674de3dd693e023ec99d501adc4706a6a6964
2026-04-22 10:26:15 -04:00
eldritch horrors 0a09782cc8 testing: migrate store-ping.sh
notably the bad-store test previously tested *bash*, not lix. we also
need to extend the list of non-fatal errors, but that's probably fine

Change-Id: I983f4adc8047fe800323099de4037711869ee547
2026-04-20 16:08:22 +00:00
piegames 5afda956a7 tests/functional2/lang: Some refactorings
I did a pass through all files, fixing bits that have annoyed me here
and there based on vibes. Roughly:

- Replaced some out values like bools or strings with lists where
appropriate. Those tests were likely older than the value printer
- Added some parser tests where it makes sense
- Gently touched some formatting woes, while trying to not cause too
much diff noise
- Removed some dead `with (import ./lib.nix);` code

Change-Id: I8c40b2110f0b7799f68ae38ba61f049c5f1f6ee8
2026-04-19 16:07:54 +02:00
rootile ae4b3d585d f2/nix: provide a high-level wrapper for calling builtins
Change-Id: I357bd7630b96e55d000fbff1032efcf8c98dfb7b
2026-04-19 10:10:37 +00:00
rootile 62b728e766 f2/nix: provide a function to serialise python objects to nix code
Change-Id: I863029263edbc701a18b18da4b58fcb35f575614
2026-04-19 10:10:22 +00:00
skye 1e986c81ab Add test for duplicate JSON keys for builtins.fromJSON
Related to #1162
Currently if JSON with duplicate object keys is passed into `builtins.toJSON`,
it will silently drop all but the last value, keeping only the last.
This may be surprising, but as this has been consistent reliable behavior that
users might depend on, we should test for it.

Change-Id: Icc2adefabb161530e7cbfa7330919bab6a6a6964
2026-04-18 17:04:48 -04:00
eldritch horrors 36e784470c f2: turn Nix.daemon into a fixture
that way we can parametrize it over the list of protocols we have

Change-Id: Ie3fc267ade9c2ca74c163347f4fa58f09a317f40
2026-04-18 12:16:28 +00:00
Felix Uhl 32f48682de Fix test_doctor_shows_trust on macOS outside sandbox
Change-Id: I1fd456a8c5563ba63f795bc4e41811ebeaec9c73
2026-04-17 21:36:17 +02:00
rootile 15c95b95d6 tests/f2/nix: remove obsolete param documentation
Change-Id: I103d529ad0dd4ad482f9facb7e44baf61ab700d1
2026-04-16 15:05:05 +00:00
piegames c1f75860d6 builtins.flakeRefToString: Force the arguments
Without this, the primop chokes on any thunks on attributes passed in
the attrset. It even is the reason why the test contained `builtins.seq`
to work around this. Supposedly, this might have been an intentional
restriction and changing this might break things in ways I cannot forsee
due to not knowing much about Flakes, however the status quo is equally
broken:

- The error message looks like an internal error and not like some
explicitly forbidden invariant violation.
- Seemingly simple syntax literals like "-1" compile to "__sub 0 1" and
thus create a thunk which then fails, which is utterly confusing ("why
does 1 work but not -1?")
- This is a stark violation of the principle of least surprise.
- Thunking relies on maybeThunk and thunk inlining optimizations, thus
not forcing thunks turns operational details of the evaluator into
language-observable behavior. That's bad.

I am changing this now regardless of the risk of breakage, because the
bytecode evaluator will have different thunk inlining optimizations and
thus inevitably cause mismatches in behavior anyways.

Change-Id: Ifc45c4d2900e40822383670b28e4e50ab8af317a
2026-04-16 15:53:38 +02:00
skye e79278b4fc Check for throw while evaluating throw message
This is a small tweak to the logic added in cl/1511 to detect explicit
throws when printing stack traces. Now when deciding whether to print
"caused by explicit throw", it checks not only that the error is a
ThrowError and that we are in a throw, but also that the ThrowError was
thrown by *this* throw, and not by another while in the process of
evaluating this throw's operand.

It turns this:

```
let
  set = {
    inner = throw "nested throw";
  };
in
throw set.inner

error:
       … caused by explicit throw
         at /pwd/in.nix:6:1:
            5| in
            6| throw set.inner
             | ^
            7|

       … while evaluating the attribute 'inner'
         at /pwd/in.nix:3:5:
            2|   set = {
            3|     inner = throw "nested throw";
             |     ^
            4|   };

       … caused by explicit throw
         at /pwd/in.nix:3:13:
            2|   set = {
            3|     inner = throw "nested throw";
             |             ^
            4|   };

       error: nested throw
```

into this:

```
error:
       … while calling the 'throw' builtin
         at /pwd/in.nix:6:1:
            5| in
            6| throw set.inner
             | ^
            7|

       … while evaluating the attribute 'inner'
         at /pwd/in.nix:3:5:
            2|   set = {
            3|     inner = throw "nested throw";
             |     ^
            4|   };

       … caused by explicit throw
         at /pwd/in.nix:3:13:
            2|   set = {
            3|     inner = throw "nested throw";
             |             ^
            4|   };

       error: nested throw
```

Notice the difference in the top context frame. Before it incorrectly
attributed the throw error to the both throws instead of just the one
that actually threw.

Change-Id: If3b0b8311f1ae2ff1471e260fe59d9166a6a6964
2026-04-11 12:46:24 -04:00
rootile 76499d36ea f2/nix: rename _serialise to _serialise_config
Change-Id: Icaa10bf615ae5fa6d3a3957f74055c9d76f67483
2026-03-28 14:06:26 +01:00
rootile 3bc59b6e0a f2/testlib: fix typechecking for None values
Change-Id: Ie744be23d2b7963d8cd8f80cfeae051249e34d34
2026-03-28 14:06:26 +01:00
Maximilian Bosch 0488a0181d libcmd: allow setting nested attributes via --arg/--argstr
Closes #496

When running

    nix-build ../nixpkgs --arg config.allowUnfree true -A hello-unfree

the package `hello-unfree` is now built rather than getting an
eval-error rejecting instantiation. This is because `config.allowUnfree`
is now interpreted as nested attribute-set declaration, similar to how
it's done in `nix repl`.

To prevent sudden breakage, this behavior was carefully deprecated with
Nix throwing an error if the identifier for `--arg` is not a pure
identifier, but an expression as above.

Any kind of merging is rejected. I.e. doing

    nix-build ../nixpkgs --arg config '{cudaSupport = true;}' --arg config.allowUnfree true

is prohibited. That way we don't have to think about merge semantics for
cases like this (or even worse `--arg config 'rec { ... }'`). Another
nice side-effect of this is that we don't need to create an EvalState to
force the values and implement merging.

Change-Id: I8b560883a4468a3f32f915764b08f5fdd8fe71bb
2026-03-21 23:16:30 +01:00
Maximilian Bosch 2a11984a58 libexpr: allow empty attr-names in parseAttrPath if they are quoted
While it doesn't make sense to have `foo..bar`, the attribute-path
`foo."".bar` is valid and shouldn't throw.

Change-Id: Ifcddaad6233c6ba8f17cb5c953c2101d276dfeb6
2026-03-21 23:16:30 +01:00
blokyk 66d702d28d libexpr/primops: make break force its argument
previously, `builtins.break` didn't force its argument, resulting in
a value wrapped with `break` being opaque to most builtins if not
also wrapped with `seq`. see [lix-project/lix#1165] for more details
on what this can break.

this tiny fix just adds a call to `forceValue` inside `prim_break`,
but unfortunately this "breaks" a few existing tests because it
changes the call stack; those tests' golden outputs have been adjusted
without modifying their intended purpose.

Fixes #1165

[lix-project/lix#1165]: https://git.lix.systems/lix-project/lix/issues/1165

Change-Id: I5fe4ee3ff28b38aaf924125b8978130812e58fef
2026-03-21 18:38:43 +01:00
rootile bcc9350bfe tests/functional2: migrate simple.sh
Change-Id: I4366ce7d877935df98e35d733650c60f59478ace
2026-03-16 16:52:14 +00:00
Jade Lovelaceandeldritch horrors 2cea406121 version.json: begin the 2.96 series
Change-Id: I21c37e20fc2e5786367aa9b6e5ebb7ba12eb8b6c
2026-03-13 22:59:53 +01:00
eldritch horrors c914b9fc53 nix/daemon: wrap kj stdio forwarding errors nicely
not doing this has lix crash if stdio forwarding fails for odd reasons,
such as ssh failing to set up a connection due to transient dns errors.

cf #1148

Change-Id: I543b7444236e69d3c13b47fb6c6eb37c65b96763
2026-03-05 21:43:52 +00:00
Raito Bezarius 31a4f4547a Revert "libexpr/primops: allow storePath in pure evaluation mode"
This reverts commit 37ccd28c3b.

Reason for revert: https://git.lix.systems/lix-project/lix/issues/1147
More impurities were introduced than we wanted.

Fixes #1147.

Change-Id: Iec3b1d0e9a77484a68c6d9307a7a527fda236ed2
2026-03-05 17:09:46 +00:00
Raito Bezariusandeldritch horrors 37ccd28c3b libexpr/primops: allow storePath in pure evaluation mode
`builtins.storePath` allows you to use "external" knowledge of present
store paths in your store to be used in your expressions.

This is sometimes used to avoid double wrapping store paths, for example
when dealing with nixpkgs sources (`builtins.storePath pkgs.path` is a
frequent pattern).

Unfortunately, using your external knowledge of present store paths is
technically impure because Flakes is about not depending on the *STATE*
of your store, no matter what you know about it or what you do to ensure
that your knowledge is accurate.

That being said, `builtins.storePath` is already possible in the
fragment of "pure Nixlang" via a clever use of `builtins.appendContext`.

Precisely:

```
  storePath = path:
  let path' = builtins.unsafeDiscardStringContext path;
  in
  # NOTE: merging the context set in all generality is impossible
because getContext on a pure path doesn't work.
    builtins.appendContext path' { ${path'} = { path = true; }; };
```

works in pure contexts.

Because of this, we deem that storePath should be allowed in pure
contexts and users do not have to come up with a `storePath` polyfill.

Fixes #402.

Change-Id: I5fff750a4feed082745431835db451f945249cfb
Signed-off-by: Raito Bezarius <raito@lix.systems>
2026-03-04 11:33:30 +00:00
Raito Bezarius e8015836e3 libcmd/profiles: keep derivations if keep-env-derivations = true
nix3 CLI never honored that setting.

When we update a nix3 profile element with new built store paths for
which we know the deriver (the derivation path which built it), we add
the derivation paths to the profile element to prevent garbage
collection the same way the nix2 CLI logic does.

Fixes #1095.

Change-Id: Icc236d174c5ce5ffe042d1c8e1968f6cb5b50359
Signed-off-by: Raito Bezarius <raito@lix.systems>
2026-03-03 22:13:02 +00:00
Raito Bezarius 092064db4c libstore/build: allow preferLocalBuild = true to bypass max-jobs = 0
When `max-jobs = 0`, our async semaphores have null capacity and
therefore no slot token can be acquired.

In addition, a derivation with `preferLocalBuild = true` with `max-jobs
= 0` which is not a built-in derivation is not considered suitable for
being possible to build.

Our documentation in `max-jobs` writes:

> `0` is useful when using remote builders to prevent any local builds
(except for preferLocalBuild derivation attribute which executes locally
regardless).

A valid interpretation is that `preferLocalBuild` derivations (all of
them) will always execute even if `max-jobs = 0`.

This CL achieves this promise by enabling `preferLocalBuild = true`
derivations to draw in priority capacity from a `preferLocalBuild`-only
pool and then fall back to the build pool (`maxBuildJobs`).

If there's non-zero max-jobs, we make the `preferLocalBuild`-only pool
empty.

If there's zero max-jobs, we make the `preferLocalBuild`-only pool
non-empty (capacity: 1).

Remark 1: if `max-jobs = 0`, no non-`preferLocalBuild = true`
derivations can be built without a remote builder and `preferLocalBuild
= true` derivations can be built one at a time if `extra-local-jobs` is
not overridden.

Remark 2: if `max-jobs != 0`, no `preferLocalBuild = true` derivations
can bypass capacity limits, i.e. `max-jobs` unless `extra-local-jobs` is
overridden.

Fixes #855.

Change-Id: I00a0acac7375a881aec6281ebb13a4530b26e460
Signed-off-by: Raito Bezarius <raito@lix.systems>
2026-03-02 23:46:38 +01:00
Raito Bezarius 74300fd0a7 libexpr/primops: reject __json in structured attrs derivations
In structured attrs derivations, __json is used to serialize the `env`
attribute into a JSON object.

If the derivation enables structured attributes AND specify its own
`__json`, one of the field will take precedence (the reader can have fun
by guessing which one).

To reduce underspecification, we disallow `__json` in structured
attributes derivations.

Fixes #380.

Change-Id: I51c3b2af1ff9449471ba81d4c72df6a7a263eef7
Signed-off-by: Raito Bezarius <raito@lix.systems>
2026-03-01 19:05:54 +00:00
eldritch horrors 30e9387cf9 testing: migrate path-from-hash-part.sh
Change-Id: Ied00671595d82c6d446f117d6aa9c42a0c758cb6
2026-02-28 22:09:44 +00:00
eldritch horrors 8d389fcccf testing: migrate selfref-gc.sh
Change-Id: Ibead4030448fb9251be78b3c876c7f054154c83c
2026-02-28 22:09:44 +00:00
eldritch horrors f4c92f8872 testing: migrate function-trace.sh
Change-Id: I44bd28165070f55f21b052bc02ba6f2ea5787a1d
2026-02-28 22:09:44 +00:00
eldritch horrors fae0242f69 testing: migrate ssh-relay.sh
Change-Id: I520c8be1c30b4ee7660c8ceeba62a6d0757c337b
2026-02-28 22:09:44 +00:00
eldritch horrors e8cb30b11c testing: fix f2 NIX_BIN_DIR determination from meson
`nix.full_path()` is the *built* path, not the *installed* path. in the
sandbox this point to a location that contains *only* `nix`, not any of
the old-cli symlinks. any test that needs them in path would thus fail.

Change-Id: Ia651db8d1151a84f8d1b52e8993f6db61b0fe104
2026-02-28 22:09:44 +00:00
eldritch horrors dda934965d testing: migrate build-jobless.sh
Change-Id: Ica9a0c5b8bea50d302ad633d3801431adcdba5e7
2026-02-27 17:43:07 +00:00
eldritch horrors 378c86eadf testing: migrate compute-levels.sh
this test wasn't even run

Change-Id: I735c8b2d2c63a65c665d6344a98ddb3bbbf94f43
2026-02-27 17:42:17 +00:00
eldritch horrors 298373615e testing: migrate impure-eval.sh
Change-Id: Ifd2b6c117511461ce08fa3f9e63635857cb5b015
2026-02-27 17:42:17 +00:00
eldritch horrors 14d8209198 testing: migrate output-normalization.sh
Change-Id: I51a021b27fa27b531bb49b8529bae2e9bf74641a
2026-02-27 17:42:17 +00:00
eldritch horrors b2ae7c3965 testing: migrate pass-as-file.sh
Change-Id: I9c3a940ede9353e977e60e0650eaa5a64cc6fa5e
2026-02-27 17:42:17 +00:00
eldritch horrors 32a96169d6 testing: migrate optimise-store.sh
Change-Id: I900183e11ba1405c9aa72028a8902ad8cf023e69
2026-02-27 17:42:17 +00:00
eldritch horrors 5fb0dd156d testing: migrate build.sh
Change-Id: I9d2da21cc226e0c1ef2dfa4d475c1989bbbfaf79
2026-02-27 17:42:17 +00:00