Compare commits

...

109 Commits

Author SHA1 Message Date
Eelco Dolstra
501a805fcd Merge pull request #11586 from NixOS/mergify/bp/2.18-maintenance/pr-11585
builtin:fetchurl: Enable TLS verification (backport #11585)
2024-09-26 00:49:30 +02:00
Eelco Dolstra
798e0bc75e Typo
(cherry picked from commit ef8987955b)
2024-09-26 00:18:08 +02:00
Eelco Dolstra
5e76cdbc79 Add release note
(cherry picked from commit 7b39cd631e)
2024-09-26 00:18:08 +02:00
Eelco Dolstra
c65ce6c6ec builtin:fetchurl: Enable TLS verification
This is better for privacy and to avoid leaking netrc credentials in a
MITM attack, but also the assumption that we check the hash no longer
holds in some cases (in particular for impure derivations).

Partially reverts 5db358d4d7.

(cherry picked from commit c04bc17a5a)
2024-09-25 21:53:27 +00:00
Eelco Dolstra
691f67d83e Bump version 2024-09-19 19:29:05 +02:00
John Ericson
d4d300c208 Merge pull request #11534 from fricklerhandwerk/backport-10652-to-2.18-maintenance
[backport 2.18] libstore: check additionalSandboxProfile
2024-09-18 15:42:38 -04:00
Théophane Hufschmitt
1524ad38d2 libstore: check additionalSandboxProfile
Make sure that `extraSandboxProfile` is set before we check whether it's
empty or not (in the `sandbox=true` case).

Also adds a test case for this.

Co-Authored-By: Artemis Tosini <lix@artem.ist>
Co-Authored-By: Eelco Dolstra <edolstra@gmail.com>
(cherry picked from commit 9bd1191fcc)
2024-09-18 21:17:07 +02:00
Eelco Dolstra
9f526847e4 Bump version 2024-09-16 20:45:50 +02:00
tomberek
a8196707ad Merge pull request #11415 from NixOS/mergify/bp/2.18-maintenance/pr-10919
install-darwin: fix _nixbld uids for macOS sequoia (backport #10919)
2024-09-16 09:19:45 -04:00
Robert Hensing
aa6f7561eb Merge pull request #11478 from NixOS/mergify/bp/2.18-maintenance/pr-11473
Fix making the build directory kept by `keep-failed` readable (backport #11473)
2024-09-16 12:38:33 +02:00
Artturin
30994e6ef4 Fix making the build directory kept by keep-failed readable
Caused by 1d3696f0fb

Without this fix the kept build directory is readable only by root

```
$ sudo ls -ld /comp-temp/nix-build-openssh-static-x86_64-unknown-linux-musl-9.8p1.drv-5
drwx------ root root 60 B Wed Sep 11 00:09:48 2024  /comp-temp/nix-build-openssh-static-x86_64-unknown-linux-musl-9.8p1.drv-5/

$ sudo ls -ld /comp-temp/nix-build-openssh-static-x86_64-unknown-linux-musl-9.8p1.drv-5/build
drwxr-xr-x nixbld1 nixbld 80 B Wed Sep 11 00:09:58 2024  /comp-temp/nix-build-openssh-static-x86_64-unknown-linux-musl-9.8p1.drv-5/build/
```

(cherry picked from commit ebebe626ff)
2024-09-11 12:54:09 +00:00
tomberek
e818523eb1 Merge branch '2.18-maintenance' into mergify/bp/2.18-maintenance/pr-10919 2024-09-10 23:39:51 -04:00
tomberek
e0fdea89c3 Merge pull request #11474 from NixOS/mergify/bp/2.18-maintenance/pr-9639
installer: allow overriding of NIX_FIRST_BUILD_ID on darwin (backport #9639)
2024-09-10 23:21:12 -04:00
Mel Zuser
c42e3e5b33 installer: allow overriding of NIX_FIRST_BUILD_ID on darwin
because there are often already users in the 300 range and it's painful
to work around.

revives #6466

(cherry picked from commit fa4bbe53e8)
2024-09-11 01:35:09 +00:00
Robert Hensing
6354f84475 Merge pull request #11445 from eclairevoyant/backport-10564-to-2.18
[backport 2.18-maintenance] AttrCursor: Remove forceErrors
2024-09-09 18:42:57 +02:00
Robert Hensing
ffaeb4b076 Merge pull request #11450 from NixOS/backport-11009-to-2.18-maintenance
installerScriptForGHA: aarch64-darwin
2024-09-09 17:57:40 +02:00
Robert Hensing
1b0805d451 installerScriptForGHA: aarch64-darwin
Backport of https://github.com/NixOS/nix/pull/11009
2024-09-09 17:47:27 +02:00
Robert Hensing
5bcc7069be Store ref<EvalState> in CachedEvalError
This makes the previous commits work.
Newer versions store it in all EvalErrors.
2024-09-09 00:38:28 +02:00
éclairevoyant
ef63ba10a2 fix 2024-09-08 12:04:26 -04:00
Eelco Dolstra
fc14197935 Typo
(cherry picked from commit eeb4c40867)
2024-09-08 10:31:25 -04:00
Eelco Dolstra
8e5ec819f8 AttrCursor: Remove forceErrors
Instead, force evaluation of the original value only if we need to
show the exception to the user.

(cherry picked from commit 2c88930ef2)
2024-09-08 10:31:23 -04:00
Eelco Dolstra
e3c55dd0d3 Add test for the evaluation cache
(cherry picked from commit 8b86f415c1)
2024-09-08 10:26:47 -04:00
Emily
517b48ffc4 install-darwin: increment base UID by 1 (#15)
(cherry picked from commit 11cf29b15c)
2024-09-03 23:57:06 +00:00
Travis A. Everett
4851e171b8 install-darwin: move nixbld gid to match first UID
(cherry picked from commit 75567423fb)

# Conflicts:
#	scripts/install-multi-user.sh
#	scripts/install-systemd-multi-user.sh
2024-09-03 23:57:05 +00:00
Travis A. Everett
3d380ed77a install-darwin: fix _nixbld uids for macOS sequoia
Starting in macOS 15 Sequoia, macOS daemon UIDs are encroaching on our
default UIDs of 301-332. This commit relocates our range up to avoid
clashing with the current UIDs of 301-304 and buy us a little time
while still leaving headroom for people installing more than 32 users.

(cherry picked from commit df36ff0d1e)

# Conflicts:
#	scripts/install-darwin-multi-user.sh
2024-09-03 23:57:05 +00:00
Robert Hensing
e154f412b7 Merge pull request #11336 from NixOS/backport-11332-to-2.18-maintenance
[Backport 2.18-maintenance] [Backport 2.22-maintenance] fix: check to see if there are any lines before
2024-08-19 17:05:38 +02:00
Tom Bereknyei
0d24420f9c fix: check to see if there are any lines before
(cherry picked from commit 59db8fd62b)
(cherry picked from commit aab801db98)
2024-08-19 14:28:08 +00:00
Eelco Dolstra
195c3e931f Bump version 2024-07-08 13:41:12 +02:00
Robert Hensing
217fadd993 Merge pull request #11047 from NixOS/backport-11046-to-2.18-maintenance
[Backport 2.18-maintenance] [Backport 2.21-maintenance] libstore: fix sandboxed builds on macOS
2024-07-05 19:40:45 +02:00
Emily
0b97319ed4 libstore: fix sandboxed builds on macOS
The recent fix for CVE-2024-38531 broke the sandbox on macOS
completely. As it’s not practical to use `chroot(2)` on
macOS, the build takes place in the main filesystem tree, and the
world‐unreadable wrapper directory prevents the build from accessing
its `$TMPDIR` at all.

The macOS sandbox probably shouldn’t be treated as any kind of a
security boundary in its current state, but this specific vulnerability
wasn’t possible to exploit on macOS anyway, as creating `set{u,g}id`
binaries is blocked by sandbox policy.

Locking down the build sandbox further may be a good idea in future,
but it already has significant compatibility issues. For now, restore
the previous status quo on macOS.

Thanks to @alois31 for helping me come to a better understanding of
the vulnerability.

Fixes: 1d3696f0fb
Closes: #11002
(cherry picked from commit af2e1142b1)
(cherry picked from commit 9feee13952)
2024-07-05 15:59:20 +00:00
Emily
ff7b9a1fd3 libstore: clean up the build directory properly
After the fix for CVE-2024-38531, this was only removing the nested
build directory, rather than the top‐level temporary directory.

Fixes: 1d3696f0fb
(cherry picked from commit 76e4adfaac)
(cherry picked from commit 0d68b40dda)
2024-07-05 15:59:20 +00:00
Robert Hensing
5e160c9cfe Merge pull request #11024 from NixOS/backport-11022-to-2.18-maintenance
[Backport 2.18-maintenance] Use proper struct sockpeercred for SO_PEERCRED for OpenBSD
2024-07-03 19:58:35 +02:00
kn
454adc40f7 Use proper struct sockpeercred for SO_PEERCRED for OpenBSD
getsockopt(2) documents this;  ucred is wrong ("cr_" member prefix, no pid).

(cherry picked from commit 10ccdb7a41)
2024-07-03 15:56:59 +00:00
John Ericson
1836493f67 Ident some CPP in nix daemon
Makes it easier for me to read.

(cherry picked from commit a09360400b)
2024-07-03 15:56:59 +00:00
Eelco Dolstra
ab9f629150 Bump version 2024-06-27 11:24:27 +02:00
tomberek
1ee7a9b84f Merge pull request from GHSA-q82p-44mg-mgh5
Fix sandbox escape 2.18
2024-06-26 18:49:22 -04:00
Eelco Dolstra
2778076699 Fix --no-sandbox
When sandboxing is disabled, we cannot put $TMPDIR underneath an
inaccessible directory.

(cherry picked from commit 86ca2d6d94c0581fda0c666c5e022784952f3542)
(cherry picked from commit 8f58b98770)
2024-06-21 16:51:11 +02:00
Eelco Dolstra
c211d3d9fe Put the chroot inside a directory that isn't group/world-accessible
Previously, the .chroot directory had permission 750 or 755 (depending
on the uid-range system feature) and was owned by root/nixbld. This
makes it possible for any nixbld user (if uid-range is disabled) or
any user (if uid-range is enabled) to inspect the contents of the
chroot of an active build and maybe interfere with it (e.g. via /tmp
in the chroot, which has 1777 permission).

To prevent this, the root is now a subdirectory of .chroot, which has
permission 700 and is owned by root/root.

(cherry picked from commit af280e72fa0e62e1c2eaccfb992c0dbb6f27f895)
2024-06-21 16:50:12 +02:00
Eelco Dolstra
5d7d7d8648 Bump version 2024-06-19 18:33:05 +02:00
Robert Hensing
c7d35a4a4d Merge pull request #10889 from NixOS/backport-10883-to-2.18-maintenance
[Backport 2.18-maintenance] fix: remove usage of XDG_RUNTIME_DIR for TMP
2024-06-10 21:01:27 +02:00
Tom Bereknyei
15fe2a81d9 fix: remove usage of XDG_RUNTIME_DIR for TMP
(cherry picked from commit 1363f51bcb)
2024-06-10 15:07:28 +00:00
Robert Hensing
fbe66d11d9 Merge pull request #10887 from NixOS/backport-10303-to-2.18-maintenance
[Backport 2.18-maintenance] fix: Treat empty TMPDIR as unset (#10303)
2024-06-10 16:48:31 +02:00
Robert Hensing
20a46e17a8 Fix includes for cherry-picks 2024-06-10 16:22:11 +02:00
Robert Hensing
45d900f5c2 HttpBinaryCacheStore: Remove *all* trailing slashes
(cherry picked from commit 850c9a6caf)
2024-06-10 16:11:04 +02:00
Robert Hensing
d1848506f8 local-derivation-goal.cc: Remove *all* trailing slashes
(cherry picked from commit dd26f41379)
2024-06-10 16:11:04 +02:00
Robert Hensing
28fc0e4f58 local-derivation-goal.cc: Reuse defaultTempDir()
(cherry picked from commit fd31945742)
2024-06-10 16:11:04 +02:00
Robert Hensing
c1f69dfc5e fix: Treat empty XDG_RUNTIME_DIR as unset
See preceding commit. Not observed in the wild, but is sensible
and consistent with TMPDIR behavior.

(cherry picked from commit b9e7f5aa2d)
2024-06-10 16:11:03 +02:00
Robert Hensing
1a336bf865 fix: Treat empty TMPDIR as unset
Fixes an instance of

    nix: src/libutil/util.cc:139: nix::Path nix::canonPath(PathView, bool): Assertion `path != ""' failed.

... which I've been getting in one of my shells for some reason.
I have yet to find out why TMPDIR was empty, but it's no reason for
Nix to break.

(cherry picked from commit c3fb2aa1f9)
2024-06-10 16:10:59 +02:00
Eelco Dolstra
8e75ad1995 Merge pull request #10609 from Ma27/backport-fchmodat2-fixes
[2.18] prohibit creating setuid/setgid binaries with fchmodat2
2024-04-25 10:27:59 +02:00
Maximilian Bosch
a75c34a2c9 Require at least libseccomp 2.5.5
Closes #10585

As it turns out, libseccomp maintains an internal syscall table and
validates each rule against it. This means that when using libseccomp
2.5.4 or older, one may pass `452` as syscall number against it, but
since it doesn't exist in the internal structure, `libseccomp` will refuse
to create a filter for that. This happens with nixpkgs-23.11, i.e. on
stable NixOS and when building Nix against the project's flake.

To work around that

* a backport of libseccomp 2.5.5 on upstream nixpkgs has been
  scheduled[1].

* the package now uses libseccomp 2.5.5 on its own already. This is to
  provide a quick fix since the correct fix for 23.11 is still a staging cycle
  away.

It must not be possible to build a Nix with an incompatible libseccomp
version (nothing can be built in a sandbox on Linux!), so configure.ac
rejects libseccomp if `__SNR_fchmodat2` is not defined.

We still need the compat header though since `SCMP_SYS(fchmodat2)`
internally transforms this into `__SNR_fchmodat2` which points to
`__NR_fchmodat2` from glibc 2.39, so it wouldn't build on glibc 2.38.
The updated syscall table from libseccomp 2.5.5 is NOT used for that
step, but used later, so we need both, our compat header and their
syscall table 🤷

[1] https://github.com/NixOS/nixpkgs/pull/306070

(cherry picked from commit 73918b0ae4)
2024-04-24 23:41:46 +02:00
Maximilian Bosch
39b08e3766 libstore/local-derivation-goal: prohibit creating setuid/setgid binaries
With Linux kernel >=6.6 & glibc 2.39 a `fchmodat2(2)` is available that
isn't filtered away by the libseccomp sandbox.

Being able to use this to bypass that restriction has surprising results
for some builds such as lxc[1]:

> With kernel ≥6.6 and glibc 2.39, lxc's install phase uses fchmodat2,
> which slips through 9b88e52846/src/libstore/build/local-derivation-goal.cc (L1650-L1663).
> The fixupPhase then uses fchmodat, which fails.
> With older kernel or glibc, setting the suid bit fails in the
> install phase, which is not treated as fatal, and then the
> fixup phase does not try to set it again.

Please note that there are still ways to bypass this sandbox[2] and this is
mostly a fix for the breaking builds.

This change works by creating a syscall filter for the `fchmodat2`
syscall (number 452 on most systems). The problem is that glibc 2.39
and seccomp 2.5.5 are needed to have the correct syscall number available
via `__NR_fchmodat2` / `__SNR_fchmodat2`, but this flake is still on
nixpkgs 23.11. To have this change everywhere and not dependent on the
glibc this package is built against, I added a header
"fchmodat2-compat.hh" that sets the syscall number based on the
architecture. On most platforms its 452 according to glibc with a few
exceptions:

    $ rg --pcre2 'define __NR_fchmodat2 (?!452)'
    sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
    58:#define __NR_fchmodat2 1073742276

    sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
    67:#define __NR_fchmodat2 6452

    sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
    62:#define __NR_fchmodat2 5452

    sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
    70:#define __NR_fchmodat2 4452

    sysdeps/unix/sysv/linux/alpha/arch-syscall.h
    59:#define __NR_fchmodat2 562

I tested the change by adding the diff below as patch to
`pkgs/tools/package-management/nix/common.nix` & then built a VM from
the following config using my dirty nixpkgs master:

    {
      vm = { pkgs, ... }: {
        virtualisation.writableStore = true;
        virtualisation.memorySize = 8192;
        virtualisation.diskSize = 12 * 1024;
        nix.package = pkgs.nixVersions.nix_2_21;
      };
    }

The original issue can be triggered via

    nix build -L github:nixos/nixpkgs/d6dc19adbda4fd92fe9a332327a8113eaa843894#lxc \
      --extra-experimental-features 'nix-command flakes'

however the problem disappears with this patch applied.

Closes #10424

[1] https://github.com/NixOS/nixpkgs/issues/300635#issuecomment-2031073804
[2] https://github.com/NixOS/nixpkgs/issues/300635#issuecomment-2030844251

(cherry picked from commit ba68045187)
2024-04-24 23:28:23 +02:00
Théophane Hufschmitt
38822ce6d7 Add a release note for the build-dir hardening 2024-04-22 18:37:54 -04:00
Théophane Hufschmitt
3481a9c41d Run the builds in a daemon-controled directory
Instead of running the builds under
`$TMPDIR/{unique-build-directory-owned-by-the-build-user}`, run them
under `$TMPDIR/{unique-build-directory-owned-by-the-daemon}/{subdir-owned-by-the-build-user}`
where the build directory is only readable and traversable by the daemon user.

This achieves two things:

1. It prevents builders from making their build directory world-readable
   (or even writeable), which would allow the outside world to interact
   with them.
2. It prevents external processes running as the build user (either
   because that somehow leaked, maybe as a consequence of 1., or because
   `build-users` isn't in use) from gaining access to the build
   directory.

fix: do not use unknown setting

tests: remove build-dir test
2024-04-22 18:37:52 -04:00
Théophane Hufschmitt
d24431dea2 Add a test for the user sandboxing
test: add user-sandboxing to hydraJobs
2024-04-22 09:56:49 -04:00
Valentin Gagarin
6f9d2e46fa show Nix logo in the manual (#10445)
the location of files is hard-coded by mdBook.
there is also seems to be no way to define custom templates, therefore
all styling has to be done in the CSS override.

Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
2024-04-09 09:37:44 +00:00
Eelco Dolstra
76364a847d Merge pull request #10327 from thufschmitt/allow-leading-dot-2.18
[Backport 2.18-maintenance] allow leading period
2024-03-26 18:08:58 +01:00
Robert Hensing
6e3548f866 Disallow store path names that are . or .. (plus opt. -)
As discussed in the maintainer meeting on 2024-01-29.

Mainly this is to avoid a situation where the name is parsed and
treated as a file name, mostly to protect users.
.-* and ..-* are also considered invalid because they might strip
on that separator to remove versions. Doesn't really work, but that's
what we decided, and I won't argue with it, because .-* probably
doesn't seem to have a real world application anyway.
We do still permit a 1-character name that's just "-", which still
poses a similar risk in such a situation. We can't start disallowing
trailing -, because a non-zero number of users will need it and we've
seen how annoying and painful such a change is.

What matters most is preventing a situation where . or .. can be
injected, and to just get this done.
2024-03-26 13:47:41 +01:00
Robert Hensing
80ea2dcc25 test: Generate distinct hashes
Gen::just is the constant generator. Don't just return that!
2024-03-26 13:47:41 +01:00
Robert Hensing
51332020c0 test: Generate distinct path names
Gen::just is the constant generator. Don't just return that!
2024-03-26 10:20:43 +00:00
Robert Hensing
752e8e4acd parseStorePath: Support leading period 2024-03-26 10:20:43 +00:00
Robert Hensing
379274fd7f Revert "StorePath: reject names starting with '.'"
This reverts commit 24bda0c7b3.
2024-03-26 10:20:43 +00:00
Eelco Dolstra
d137077271 Bump version 2024-03-07 15:03:40 +01:00
Eelco Dolstra
0bd62229cd Bump version 2024-03-07 13:10:53 +01:00
Eelco Dolstra
17a598e644 Merge pull request from GHSA-2ffj-w4mj-pg37
Sandbox escape 2.18
2024-03-07 11:56:24 +01:00
Tom Bereknyei
9e7065bef5 Add release notes
Co-authored-by: Theophane Hufschmitt <theophane.hufschmitt@tweag.io>
2024-03-07 09:33:44 +01:00
Tom Bereknyei
4bc5a3510f Copy the output of fixed-output derivations before registering them
It is possible to exfiltrate a file descriptor out of the build sandbox
of FODs, and use it to modify the store path after it has been
registered.
To avoid that issue, don't register the output of the build, but a copy
of it (that will be free of any leaked file descriptor).

Co-authored-by: Theophane Hufschmitt <theophane.hufschmitt@tweag.io>
Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
2024-03-07 09:33:44 +01:00
Tom Bereknyei
f8d20e91a4 Add a NixOS test for the sandbox escape
Test that we can't leverage abstract unix domain sockets to leak file
descriptors out of the sandbox and modify the path after it has been
registered.

Co-authored-by: Theophane Hufschmitt <theophane.hufschmitt@tweag.io>
2024-03-07 09:33:40 +01:00
tomberek
ec177b98f3 Merge pull request #10170 from johnrichardrinehart/jrinehart/2_18-faster-flake-lock-parsing
2.18 faster flake lock parsing
2024-03-07 00:11:54 -05:00
Graham Dennis
7b237ebe5c Faster flake.lock parsing
This PR reduces the creation of short-lived basic_json objects while
parsing flake.lock files. For large flake.lock files (~1.5MB) I was
observing ~60s being spent for trivial nix build operations while
after this change it is now taking ~1.6s.

(cherry picked from commit 7fd0de38c6)
2024-03-06 17:57:15 -08:00
github-actions[bot]
afb55f36df Fix bad_format_string error when builder stdout contains % (#10063)
(cherry picked from commit e2b6821ca0)

Co-authored-by: roblabla <unfiltered@roblab.la>
2024-02-22 23:12:29 +01:00
Eelco Dolstra
2a6a7aad3f Merge pull request #10018 from NixOS/fix-18-build
[2.18] Fix the build
2024-02-15 11:00:13 +01:00
Théophane Hufschmitt
f36d4aefd3 Fix the build
bef68e53b9 (backport of
31ebc6028b) accidentally broke the build
because of a change in the constructor of `SourcePath` between 2.18 and
master. Fix that.
2024-02-15 09:50:12 +01:00
github-actions[bot]
2db5c5326b fix location of _redirects file (#9956) 2024-02-07 11:44:06 +01:00
Eelco Dolstra
5f7f68e0a8 Merge pull request #9827 from NixOS/backport-9363-to-2.18-maintenance
[Backport 2.18-maintenance] Fix symlink handling
2024-01-22 14:30:17 +01:00
Eelco Dolstra
bef68e53b9 Fix symlink handling
This restores the symlink handling behaviour prior to
94812cca98.

Fixes #9298.

(cherry picked from commit 31ebc6028b)
2024-01-21 20:53:30 +00:00
John Ericson
60eb80593f Merge pull request #9738 from shlevy/ifd-buildStore-2.18
(Backport #9661) Build IFD in the build store when using eval-store.
2024-01-11 10:06:20 -05:00
Shea Levy
ba48ab4b95 Merge branch '2.18-maintenance' into ifd-buildStore-2.18 2024-01-11 07:21:16 -05:00
Shea Levy
e7c2b35827 Build IFD in the build store when using eval-store.
Previously, IFDs would be built within the eval store, even though one
is typically using `--eval-store` precisely to *avoid* local builds.

Because the resulting Nix expression must be copied back to the eval
store in order to be imported, this requires the eval store to trust
the build store's signatures.

(cherry picked from commit c3942ef85f)
2024-01-11 06:34:27 -05:00
Shea Levy
be208d8e78 remote-store test: Break out IFD expression into a separate file
(cherry picked from commit 9cb287657b)
2024-01-11 06:30:02 -05:00
github-actions[bot]
4dd5171652 fix an old lost direct (#9717)
this part must have been moved quite a while ago, but apparently so far
no one noticed

(cherry picked from commit 6db805b3d1)

Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
2024-01-08 20:57:39 +01:00
John Ericson
4a1c3762df Merge pull request #9543 from NixOS/backport-9542-to-2.18-maintenance
[Backport 2.18-maintenance] Add missing `-pthread` for test support libraries
2023-12-05 19:26:18 -05:00
John Ericson
615bd655e5 Add missing -pthread for test support libraries
This is good in general (see how the other libraries also have long had
it, since 49fe9592a4) but in particular
needed to fix the NetBSD build.

(cherry picked from commit b23273f6a2)
2023-12-05 23:44:41 +00:00
John Ericson
211b6e1855 Merge pull request #9517 from NixOS/2.18-flatten-tests
[Backport 2.18-maintanence] Backport test source layout reorgs
2023-12-01 13:53:13 -05:00
John Ericson
f7f37035c8 Move tests to separate directories, and document
Today, with the tests inside a `tests` intermingled with the
corresponding library's source code, we have a few problems:

- We have to be careful that wildcards don't end up with tests being
  built as part of Nix proper, or test headers being installed as part
  of Nix proper.

- Tests in libraries but not executables is not right:

  - It means each executable runs the previous unit tests again, because
    it needs the libraries.

  - It doesn't work right on Windows, which doesn't want you to load a
    DLL just for the side global variable . It could be made to work
    with the dlopen equivalent, but that's gross!

This reorg solves these problems.

There is a remaining problem which is that sibbling headers (like
`hash.hh` the test header vs `hash.hh` the main `libnixutil` header) end
up shadowing each other. This PR doesn't solve that. That is left as
future work for a future PR.

Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>

(cherry picked from commit 91b6833686)
(cherry picked from commit a61e42adb5)
2023-12-01 13:05:03 -05:00
John Ericson
30dcc19d1f Put functional tests in tests/functional
I think it is bad for these reasons when `tests/` contains a mix of
functional and integration tests

 - Concepts is harder to understand, the documentation makes a good
   unit vs functional vs integration distinction, but when the
   integration tests are just two subdirs within `tests/` this is not
   clear.

 - Source filtering in the `flake.nix` is more complex. We need to
   filter out some of the dirs from `tests/`, rather than simply pick
   the dirs we want and take all of them. This is a good sign the
   structure of what we are trying to do is not matching the structure
   of the files.

With this change we have a clean:
```shell-session
$ git show 'HEAD:tests'
tree HEAD:tests

functional/
installer/
nixos/
```

(cherry picked from commit 68c81c7375)
2023-12-01 12:06:43 -05:00
John Ericson
7242521265 Merge pull request #9514 from NixOS/2.18-nixpkgs-bump
[Backport 2.18-maintainence] nixpkgs bump
2023-12-01 11:30:05 -05:00
Robert Hensing
016f936df6 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/31ed632c692e6a36cfc18083b88ece892f863ed4' (2023-09-21)
  → 'github:NixOS/nixpkgs/9ba29e2346bc542e9909d1021e8fd7d4b3f64db0' (2023-11-23)

(cherry picked from commit fe4f573d49)
(cherry picked from commit f01baf5f06
2023-12-01 11:08:15 -05:00
Robert Hensing
083b198bb7 Merge pull request #9471 from NixOS/backport-9459-to-2.18-maintenance
[Backport 2.18-maintenance] add path based redirects
2023-11-27 15:15:52 +01:00
Valentin Gagarin
8fb477a6e7 add path based redirects
up to now, those were managed outside of this repo, which as
unsurprisingly a real hassle to deal with if one wanted to prevent URLs
from breaking when moving pages around. this change removes a large part
of the friction involved in moving content in the Nix manual.

possible next steps for further automation:
- check for content that moved and warn if it's not reachable from
  links that were valid prior to a change
- create redirect rules automatically based on this information

(cherry picked from commit 2b7016cc56)
2023-11-27 13:29:00 +00:00
John Ericson
05b7e2dc57 Merge pull request #9436 from NixOS/backport-9431-to-2.18-maintenance
[Backport 2.18-maintenance] Add missing `-lrapidcheck` fixing build with shared lib
2023-11-22 09:35:24 -05:00
John Ericson
89a66633b7 Add missing -lrapidcheck fixing build with shared lib
https://github.com/NixOS/nixpkgs/pull/269064 makes rapidcheck be build
as a shared lib, but that broke Nix because the `-lrapidcheck` was
missing. This fixes that (and doesn't break Nix what the library is a
static archive as today).

(cherry picked from commit 46131567da)
2023-11-22 04:48:11 +00:00
Théophane Hufschmitt
fadad86276 Merge pull request #9406 from NixOS/backport-9390-to-2.18-maintenance
[Backport 2.18-maintenance] fetchTree: clarify docs for shallow flag
2023-11-20 15:38:25 +01:00
DavHau
23775b7364 fetchTree: clarify docs for shallow flag
(cherry picked from commit 796a7eb92d)
2023-11-20 14:16:03 +00:00
Robert Hensing
8e72a529da Merge pull request #9366 from NixOS/backport-9187-to-2.18-maintenance
[2.18-maintenance] Backport #9187 apple-virt
2023-11-16 19:44:32 +01:00
Robert Hensing
af21431140 libstore: Add apple-virt to system features when available
I'm sure that we'll adjust the implementation over time, but this
at least discerns between an apple silicon bare metal machine and
a tart VM.

(cherry picked from commit 9277eb276b)
2023-11-16 18:59:06 +01:00
Eelco Dolstra
184a20ec04 Merge pull request #9334 from fricklerhandwerk/backport-2.18-fix-anchors
backport fix for the `--help` output to 2.18
2023-11-16 15:02:18 +01:00
Valentin Gagarin
a68bf15fe6 backport fix for the --help output 2023-11-10 19:22:42 +01:00
John Ericson
78fd621397 Merge pull request #9122 from NixOS/backport-9095-to-2.18-maintenance
[Backport 2.18-maintenance] StorePath: reject names starting with '.'
2023-10-09 10:27:51 -04:00
edef
82040664e4 StorePath: reject names starting with '.'
This has been the behaviour before Nix 2.4. It was dropped in a rewrite
in 759947bf72, allowing the creation of
store paths that aren't considered valid by older Nix versions or other
Nix tooling.

Nix 2.4 didn't ship in NixOS until 22.05, and stdenv.mkDerivation in
nixpkgs drops leading periods since April 2022, so it's unlikely anyone
is relying on the current lax behaviour.

Closes #9091.

Change-Id: I4a57bd9899e1b0dba56870ae5a1b680918a18ce9
(cherry picked from commit 24bda0c7b3)
2023-10-08 12:21:18 +00:00
Eelco Dolstra
f5f4de6a55 Merge pull request #9086 from NixOS/backport-9081-to-2.18-maintenance
[Backport 2.18-maintenance] Revert "Adapt scheduler to work with dynamic derivations"
2023-10-02 17:05:54 +02:00
John Ericson
72b65981f9 Revert "Adapt scheduler to work with dynamic derivations"
This reverts commit 5e3986f59c. This
un-implements RFC 92 but fixes the critical bug #9052 which many people
are hitting. This is a decent stop-gap until a minimal reproduction of
that bug is found and a proper fix can be made.

Mostly fixed #9052, but I would like to leave that issue open until we
have a regression test, so I can then properly fix the bug (unbreaking
RFC 92) later.

(cherry picked from commit 8440afbed7)
2023-10-02 15:05:23 +00:00
Eelco Dolstra
7e2399b123 Merge pull request #9079 from hercules-ci/backport-9022-to-2.18-maintenance
[Backport 2.18-maintenance] pathExists: isDir when endswith /.
2023-10-02 14:08:25 +02:00
Robert Hensing
860f64c345 pathExists: isDir when endswith /.
(cherry picked from commit f8a3893e8d)
2023-10-01 13:58:20 +01:00
Eelco Dolstra
9e212344f9 Merge pull request #9036 from NixOS/backport-9026-to-2.18-maintenance
[Backport 2.18-maintenance] flake: complete update to 23.05
2023-09-25 15:05:25 +02:00
Gerg-L
277ba90779 flake: complete update to 23.05
(cherry picked from commit f264d9ff08)
2023-09-25 08:43:54 +00:00
Robert Hensing
a4445859ab Merge pull request #9009 from NixOS/backport-9008-to-2.18-maintenance
[Backport 2.18-maintenance] Re-enable systemd-nspawn test
2023-09-21 13:13:16 +02:00
Cole Helbling
f3005632c4 Re-enable systemd-nspawn test
It was disabled in c6953d1ff6 because
a recent Nixpkgs bump brought in a new systemd which changed how
systemd-nspawn worked.

As far as I can tell, the issue was caused by this upstream systemd
commit:
b71a0192c0

Bind-mounting the host's `/sys` and `/proc` into the container's
`/run/host/{sys,proc}` fixes the issue and allows the test to succeed.

(cherry picked from commit 883092e3f7)
2023-09-20 17:03:47 +00:00
Eelco Dolstra
40a014416b Bump version 2023-09-20 15:20:52 +02:00
Eelco Dolstra
44fb119218 Mark official release 2023-09-20 12:49:01 +02:00
728 changed files with 1666 additions and 935 deletions

2
.github/labeler.yml vendored
View File

@@ -20,4 +20,4 @@
# Unit tests
- src/*/tests/**/*
# Functional and integration tests
- tests/**/*
- tests/functional/**/*

40
.gitignore vendored
View File

@@ -41,14 +41,14 @@ perl/Makefile.config
/src/libexpr/parser-tab.hh
/src/libexpr/parser-tab.output
/src/libexpr/nix.tbl
/src/libexpr/tests/libnixexpr-tests
/tests/unit/libexpr/libnixexpr-tests
# /src/libstore/
*.gen.*
/src/libstore/tests/libnixstore-tests
/tests/unit/libstore/libnixstore-tests
# /src/libutil/
/src/libutil/tests/libnixutil-tests
/tests/unit/libutil/libnixutil-tests
/src/nix/nix
@@ -79,24 +79,24 @@ perl/Makefile.config
/src/build-remote/build-remote
# /tests/
/tests/test-tmp
/tests/common/vars-and-functions.sh
/tests/result*
/tests/restricted-innocent
/tests/shell
/tests/shell.drv
/tests/config.nix
/tests/ca/config.nix
/tests/dyn-drv/config.nix
/tests/repl-result-out
/tests/test-libstoreconsumer/test-libstoreconsumer
# /tests/functional/
/tests/functional/test-tmp
/tests/functional/common/vars-and-functions.sh
/tests/functional/result*
/tests/functional/restricted-innocent
/tests/functional/shell
/tests/functional/shell.drv
/tests/functional/config.nix
/tests/functional/ca/config.nix
/tests/functional/dyn-drv/config.nix
/tests/functional/repl-result-out
/tests/functional/test-libstoreconsumer/test-libstoreconsumer
# /tests/lang/
/tests/lang/*.out
/tests/lang/*.out.xml
/tests/lang/*.err
/tests/lang/*.ast
# /tests/functional/lang/
/tests/functional/lang/*.out
/tests/functional/lang/*.out.xml
/tests/functional/lang/*.err
/tests/functional/lang/*.ast
/perl/lib/Nix/Config.pm
/perl/lib/Nix/Store.cc

View File

@@ -1 +1 @@
2.18.0
2.18.8

View File

@@ -52,7 +52,7 @@ Check out the [security policy](https://github.com/NixOS/nix/security/policy).
- [ ] Fixes an [idea approved](https://github.com/NixOS/nix/labels/idea%20approved) issue
- [ ] Tests, as appropriate:
- Functional tests [`tests/**.sh`](./tests)
- Functional tests [`tests/functional/**.sh`](./tests/functional)
- Unit tests [`src/*/tests`](./src/)
- Integration tests [`tests/nixos/*`](./tests/nixos)
- [ ] User documentation in the [manual](..doc/manual/src)

View File

@@ -23,14 +23,17 @@ makefiles = \
ifeq ($(tests), yes)
makefiles += \
src/libutil/tests/local.mk \
src/libstore/tests/local.mk \
src/libexpr/tests/local.mk \
tests/local.mk \
tests/ca/local.mk \
tests/dyn-drv/local.mk \
tests/test-libstoreconsumer/local.mk \
tests/plugins/local.mk
tests/unit/libutil/local.mk \
tests/unit/libutil-support/local.mk \
tests/unit/libstore/local.mk \
tests/unit/libstore-support/local.mk \
tests/unit/libexpr/local.mk \
tests/unit/libexpr-support/local.mk \
tests/functional/local.mk \
tests/functional/ca/local.mk \
tests/functional/dyn-drv/local.mk \
tests/functional/test-libstoreconsumer/local.mk \
tests/functional/plugins/local.mk
else
makefiles += \
mk/disable-tests.mk

View File

@@ -252,6 +252,17 @@ case "$host_os" in
[CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS"])
have_seccomp=1
AC_DEFINE([HAVE_SECCOMP], [1], [Whether seccomp is available and should be used for sandboxing.])
AC_COMPILE_IFELSE([
AC_LANG_SOURCE([[
#include <seccomp.h>
#ifndef __SNR_fchmodat2
# error "Missing support for fchmodat2"
#endif
]])
], [], [
echo "libseccomp is missing __SNR_fchmodat2. Please provide libseccomp 2.5.5 or later"
exit 1
])
else
have_seccomp=
fi

View File

@@ -39,17 +39,21 @@ INPUT = \
src/libcmd \
src/libexpr \
src/libexpr/flake \
src/libexpr/tests \
src/libexpr/tests/value \
tests/unit/libexpr \
tests/unit/libexpr/value \
tests/unit/libexpr/test \
tests/unit/libexpr/test/value \
src/libexpr/value \
src/libfetchers \
src/libmain \
src/libstore \
src/libstore/build \
src/libstore/builtins \
src/libstore/tests \
tests/unit/libstore \
tests/unit/libstore/test \
src/libutil \
src/libutil/tests \
tests/unit/libutil \
tests/unit/libutil/test \
src/nix \
src/nix-env \
src/nix-store

View File

@@ -1,3 +1,25 @@
:root {
--sidebar-width: 23em;
}
h1.menu-title::before {
content: "";
background-image: url("./favicon.svg");
padding: 1.25em;
background-position: center center;
background-size: 2em;
background-repeat: no-repeat;
}
h1.menu-title {
padding: 0.5em;
}
.sidebar .sidebar-scrollbox {
padding: 1em;
}
h1:not(:first-of-type) {
margin-top: 1.3em;
}

View File

@@ -5,7 +5,7 @@ let
inherit (import ./utils.nix) concatStrings optionalString filterAttrs trim squash unique showSettings;
in
commandDump:
inlineHTML: commandDump:
let
@@ -30,7 +30,7 @@ let
${maybeSubcommands}
${maybeDocumentation}
${maybeStoreDocs}
${maybeOptions}
'';
@@ -70,7 +70,7 @@ let
* [`${command} ${name}`](./${appendName filename name}.md) - ${subcmd.description}
'';
maybeDocumentation = optionalString
maybeStoreDocs = optionalString
(details ? doc)
(replaceStrings ["@stores@"] [storeDocs] details.doc);
@@ -91,17 +91,20 @@ let
listOptions = opts: concatStringsSep "\n" (attrValues (mapAttrs showOption opts));
showOption = name: option:
let
result = trim ''
- ${item}
${option.description}
'';
item = if inlineHTML
then ''<span id="opt-${name}">[`--${name}`](#opt-${name})</span> ${shortName} ${labels}''
else "`--${name}` ${shortName} ${labels}";
shortName = optionalString
(option ? shortName)
("/ `-${option.shortName}`");
labels = optionalString
(option ? labels)
(concatStringsSep " " (map (s: "*${s}*") option.labels));
in trim ''
- <span id="opt-${name}">[`--${name}`](#opt-${name})</span> ${shortName} ${labels}
${option.description}
'';
in result;
categories = sort lessThan (unique (map (cmd: cmd.category) (attrValues allOptions)));
in concatStrings (map showCategory categories);
in squash result;
@@ -162,7 +165,7 @@ let
**Settings**:
${showSettings { useAnchors = false; } settings}
${showSettings { inherit inlineHTML; } settings}
'';
in concatStrings (attrValues (mapAttrs showStore commandInfo.stores));

View File

@@ -98,12 +98,12 @@ $(d)/src/SUMMARY.md: $(d)/src/SUMMARY.md.in $(d)/src/command-ref/new-cli $(d)/sr
$(d)/src/command-ref/new-cli: $(d)/nix.json $(d)/utils.nix $(d)/generate-manpage.nix $(bindir)/nix
@rm -rf $@ $@.tmp
$(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-manpage.nix (builtins.readFile $<)'
$(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-manpage.nix true (builtins.readFile $<)'
@mv $@.tmp $@
$(d)/src/command-ref/conf-file.md: $(d)/conf-file.json $(d)/utils.nix $(d)/src/command-ref/conf-file-prefix.md $(d)/src/command-ref/experimental-features-shortlist.md $(bindir)/nix
@cat doc/manual/src/command-ref/conf-file-prefix.md > $@.tmp
$(trace-gen) $(nix-eval) --expr '(import doc/manual/utils.nix).showSettings { useAnchors = true; } (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp;
$(trace-gen) $(nix-eval) --expr '(import doc/manual/utils.nix).showSettings { inlineHTML = true; } (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp;
@mv $@.tmp $@
$(d)/nix.json: $(bindir)/nix
@@ -173,7 +173,7 @@ doc/manual/generated/man1/nix3-manpages: $(d)/src/command-ref/new-cli
done
@touch $@
$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/src/SUMMARY.md $(d)/src/command-ref/new-cli $(d)/src/contributing/experimental-feature-descriptions.md $(d)/src/command-ref/conf-file.md $(d)/src/language/builtins.md $(d)/src/language/builtin-constants.md
$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/src/SUMMARY.md $(d)/src/command-ref/new-cli $(d)/src/contributing/experimental-feature-descriptions.md $(d)/src/command-ref/conf-file.md $(d)/src/language/builtins.md $(d)/src/language/builtin-constants.md $(d)/src/favicon.png $(d)/src/favicon.svg
$(trace-gen) \
tmp="$$(mktemp -d)"; \
cp -r doc/manual "$$tmp"; \

View File

@@ -1,7 +1,9 @@
// redirect rules for anchors ensure backwards compatibility of URLs.
// this must be done on the client side, as web servers do not see the anchor part of the URL.
// redirect rules for URL fragments (client-side) to prevent link rot.
// this must be done on the client side, as web servers do not see the fragment part of the URL.
// it will only work with JavaScript enabled in the browser, but this is the best we can do here.
// see ./_redirects for path redirects (client-side)
// redirections are declared as follows:
// redirects are declared as follows:
// each entry has as its key a path matching the requested URL path, relative to the mdBook document root.
//
// IMPORTANT: it must specify the full path with file name and suffix
@@ -19,6 +21,7 @@ const redirects = {
"chap-distributed-builds": "advanced-topics/distributed-builds.html",
"chap-post-build-hook": "advanced-topics/post-build-hook.html",
"chap-post-build-hook-caveats": "advanced-topics/post-build-hook.html#implementation-caveats",
"chap-writing-nix-expressions": "language/index.html",
"part-command-ref": "command-ref/command-ref.html",
"conf-allow-import-from-derivation": "command-ref/conf-file.html#conf-allow-import-from-derivation",
"conf-allow-new-privileges": "command-ref/conf-file.html#conf-allow-new-privileges",

View File

@@ -0,0 +1,8 @@
---
synopsis: Harden the user sandboxing
significance: significant
issues:
prs: <only provided once merged>
---
The build directory has been hardened against interference with the outside world by nesting it inside another directory owned by (and only readable by) the daemon user.

View File

@@ -0,0 +1,10 @@
---
synopsis: Store paths are allowed to start with `.`
issues: 912
prs: 9867 9091 9095 9120 9121 9122 9130 9219 9224
---
Leading periods were allowed by accident in Nix 2.4. The Nix team has considered this to be a bug, but this behavior has since been relied on by users, leading to unnecessary difficulties.
From now on, leading periods are officially, definitively supported. The names `.` and `..` are disallowed, as well as those starting with `.-` or `..-`.
Nix versions that denied leading periods are documented [in the issue](https://github.com/NixOS/nix/issues/912#issuecomment-1919583286).

View File

@@ -0,0 +1,8 @@
---
synopsis: "`<nix/fetchurl.nix>` uses TLS verification"
prs: [11585]
---
Previously `<nix/fetchurl.nix>` did not do TLS verification. This was because the Nix sandbox in the past did not have access to TLS certificates, and Nix checks the hash of the fetched file anyway. However, this can expose authentication data from `netrc` and URLs to man-in-the-middle attackers. In addition, Nix now in some cases (such as when using impure derivations) does *not* check the hash. Therefore we have now enabled TLS verification. This means that downloads by `<nix/fetchurl.nix>` will now fail if you're fetching from a HTTPS server that does not have a valid certificate.
`<nix/fetchurl.nix>` is also known as the builtin derivation builder `builtin:fetchurl`. It's not to be confused with the evaluation-time function `builtins.fetchurl`, which was not affected by this issue.

View File

@@ -109,7 +109,6 @@
- [CLI guideline](contributing/cli-guideline.md)
- [C++ style guide](contributing/cxx.md)
- [Release Notes](release-notes/release-notes.md)
- [Release X.Y (202?-??-??)](release-notes/rl-next.md)
- [Release 2.18 (2023-09-20)](release-notes/rl-2.18.md)
- [Release 2.17 (2023-07-24)](release-notes/rl-2.17.md)
- [Release 2.16 (2023-05-31)](release-notes/rl-2.16.md)

30
doc/manual/src/_redirects Normal file
View File

@@ -0,0 +1,30 @@
# redirect rules for paths (server-side) to prevent link rot.
# see ./redirects.js for redirects based on URL fragments (client-side)
#
# concrete user story this supports:
# - user finds URL to the manual for Nix x.y
# - Nix x.z (z > y) is the most recent release
# - updating the version in the URL will show the right thing
#
# format documentation:
# - https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file
# - https://docs.netlify.com/routing/redirects/redirect-options/
#
# conventions:
# - always force (<CODE>!) since this allows re-using file names
# - group related paths to ease readability
# - always append new redirects to the end of the file
# - redirects that should have been there but are missing can be inserted where they belong
/expressions/expression-language /language/ 301!
/expressions/language-values /language/values 301!
/expressions/language-constructs /language/constructs 301!
/expressions/language-operators /language/operators 301!
/expressions/* /language/:splat 301!
/package-management/basic-package-mgmt /command-ref/nix-env 301!
/package-management/channels* /command-ref/nix-channel 301!
/package-management/s3-substituter* /command-ref/new-cli/nix3-help-stores#s3-binary-cache-store 301!

View File

@@ -3,16 +3,28 @@
## Unit-tests
The unit-tests for each Nix library (`libexpr`, `libstore`, etc..) are defined
under `src/{library_name}/tests` using the
under `tests/unit/{library_name}/tests` using the
[googletest](https://google.github.io/googletest/) and
[rapidcheck](https://github.com/emil-e/rapidcheck) frameworks.
You can run the whole testsuite with `make check`, or the tests for a specific component with `make libfoo-tests_RUN`.
Finer-grained filtering is also possible using the [--gtest_filter](https://google.github.io/googletest/advanced.html#running-a-subset-of-the-tests) command-line option, or the `GTEST_FILTER` environment variable.
### Unit test support libraries
There are headers and code which are not just used to test the library in question, but also downstream libraries.
For example, we do [property testing] with the [rapidcheck] library.
This requires writing `Arbitrary` "instances", which are used to describe how to generate values of a given type for the sake of running property tests.
Because types contain other types, `Arbitrary` "instances" for some type are not just useful for testing that type, but also any other type that contains it.
Downstream types frequently contain upstream types, so it is very important that we share arbitrary instances so that downstream libraries' property tests can also use them.
It is important that these testing libraries don't contain any actual tests themselves.
On some platforms they would be run as part of every test executable that uses them, which is redundant.
On other platforms they wouldn't be run at all.
## Functional tests
The functional tests reside under the `tests` directory and are listed in `tests/local.mk`.
The functional tests reside under the `tests/functional` directory and are listed in `tests/functional/local.mk`.
Each test is a bash script.
### Running the whole test suite
@@ -21,8 +33,8 @@ The whole test suite can be run with:
```shell-session
$ make install && make installcheck
ran test tests/foo.sh... [PASS]
ran test tests/bar.sh... [PASS]
ran test tests/functional/foo.sh... [PASS]
ran test tests/functional/bar.sh... [PASS]
...
```
@@ -30,14 +42,14 @@ ran test tests/bar.sh... [PASS]
Sometimes it is useful to group related tests so they can be easily run together without running the entire test suite.
Each test group is in a subdirectory of `tests`.
For example, `tests/ca/local.mk` defines a `ca` test group for content-addressed derivation outputs.
For example, `tests/functional/ca/local.mk` defines a `ca` test group for content-addressed derivation outputs.
That test group can be run like this:
```shell-session
$ make ca.test-group -j50
ran test tests/ca/nix-run.sh... [PASS]
ran test tests/ca/import-derivation.sh... [PASS]
ran test tests/functional/ca/nix-run.sh... [PASS]
ran test tests/functional/ca/import-derivation.sh... [PASS]
...
```
@@ -56,21 +68,21 @@ install-tests-groups += $(test-group-name)
Individual tests can be run with `make`:
```shell-session
$ make tests/${testName}.sh.test
ran test tests/${testName}.sh... [PASS]
$ make tests/functional/${testName}.sh.test
ran test tests/functional/${testName}.sh... [PASS]
```
or without `make`:
```shell-session
$ ./mk/run-test.sh tests/${testName}.sh
ran test tests/${testName}.sh... [PASS]
$ ./mk/run-test.sh tests/functional/${testName}.sh
ran test tests/functional/${testName}.sh... [PASS]
```
To see the complete output, one can also run:
```shell-session
$ ./mk/debug-test.sh tests/${testName}.sh
$ ./mk/debug-test.sh tests/functional/${testName}.sh
+ foo
output from foo
+ bar
@@ -105,7 +117,7 @@ edit it like so:
Then, running the test with `./mk/debug-test.sh` will drop you into GDB once the script reaches that point:
```shell-session
$ ./mk/debug-test.sh tests/${testName}.sh
$ ./mk/debug-test.sh tests/functional/${testName}.sh
...
+ gdb blash blub
GNU gdb (GDB) 12.1
@@ -124,9 +136,11 @@ This technique is to include the exact output/behavior of a former version of Ni
For example, this technique is used for the language tests, to check both the printed final value if evaluation was successful, and any errors and warnings encountered.
It is frequently useful to regenerate the expected output.
To do that, rerun the failed test with `_NIX_TEST_ACCEPT=1`.
(At least, this is the convention we've used for `tests/lang.sh`.
If we add more characterization testing we should always strive to be consistent.)
To do that, rerun the failed test(s) with `_NIX_TEST_ACCEPT=1`.
For example:
```bash
_NIX_TEST_ACCEPT=1 make tests/functional/lang.sh.test
```
An interesting situation to document is the case when these tests are "overfitted".
The language tests are, again, an example of this.

BIN
doc/manual/src/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="587.11" height="516.604" viewBox="0 0 550.416 484.317"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#699ad7;stop-opacity:1"/><stop offset=".243" style="stop-color:#7eb1dd;stop-opacity:1"/><stop offset="1" style="stop-color:#7ebae4;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#415e9a;stop-opacity:1"/><stop offset=".232" style="stop-color:#4a6baf;stop-opacity:1"/><stop offset="1" style="stop-color:#5277c3;stop-opacity:1"/></linearGradient><linearGradient xlink:href="#a" id="c" x1="200.597" x2="290.087" y1="351.411" y2="506.188" gradientTransform="translate(70.65 -1055.151)" gradientUnits="userSpaceOnUse"/><linearGradient xlink:href="#b" id="e" x1="-584.199" x2="-496.297" y1="782.336" y2="937.714" gradientTransform="translate(864.696 -1491.34)" gradientUnits="userSpaceOnUse"/></defs><g style="display:inline;opacity:1" transform="translate(-132.651 958.04)"><path id="d" d="m309.549-710.388 122.197 211.675-56.157.527-32.624-56.87-32.856 56.566-27.903-.011-14.29-24.69 46.81-80.49-33.23-57.826z" style="opacity:1;fill:url(#c);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><use xlink:href="#d" width="100%" height="100%" transform="rotate(60 407.112 -715.787)"/><use xlink:href="#d" width="100%" height="100%" transform="rotate(-60 407.312 -715.7)"/><use xlink:href="#d" width="100%" height="100%" transform="rotate(180 407.419 -715.756)"/><path id="f" d="m309.549-710.388 122.197 211.675-56.157.527-32.624-56.87-32.856 56.566-27.903-.011-14.29-24.69 46.81-80.49-33.23-57.826z" style="color:#000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000;solid-opacity:1;fill:url(#e);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"/><use xlink:href="#f" width="100%" height="100%" style="display:inline" transform="rotate(120 407.34 -716.084)"/><use xlink:href="#f" width="100%" height="100%" style="display:inline" transform="rotate(-120 407.288 -715.87)"/></g></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1 +1,9 @@
# Release X.Y (202?-??-??)
- Fix a FOD sandbox escape:
Cooperating Nix derivations could send file descriptors to files in the Nix
store to each other via Unix domain sockets in the abstract namespace. This
allowed one derivation to modify the output of the other derivation, after Nix
has registered the path as "valid" and immutable in the Nix database.
In particular, this allowed the output of fixed-output derivations to be
modified from their expected content. This isn't the case any more.

View File

@@ -44,10 +44,10 @@ rec {
optionalString = cond: string: if cond then string else "";
showSetting = { useAnchors }: name: { description, documentDefault, defaultValue, aliases, value, experimentalFeature }:
showSetting = { inlineHTML }: name: { description, documentDefault, defaultValue, aliases, value, experimentalFeature }:
let
result = squash ''
- ${if useAnchors
- ${if inlineHTML
then ''<span id="conf-${name}">[`${name}`](#conf-${name})</span>''
else ''`${name}`''}

12
flake.lock generated
View File

@@ -34,16 +34,16 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1695124524,
"narHash": "sha256-trXDytVCqf3KryQQQrHOZKUabu1/lB8/ndOAuZKQrOE=",
"owner": "edolstra",
"lastModified": 1700748986,
"narHash": "sha256-/nqLrNU297h3PCw4QyDpZKZEUHmialJdZW2ceYFobds=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a3d30b525535e3158221abc1a957ce798ab159fe",
"rev": "9ba29e2346bc542e9909d1021e8fd7d4b3f64db0",
"type": "github"
},
"original": {
"owner": "edolstra",
"ref": "fix-aws-sdk-cpp",
"owner": "NixOS",
"ref": "nixos-23.05-small",
"repo": "nixpkgs",
"type": "github"
}

View File

@@ -1,8 +1,7 @@
{
description = "The purely functional package manager";
#inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.05-small";
inputs.nixpkgs.url = "github:edolstra/nixpkgs/fix-aws-sdk-cpp";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.05-small";
inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
inputs.lowdown-src = { url = "github:kristapsdz/lowdown"; flake = false; };
inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
@@ -12,7 +11,7 @@
let
inherit (nixpkgs) lib;
officialRelease = false;
officialRelease = true;
version = lib.fileContents ./.version + versionSuffix;
versionSuffix =
@@ -25,7 +24,7 @@
linuxSystems = linux32BitSystems ++ linux64BitSystems;
darwinSystems = [ "x86_64-darwin" "aarch64-darwin" ];
systems = linuxSystems ++ darwinSystems;
crossSystems = [ "armv6l-linux" "armv7l-linux" ];
stdenvs = [ "gccStdenv" "clangStdenv" "clang11Stdenv" "stdenv" "libcxxStdenv" "ccacheStdenv" ];
@@ -59,35 +58,28 @@
nixSrc = fileset.toSource {
root = ./.;
fileset = fileset.intersect baseFiles (
fileset.difference
(fileset.unions [
./.version
./boehmgc-coroutine-sp-fallback.diff
./bootstrap.sh
./configure.ac
./doc
./local.mk
./m4
./Makefile
./Makefile.config.in
./misc
./mk
./precompiled-headers.h
./src
./tests
./COPYING
./scripts/local.mk
(fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts)
# TODO: do we really need README.md? It doesn't seem used in the build.
./README.md
])
(fileset.unions [
# Removed file sets
./tests/nixos
./tests/installer
])
);
fileset = fileset.intersect baseFiles (fileset.unions [
./.version
./boehmgc-coroutine-sp-fallback.diff
./bootstrap.sh
./configure.ac
./doc
./local.mk
./m4
./Makefile
./Makefile.config.in
./misc
./mk
./precompiled-headers.h
./src
./tests/functional
./tests/unit
./COPYING
./scripts/local.mk
(fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts)
# TODO: do we really need README.md? It doesn't seem used in the build.
./README.md
]);
};
# Memoize nixpkgs for different platforms for efficiency.
@@ -181,7 +173,13 @@
boost
lowdown-nix
]
++ lib.optionals stdenv.isLinux [libseccomp]
++ lib.optionals stdenv.isLinux [(libseccomp.overrideAttrs (_: rec {
version = "2.5.5";
src = fetchurl {
url = "https://github.com/seccomp/libseccomp/releases/download/v${version}/libseccomp-${version}.tar.gz";
hash = "sha256-JIosik2bmFiqa69ScSw0r+/PnJ6Ut23OAsHJqiX7M3U=";
};
}))]
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid;
@@ -558,7 +556,7 @@
# tarball for the user's system and calls the second half of the
# installation script.
installerScript = installScriptFor [ "x86_64-linux" "i686-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" "armv6l-linux" "armv7l-linux" ];
installerScriptForGHA = installScriptFor [ "x86_64-linux" "x86_64-darwin" "armv6l-linux" "armv7l-linux"];
installerScriptForGHA = installScriptFor [ "x86_64-linux" "aarch64-darwin" "armv6l-linux" "armv7l-linux"];
# docker image with Nix inside
dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage);
@@ -642,6 +640,10 @@
["i686-linux" "x86_64-linux"]
(system: runNixOSTestFor system ./tests/nixos/setuid.nix);
tests.ca-fd-leak = runNixOSTestFor "x86_64-linux" ./tests/nixos/ca-fd-leak;
tests.user-sandboxing = runNixOSTestFor "x86_64-linux" ./tests/nixos/user-sandboxing;
# Make sure that nix-env still produces the exact same result
# on a particular version of Nixpkgs.

View File

@@ -1,11 +1,15 @@
test_dir=tests/functional
test=$(echo -n "$test" | sed -e "s|^$test_dir/||")
TESTS_ENVIRONMENT=("TEST_NAME=${test%.*}" 'NIX_REMOTE=')
: ${BASH:=/usr/bin/env bash}
init_test () {
cd tests && env "${TESTS_ENVIRONMENT[@]}" $BASH -e init.sh 2>/dev/null > /dev/null
cd "$test_dir" && env "${TESTS_ENVIRONMENT[@]}" $BASH -e init.sh 2>/dev/null > /dev/null
}
run_test_proper () {
cd $(dirname $test) && env "${TESTS_ENVIRONMENT[@]}" $BASH -e $(basename $test)
cd "$test_dir/$(dirname $test)" && env "${TESTS_ENVIRONMENT[@]}" $BASH -e $(basename $test)
}

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
((NEW_NIX_FIRST_BUILD_UID=301))
((NEW_NIX_FIRST_BUILD_UID=351))
id_available(){
dscl . list /Users UniqueID | grep -E '\b'$1'\b' >/dev/null

View File

@@ -3,11 +3,24 @@
set -eu
set -o pipefail
# System specific settings
# Notes:
# - up to macOS Big Sur we used the same GID/UIDs as Linux (30000:30001-32)
# - we changed UID to 301 because Big Sur updates failed into recovery mode
# we're targeting the 200-400 UID range for role users mentioned in the
# usage note for sysadminctl
# - we changed UID to 351 because Sequoia now uses UIDs 300-304 for its own
# daemon users
# - we changed GID to 350 alongside above just because it hides the nixbld
# group from the Users & Groups settings panel :)
export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-351}"
export NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-350}"
export NIX_BUILD_USER_NAME_TEMPLATE="_nixbld%d"
readonly NIX_DAEMON_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist
# create by default; set 0 to DIY, use a symlink, etc.
readonly NIX_VOLUME_CREATE=${NIX_VOLUME_CREATE:-1} # now default
NIX_FIRST_BUILD_UID="301"
NIX_BUILD_USER_NAME_TEMPLATE="_nixbld%d"
# caution: may update times on / if not run as normal non-root user
read_only_root() {

View File

@@ -23,11 +23,12 @@ readonly RED='\033[31m'
# installer allows overriding build user count to speed up installation
# as creating each user takes non-trivial amount of time on macos
readonly NIX_USER_COUNT=${NIX_USER_COUNT:-32}
readonly NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-30000}"
readonly NIX_BUILD_GROUP_NAME="nixbld"
# darwin installer needs to override these
NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-30001}"
NIX_BUILD_USER_NAME_TEMPLATE="nixbld%d"
# each system specific installer must set these:
# NIX_FIRST_BUILD_UID
# NIX_BUILD_GROUP_ID
# NIX_BUILD_USER_NAME_TEMPLATE
# Please don't change this. We don't support it, because the
# default shell profile that comes with Nix doesn't support it.
readonly NIX_ROOT="/nix"
@@ -522,9 +523,7 @@ It seems the build group $NIX_BUILD_GROUP_NAME already exists, but
with the UID $primary_group_id. This script can't really handle
that right now, so I'm going to give up.
You can fix this by editing this script and changing the
NIX_BUILD_GROUP_ID variable near the top to from $NIX_BUILD_GROUP_ID
to $primary_group_id and re-run.
You can export NIX_BUILD_GROUP_ID=$primary_group_id and re-run.
EOF
else
row " Exists" "Yes"
@@ -699,6 +698,12 @@ EOF
fi
}
check_required_system_specific_settings() {
if [ -z "${NIX_FIRST_BUILD_UID+x}" ] || [ -z "${NIX_BUILD_USER_NAME_TEMPLATE+x}" ]; then
failure "Internal error: System specific installer for $(uname) ($1) does not export required settings."
fi
}
welcome_to_nix() {
local -r NIX_UID_RANGES="${NIX_FIRST_BUILD_UID}..$((NIX_FIRST_BUILD_UID + NIX_USER_COUNT - 1))"
local -r RANGE_TEXT=$(echo -ne "${BLUE}(uids [${NIX_UID_RANGES}])${ESC}")
@@ -718,7 +723,9 @@ manager. This will happen in a few stages:
if you are ready to continue.
3. Create the system users ${RANGE_TEXT} and groups ${GROUP_TEXT}
that the Nix daemon uses to run builds.
that the Nix daemon uses to run builds. To create system users
in a different range, exit and run this tool again with
NIX_FIRST_BUILD_UID set.
4. Perform the basic installation of the Nix files daemon.
@@ -960,13 +967,16 @@ main() {
if is_os_darwin; then
# shellcheck source=./install-darwin-multi-user.sh
. "$EXTRACTED_NIX_PATH/install-darwin-multi-user.sh"
check_required_system_specific_settings "install-darwin-multi-user.sh"
elif is_os_linux; then
# shellcheck source=./install-systemd-multi-user.sh
. "$EXTRACTED_NIX_PATH/install-systemd-multi-user.sh" # most of this works on non-systemd distros also
check_required_system_specific_settings "install-systemd-multi-user.sh"
else
failure "Sorry, I don't know what to do on $(uname)"
fi
welcome_to_nix
if ! is_root; then

View File

@@ -3,6 +3,11 @@
set -eu
set -o pipefail
# System specific settings
export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-30001}"
export NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-30000}"
export NIX_BUILD_USER_NAME_TEMPLATE="nixbld%d"
readonly SERVICE_SRC=/lib/systemd/system/nix-daemon.service
readonly SERVICE_DEST=/etc/systemd/system/nix-daemon.service

View File

@@ -6,6 +6,25 @@
namespace nix::eval_cache {
CachedEvalError::CachedEvalError(ref<EvalState> state, ref<AttrCursor> cursor, Symbol attr)
: EvalError("cached failure of attribute '%s'", cursor->getAttrPathStr(attr))
, state(state), cursor(cursor), attr(attr)
{ }
void CachedEvalError::force()
{
auto & v = cursor->forceValue();
if (v.type() == nAttrs) {
auto a = v.attrs->get(this->attr);
state->forceValue(*a->value, a->pos);
}
// Shouldn't happen.
throw EvalError("evaluation of cached failed attribute '%s' unexpectedly succeeded", cursor->getAttrPathStr(attr));
}
static const char * schema = R"sql(
create table if not exists Attributes (
parent integer not null,
@@ -469,7 +488,7 @@ Suggestions AttrCursor::getSuggestionsForAttr(Symbol name)
return Suggestions::bestMatches(strAttrNames, root->state.symbols[name]);
}
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErrors)
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name)
{
if (root->db) {
if (!cachedValue)
@@ -486,12 +505,9 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
if (attr) {
if (std::get_if<missing_t>(&attr->second))
return nullptr;
else if (std::get_if<failed_t>(&attr->second)) {
if (forceErrors)
debug("reevaluating failed cached attribute '%s'", getAttrPathStr(name));
else
throw CachedEvalError("cached failure of attribute '%s'", getAttrPathStr(name));
} else
else if (std::get_if<failed_t>(&attr->second))
throw CachedEvalError(ref(root->state.shared_from_this()), ref(shared_from_this()), name);
else
return std::make_shared<AttrCursor>(root,
std::make_pair(shared_from_this(), name), nullptr, std::move(attr));
}
@@ -536,9 +552,9 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name)
return maybeGetAttr(root->state.symbols.create(name));
}
ref<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
ref<AttrCursor> AttrCursor::getAttr(Symbol name)
{
auto p = maybeGetAttr(name, forceErrors);
auto p = maybeGetAttr(name);
if (!p)
throw Error("attribute '%s' does not exist", getAttrPathStr(name));
return ref(p);
@@ -549,11 +565,11 @@ ref<AttrCursor> AttrCursor::getAttr(std::string_view name)
return getAttr(root->state.symbols.create(name));
}
OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force)
OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath)
{
auto res = shared_from_this();
for (auto & attr : attrPath) {
auto child = res->maybeGetAttr(attr, force);
auto child = res->maybeGetAttr(attr);
if (!child) {
auto suggestions = res->getSuggestionsForAttr(attr);
return OrSuggestions<ref<AttrCursor>>::failed(suggestions);
@@ -750,7 +766,7 @@ bool AttrCursor::isDerivation()
StorePath AttrCursor::forceDerivation()
{
auto aDrvPath = getAttr(root->state.sDrvPath, true);
auto aDrvPath = getAttr(root->state.sDrvPath);
auto drvPath = root->state.store->parseStorePath(aDrvPath->getString());
if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) {
/* The eval cache contains 'drvPath', but the actual path has

View File

@@ -10,14 +10,29 @@
namespace nix::eval_cache {
MakeError(CachedEvalError, EvalError);
struct AttrDb;
class AttrCursor;
struct CachedEvalError : EvalError
{
const ref<EvalState> state;
const ref<AttrCursor> cursor;
const Symbol attr;
CachedEvalError(ref<EvalState>, ref<AttrCursor> cursor, Symbol attr);
/**
* Evaluate this attribute, which should result in a regular
* `EvalError` exception being thrown.
*/
[[noreturn]]
void force();
};
class EvalCache : public std::enable_shared_from_this<EvalCache>
{
friend class AttrCursor;
friend class CachedEvalError;
std::shared_ptr<AttrDb> db;
EvalState & state;
@@ -73,6 +88,7 @@ typedef std::variant<
class AttrCursor : public std::enable_shared_from_this<AttrCursor>
{
friend class EvalCache;
friend class CachedEvalError;
ref<EvalCache> root;
typedef std::optional<std::pair<std::shared_ptr<AttrCursor>, Symbol>> Parent;
@@ -102,11 +118,11 @@ public:
Suggestions getSuggestionsForAttr(Symbol name);
std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name, bool forceErrors = false);
std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name);
std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name);
ref<AttrCursor> getAttr(Symbol name, bool forceErrors = false);
ref<AttrCursor> getAttr(Symbol name);
ref<AttrCursor> getAttr(std::string_view name);
@@ -114,7 +130,7 @@ public:
* Get an attribute along a chain of attrsets. Note that this does
* not auto-call functors or functions.
*/
OrSuggestions<ref<AttrCursor>> findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force = false);
OrSuggestions<ref<AttrCursor>> findAlongAttrPath(const std::vector<Symbol> & attrPath);
std::string getString();

View File

@@ -802,7 +802,7 @@ std::string showType(const Value & v);
/**
* If `path` refers to a directory, then append "/default.nix".
*/
SourcePath resolveExprPath(const SourcePath & path);
SourcePath resolveExprPath(SourcePath path);
struct InvalidPathError : EvalError
{

View File

@@ -89,7 +89,7 @@ LockFile::LockFile(const nlohmann::json & json, const Path & path)
std::string inputKey = i.value();
auto k = nodeMap.find(inputKey);
if (k == nodeMap.end()) {
auto nodes = json["nodes"];
auto & nodes = json["nodes"];
auto jsonNode2 = nodes.find(inputKey);
if (jsonNode2 == nodes.end())
throw Error("lock file references missing node '%s'", inputKey);

View File

@@ -682,17 +682,25 @@ Expr * EvalState::parse(
}
SourcePath resolveExprPath(const SourcePath & path)
SourcePath resolveExprPath(SourcePath path)
{
unsigned int followCount = 0, maxFollow = 1024;
/* If `path' is a symlink, follow it. This is so that relative
path references work. */
auto path2 = path.resolveSymlinks();
while (true) {
// Basic cycle/depth limit to avoid infinite loops.
if (++followCount >= maxFollow)
throw Error("too many symbolic links encountered while traversing the path '%s'", path);
if (path.lstat().type != InputAccessor::tSymlink) break;
path = {CanonPath(path.readLink(), path.path.parent().value_or(CanonPath::root))};
}
/* If `path' refers to a directory, append `/default.nix'. */
if (path2.lstat().type == InputAccessor::tDirectory)
return path2 + "default.nix";
if (path.lstat().type == InputAccessor::tDirectory)
return path + "default.nix";
return path2;
return path;
}

View File

@@ -82,16 +82,15 @@ StringMap EvalState::realiseContext(const NixStringContext & context)
/* Build/substitute the context. */
std::vector<DerivedPath> buildReqs;
for (auto & d : drvs) buildReqs.emplace_back(DerivedPath { d });
store->buildPaths(buildReqs);
buildStore->buildPaths(buildReqs, bmNormal, store);
StorePathSet outputsToCopyAndAllow;
for (auto & drv : drvs) {
auto outputs = resolveDerivedPath(*store, drv);
auto outputs = resolveDerivedPath(*buildStore, drv, &*store);
for (auto & [outputName, outputPath] : outputs) {
/* Add the output of this derivations to the allowed
paths. */
if (allowedPaths) {
allowPath(outputPath);
}
outputsToCopyAndAllow.insert(outputPath);
/* Get all the output paths corresponding to the placeholders we had */
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) {
res.insert_or_assign(
@@ -100,12 +99,21 @@ StringMap EvalState::realiseContext(const NixStringContext & context)
.drvPath = drv.drvPath,
.output = outputName,
}).render(),
store->printStorePath(outputPath)
buildStore->printStorePath(outputPath)
);
}
}
}
if (store != buildStore) copyClosure(*buildStore, *store, outputsToCopyAndAllow);
if (allowedPaths) {
for (auto & outputPath : outputsToCopyAndAllow) {
/* Add the output of this derivations to the allowed
paths. */
allowPath(store->toRealPath(outputPath));
}
}
return res;
}
@@ -1528,7 +1536,9 @@ static void prim_pathExists(EvalState & state, const PosIdx pos, Value * * args,
auto path = realisePath(state, pos, arg, { .checkForPureEval = false });
/* SourcePath doesn't know about trailing slash. */
auto mustBeDir = arg.type() == nString && arg.str().ends_with("/");
auto mustBeDir = arg.type() == nString
&& (arg.str().ends_with("/")
|| arg.str().ends_with("/."));
try {
auto checked = state.checkSourcePath(path);

View File

@@ -395,7 +395,8 @@ static RegisterPrimOp primop_fetchGit({
- `shallow` (default: `false`)
A Boolean parameter that specifies whether fetching a shallow clone is allowed.
A Boolean parameter that specifies whether fetching from a shallow remote repository is allowed.
This still performs a full clone of what is available on the remote.
- `allRefs`

View File

@@ -1,19 +0,0 @@
check: libexpr-tests_RUN
programs += libexpr-tests
libexpr-tests_NAME := libnixexpr-tests
libexpr-tests_DIR := $(d)
libexpr-tests_INSTALL_DIR :=
libexpr-tests_SOURCES := \
$(wildcard $(d)/*.cc) \
$(wildcard $(d)/value/*.cc)
libexpr-tests_CXXFLAGS += -I src/libexpr -I src/libutil -I src/libstore -I src/libexpr/tests -I src/libfetchers
libexpr-tests_LIBS = libstore-tests libutils-tests libexpr libutil libstore libfetchers
libexpr-tests_LDFLAGS := $(GTEST_LIBS) -lgmock

View File

@@ -1,157 +0,0 @@
#include "create-derivation-and-realise-goal.hh"
#include "worker.hh"
namespace nix {
CreateDerivationAndRealiseGoal::CreateDerivationAndRealiseGoal(ref<SingleDerivedPath> drvReq,
const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode)
: Goal(worker, DerivedPath::Built { .drvPath = drvReq, .outputs = wantedOutputs })
, drvReq(drvReq)
, wantedOutputs(wantedOutputs)
, buildMode(buildMode)
{
state = &CreateDerivationAndRealiseGoal::getDerivation;
name = fmt(
"outer obtaining drv from '%s' and then building outputs %s",
drvReq->to_string(worker.store),
std::visit(overloaded {
[&](const OutputsSpec::All) -> std::string {
return "* (all of them)";
},
[&](const OutputsSpec::Names os) {
return concatStringsSep(", ", quoteStrings(os));
},
}, wantedOutputs.raw));
trace("created outer");
worker.updateProgress();
}
CreateDerivationAndRealiseGoal::~CreateDerivationAndRealiseGoal()
{
}
static StorePath pathPartOfReq(const SingleDerivedPath & req)
{
return std::visit(overloaded {
[&](const SingleDerivedPath::Opaque & bo) {
return bo.path;
},
[&](const SingleDerivedPath::Built & bfd) {
return pathPartOfReq(*bfd.drvPath);
},
}, req.raw());
}
std::string CreateDerivationAndRealiseGoal::key()
{
/* Ensure that derivations get built in order of their name,
i.e. a derivation named "aardvark" always comes before "baboon". And
substitution goals and inner derivation goals always happen before
derivation goals (due to "b$"). */
return "c$" + std::string(pathPartOfReq(*drvReq).name()) + "$" + drvReq->to_string(worker.store);
}
void CreateDerivationAndRealiseGoal::timedOut(Error && ex)
{
}
void CreateDerivationAndRealiseGoal::work()
{
(this->*state)();
}
void CreateDerivationAndRealiseGoal::addWantedOutputs(const OutputsSpec & outputs)
{
/* If we already want all outputs, there is nothing to do. */
auto newWanted = wantedOutputs.union_(outputs);
bool needRestart = !newWanted.isSubsetOf(wantedOutputs);
wantedOutputs = newWanted;
if (!needRestart) return;
if (!optDrvPath)
// haven't started steps where the outputs matter yet
return;
worker.makeDerivationGoal(*optDrvPath, outputs, buildMode);
}
void CreateDerivationAndRealiseGoal::getDerivation()
{
trace("outer init");
/* The first thing to do is to make sure that the derivation
exists. If it doesn't, it may be created through a
substitute. */
if (auto optDrvPath = [this]() -> std::optional<StorePath> {
if (buildMode != bmNormal) return std::nullopt;
auto drvPath = StorePath::dummy;
try {
drvPath = resolveDerivedPath(worker.store, *drvReq);
} catch (MissingRealisation &) {
return std::nullopt;
}
return worker.evalStore.isValidPath(drvPath) || worker.store.isValidPath(drvPath)
? std::optional { drvPath }
: std::nullopt;
}()) {
trace(fmt("already have drv '%s' for '%s', can go straight to building",
worker.store.printStorePath(*optDrvPath),
drvReq->to_string(worker.store)));
loadAndBuildDerivation();
} else {
trace("need to obtain drv we want to build");
addWaitee(worker.makeGoal(DerivedPath::fromSingle(*drvReq)));
state = &CreateDerivationAndRealiseGoal::loadAndBuildDerivation;
if (waitees.empty()) work();
}
}
void CreateDerivationAndRealiseGoal::loadAndBuildDerivation()
{
trace("outer load and build derivation");
if (nrFailed != 0) {
amDone(ecFailed, Error("cannot build missing derivation '%s'", drvReq->to_string(worker.store)));
return;
}
StorePath drvPath = resolveDerivedPath(worker.store, *drvReq);
/* Build this step! */
concreteDrvGoal = worker.makeDerivationGoal(drvPath, wantedOutputs, buildMode);
addWaitee(upcast_goal(concreteDrvGoal));
state = &CreateDerivationAndRealiseGoal::buildDone;
optDrvPath = std::move(drvPath);
if (waitees.empty()) work();
}
void CreateDerivationAndRealiseGoal::buildDone()
{
trace("outer build done");
buildResult = upcast_goal(concreteDrvGoal)->getBuildResult(DerivedPath::Built {
.drvPath = drvReq,
.outputs = wantedOutputs,
});
if (buildResult.success())
amDone(ecSuccess);
else
amDone(ecFailed, Error("building '%s' failed", drvReq->to_string(worker.store)));
}
}

View File

@@ -1,96 +0,0 @@
#pragma once
#include "parsed-derivations.hh"
#include "lock.hh"
#include "store-api.hh"
#include "pathlocks.hh"
#include "goal.hh"
namespace nix {
struct DerivationGoal;
/**
* This goal type is essentially the serial composition (like function
* composition) of a goal for getting a derivation, and then a
* `DerivationGoal` using the newly-obtained derivation.
*
* In the (currently experimental) general inductive case of derivations
* that are themselves build outputs, that first goal will be *another*
* `CreateDerivationAndRealiseGoal`. In the (much more common) base-case
* where the derivation has no provence and is just referred to by
* (content-addressed) store path, that first goal is a
* `SubstitutionGoal`.
*
* If we already have the derivation (e.g. if the evalutator has created
* the derivation locally and then instructured the store to build it),
* we can skip the first goal entirely as a small optimization.
*/
struct CreateDerivationAndRealiseGoal : public Goal
{
/**
* How to obtain a store path of the derivation to build.
*/
ref<SingleDerivedPath> drvReq;
/**
* The path of the derivation, once obtained.
**/
std::optional<StorePath> optDrvPath;
/**
* The goal for the corresponding concrete derivation.
**/
std::shared_ptr<DerivationGoal> concreteDrvGoal;
/**
* The specific outputs that we need to build.
*/
OutputsSpec wantedOutputs;
typedef void (CreateDerivationAndRealiseGoal::*GoalState)();
GoalState state;
/**
* The final output paths of the build.
*
* - For input-addressed derivations, always the precomputed paths
*
* - For content-addressed derivations, calcuated from whatever the
* hash ends up being. (Note that fixed outputs derivations that
* produce the "wrong" output still install that data under its
* true content-address.)
*/
OutputPathMap finalOutputs;
BuildMode buildMode;
CreateDerivationAndRealiseGoal(ref<SingleDerivedPath> drvReq,
const OutputsSpec & wantedOutputs, Worker & worker,
BuildMode buildMode = bmNormal);
virtual ~CreateDerivationAndRealiseGoal();
void timedOut(Error && ex) override;
std::string key() override;
void work() override;
/**
* Add wanted outputs to an already existing derivation goal.
*/
void addWantedOutputs(const OutputsSpec & outputs);
/**
* The states.
*/
void getDerivation();
void loadAndBuildDerivation();
void buildDone();
JobCategory jobCategory() const override {
return JobCategory::Administration;
};
};
}

View File

@@ -71,7 +71,7 @@ DerivationGoal::DerivationGoal(const StorePath & drvPath,
, wantedOutputs(wantedOutputs)
, buildMode(buildMode)
{
state = &DerivationGoal::loadDerivation;
state = &DerivationGoal::getDerivation;
name = fmt(
"building of '%s' from .drv file",
DerivedPath::Built { makeConstantStorePathRef(drvPath), wantedOutputs }.to_string(worker.store));
@@ -164,6 +164,24 @@ void DerivationGoal::addWantedOutputs(const OutputsSpec & outputs)
}
void DerivationGoal::getDerivation()
{
trace("init");
/* The first thing to do is to make sure that the derivation
exists. If it doesn't, it may be created through a
substitute. */
if (buildMode == bmNormal && worker.evalStore.isValidPath(drvPath)) {
loadDerivation();
return;
}
addWaitee(upcast_goal(worker.makePathSubstitutionGoal(drvPath)));
state = &DerivationGoal::loadDerivation;
}
void DerivationGoal::loadDerivation()
{
trace("loading derivation");
@@ -1498,24 +1516,23 @@ void DerivationGoal::waiteeDone(GoalPtr waitee, ExitCode result)
if (!useDerivation) return;
auto & fullDrv = *dynamic_cast<Derivation *>(drv.get());
std::optional info = tryGetConcreteDrvGoal(waitee);
if (!info) return;
const auto & [dg, drvReq] = *info;
auto * dg = dynamic_cast<DerivationGoal *>(&*waitee);
if (!dg) return;
auto * nodeP = fullDrv.inputDrvs.findSlot(drvReq.get());
auto * nodeP = fullDrv.inputDrvs.findSlot(DerivedPath::Opaque { .path = dg->drvPath });
if (!nodeP) return;
auto & outputs = nodeP->value;
for (auto & outputName : outputs) {
auto buildResult = dg.get().getBuildResult(DerivedPath::Built {
.drvPath = makeConstantStorePathRef(dg.get().drvPath),
auto buildResult = dg->getBuildResult(DerivedPath::Built {
.drvPath = makeConstantStorePathRef(dg->drvPath),
.outputs = OutputsSpec::Names { outputName },
});
if (buildResult.success()) {
auto i = buildResult.builtOutputs.find(outputName);
if (i != buildResult.builtOutputs.end())
inputDrvOutputs.insert_or_assign(
{ dg.get().drvPath, outputName },
{ dg->drvPath, outputName },
i->second.outPath);
}
}

View File

@@ -52,10 +52,6 @@ struct InitialOutput {
/**
* A goal for building some or all of the outputs of a derivation.
*
* The derivation must already be present, either in the store in a drv
* or in memory. If the derivation itself needs to be gotten first, a
* `CreateDerivationAndRealiseGoal` goal must be used instead.
*/
struct DerivationGoal : public Goal
{
@@ -235,6 +231,7 @@ struct DerivationGoal : public Goal
/**
* The states.
*/
void getDerivation();
void loadDerivation();
void haveDerivation();
void outputsSubstitutionTried();

View File

@@ -1,6 +1,5 @@
#include "worker.hh"
#include "substitution-goal.hh"
#include "create-derivation-and-realise-goal.hh"
#include "derivation-goal.hh"
#include "local-store.hh"
@@ -16,7 +15,7 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod
worker.run(goals);
StringSet failed;
StorePathSet failed;
std::optional<Error> ex;
for (auto & i : goals) {
if (i->ex) {
@@ -26,10 +25,10 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod
ex = std::move(i->ex);
}
if (i->exitCode != Goal::ecSuccess) {
if (auto i2 = dynamic_cast<CreateDerivationAndRealiseGoal *>(i.get()))
failed.insert(i2->drvReq->to_string(*this));
if (auto i2 = dynamic_cast<DerivationGoal *>(i.get()))
failed.insert(i2->drvPath);
else if (auto i2 = dynamic_cast<PathSubstitutionGoal *>(i.get()))
failed.insert(printStorePath(i2->storePath));
failed.insert(i2->storePath);
}
}
@@ -38,7 +37,7 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod
throw std::move(*ex);
} else if (!failed.empty()) {
if (ex) logError(ex->info());
throw Error(worker.failingExitStatus(), "build of %s failed", concatStringsSep(", ", quoteStrings(failed)));
throw Error(worker.failingExitStatus(), "build of %s failed", showPaths(failed));
}
}

View File

@@ -49,16 +49,6 @@ enum struct JobCategory {
* A substitution an arbitrary store object; it will use network resources.
*/
Substitution,
/**
* A goal that does no "real" work by itself, and just exists to depend on
* other goals which *do* do real work. These goals therefore are not
* limited.
*
* These goals cannot infinitely create themselves, so there is no risk of
* a "fork bomb" type situation (which would be a problem even though the
* goal do no real work) either.
*/
Administration,
};
struct Goal : public std::enable_shared_from_this<Goal>

View File

@@ -16,6 +16,7 @@
#include "cgroup.hh"
#include "personality.hh"
#include "namespaces.hh"
#include "file-system.hh"
#include <regex>
#include <queue>
@@ -35,6 +36,7 @@
/* Includes required for chroot support. */
#if __linux__
#include <sys/ioctl.h>
#include "linux/fchmodat2-compat.hh"
#include <net/if.h>
#include <netinet/ip.h>
#include <sys/mman.h>
@@ -170,6 +172,10 @@ void LocalDerivationGoal::killSandbox(bool getStats)
void LocalDerivationGoal::tryLocalBuild()
{
#if __APPLE__
additionalSandboxProfile = parsedDrv->getStringAttr("__sandboxProfile").value_or("");
#endif
unsigned int curBuilds = worker.getNrLocalBuilds();
if (curBuilds >= settings.maxBuildJobs) {
state = &DerivationGoal::tryToBuild;
@@ -476,14 +482,26 @@ void LocalDerivationGoal::startBuilder()
settings.thisSystem,
concatStringsSep<StringSet>(", ", worker.store.systemFeatures));
#if __APPLE__
additionalSandboxProfile = parsedDrv->getStringAttr("__sandboxProfile").value_or("");
#endif
/* Create a temporary directory where the build will take
place. */
tmpDir = createTempDir("", "nix-build-" + std::string(drvPath.name()), false, false, 0700);
topTmpDir = createTempDir("", "nix-build-" + std::string(drvPath.name()), false, false, 0700);
#if __APPLE__
if (false) {
#else
if (useChroot) {
#endif
/* If sandboxing is enabled, put the actual TMPDIR underneath
an inaccessible root-owned directory, to prevent outside
access.
On macOS, we don't use an actual chroot, so this isn't
possible. Any mitigation along these lines would have to be
done directly in the sandbox profile. */
tmpDir = topTmpDir + "/build";
createDir(tmpDir, 0700);
} else {
tmpDir = topTmpDir;
}
chownToBuilder(tmpDir);
for (auto & [outputName, status] : initialOutputs) {
@@ -649,17 +667,21 @@ void LocalDerivationGoal::startBuilder()
#if __linux__
/* Create a temporary directory in which we set up the chroot
environment using bind-mounts. We put it in the Nix store
to ensure that we can create hard-links to non-directory
inputs in the fake Nix store in the chroot (see below). */
chrootRootDir = worker.store.Store::toRealPath(drvPath) + ".chroot";
deletePath(chrootRootDir);
so that the build outputs can be moved efficiently from the
chroot to their final location. */
chrootParentDir = worker.store.Store::toRealPath(drvPath) + ".chroot";
deletePath(chrootParentDir);
/* Clean up the chroot directory automatically. */
autoDelChroot = std::make_shared<AutoDelete>(chrootRootDir);
autoDelChroot = std::make_shared<AutoDelete>(chrootParentDir);
printMsg(lvlChatty, "setting up chroot environment in '%1%'", chrootRootDir);
printMsg(lvlChatty, "setting up chroot environment in '%1%'", chrootParentDir);
if (mkdir(chrootParentDir.c_str(), 0700) == -1)
throw SysError("cannot create '%s'", chrootRootDir);
chrootRootDir = chrootParentDir + "/root";
// FIXME: make this 0700
if (mkdir(chrootRootDir.c_str(), buildUser && buildUser->getUIDCount() != 1 ? 0755 : 0750) == -1)
throw SysError("cannot create '%1%'", chrootRootDir);
@@ -1662,6 +1684,10 @@ void setupSeccomp()
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmodat), 1,
SCMP_A2(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
throw SysError("unable to add seccomp rule");
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), NIX_SYSCALL_FCHMODAT2, 1,
SCMP_A2(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
throw SysError("unable to add seccomp rule");
}
/* Prevent builders from creating EAs or ACLs. Not all filesystems
@@ -2111,10 +2137,11 @@ void LocalDerivationGoal::runChild()
/* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms
to find temporary directories, so we want to open up a broader place for them to dump their files, if needed. */
Path globalTmpDir = canonPath(getEnvNonEmpty("TMPDIR").value_or("/tmp"), true);
Path globalTmpDir = canonPath(defaultTempDir(), true);
/* They don't like trailing slashes on subpath directives */
if (globalTmpDir.back() == '/') globalTmpDir.pop_back();
while (!globalTmpDir.empty() && globalTmpDir.back() == '/')
globalTmpDir.pop_back();
if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") {
builder = "/usr/bin/sandbox-exec";
@@ -2558,6 +2585,12 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
[&](const DerivationOutput::CAFixed & dof) {
auto & wanted = dof.ca.hash;
// Replace the output by a fresh copy of itself to make sure
// that there's no stale file descriptor pointing to it
Path tmpOutput = actualPath + ".tmp";
copyFile(actualPath, tmpOutput, true);
renameFile(tmpOutput, actualPath);
auto newInfo0 = newInfoFromCA(DerivationOutput::CAFloating {
.method = dof.ca.method,
.hashType = wanted.type,
@@ -2934,15 +2967,17 @@ void LocalDerivationGoal::checkOutputs(const std::map<std::string, ValidPathInfo
void LocalDerivationGoal::deleteTmpDir(bool force)
{
if (tmpDir != "") {
if (topTmpDir != "") {
/* Don't keep temporary directories for builtins because they
might have privileged stuff (like a copy of netrc). */
if (settings.keepFailed && !force && !drv->isBuiltin()) {
printError("note: keeping build directory '%s'", tmpDir);
chmod(topTmpDir.c_str(), 0755);
chmod(tmpDir.c_str(), 0755);
}
else
deletePath(tmpDir);
deletePath(topTmpDir);
topTmpDir = "";
tmpDir = "";
}
}

View File

@@ -26,10 +26,16 @@ struct LocalDerivationGoal : public DerivationGoal
std::optional<Path> cgroup;
/**
* The temporary directory.
* The temporary directory used for the build.
*/
Path tmpDir;
/**
* The top-level temporary directory. `tmpDir` is either equal to
* or a child of this directory.
*/
Path topTmpDir;
/**
* The path of the temporary directory in the sandbox.
*/
@@ -64,6 +70,16 @@ struct LocalDerivationGoal : public DerivationGoal
*/
bool useChroot = false;
/**
* The parent directory of `chrootRootDir`. It has permission 700
* and is owned by root to ensure other users cannot mess with
* `chrootRootDir`.
*/
Path chrootParentDir;
/**
* The root of the chroot environment.
*/
Path chrootRootDir;
/**

View File

@@ -2,7 +2,6 @@
#include "worker.hh"
#include "substitution-goal.hh"
#include "drv-output-substitution-goal.hh"
#include "create-derivation-and-realise-goal.hh"
#include "local-derivation-goal.hh"
#include "hook-instance.hh"
@@ -42,24 +41,6 @@ Worker::~Worker()
}
std::shared_ptr<CreateDerivationAndRealiseGoal> Worker::makeCreateDerivationAndRealiseGoal(
ref<SingleDerivedPath> drvReq,
const OutputsSpec & wantedOutputs,
BuildMode buildMode)
{
std::weak_ptr<CreateDerivationAndRealiseGoal> & goal_weak = outerDerivationGoals.ensureSlot(*drvReq).value;
std::shared_ptr<CreateDerivationAndRealiseGoal> goal = goal_weak.lock();
if (!goal) {
goal = std::make_shared<CreateDerivationAndRealiseGoal>(drvReq, wantedOutputs, *this, buildMode);
goal_weak = goal;
wakeUp(goal);
} else {
goal->addWantedOutputs(wantedOutputs);
}
return goal;
}
std::shared_ptr<DerivationGoal> Worker::makeDerivationGoalCommon(
const StorePath & drvPath,
const OutputsSpec & wantedOutputs,
@@ -130,7 +111,10 @@ GoalPtr Worker::makeGoal(const DerivedPath & req, BuildMode buildMode)
{
return std::visit(overloaded {
[&](const DerivedPath::Built & bfd) -> GoalPtr {
return makeCreateDerivationAndRealiseGoal(bfd.drvPath, bfd.outputs, buildMode);
if (auto bop = std::get_if<DerivedPath::Opaque>(&*bfd.drvPath))
return makeDerivationGoal(bop->path, bfd.outputs, buildMode);
else
throw UnimplementedError("Building dynamic derivations in one shot is not yet implemented.");
},
[&](const DerivedPath::Opaque & bo) -> GoalPtr {
return makePathSubstitutionGoal(bo.path, buildMode == bmRepair ? Repair : NoRepair);
@@ -139,46 +123,24 @@ GoalPtr Worker::makeGoal(const DerivedPath & req, BuildMode buildMode)
}
template<typename K, typename V, typename F>
static void cullMap(std::map<K, V> & goalMap, F f)
{
for (auto i = goalMap.begin(); i != goalMap.end();)
if (!f(i->second))
i = goalMap.erase(i);
else ++i;
}
template<typename K, typename G>
static void removeGoal(std::shared_ptr<G> goal, std::map<K, std::weak_ptr<G>> & goalMap)
{
/* !!! inefficient */
cullMap(goalMap, [&](const std::weak_ptr<G> & gp) -> bool {
return gp.lock() != goal;
});
}
template<typename K>
static void removeGoal(std::shared_ptr<CreateDerivationAndRealiseGoal> goal, std::map<K, DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>>::ChildNode> & goalMap);
template<typename K>
static void removeGoal(std::shared_ptr<CreateDerivationAndRealiseGoal> goal, std::map<K, DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>>::ChildNode> & goalMap)
{
/* !!! inefficient */
cullMap(goalMap, [&](DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>>::ChildNode & node) -> bool {
if (node.value.lock() == goal)
node.value.reset();
removeGoal(goal, node.childMap);
return !node.value.expired() || !node.childMap.empty();
});
for (auto i = goalMap.begin();
i != goalMap.end(); )
if (i->second.lock() == goal) {
auto j = i; ++j;
goalMap.erase(i);
i = j;
}
else ++i;
}
void Worker::removeGoal(GoalPtr goal)
{
if (auto drvGoal = std::dynamic_pointer_cast<CreateDerivationAndRealiseGoal>(goal))
nix::removeGoal(drvGoal, outerDerivationGoals.map);
else if (auto drvGoal = std::dynamic_pointer_cast<DerivationGoal>(goal))
if (auto drvGoal = std::dynamic_pointer_cast<DerivationGoal>(goal))
nix::removeGoal(drvGoal, derivationGoals);
else if (auto subGoal = std::dynamic_pointer_cast<PathSubstitutionGoal>(goal))
nix::removeGoal(subGoal, substitutionGoals);
@@ -236,19 +198,8 @@ void Worker::childStarted(GoalPtr goal, const std::set<int> & fds,
child.respectTimeouts = respectTimeouts;
children.emplace_back(child);
if (inBuildSlot) {
switch (goal->jobCategory()) {
case JobCategory::Substitution:
nrSubstitutions++;
break;
case JobCategory::Build:
nrLocalBuilds++;
break;
case JobCategory::Administration:
/* Intentionally not limited, see docs */
break;
default:
abort();
}
if (goal->jobCategory() == JobCategory::Substitution) nrSubstitutions++;
else nrLocalBuilds++;
}
}
@@ -260,20 +211,12 @@ void Worker::childTerminated(Goal * goal, bool wakeSleepers)
if (i == children.end()) return;
if (i->inBuildSlot) {
switch (goal->jobCategory()) {
case JobCategory::Substitution:
if (goal->jobCategory() == JobCategory::Substitution) {
assert(nrSubstitutions > 0);
nrSubstitutions--;
break;
case JobCategory::Build:
} else {
assert(nrLocalBuilds > 0);
nrLocalBuilds--;
break;
case JobCategory::Administration:
/* Intentionally not limited, see docs */
break;
default:
abort();
}
}
@@ -324,9 +267,9 @@ void Worker::run(const Goals & _topGoals)
for (auto & i : _topGoals) {
topGoals.insert(i);
if (auto goal = dynamic_cast<CreateDerivationAndRealiseGoal *>(i.get())) {
if (auto goal = dynamic_cast<DerivationGoal *>(i.get())) {
topPaths.push_back(DerivedPath::Built {
.drvPath = goal->drvReq,
.drvPath = makeConstantStorePathRef(goal->drvPath),
.outputs = goal->wantedOutputs,
});
} else if (auto goal = dynamic_cast<PathSubstitutionGoal *>(i.get())) {
@@ -589,19 +532,4 @@ GoalPtr upcast_goal(std::shared_ptr<DrvOutputSubstitutionGoal> subGoal)
return subGoal;
}
GoalPtr upcast_goal(std::shared_ptr<DerivationGoal> subGoal)
{
return subGoal;
}
std::optional<std::pair<std::reference_wrapper<const DerivationGoal>, std::reference_wrapper<const SingleDerivedPath>>> tryGetConcreteDrvGoal(GoalPtr waitee)
{
auto * odg = dynamic_cast<CreateDerivationAndRealiseGoal *>(&*waitee);
if (!odg) return std::nullopt;
return {{
std::cref(*odg->concreteDrvGoal),
std::cref(*odg->drvReq),
}};
}
}

View File

@@ -4,7 +4,6 @@
#include "types.hh"
#include "lock.hh"
#include "store-api.hh"
#include "derived-path-map.hh"
#include "goal.hh"
#include "realisation.hh"
@@ -14,7 +13,6 @@
namespace nix {
/* Forward definition. */
struct CreateDerivationAndRealiseGoal;
struct DerivationGoal;
struct PathSubstitutionGoal;
class DrvOutputSubstitutionGoal;
@@ -33,25 +31,9 @@ class DrvOutputSubstitutionGoal;
*/
GoalPtr upcast_goal(std::shared_ptr<PathSubstitutionGoal> subGoal);
GoalPtr upcast_goal(std::shared_ptr<DrvOutputSubstitutionGoal> subGoal);
GoalPtr upcast_goal(std::shared_ptr<DerivationGoal> subGoal);
typedef std::chrono::time_point<std::chrono::steady_clock> steady_time_point;
/**
* The current implementation of impure derivations has
* `DerivationGoal`s accumulate realisations from their waitees.
* Unfortunately, `DerivationGoal`s don't directly depend on other
* goals, but instead depend on `CreateDerivationAndRealiseGoal`s.
*
* We try not to share any of the details of any goal type with any
* other, for sake of modularity and quicker rebuilds. This means we
* cannot "just" downcast and fish out the field. So as an escape hatch,
* we have made the function, written in `worker.cc` where all the goal
* types are visible, and use it instead.
*/
std::optional<std::pair<std::reference_wrapper<const DerivationGoal>, std::reference_wrapper<const SingleDerivedPath>>> tryGetConcreteDrvGoal(GoalPtr waitee);
/**
* A mapping used to remember for each child process to what goal it
* belongs, and file descriptors for receiving log data and output
@@ -119,9 +101,6 @@ private:
* Maps used to prevent multiple instantiations of a goal for the
* same derivation / path.
*/
DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>> outerDerivationGoals;
std::map<StorePath, std::weak_ptr<DerivationGoal>> derivationGoals;
std::map<StorePath, std::weak_ptr<PathSubstitutionGoal>> substitutionGoals;
std::map<DrvOutput, std::weak_ptr<DrvOutputSubstitutionGoal>> drvOutputSubstitutionGoals;
@@ -209,9 +188,6 @@ public:
* @ref DerivationGoal "derivation goal"
*/
private:
std::shared_ptr<CreateDerivationAndRealiseGoal> makeCreateDerivationAndRealiseGoal(
ref<SingleDerivedPath> drvPath,
const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal);
std::shared_ptr<DerivationGoal> makeDerivationGoalCommon(
const StorePath & drvPath, const OutputsSpec & wantedOutputs,
std::function<std::shared_ptr<DerivationGoal>()> mkDrvGoal);

View File

@@ -34,10 +34,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
auto source = sinkToSource([&](Sink & sink) {
/* No need to do TLS verification, because we check the hash of
the result anyway. */
FileTransferRequest request(url);
request.verifyTLS = false;
request.decompress = false;
auto decompressor = makeDecompressionSink(

View File

@@ -51,11 +51,8 @@ typename DerivedPathMap<V>::ChildNode * DerivedPathMap<V>::findSlot(const Single
// instantiations
#include "create-derivation-and-realise-goal.hh"
namespace nix {
template struct DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>>;
GENERATE_CMP_EXT(
template<>,
DerivedPathMap<std::set<std::string>>::ChildNode,

View File

@@ -20,11 +20,8 @@ namespace nix {
*
* @param V A type to instantiate for each output. It should probably
* should be an "optional" type so not every interior node has to have a
* value. For example, the scheduler uses
* `DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>>` to
* remember which goals correspond to which outputs. `* const Something`
* or `std::optional<Something>` would also be good choices for
* "optional" types.
* value. `* const Something` or `std::optional<Something>` would be
* good choices for "optional" types.
*/
template<typename V>
struct DerivedPathMap {

View File

@@ -776,7 +776,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
}
};
/* Synchronisation point for testing, see tests/gc-concurrent.sh. */
/* Synchronisation point for testing, see tests/functional/gc-concurrent.sh. */
if (auto p = getEnv("_NIX_TEST_GC_SYNC"))
readFile(*p);

View File

@@ -4,6 +4,7 @@
#include "args.hh"
#include "abstract-setting-to-json.hh"
#include "compute-levels.hh"
#include "file-system.hh"
#include <algorithm>
#include <map>
@@ -24,6 +25,9 @@
#include "config-impl.hh"
#ifdef __APPLE__
#include <sys/sysctl.h>
#endif
namespace nix {
@@ -154,6 +158,29 @@ unsigned int Settings::getDefaultCores()
return concurrency;
}
#if __APPLE__
static bool hasVirt() {
int hasVMM;
int hvSupport;
size_t size;
size = sizeof(hasVMM);
if (sysctlbyname("kern.hv_vmm_present", &hasVMM, &size, NULL, 0) == 0) {
if (hasVMM)
return false;
}
// whether the kernel and hardware supports virt
size = sizeof(hvSupport);
if (sysctlbyname("kern.hv_support", &hvSupport, &size, NULL, 0) == 0) {
return hvSupport == 1;
} else {
return false;
}
}
#endif
StringSet Settings::getDefaultSystemFeatures()
{
/* For backwards compatibility, accept some "features" that are
@@ -170,6 +197,11 @@ StringSet Settings::getDefaultSystemFeatures()
features.insert("kvm");
#endif
#if __APPLE__
if (hasVirt())
features.insert("apple-virt");
#endif
return features;
}
@@ -377,7 +409,7 @@ void initLibStore() {
sshd). This breaks build users because they don't have access
to the TMPDIR, in particular in nix-store --serve. */
#if __APPLE__
if (hasPrefix(getEnv("TMPDIR").value_or("/tmp"), "/var/folders/"))
if (hasPrefix(defaultTempDir(), "/var/folders/"))
unsetenv("TMPDIR");
#endif

View File

@@ -708,6 +708,7 @@ public:
`kvm` feature.
This setting by default includes `kvm` if `/dev/kvm` is accessible,
`apple-virt` if hardware virtualization is available on macOS,
and the pseudo-features `nixos-test`, `benchmark` and `big-parallel`
that are used in Nixpkgs to route builds to specific machines.
)", {}, false};

View File

@@ -49,7 +49,7 @@ public:
, BinaryCacheStore(params)
, cacheUri(scheme + "://" + _cacheUri)
{
if (cacheUri.back() == '/')
while (!cacheUri.empty() && cacheUri.back() == '/')
cacheUri.pop_back();
diskCache = getNarInfoDiskCache();

View File

@@ -0,0 +1,34 @@
/*
* Determine the syscall number for `fchmodat2`.
*
* On most platforms this is 452. Exceptions can be found on
* a glibc git checkout via `rg --pcre2 'define __NR_fchmodat2 (?!452)'`.
*
* The problem is that glibc 2.39 and libseccomp 2.5.5 are needed to
* get the syscall number. However, a Nix built against nixpkgs 23.11
* (glibc 2.38) should still have the issue fixed without depending
* on the build environment.
*
* To achieve that, the macros below try to determine the platform and
* set the syscall number which is platform-specific, but
* in most cases 452.
*
* TODO: remove this when 23.11 is EOL and the entire (supported) ecosystem
* is on glibc 2.39.
*/
#if HAVE_SECCOMP
# if defined(__alpha__)
# define NIX_SYSCALL_FCHMODAT2 562
# elif defined(__x86_64__) && SIZE_MAX == 0xFFFFFFFF // x32
# define NIX_SYSCALL_FCHMODAT2 1073742276
# elif defined(__mips__) && defined(__mips64) && defined(_ABIN64) // mips64/n64
# define NIX_SYSCALL_FCHMODAT2 5452
# elif defined(__mips__) && defined(__mips64) && defined(_ABIN32) // mips64/n32
# define NIX_SYSCALL_FCHMODAT2 6452
# elif defined(__mips__) && defined(_ABIO32) // mips32
# define NIX_SYSCALL_FCHMODAT2 4452
# else
# define NIX_SYSCALL_FCHMODAT2 452
# endif
#endif // HAVE_SECCOMP

View File

@@ -3,6 +3,11 @@
namespace nix {
static constexpr std::string_view nameRegexStr = R"([0-9a-zA-Z\+\-\._\?=]+)";
static constexpr std::string_view nameRegexStr =
// This uses a negative lookahead: (?!\.\.?(-|$))
// - deny ".", "..", or those strings followed by '-'
// - when it's not those, start again at the start of the input and apply the next regex, which is [0-9a-zA-Z\+\-\._\?=]+
R"((?!\.\.?(-|$))[0-9a-zA-Z\+\-\._\?=]+)";
}

View File

@@ -12,6 +12,19 @@ static void checkName(std::string_view path, std::string_view name)
throw BadStorePath("store path '%s' has a name longer than %d characters",
path, StorePath::MaxPathLen);
// See nameRegexStr for the definition
if (name[0] == '.') {
// check against "." and "..", followed by end or dash
if (name.size() == 1)
throw BadStorePath("store path '%s' has invalid name '%s'", path, name);
if (name[1] == '-')
throw BadStorePath("store path '%s' has invalid name '%s': first dash-separated component must not be '%s'", path, name, ".");
if (name[1] == '.') {
if (name.size() == 2)
throw BadStorePath("store path '%s' has invalid name '%s'", path, name);
if (name[2] == '-')
throw BadStorePath("store path '%s' has invalid name '%s': first dash-separated component must not be '%s'", path, name, "..");
}
}
for (auto c : name)
if (!((c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'z')

View File

@@ -1,29 +0,0 @@
check: libstore-tests-exe_RUN
programs += libstore-tests-exe
libstore-tests-exe_NAME = libnixstore-tests
libstore-tests-exe_DIR := $(d)
libstore-tests-exe_INSTALL_DIR :=
libstore-tests-exe_LIBS = libstore-tests
libstore-tests-exe_LDFLAGS := $(GTEST_LIBS)
libraries += libstore-tests
libstore-tests_NAME = libnixstore-tests
libstore-tests_DIR := $(d)
libstore-tests_INSTALL_DIR :=
libstore-tests_SOURCES := $(wildcard $(d)/*.cc)
libstore-tests_CXXFLAGS += -I src/libstore -I src/libutil
libstore-tests_LIBS = libutil-tests libstore libutil
libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)

View File

@@ -0,0 +1,17 @@
#pragma once
/**
* @file
*
* Utiltities for working with the file sytem and file paths.
*/
#include "types.hh"
namespace nix {
/**
* Return `TMPDIR`, or the default temporary directory if unset or empty.
*/
Path defaultTempDir();
}

View File

@@ -5,15 +5,20 @@
#include "finally.hh"
#include "util.hh"
#include "types.hh"
#include "file-system.hh"
namespace fs = std::filesystem;
namespace nix {
std::string defaultTempDir() {
return getEnvNonEmpty("TMPDIR").value_or("/tmp");
}
static Path tempName(Path tmpRoot, const Path & prefix, bool includePid,
std::atomic<unsigned int> & counter)
{
tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR").value_or("/tmp") : tmpRoot, true);
tmpRoot = canonPath(tmpRoot.empty() ? defaultTempDir() : tmpRoot, true);
if (includePid)
return fmt("%1%/%2%-%3%-%4%", tmpRoot, prefix, getpid(), counter++);
else
@@ -53,7 +58,7 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
{
Path tmpl(getEnv("TMPDIR").value_or("/tmp") + "/" + prefix + ".XXXXXX");
Path tmpl(defaultTempDir() + "/" + prefix + ".XXXXXX");
// Strictly speaking, this is UB, but who cares...
// FIXME: use O_TMPFILE.
AutoCloseFD fd(mkstemp((char *) tmpl.c_str()));
@@ -133,6 +138,12 @@ void copy(const fs::directory_entry & from, const fs::path & to, bool andDelete)
}
}
void copyFile(const Path & oldPath, const Path & newPath, bool andDelete)
{
return copy(fs::directory_entry(fs::path(oldPath)), fs::path(newPath), andDelete);
}
void renameFile(const Path & oldName, const Path & newName)
{
fs::rename(oldName, newName);

View File

@@ -444,7 +444,7 @@ Error readError(Source & source)
auto msg = readString(source);
ErrorInfo info {
.level = level,
.msg = hintformat(fmt("%s", msg)),
.msg = hintfmt(msg),
};
auto havePos = readNum<size_t>(source);
assert(havePos == 0);
@@ -453,7 +453,7 @@ Error readError(Source & source)
havePos = readNum<size_t>(source);
assert(havePos == 0);
info.traces.push_back(Trace {
.hint = hintformat(fmt("%s", readString(source)))
.hint = hintfmt(readString(source))
});
}
return Error(std::move(info));

View File

@@ -1,29 +0,0 @@
check: libutil-tests_RUN
programs += libutil-tests
libutil-tests-exe_NAME = libnixutil-tests
libutil-tests-exe_DIR := $(d)
libutil-tests-exe_INSTALL_DIR :=
libutil-tests-exe_LIBS = libutil-tests
libutil-tests-exe_LDFLAGS := $(GTEST_LIBS)
libraries += libutil-tests
libutil-tests_NAME = libnixutil-tests
libutil-tests_DIR := $(d)
libutil-tests_INSTALL_DIR :=
libutil-tests_SOURCES := $(wildcard $(d)/*.cc)
libutil-tests_CXXFLAGS += -I src/libutil
libutil-tests_LIBS = libutil
libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)

View File

@@ -30,7 +30,7 @@ extern std::regex refRegex;
/// Instead of defining what a good Git Ref is, we define what a bad Git Ref is
/// This is because of the definition of a ref in refs.c in https://github.com/git/git
/// See tests/fetchGitRefs.sh for the full definition
/// See tests/functional/fetchGitRefs.sh for the full definition
const static std::string badGitRefRegexS = "//|^[./]|/\\.|\\.\\.|[[:cntrl:][:space:]:?^~\[]|\\\\|\\*|\\.lock$|\\.lock/|@\\{|[/.]$|^@$|^$";
extern std::regex badGitRefRegex;

View File

@@ -679,6 +679,11 @@ std::optional<Path> getSelfExe()
return cached;
}
void createDir(const Path &path, mode_t mode)
{
if (mkdir(path.c_str(), mode) == -1)
throw SysError("creating directory '%1%'", path);
}
Paths createDirs(const Path & path)
{

View File

@@ -253,6 +253,11 @@ inline Paths createDirs(PathView path)
return createDirs(Path(path));
}
/**
* Create a single directory.
*/
void createDir(const Path & path, mode_t mode = 0755);
/**
* Create a symlink.
*/
@@ -274,6 +279,13 @@ void renameFile(const Path & src, const Path & dst);
*/
void moveFile(const Path & src, const Path & dst);
/**
* Recursively copy the content of `oldPath` to `newPath`. If `andDelete` is
* `true`, then also remove `oldPath` (making this equivalent to `moveFile`, but
* with the guaranty that the destination will be “fresh”, with no stale inode
* or file descriptor pointing to it).
*/
void copyFile(const Path & oldPath, const Path & newPath, bool andDelete);
/**
* Wrappers arount read()/write() that read/write exactly the

View File

@@ -119,7 +119,7 @@ static void main_nix_build(int argc, char * * argv)
script = argv[1];
try {
auto lines = tokenizeString<Strings>(readFile(script), "\n");
if (std::regex_search(lines.front(), std::regex("^#!"))) {
if (!lines.empty() && std::regex_search(lines.front(), std::regex("^#!"))) {
lines.pop_front();
inShebang = true;
for (int i = 2; i < argc; ++i)
@@ -457,8 +457,7 @@ static void main_nix_build(int argc, char * * argv)
// Set the environment.
auto env = getEnv();
auto tmp = getEnv("TMPDIR");
if (!tmp) tmp = getEnv("XDG_RUNTIME_DIR").value_or("/tmp");
auto tmp = getEnvNonEmpty("TMPDIR").value_or("/tmp");
if (pure) {
decltype(env) newEnv;
@@ -470,7 +469,7 @@ static void main_nix_build(int argc, char * * argv)
env["__ETC_PROFILE_SOURCED"] = "1";
}
env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = *tmp;
env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmp;
env["NIX_STORE"] = store->storeDir;
env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores);

View File

@@ -201,7 +201,11 @@ static PeerInfo getPeerInfo(int remote)
#if defined(SO_PEERCRED)
ucred cred;
# if defined(__OpenBSD__)
struct sockpeercred cred;
# else
ucred cred;
# endif
socklen_t credLen = sizeof(cred);
if (getsockopt(remote, SOL_SOCKET, SO_PEERCRED, &cred, &credLen) == -1)
throw SysError("getting peer credentials");
@@ -209,9 +213,9 @@ static PeerInfo getPeerInfo(int remote)
#elif defined(LOCAL_PEERCRED)
#if !defined(SOL_LOCAL)
#define SOL_LOCAL 0
#endif
# if !defined(SOL_LOCAL)
# define SOL_LOCAL 0
# endif
xucred cred;
socklen_t credLen = sizeof(cred);

View File

@@ -1110,7 +1110,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
// If we don't recognize it, it's probably content
return true;
} catch (EvalError & e) {
// Some attrs may contain errors, eg. legacyPackages of
// Some attrs may contain errors, e.g. legacyPackages of
// nixpkgs. We still want to recurse into it, instead of
// skipping it at all.
return true;

View File

@@ -12,6 +12,7 @@
#include "finally.hh"
#include "loggers.hh"
#include "markdown.hh"
#include "eval-cache.hh"
#include <sys/types.h>
#include <sys/socket.h>
@@ -218,7 +219,8 @@ static void showHelp(std::vector<std::string> subcommand, NixArgs & toplevel)
vDump->mkString(toplevel.dumpCli());
auto vRes = state.allocValue();
state.callFunction(*vGenerateManpage, *vDump, *vRes, noPos);
state.callFunction(*vGenerateManpage, state.getBuiltin("false"), *vRes, noPos);
state.callFunction(*vRes, *vDump, *vRes, noPos);
auto attr = vRes->attrs->get(state.symbols.create(mdName + ".md"));
if (!attr)
@@ -479,7 +481,15 @@ void mainWrapped(int argc, char * * argv)
if (args.command->second->forceImpureByDefault() && !evalSettings.pureEval.overridden) {
evalSettings.pureEval = false;
}
args.command->second->run();
try {
args.command->second->run();
} catch (eval_cache::CachedEvalError & e) {
/* Evaluate the original attribute that resulted in this
cached error so that we can show the original error to the
user. */
e.force();
}
}
}

View File

@@ -1,11 +0,0 @@
#!/usr/bin/env bash
source common.sh
out1=$(nix-build ./text-hashed-output.nix -A hello --no-out-link)
clearStore
out2=$(nix-build ./text-hashed-output.nix -A wrapper --no-out-link)
diff -r $out1 $out2

View File

@@ -1,6 +1,6 @@
source common.sh
sed -e "s|@localstatedir@|$TEST_ROOT/profile-var|g" -e "s|@coreutils@|$coreutils|g" < ../scripts/nix-profile.sh.in > $TEST_ROOT/nix-profile.sh
sed -e "s|@localstatedir@|$TEST_ROOT/profile-var|g" -e "s|@coreutils@|$coreutils|g" < ../../scripts/nix-profile.sh.in > $TEST_ROOT/nix-profile.sh
user=$(whoami)
rm -rf $TEST_HOME $TEST_ROOT/profile-var

View File

@@ -6,7 +6,7 @@ unset NIX_STATE_DIR
remoteDir=$TEST_ROOT/remote
# Note: ssh{-ng}://localhost bypasses ssh. See tests/build-remote.sh for
# Note: ssh{-ng}://localhost bypasses ssh. See tests/functional/build-remote.sh for
# more details.
nix-build $file -o $TEST_ROOT/result --max-jobs 0 \
--arg busybox $busybox \

Some files were not shown because too many files have changed in this diff Show More