Compare commits

...

60 Commits

Author SHA1 Message Date
Jörg Thalheim
adbf23e818 Merge pull request #12922 from NixOS/mergify/bp/2.24-maintenance/pr-12911
create cache entry for paths already in the nix store (backport #12911)
2025-04-04 16:32:47 +02:00
Jörg Thalheim
2a4e2ecd89 create cache entry for paths already in the nix store
This allows path:/nix/store/* paths to not be copied twice to the nix
store.

(cherry picked from commit 61c6210dbf)
2025-04-04 16:01:17 +02:00
mergify[bot]
b47bd02a6a Merge pull request #12854 from NixOS/mergify/bp/2.24-maintenance/pr-12765
Add various clang tidy fixes (backport #12765)
2025-04-01 14:35:45 +00:00
Jörg Thalheim
8abb67b842 libstore/daemon: make sure monitor is not considered "unused"
(cherry picked from commit 5c3682d7a1)
2025-04-01 13:37:38 +00:00
Jörg Thalheim
97f9f8e909 test/ca-fd-leak: fix clang-tidy lints
(cherry picked from commit b050db951b)
2025-04-01 13:37:37 +00:00
Jörg Thalheim
7ef04ba6dd git/getStringUntil: fix uninitialized stack variable
at least clang-tidy is not convinced that this initialized.
If this is not the case, the impact should be small and hopefully also
more robust if changed.

(cherry picked from commit 7e540059a3)
2025-04-01 13:37:37 +00:00
Jörg Thalheim
bc6e78402c libstore/local-store: fix linting warning about unused variable
(cherry picked from commit 05082ea1c5)
2025-04-01 13:37:37 +00:00
mergify[bot]
4687dc99f7 Merge pull request #12840 from NixOS/mergify/bp/2.24-maintenance/pr-12805
nix-daemon: source nix-profile-daemon.sh only once (backport #12805)
2025-04-01 07:47:08 +00:00
Thomas Miedema
8d99b6578a nix-daemon: source nix-profile-daemon.sh only once
On my system (Ubuntu 24.04 with nix installed using
https://zero-to-nix.com/), I noticed that my PATH
contained multiple times the following entries:

  /home/thomas/.nix-profile/bin
  /nix/var/nix/profiles/default/bin

Fix it by inserting a missing `export`, to make
sure `nix-daemon.sh` is really only executed once.

(cherry picked from commit 2b4e3fa144)
2025-04-01 06:47:25 +00:00
John Ericson
e1dad7daa5 Merge pull request #12795 from NixOS/mergify/bp/2.24-maintenance/pr-12794
Fix windows build (backport #12794)
2025-03-28 21:54:39 -04:00
John Ericson
d92b509bda Fix windows build
PR #12767 accidentally broke it.

(cherry picked from commit 99041b4d84)
2025-03-28 21:07:08 -04:00
mergify[bot]
8adc1f3011 Merge pull request #12774 from NixOS/mergify/bp/2.24-maintenance/pr-12767
use createDirs consistently everywhere (backport #12767)
2025-03-28 16:48:21 +00:00
Jörg Thalheim
076fa01a84 use createDirs consistently everywhere
(cherry picked from commit a8217f2642)
2025-03-28 15:54:56 +00:00
Eelco Dolstra
61f8fd3e9c Bump version 2025-03-24 19:35:50 +01:00
Eelco Dolstra
5ce8d922fd Merge pull request #12737 from NixOS/mergify/bp/2.24-maintenance/pr-12736
`MonitorFdHup::~MonitorFdHup`: use proper close method instead of lib… (backport #12736)
2025-03-24 14:00:41 +01:00
Jörg Thalheim
333479e6be MonitorFdHup::~MonitorFdHup: use proper close method instead of libc close()
Otherwise closing it again will cause an EBADF in the AutoCloseFd class.

(cherry picked from commit 87a34a45ff)
2025-03-24 12:16:00 +00:00
John Ericson
71ab003a0c Merge pull request #12731 from NixOS/mergify/bp/2.24-maintenance/pr-12714
`MonitorFdHup`: replace `pthread_cancel` trick with a notification pipe (backport #12714)
2025-03-23 20:39:08 -04:00
John Ericson
3fccc71492 MonitorFdHup: Don't sleep anymore
After the previous commit it should not be necessary. Furthermore, if we
*do* sleep, we'll exacerbate a race condition (in conjunction with
getting rid of the thread cancellation) that will cause test failures.

(cherry picked from commit 49f486d8e0)
2025-03-23 23:54:09 +00:00
Jade Lovelace
729d18fd4c daemon: remove workaround for macOS kernel bug that seems fixed
This was filed as https://github.com/nixos/nix/issues/7584, but as far
as I can tell, the previous solution of POLLHUP works just fine on macOS
14. I've also tested on an ancient machine with macOS 10.15.7, which
also has POLLHUP work correctly.

It's possible this might regress some older versions of macOS that have
a kernel bug, but I went looking through the history on the sources and
didn't find anything that looked terribly convincingly like a bug fix
between 2020 and today. If such a broken version exists, it seems pretty
reasonable to suggest simply updating the OS.

Change-Id: I178a038baa000f927ea2cbc4587d69d8ab786843

Based off of commit 69e2ee5b25752ba5fd8644cef56fb9d627ca4a64. Ericson2314 added
additional other information.

(cherry picked from commit 9b3352c3c8)
2025-03-23 23:54:08 +00:00
Félix Baylac Jacqué
699f27c4ea MonitorFdHup: replace pthread_cancel trick with a notification pipe
On https://github.com/NixOS/nix/issues/8946, we faced a surprising
behaviour wrt. exception when using pthread_cancel. In a nutshell when
a thread is inside a catch block and it's getting pthread_cancel by
another one, then the original exception is bubbled up and crashes the
process.

We now poll on the notification pipe from the thread and exit when the
main thread closes its end. This solution does not exhibit surprising
behaviour wrt. exceptions.

Co-authored-by: Mic92 <joerg@thalheim.io>

Fixes https://github.com/NixOS/nix/issues/8946

See also Lix https://gerrit.lix.systems/c/lix/+/1605 which is very
similar by coincidence. Pulled a comment from that.

(cherry picked from commit 1c636284a3)
2025-03-23 23:54:08 +00:00
John Ericson
2d792a1867 MonitorFdHup: introduce a num_fds variable
Better than just putting `1` in multiple spots.

(cherry picked from commit cb95791198)
2025-03-23 23:54:08 +00:00
John Ericson
da213e8ee5 MonitorFdHup: Cleanup a bit with designated initializers
(cherry picked from commit d028bb4c4a)
2025-03-23 23:54:08 +00:00
Jörg Thalheim
787a14b173 MonitorFdHup: raise explicit SysError rather unreachable
Syscalls can fail for many reasons and we don't want to loose the errno
and error context.

(cherry picked from commit 8e0bc2c3a8)
2025-03-23 23:54:07 +00:00
John Ericson
01aace706a monitor-fd.hh: Format
It's a pretty small diff, so let's just start formatting before we make
other changes.

(cherry picked from commit 041394b741)
2025-03-23 23:54:07 +00:00
mergify[bot]
74a0ab3eea Merge pull request #12683 from NixOS/mergify/bp/2.24-maintenance/pr-12570
Fix macos sandbox issue (backport #12570)
2025-03-19 21:07:12 +00:00
Pierre-Etienne Meunier
589da451e4 Fix macos sandbox issue
Co-authored-by: John Ericson <git@JohnEricson.me>

Co-authored-by: Poliorcetics <poliorcetics@users.noreply.github.com>
(cherry picked from commit 300465c7b8)
2025-03-19 20:20:48 +00:00
mergify[bot]
56e113d67a Merge pull request #12653 from NixOS/mergify/bp/2.24-maintenance/pr-12645
Make debugger significantly faster (backport #12645)
2025-03-14 14:11:27 +00:00
Sergei Zimmerman
aaf86cc0d5 {libexpr,libcmd}: Make debugger significantly faster
The underlying issue is that debugger code path was
calling PosTable::operator[] in each eval method.
This has become incredibly expensive since 5d9fdab3de.

While we are it it, I've reworked the code to
not use std::shared_ptr where it really isn't necessary.

As I've documented in previous commits, this is actually
more a workaround for recursive header dependencies now
and is only necessary in `error.hh` code.

Some ad-hoc benchmarking:

After this commit:

```
Benchmark 1: nix eval nixpkgs#hello --impure --ignore-try --no-eval-cache --debugger
  Time (mean ± σ):     784.2 ms ±   7.1 ms    [User: 561.4 ms, System: 147.7 ms]
  Range (min … max):   773.5 ms … 792.6 ms    10 runs
```

On master 3604c7c51:

```
Benchmark 1: nix eval nixpkgs#hello --impure --ignore-try --no-eval-cache --debugger
  Time (mean ± σ):     22.914 s ±  0.178 s    [User: 18.524 s, System: 4.151 s]
  Range (min … max):   22.738 s … 23.290 s    10 runs
```

(cherry picked from commit adbd08399c)
2025-03-14 13:22:44 +00:00
Sergei Zimmerman
6faf66d2f7 libutil: Fix Pos::getSourcePath
Previous implementation didn't actually check if
std::get_if returned a nullptr:

std::optional<SourcePath> getSourcePath() const {
    return *std::get_if<SourcePath>(&origin);
}

(cherry picked from commit 50123f2a56)
2025-03-14 13:22:44 +00:00
Sergei Zimmerman
3ab83f507c libutil: Document hacks and problems around Pos class
This should provide context for follow-up commits in
the patch series.

(cherry picked from commit bf12aedf2e)
2025-03-14 13:22:43 +00:00
Sergei Zimmerman
0033cf4270 {libutil,libexpr}: Move pos-idx,pos-table code to libutil
All of this code doesn't actually depend on anything from
libexpr. Because Pos is so tigtly coupled with Error, it
makes sense to have in the same library.

(cherry picked from commit a53b184e63)
2025-03-14 13:22:43 +00:00
mergify[bot]
79828c12e0 Merge pull request #12535 from NixOS/mergify/bp/2.24-maintenance/pr-12391
Only try to chmod /nix/var/nix/profiles/per-user when necessary (backport #12391)
2025-02-20 16:55:38 +00:00
Sandro Jäckel
2a795bb793 Only try to chmod /nix/var/nix/profiles/per-user when necessary
Co-authored-by: Eelco Dolstra <edolstra@gmail.com>
(cherry picked from commit dcbf4dcc09)
2025-02-20 16:11:26 +00:00
mergify[bot]
9238c892d3 Merge pull request #12528 from NixOS/mergify/bp/2.24-maintenance/pr-12439
Set FD_CLOEXEC on sockets created by curl (backport #12439)
2025-02-19 20:30:16 +00:00
MaxHearnden
5862686ce2 Set FD_CLOEXEC on sockets created by curl
Curl creates sockets without setting FD_CLOEXEC/SOCK_CLOEXEC, this can
cause connections to remain open forever when using commands like `nix
shell`

This change sets the FD_CLOEXEC flag using a CURLOPT_SOCKOPTFUNCTION
callback.

(cherry picked from commit 12d2527276)
2025-02-19 19:47:40 +00:00
John Ericson
feadb3178d Merge pull request #12508 from NixOS/mergify/bp/2.24-maintenance/pr-12499
startDaemon(): Detect if the daemon crashes before creating the socket (backport #12499)
2025-02-18 12:21:39 -05:00
Eelco Dolstra
be35515ef7 startDaemon(): Detect if the daemon crashes before creating the socket
This avoids timeouts like those seen in
https://github.com/NixOS/nix/actions/runs/13376958708/job/37358120348?pr=6962.

(cherry picked from commit 11c42cb2e1)
2025-02-18 16:38:55 +00:00
Eelco Dolstra
71f93012fd Merge pull request #12487 from NixOS/mergify/bp/2.24-maintenance/pr-12481
resolveLookupPathPath(): Fix caching of negative lookups (backport #12481)
2025-02-18 17:27:52 +01:00
Eelco Dolstra
b706642133 resolveLookupPathPath(): Fix caching of negative lookups
This avoids spamming in case the missing search path entry does not
exist (#12480).

(cherry picked from commit df08e1e204)
2025-02-18 16:58:07 +01:00
Eelco Dolstra
658392e029 getDefaultNixPath(): Don't add symlinks if the target doesn't exist
(cherry picked from commit 8ac49ea5de)
2025-02-17 17:08:45 +00:00
mergify[bot]
d3a52c2ef4 Merge pull request #12451 from NixOS/mergify/bp/2.24-maintenance/pr-12448
copyPathToStore(): Preserve symlinks (backport #12448)
2025-02-11 22:21:12 +00:00
Eelco Dolstra
3d6a9c7410 copyPathToStore(): Preserve symlinks
E.g. in a derivation attribute `foo = ./bar`, if ./bar is a symlink,
we should copy the symlink to the store, not its target. This restores
the behaviour of Nix <= 2.19.

(cherry picked from commit 26b87e78b5)

# Conflicts:
#	tests/functional/meson.build
2025-02-11 21:51:20 +00:00
mergify[bot]
0f5f24223d Merge pull request #12434 from NixOS/mergify/bp/2.24-maintenance/pr-12373
pre-commit/check-merge-conflicts-2: fix use outside dev shell (backport #12373)
2025-02-10 14:37:20 +00:00
Robert Hensing
fcea626e49 test: Fix shellcheck by giving git-hashing scripts shebangs
This seems to be the way to do it now, even though I can't run them
without setting at least one env var.
I'll only fix shellcheck for now. Don't shoot the messenger.

It isn't quite clear to me why the previous commit masked this problem,
but I'm glad shellcheck has an effect or more effect now.
2025-02-10 15:09:36 +01:00
Robert Hensing
c6e09073ea pre-commit/check-merge-conflicts-2: fix use outside dev shell
Note that this is just a script that is meant to run outside a
derivation (but also can be called by a derivation builder).
`touch $out` does not belong in it.

`touch $out` worked accidentally in the derivation-based check,
and also in the dev shell, but if pre-commit is invoked without
the dev shell it would fail.
2025-02-10 15:08:54 +01:00
mergify[bot]
b9e6e00fe1 Merge pull request #12357 from NixOS/mergify/bp/2.24-maintenance/pr-12356
Improve "illegal path references in fixed output derivation" error (backport #12356)
2025-01-28 09:37:45 +00:00
mergify[bot]
5fb6551217 Merge pull request #12365 from NixOS/mergify/bp/2.24-maintenance/pr-12362
refactor: Extract EvalState::realiseString (backport #12362)
2025-01-28 08:51:24 +00:00
Robert Hensing
0f19bfe811 Fix conflict 2025-01-28 09:20:56 +01:00
Robert Hensing
865239c732 refactor: Extract EvalState::realiseString
(cherry picked from commit 7465fbe926)

# Conflicts:
#	src/libexpr/primops.cc
2025-01-27 15:50:52 +00:00
Ben Millwood
9c5482167f Improve "illegal path references in fixed output derivation" error
The main improvement is that the new message gives an example of a path
that is referenced, which should make it easier to track down. While
there, I also clarified the wording, saying exactly why the paths in
question were illegal.

(cherry picked from commit 4e5d1b281e)
2025-01-26 19:38:38 +00:00
Robert Hensing
a28791a91e Merge pull request #12352 from NixOS/nixfmt-on-2.24
Apply nixfmt (backport 2.24)
2025-01-24 22:01:53 +01:00
Robert Hensing
ae0bb7d71c test: Fix shifted source positions after formatting 2025-01-24 21:32:07 +01:00
Robert Hensing
2f1b70a529 Format .nix files
This does not include any automation for the release branch, but
is based on the configuration of https://github.com/NixOS/nix/pull/12349

    pre-commit run -a nixfmt-rfc-style
2025-01-24 20:30:07 +01:00
Eelco Dolstra
42b22fe3de Actually bump the version
Fixes 532092a812.
2025-01-24 16:47:16 +01:00
mergify[bot]
62e7144ba7 Merge pull request #12344 from NixOS/mergify/bp/2.24-maintenance/pr-12336
libstore: Fix progress bars (backport #12336)
2025-01-24 11:52:17 +00:00
Philipp Otterbein
a106e33bab libstore: fix progress bars
(cherry picked from commit be97dc1efc)
2025-01-24 11:10:16 +00:00
Eelco Dolstra
7616bae342 Merge pull request #12332 from NixOS/mergify/bp/2.24-maintenance/pr-12331
GitRepo::fetch(): Ignore $GIT_DIR (backport #12331)
2025-01-22 22:49:18 +01:00
Eelco Dolstra
1a402db046 GitRepo::fetch(): Ignore $GIT_DIR
Fixes #12325.

(cherry picked from commit 41983dba8f)
2025-01-22 22:10:09 +01:00
Eelco Dolstra
4511c47ab7 GitRepo::fetch(): Cleanup
(cherry picked from commit bd10b859f7)

# Conflicts:
#	src/libfetchers/git-utils.cc
2025-01-22 22:10:09 +01:00
Eelco Dolstra
532092a812 Bump version 2025-01-22 11:20:50 +01:00
342 changed files with 8708 additions and 5766 deletions

View File

@@ -1 +1 @@
2.24.12
2.24.14

View File

@@ -1,10 +1,9 @@
(import
(
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{ src = ./.; }
).defaultNix
(import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
) { src = ./.; }).defaultNix

View File

@@ -5,7 +5,15 @@ in
builtinsInfo:
let
showBuiltin = name: { doc, type ? null, args ? [ ], experimental-feature ? null, impure-only ? false }:
showBuiltin =
name:
{
doc,
type ? null,
args ? [ ],
experimental-feature ? null,
impure-only ? false,
}:
let
type' = optionalString (type != null) " (${type})";

View File

@@ -32,7 +32,13 @@ let
commandInfo = fromJSON commandDump;
showCommand = { command, details, filename, toplevel }:
showCommand =
{
command,
details,
filename,
toplevel,
}:
let
result = ''
@@ -56,26 +62,27 @@ let
${maybeOptions}
'';
showSynopsis = command: args:
showSynopsis =
command: args:
let
showArgument = arg: "*${arg.label}*" + optionalString (! arg ? arity) "...";
showArgument = arg: "*${arg.label}*" + optionalString (!arg ? arity) "...";
arguments = concatStringsSep " " (map showArgument args);
in ''
in
''
`${command}` [*option*...] ${arguments}
'';
maybeSubcommands = optionalString (details ? commands && details.commands != {})
''
where *subcommand* is one of the following:
maybeSubcommands = optionalString (details ? commands && details.commands != { }) ''
where *subcommand* is one of the following:
${subcommands}
'';
${subcommands}
'';
subcommands = if length categories > 1
then listCategories
else listSubcommands details.commands;
subcommands = if length categories > 1 then listCategories else listSubcommands details.commands;
categories = sort (x: y: x.id < y.id) (unique (map (cmd: cmd.category) (attrValues details.commands)));
categories = sort (x: y: x.id < y.id) (
unique (map (cmd: cmd.category) (attrValues details.commands))
);
listCategories = concatStrings (map showCategory categories);
@@ -99,38 +106,39 @@ let
${allStores}
'';
index = replaceStrings
[ "@store-types@" "./local-store.md" "./local-daemon-store.md" ]
[ storesOverview "#local-store" "#local-daemon-store" ]
details.doc;
index =
replaceStrings
[ "@store-types@" "./local-store.md" "./local-daemon-store.md" ]
[ storesOverview "#local-store" "#local-daemon-store" ]
details.doc;
storesOverview =
let
showEntry = store:
"- [${store.name}](#${store.slug})";
showEntry = store: "- [${store.name}](#${store.slug})";
in
concatStringsSep "\n" (map showEntry storesList) + "\n";
allStores = concatStringsSep "\n" (attrValues storePages);
storePages = listToAttrs
(map (s: { name = s.filename; value = s.page; }) storesList);
storePages = listToAttrs (
map (s: {
name = s.filename;
value = s.page;
}) storesList
);
storesList = showStoreDocs {
storeInfo = commandInfo.stores;
inherit inlineHTML;
};
hasInfix = infix: content:
hasInfix =
infix: content:
builtins.stringLength content != builtins.stringLength (replaceStrings [ infix ] [ "" ] content);
in
optionalString (details ? doc) (
# An alternate implementation with builtins.match stack overflowed on some systems.
if hasInfix "@store-types@" details.doc
then help-stores
else details.doc
if hasInfix "@store-types@" details.doc then help-stores else details.doc
);
maybeOptions =
let
allVisibleOptions = filterAttrs
(_: o: ! o.hiddenCategory)
(details.flags // toplevel.flags);
allVisibleOptions = filterAttrs (_: o: !o.hiddenCategory) (details.flags // toplevel.flags);
in
optionalString (allVisibleOptions != { }) ''
# Options
@@ -142,55 +150,73 @@ let
> See [`man nix.conf`](@docroot@/command-ref/conf-file.md#command-line-flags) for overriding configuration settings with command line flags.
'';
showOptions = inlineHTML: allOptions:
showOptions =
inlineHTML: allOptions:
let
showCategory = cat: opts: ''
${optionalString (cat != "") "## ${cat}"}
${concatStringsSep "\n" (attrValues (mapAttrs showOption opts))}
'';
showOption = name: option:
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 result;
categories = mapAttrs
# Convert each group from a list of key-value pairs back to an attrset
(_: listToAttrs)
(groupBy
(cmd: cmd.value.category)
(attrsToList allOptions));
in concatStrings (attrValues (mapAttrs showCategory categories));
in squash result;
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
result;
categories =
mapAttrs
# Convert each group from a list of key-value pairs back to an attrset
(_: listToAttrs)
(groupBy (cmd: cmd.value.category) (attrsToList allOptions));
in
concatStrings (attrValues (mapAttrs showCategory categories));
in
squash result;
appendName = filename: name: (if filename == "nix" then "nix3" else filename) + "-" + name;
processCommand = { command, details, filename, toplevel }:
processCommand =
{
command,
details,
filename,
toplevel,
}:
let
cmd = {
inherit command;
name = filename + ".md";
value = showCommand { inherit command details filename toplevel; };
value = showCommand {
inherit
command
details
filename
toplevel
;
};
};
subcommand = subCmd: processCommand {
command = command + " " + subCmd;
details = details.commands.${subCmd};
filename = appendName filename subCmd;
inherit toplevel;
};
in [ cmd ] ++ concatMap subcommand (attrNames details.commands or {});
subcommand =
subCmd:
processCommand {
command = command + " " + subCmd;
details = details.commands.${subCmd};
filename = appendName filename subCmd;
inherit toplevel;
};
in
[ cmd ] ++ concatMap subcommand (attrNames details.commands or { });
manpages = processCommand {
command = "nix";
@@ -199,9 +225,11 @@ let
toplevel = commandInfo.args;
};
tableOfContents = let
showEntry = page:
" - [${page.command}](command-ref/new-cli/${page.name})";
in concatStringsSep "\n" (map showEntry manpages) + "\n";
tableOfContents =
let
showEntry = page: " - [${page.command}](command-ref/new-cli/${page.name})";
in
concatStringsSep "\n" (map showEntry manpages) + "\n";
in (listToAttrs manpages) // { "SUMMARY.md" = tableOfContents; }
in
(listToAttrs manpages) // { "SUMMARY.md" = tableOfContents; }

View File

@@ -1,67 +1,99 @@
let
inherit (builtins) attrValues concatStringsSep isAttrs isBool mapAttrs;
inherit (import <nix/utils.nix>) concatStrings indent optionalString squash;
inherit (builtins)
attrValues
concatStringsSep
isAttrs
isBool
mapAttrs
;
inherit (import <nix/utils.nix>)
concatStrings
indent
optionalString
squash
;
in
# `inlineHTML` is a hack to accommodate inconsistent output from `lowdown`
{ prefix, inlineHTML ? true }: settingsInfo:
{
prefix,
inlineHTML ? true,
}:
settingsInfo:
let
showSetting = prefix: setting: { description, documentDefault, defaultValue, aliases, value, experimentalFeature }:
showSetting =
prefix: setting:
{
description,
documentDefault,
defaultValue,
aliases,
value,
experimentalFeature,
}:
let
result = squash ''
- ${item}
- ${item}
${indent " " body}
'';
item = if inlineHTML
then ''<span id="${prefix}-${setting}">[`${setting}`](#${prefix}-${setting})</span>''
else "`${setting}`";
${indent " " body}
'';
item =
if inlineHTML then
''<span id="${prefix}-${setting}">[`${setting}`](#${prefix}-${setting})</span>''
else
"`${setting}`";
# separate body to cleanly handle indentation
body = ''
${experimentalFeatureNote}
${experimentalFeatureNote}
${description}
${description}
**Default:** ${showDefault documentDefault defaultValue}
**Default:** ${showDefault documentDefault defaultValue}
${showAliases aliases}
'';
${showAliases aliases}
'';
experimentalFeatureNote = optionalString (experimentalFeature != null) ''
> **Warning**
>
> This setting is part of an
> [experimental feature](@docroot@/development/experimental-features.md).
>
> To change this setting, make sure the
> [`${experimentalFeature}` experimental feature](@docroot@/development/experimental-features.md#xp-feature-${experimentalFeature})
> is enabled.
> For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md):
>
> ```
> extra-experimental-features = ${experimentalFeature}
> ${setting} = ...
> ```
'';
> **Warning**
>
> This setting is part of an
> [experimental feature](@docroot@/development/experimental-features.md).
>
> To change this setting, make sure the
> [`${experimentalFeature}` experimental feature](@docroot@/development/experimental-features.md#xp-feature-${experimentalFeature})
> is enabled.
> For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md):
>
> ```
> extra-experimental-features = ${experimentalFeature}
> ${setting} = ...
> ```
'';
showDefault = documentDefault: defaultValue:
showDefault =
documentDefault: defaultValue:
if documentDefault then
# a StringMap value type is specified as a string, but
# this shows the value type. The empty stringmap is `null` in
# JSON, but that converts to `{ }` here.
if defaultValue == "" || defaultValue == [] || isAttrs defaultValue
then "*empty*"
else if isBool defaultValue then
if defaultValue then "`true`" else "`false`"
else "`${toString defaultValue}`"
else "*machine-specific*";
if defaultValue == "" || defaultValue == [ ] || isAttrs defaultValue then
"*empty*"
else if isBool defaultValue then
if defaultValue then "`true`" else "`false`"
else
"`${toString defaultValue}`"
else
"*machine-specific*";
showAliases = aliases:
optionalString (aliases != [])
"**Deprecated alias:** ${(concatStringsSep ", " (map (s: "`${s}`") aliases))}";
showAliases =
aliases:
optionalString (aliases != [ ])
"**Deprecated alias:** ${(concatStringsSep ", " (map (s: "`${s}`") aliases))}";
in result;
in
result;
in concatStrings (attrValues (mapAttrs (showSetting prefix) settingsInfo))
in
concatStrings (attrValues (mapAttrs (showSetting prefix) settingsInfo))

View File

@@ -1,6 +1,20 @@
let
inherit (builtins) attrNames listToAttrs concatStringsSep readFile replaceStrings;
inherit (import <nix/utils.nix>) optionalString filterAttrs trim squash toLower unique indent;
inherit (builtins)
attrNames
listToAttrs
concatStringsSep
readFile
replaceStrings
;
inherit (import <nix/utils.nix>)
optionalString
filterAttrs
trim
squash
toLower
unique
indent
;
showSettings = import <nix/generate-settings.nix>;
in
@@ -14,7 +28,13 @@ in
let
showStore = { name, slug }: { settings, doc, experimentalFeature }:
showStore =
{ name, slug }:
{
settings,
doc,
experimentalFeature,
}:
let
result = squash ''
# ${name}
@@ -25,7 +45,10 @@ let
## Settings
${showSettings { prefix = "store-${slug}"; inherit inlineHTML; } settings}
${showSettings {
prefix = "store-${slug}";
inherit inlineHTML;
} settings}
'';
experimentalFeatureNote = optionalString (experimentalFeature != null) ''
@@ -43,15 +66,15 @@ let
> extra-experimental-features = ${experimentalFeature}
> ```
'';
in result;
in
result;
storesList = map
(name: rec {
inherit name;
slug = replaceStrings [ " " ] [ "-" ] (toLower name);
filename = "${slug}.md";
page = showStore { inherit name slug; } storeInfo.${name};
})
(attrNames storeInfo);
storesList = map (name: rec {
inherit name;
slug = replaceStrings [ " " ] [ "-" ] (toLower name);
filename = "${slug}.md";
page = showStore { inherit name slug; } storeInfo.${name};
}) (attrNames storeInfo);
in storesList
in
storesList

View File

@@ -1,5 +1,11 @@
let
inherit (builtins) attrNames listToAttrs concatStringsSep readFile replaceStrings;
inherit (builtins)
attrNames
listToAttrs
concatStringsSep
readFile
replaceStrings
;
showSettings = import <nix/generate-settings.nix>;
showStoreDocs = import <nix/generate-store-info.nix>;
in
@@ -14,26 +20,26 @@ let
index =
let
showEntry = store:
"- [${store.name}](./${store.filename})";
showEntry = store: "- [${store.name}](./${store.filename})";
in
concatStringsSep "\n" (map showEntry storesList);
"index.md" = replaceStrings
[ "@store-types@" ] [ index ]
(readFile ./src/store/types/index.md.in);
"index.md" = replaceStrings [ "@store-types@" ] [ index ] (readFile ./src/store/types/index.md.in);
tableOfContents =
let
showEntry = store:
" - [${store.name}](store/types/${store.filename})";
showEntry = store: " - [${store.name}](store/types/${store.filename})";
in
concatStringsSep "\n" (map showEntry storesList) + "\n";
"SUMMARY.md" = tableOfContents;
storePages = listToAttrs
(map (s: { name = s.filename; value = s.page; }) storesList);
storePages = listToAttrs (
map (s: {
name = s.filename;
value = s.page;
}) storesList
);
in
storePages // { inherit "index.md" "SUMMARY.md"; }

View File

@@ -2,8 +2,8 @@ with builtins;
with import <nix/utils.nix>;
let
showExperimentalFeature = name: doc:
''
- [`${name}`](@docroot@/development/experimental-features.md#xp-feature-${name})
'';
in xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps)))
showExperimentalFeature = name: doc: ''
- [`${name}`](@docroot@/development/experimental-features.md#xp-feature-${name})
'';
in
xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps)))

View File

@@ -2,7 +2,8 @@ with builtins;
with import <nix/utils.nix>;
let
showExperimentalFeature = name: doc:
showExperimentalFeature =
name: doc:
squash ''
## [`${name}`]{#xp-feature-${name}}

View File

@@ -0,0 +1,10 @@
---
synopsis: Set FD_CLOEXEC on sockets created by curl
issues: []
prs: [12439]
---
Curl creates sockets without setting FD_CLOEXEC/SOCK_CLOEXEC, this can cause connections to remain open forever when using commands like `nix shell`
This change sets the FD_CLOEXEC flag using a CURLOPT_SOCKOPTFUNCTION callback.

View File

@@ -11,10 +11,15 @@ rec {
concatStrings = concatStringsSep "";
attrsToList = a:
map (name: { inherit name; value = a.${name}; }) (builtins.attrNames a);
attrsToList =
a:
map (name: {
inherit name;
value = a.${name};
}) (builtins.attrNames a);
replaceStringsRec = from: to: string:
replaceStringsRec =
from: to: string:
# recursively replace occurrences of `from` with `to` within `string`
# example:
# replaceStringRec "--" "-" "hello-----world"
@@ -22,16 +27,18 @@ rec {
let
replaced = replaceStrings [ from ] [ to ] string;
in
if replaced == string then string else replaceStringsRec from to replaced;
if replaced == string then string else replaceStringsRec from to replaced;
toLower = replaceStrings upperChars lowerChars;
squash = replaceStringsRec "\n\n\n" "\n\n";
trim = string:
trim =
string:
# trim trailing spaces and squash non-leading spaces
let
trimLine = line:
trimLine =
line:
let
# separate leading spaces from the rest
parts = split "(^ *)" line;
@@ -39,19 +46,30 @@ rec {
rest = elemAt parts 2;
# drop trailing spaces
body = head (split " *$" rest);
in spaces + replaceStringsRec " " " " body;
in concatStringsSep "\n" (map trimLine (splitLines string));
in
spaces + replaceStringsRec " " " " body;
in
concatStringsSep "\n" (map trimLine (splitLines string));
# FIXME: O(n^2)
unique = foldl' (acc: e: if elem e acc then acc else acc ++ [ e ]) [];
unique = foldl' (acc: e: if elem e acc then acc else acc ++ [ e ]) [ ];
nameValuePair = name: value: { inherit name value; };
filterAttrs = pred: set:
listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set));
filterAttrs =
pred: set:
listToAttrs (
concatMap (
name:
let
v = set.${name};
in
if pred name v then [ (nameValuePair name v) ] else [ ]
) (attrNames set)
);
optionalString = cond: string: if cond then string else "";
indent = prefix: s:
concatStringsSep "\n" (map (x: if x == "" then x else "${prefix}${x}") (splitLines s));
indent =
prefix: s: concatStringsSep "\n" (map (x: if x == "" then x else "${prefix}${x}") (splitLines s));
}

View File

@@ -1,70 +1,72 @@
{ pkgs ? import <nixpkgs> { }
, lib ? pkgs.lib
, name ? "nix"
, tag ? "latest"
, bundleNixpkgs ? true
, channelName ? "nixpkgs"
, channelURL ? "https://nixos.org/channels/nixpkgs-unstable"
, extraPkgs ? []
, maxLayers ? 100
, nixConf ? {}
, flake-registry ? null
{
pkgs ? import <nixpkgs> { },
lib ? pkgs.lib,
name ? "nix",
tag ? "latest",
bundleNixpkgs ? true,
channelName ? "nixpkgs",
channelURL ? "https://nixos.org/channels/nixpkgs-unstable",
extraPkgs ? [ ],
maxLayers ? 100,
nixConf ? { },
flake-registry ? null,
}:
let
defaultPkgs = with pkgs; [
nix
bashInteractive
coreutils-full
gnutar
gzip
gnugrep
which
curl
less
wget
man
cacert.out
findutils
iana-etc
git
openssh
] ++ extraPkgs;
defaultPkgs =
with pkgs;
[
nix
bashInteractive
coreutils-full
gnutar
gzip
gnugrep
which
curl
less
wget
man
cacert.out
findutils
iana-etc
git
openssh
]
++ extraPkgs;
users = {
users =
{
root = {
uid = 0;
shell = "${pkgs.bashInteractive}/bin/bash";
home = "/root";
gid = 0;
groups = [ "root" ];
description = "System administrator";
};
root = {
uid = 0;
shell = "${pkgs.bashInteractive}/bin/bash";
home = "/root";
gid = 0;
groups = [ "root" ];
description = "System administrator";
};
nobody = {
uid = 65534;
shell = "${pkgs.shadow}/bin/nologin";
home = "/var/empty";
gid = 65534;
groups = [ "nobody" ];
description = "Unprivileged account (don't use!)";
};
nobody = {
uid = 65534;
shell = "${pkgs.shadow}/bin/nologin";
home = "/var/empty";
gid = 65534;
groups = [ "nobody" ];
description = "Unprivileged account (don't use!)";
};
} // lib.listToAttrs (
map
(
n: {
name = "nixbld${toString n}";
value = {
uid = 30000 + n;
gid = 30000;
groups = [ "nixbld" ];
description = "Nix build user ${toString n}";
};
}
)
(lib.lists.range 1 32)
);
}
// lib.listToAttrs (
map (n: {
name = "nixbld${toString n}";
value = {
uid = 30000 + n;
gid = 30000;
groups = [ "nixbld" ];
description = "Nix build user ${toString n}";
};
}) (lib.lists.range 1 32)
);
groups = {
root.gid = 0;
@@ -74,24 +76,20 @@ let
userToPasswd = (
k:
{ uid
, gid ? 65534
, home ? "/var/empty"
, description ? ""
, shell ? "/bin/false"
, groups ? [ ]
}: "${k}:x:${toString uid}:${toString gid}:${description}:${home}:${shell}"
);
passwdContents = (
lib.concatStringsSep "\n"
(lib.attrValues (lib.mapAttrs userToPasswd users))
{
uid,
gid ? 65534,
home ? "/var/empty",
description ? "",
shell ? "/bin/false",
groups ? [ ],
}:
"${k}:x:${toString uid}:${toString gid}:${description}:${home}:${shell}"
);
passwdContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs userToPasswd users)));
userToShadow = k: { ... }: "${k}:!:1::::::";
shadowContents = (
lib.concatStringsSep "\n"
(lib.attrValues (lib.mapAttrs userToShadow users))
);
shadowContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs userToShadow users)));
# Map groups to members
# {
@@ -101,42 +99,35 @@ let
let
# Create a flat list of user/group mappings
mappings = (
builtins.foldl'
(
acc: user:
let
groups = users.${user}.groups or [ ];
in
acc ++ map
(group: {
inherit user group;
})
groups
)
[ ]
(lib.attrNames users)
builtins.foldl' (
acc: user:
let
groups = users.${user}.groups or [ ];
in
acc
++ map (group: {
inherit user group;
}) groups
) [ ] (lib.attrNames users)
);
in
(
builtins.foldl'
(
acc: v: acc // {
${v.group} = acc.${v.group} or [ ] ++ [ v.user ];
}
)
{ }
mappings)
(builtins.foldl' (
acc: v:
acc
// {
${v.group} = acc.${v.group} or [ ] ++ [ v.user ];
}
) { } mappings)
);
groupToGroup = k: { gid }:
groupToGroup =
k:
{ gid }:
let
members = groupMemberMap.${k} or [ ];
in
"${k}:x:${toString gid}:${lib.concatStringsSep "," members}";
groupContents = (
lib.concatStringsSep "\n"
(lib.attrValues (lib.mapAttrs groupToGroup groups))
);
groupContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs groupToGroup groups)));
defaultNixConf = {
sandbox = "false";
@@ -144,11 +135,17 @@ let
trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ];
};
nixConfContents = (lib.concatStringsSep "\n" (lib.mapAttrsFlatten (n: v:
let
vStr = if builtins.isList v then lib.concatStringsSep " " v else v;
in
"${n} = ${vStr}") (defaultNixConf // nixConf))) + "\n";
nixConfContents =
(lib.concatStringsSep "\n" (
lib.mapAttrsFlatten (
n: v:
let
vStr = if builtins.isList v then lib.concatStringsSep " " v else v;
in
"${n} = ${vStr}"
) (defaultNixConf // nixConf)
))
+ "\n";
baseSystem =
let
@@ -167,21 +164,29 @@ let
manifest = pkgs.buildPackages.runCommand "manifest.nix" { } ''
cat > $out <<EOF
[
${lib.concatStringsSep "\n" (builtins.map (drv: let
outputs = drv.outputsToInstall or [ "out" ];
in ''
{
${lib.concatStringsSep "\n" (builtins.map (output: ''
${output} = { outPath = "${lib.getOutput output drv}"; };
'') outputs)}
outputs = [ ${lib.concatStringsSep " " (builtins.map (x: "\"${x}\"") outputs)} ];
name = "${drv.name}";
outPath = "${drv}";
system = "${drv.system}";
type = "derivation";
meta = { };
}
'') defaultPkgs)}
${lib.concatStringsSep "\n" (
builtins.map (
drv:
let
outputs = drv.outputsToInstall or [ "out" ];
in
''
{
${lib.concatStringsSep "\n" (
builtins.map (output: ''
${output} = { outPath = "${lib.getOutput output drv}"; };
'') outputs
)}
outputs = [ ${lib.concatStringsSep " " (builtins.map (x: "\"${x}\"") outputs)} ];
name = "${drv.name}";
outPath = "${drv}";
system = "${drv.system}";
type = "derivation";
meta = { };
}
''
) defaultPkgs
)}
]
EOF
'';
@@ -190,16 +195,22 @@ let
cp -a ${rootEnv}/* $out/
ln -s ${manifest} $out/manifest.nix
'';
flake-registry-path = if (flake-registry == null) then
null
else if (builtins.readFileType (toString flake-registry)) == "directory" then
"${flake-registry}/flake-registry.json"
else
flake-registry;
flake-registry-path =
if (flake-registry == null) then
null
else if (builtins.readFileType (toString flake-registry)) == "directory" then
"${flake-registry}/flake-registry.json"
else
flake-registry;
in
pkgs.runCommand "base-system"
{
inherit passwdContents groupContents shadowContents nixConfContents;
inherit
passwdContents
groupContents
shadowContents
nixConfContents
;
passAsFile = [
"passwdContents"
"groupContents"
@@ -208,62 +219,66 @@ let
];
allowSubstitutes = false;
preferLocalBuild = true;
} (''
env
set -x
mkdir -p $out/etc
}
(
''
env
set -x
mkdir -p $out/etc
mkdir -p $out/etc/ssl/certs
ln -s /nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt $out/etc/ssl/certs
mkdir -p $out/etc/ssl/certs
ln -s /nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt $out/etc/ssl/certs
cat $passwdContentsPath > $out/etc/passwd
echo "" >> $out/etc/passwd
cat $passwdContentsPath > $out/etc/passwd
echo "" >> $out/etc/passwd
cat $groupContentsPath > $out/etc/group
echo "" >> $out/etc/group
cat $groupContentsPath > $out/etc/group
echo "" >> $out/etc/group
cat $shadowContentsPath > $out/etc/shadow
echo "" >> $out/etc/shadow
cat $shadowContentsPath > $out/etc/shadow
echo "" >> $out/etc/shadow
mkdir -p $out/usr
ln -s /nix/var/nix/profiles/share $out/usr/
mkdir -p $out/usr
ln -s /nix/var/nix/profiles/share $out/usr/
mkdir -p $out/nix/var/nix/gcroots
mkdir -p $out/nix/var/nix/gcroots
mkdir $out/tmp
mkdir $out/tmp
mkdir -p $out/var/tmp
mkdir -p $out/var/tmp
mkdir -p $out/etc/nix
cat $nixConfContentsPath > $out/etc/nix/nix.conf
mkdir -p $out/etc/nix
cat $nixConfContentsPath > $out/etc/nix/nix.conf
mkdir -p $out/root
mkdir -p $out/nix/var/nix/profiles/per-user/root
mkdir -p $out/root
mkdir -p $out/nix/var/nix/profiles/per-user/root
ln -s ${profile} $out/nix/var/nix/profiles/default-1-link
ln -s /nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default
ln -s /nix/var/nix/profiles/default $out/root/.nix-profile
ln -s ${profile} $out/nix/var/nix/profiles/default-1-link
ln -s /nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default
ln -s /nix/var/nix/profiles/default $out/root/.nix-profile
ln -s ${channel} $out/nix/var/nix/profiles/per-user/root/channels-1-link
ln -s /nix/var/nix/profiles/per-user/root/channels-1-link $out/nix/var/nix/profiles/per-user/root/channels
ln -s ${channel} $out/nix/var/nix/profiles/per-user/root/channels-1-link
ln -s /nix/var/nix/profiles/per-user/root/channels-1-link $out/nix/var/nix/profiles/per-user/root/channels
mkdir -p $out/root/.nix-defexpr
ln -s /nix/var/nix/profiles/per-user/root/channels $out/root/.nix-defexpr/channels
echo "${channelURL} ${channelName}" > $out/root/.nix-channels
mkdir -p $out/root/.nix-defexpr
ln -s /nix/var/nix/profiles/per-user/root/channels $out/root/.nix-defexpr/channels
echo "${channelURL} ${channelName}" > $out/root/.nix-channels
mkdir -p $out/bin $out/usr/bin
ln -s ${pkgs.coreutils}/bin/env $out/usr/bin/env
ln -s ${pkgs.bashInteractive}/bin/bash $out/bin/sh
mkdir -p $out/bin $out/usr/bin
ln -s ${pkgs.coreutils}/bin/env $out/usr/bin/env
ln -s ${pkgs.bashInteractive}/bin/bash $out/bin/sh
'' + (lib.optionalString (flake-registry-path != null) ''
nixCacheDir="/root/.cache/nix"
mkdir -p $out$nixCacheDir
globalFlakeRegistryPath="$nixCacheDir/flake-registry.json"
ln -s ${flake-registry-path} $out$globalFlakeRegistryPath
mkdir -p $out/nix/var/nix/gcroots/auto
rootName=$(${pkgs.nix}/bin/nix --extra-experimental-features nix-command hash file --type sha1 --base32 <(echo -n $globalFlakeRegistryPath))
ln -s $globalFlakeRegistryPath $out/nix/var/nix/gcroots/auto/$rootName
''));
''
+ (lib.optionalString (flake-registry-path != null) ''
nixCacheDir="/root/.cache/nix"
mkdir -p $out$nixCacheDir
globalFlakeRegistryPath="$nixCacheDir/flake-registry.json"
ln -s ${flake-registry-path} $out$globalFlakeRegistryPath
mkdir -p $out/nix/var/nix/gcroots/auto
rootName=$(${pkgs.nix}/bin/nix --extra-experimental-features nix-command hash file --type sha1 --base32 <(echo -n $globalFlakeRegistryPath))
ln -s $globalFlakeRegistryPath $out/nix/var/nix/gcroots/auto/$rootName
'')
);
in
pkgs.dockerTools.buildLayeredImageWithNixDb {
@@ -285,15 +300,19 @@ pkgs.dockerTools.buildLayeredImageWithNixDb {
Cmd = [ "/root/.nix-profile/bin/bash" ];
Env = [
"USER=root"
"PATH=${lib.concatStringsSep ":" [
"/root/.nix-profile/bin"
"/nix/var/nix/profiles/default/bin"
"/nix/var/nix/profiles/default/sbin"
]}"
"MANPATH=${lib.concatStringsSep ":" [
"/root/.nix-profile/share/man"
"/nix/var/nix/profiles/default/share/man"
]}"
"PATH=${
lib.concatStringsSep ":" [
"/root/.nix-profile/bin"
"/nix/var/nix/profiles/default/bin"
"/nix/var/nix/profiles/default/sbin"
]
}"
"MANPATH=${
lib.concatStringsSep ":" [
"/root/.nix-profile/share/man"
"/nix/var/nix/profiles/default/share/man"
]
}"
"SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
"GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
"NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"

567
flake.nix
View File

@@ -4,8 +4,14 @@
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
inputs.nixpkgs-23-11.url = "github:NixOS/nixpkgs/a62e6edd6d5e1fa0329b8653c801147986f8d446";
inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
inputs.libgit2 = { url = "github:libgit2/libgit2/v1.8.1"; flake = false; };
inputs.flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
inputs.libgit2 = {
url = "github:libgit2/libgit2/v1.8.1";
flake = false;
};
# dev tooling
inputs.flake-parts.url = "github:hercules-ci/flake-parts";
@@ -18,8 +24,14 @@
inputs.git-hooks-nix.inputs.flake-compat.follows = "";
inputs.git-hooks-nix.inputs.gitignore.follows = "";
outputs = inputs@{ self, nixpkgs, nixpkgs-regression, libgit2, ... }:
outputs =
inputs@{
self,
nixpkgs,
nixpkgs-regression,
libgit2,
...
}:
let
inherit (nixpkgs) lib;
@@ -28,14 +40,23 @@
version = lib.fileContents ./.version + versionSuffix;
versionSuffix =
if officialRelease
then ""
else "pre${builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}_${self.shortRev or "dirty"}";
if officialRelease then
""
else
"pre${
builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")
}_${self.shortRev or "dirty"}";
linux32BitSystems = [ "i686-linux" ];
linux64BitSystems = [ "x86_64-linux" "aarch64-linux" ];
linux64BitSystems = [
"x86_64-linux"
"aarch64-linux"
];
linuxSystems = linux32BitSystems ++ linux64BitSystems;
darwinSystems = [ "x86_64-darwin" "aarch64-darwin" ];
darwinSystems = [
"x86_64-darwin"
"aarch64-darwin"
];
systems = linuxSystems ++ darwinSystems;
crossSystems = [
@@ -64,62 +85,76 @@
(Provided that the names are unique.)
See https://nixos.org/manual/nixpkgs/stable/index.html#function-library-lib.attrsets.concatMapAttrs
*/
*/
flatMapAttrs = attrs: f: lib.concatMapAttrs f attrs;
forAllSystems = lib.genAttrs systems;
forAllCrossSystems = lib.genAttrs crossSystems;
forAllStdenvs = f:
lib.listToAttrs
(map
(stdenvName: {
name = "${stdenvName}Packages";
value = f stdenvName;
})
stdenvs);
forAllStdenvs =
f:
lib.listToAttrs (
map (stdenvName: {
name = "${stdenvName}Packages";
value = f stdenvName;
}) stdenvs
);
# We don't apply flake-parts to the whole flake so that non-development attributes
# load without fetching any development inputs.
devFlake = inputs.flake-parts.lib.mkFlake { inherit inputs; } {
imports = [ ./maintainers/flake-module.nix ];
systems = lib.subtractLists crossSystems systems;
perSystem = { system, ... }: {
_module.args.pkgs = nixpkgsFor.${system}.native;
};
perSystem =
{ system, ... }:
{
_module.args.pkgs = nixpkgsFor.${system}.native;
};
};
# Memoize nixpkgs for different platforms for efficiency.
nixpkgsFor = forAllSystems
(system: let
make-pkgs = crossSystem: stdenv: import nixpkgs {
localSystem = {
inherit system;
nixpkgsFor = forAllSystems (
system:
let
make-pkgs =
crossSystem: stdenv:
import nixpkgs {
localSystem = {
inherit system;
};
crossSystem =
if crossSystem == null then
null
else
{
config = crossSystem;
}
// lib.optionalAttrs (crossSystem == "x86_64-unknown-freebsd13") {
useLLVM = true;
};
overlays = [
(overlayFor (p: p.${stdenv}))
];
};
crossSystem = if crossSystem == null then null else {
config = crossSystem;
} // lib.optionalAttrs (crossSystem == "x86_64-unknown-freebsd13") {
useLLVM = true;
};
overlays = [
(overlayFor (p: p.${stdenv}))
];
};
stdenvs = forAllStdenvs (make-pkgs null);
native = stdenvs.stdenvPackages;
in {
in
{
inherit stdenvs native;
static = native.pkgsStatic;
cross = forAllCrossSystems (crossSystem: make-pkgs crossSystem "stdenv");
});
}
);
binaryTarball = nix: pkgs: pkgs.callPackage ./scripts/binary-tarball.nix {
inherit nix;
};
binaryTarball =
nix: pkgs:
pkgs.callPackage ./scripts/binary-tarball.nix {
inherit nix;
};
overlayFor = getStdenv: final: prev:
overlayFor =
getStdenv: final: prev:
let
stdenv = getStdenv final;
in
@@ -134,10 +169,12 @@
# The dependencies are in their own scope, so that they don't have to be
# in Nixpkgs top level `pkgs` or `nixComponents`.
nixDependencies = lib.makeScope final.newScope (import ./packaging/dependencies.nix {
inherit inputs stdenv versionSuffix;
pkgs = final;
});
nixDependencies = lib.makeScope final.newScope (
import ./packaging/dependencies.nix {
inherit inputs stdenv versionSuffix;
pkgs = final;
}
);
nix = final.nixComponents.nix;
@@ -149,13 +186,20 @@
# See https://github.com/NixOS/nixpkgs/pull/214409
# Remove when fixed in this flake's nixpkgs
pre-commit =
if prev.stdenv.hostPlatform.system == "i686-linux"
then (prev.pre-commit.override (o: { dotnet-sdk = ""; })).overridePythonAttrs (o: { doCheck = false; })
else prev.pre-commit;
if prev.stdenv.hostPlatform.system == "i686-linux" then
(prev.pre-commit.override (o: {
dotnet-sdk = "";
})).overridePythonAttrs
(o: {
doCheck = false;
})
else
prev.pre-commit;
};
in {
in
{
# A Nixpkgs overlay that overrides the 'nix' and
# 'nix-perl-bindings' packages.
overlays.default = overlayFor (p: p.stdenv);
@@ -173,53 +217,69 @@
;
};
checks = forAllSystems (system: {
installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system};
installTests = self.hydraJobs.installTests.${system};
nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system};
rl-next =
let pkgs = nixpkgsFor.${system}.native;
in pkgs.buildPackages.runCommand "test-rl-next-release-notes" { } ''
LANG=C.UTF-8 ${pkgs.changelog-d}/bin/changelog-d ${./doc/manual/rl-next} >$out
'';
repl-completion = nixpkgsFor.${system}.native.callPackage ./tests/repl-completion.nix { };
} // (lib.optionalAttrs (builtins.elem system linux64BitSystems)) {
dockerImage = self.hydraJobs.dockerImage.${system};
} // (lib.optionalAttrs (!(builtins.elem system linux32BitSystems))) {
# Some perl dependencies are broken on i686-linux.
# Since the support is only best-effort there, disable the perl
# bindings
checks = forAllSystems (
system:
{
installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system};
installTests = self.hydraJobs.installTests.${system};
nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system};
rl-next =
let
pkgs = nixpkgsFor.${system}.native;
in
pkgs.buildPackages.runCommand "test-rl-next-release-notes" { } ''
LANG=C.UTF-8 ${pkgs.changelog-d}/bin/changelog-d ${./doc/manual/rl-next} >$out
'';
repl-completion = nixpkgsFor.${system}.native.callPackage ./tests/repl-completion.nix { };
}
// (lib.optionalAttrs (builtins.elem system linux64BitSystems)) {
dockerImage = self.hydraJobs.dockerImage.${system};
}
// (lib.optionalAttrs (!(builtins.elem system linux32BitSystems))) {
# Some perl dependencies are broken on i686-linux.
# Since the support is only best-effort there, disable the perl
# bindings
# Temporarily disabled because GitHub Actions OOM issues. Once
# the old build system is gone and we are back to one build
# system, we should reenable this.
#perlBindings = self.hydraJobs.perlBindings.${system};
}
# Add "passthru" tests
// flatMapAttrs ({
"" = nixpkgsFor.${system}.native;
} // lib.optionalAttrs (! nixpkgsFor.${system}.native.stdenv.hostPlatform.isDarwin) {
# TODO: enable static builds for darwin, blocked on:
# https://github.com/NixOS/nixpkgs/issues/320448
"static-" = nixpkgsFor.${system}.static;
})
(nixpkgsPrefix: nixpkgs:
flatMapAttrs nixpkgs.nixComponents
(pkgName: pkg:
flatMapAttrs pkg.tests or {}
(testName: test: {
"${nixpkgsPrefix}${pkgName}-${testName}" = test;
})
# Temporarily disabled because GitHub Actions OOM issues. Once
# the old build system is gone and we are back to one build
# system, we should reenable this.
#perlBindings = self.hydraJobs.perlBindings.${system};
}
# Add "passthru" tests
//
flatMapAttrs
(
{
"" = nixpkgsFor.${system}.native;
}
// lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.hostPlatform.isDarwin) {
# TODO: enable static builds for darwin, blocked on:
# https://github.com/NixOS/nixpkgs/issues/320448
"static-" = nixpkgsFor.${system}.static;
}
)
)
// devFlake.checks.${system} or {}
(
nixpkgsPrefix: nixpkgs:
flatMapAttrs nixpkgs.nixComponents (
pkgName: pkg:
flatMapAttrs pkg.tests or { } (
testName: test: {
"${nixpkgsPrefix}${pkgName}-${testName}" = test;
}
)
)
)
// devFlake.checks.${system} or { }
);
packages = forAllSystems (system:
{ # Here we put attributes that map 1:1 into packages.<system>, ie
packages = forAllSystems (
system:
{
# Here we put attributes that map 1:1 into packages.<system>, ie
# for which we don't apply the full build matrix such as cross or static.
inherit (nixpkgsFor.${system}.native)
changelog-d;
changelog-d
;
default = self.packages.${system}.nix;
binaryTarball = self.hydraJobs.binaryTarball.${system};
installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system};
@@ -227,148 +287,191 @@
nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs;
}
# We need to flatten recursive attribute sets of derivations to pass `flake check`.
// flatMapAttrs
{ # Components we'll iterate over in the upcoming lambda
"nix" = { };
# Temporarily disabled because GitHub Actions OOM issues. Once
# the old build system is gone and we are back to one build
# system, we should reenable these.
#"nix-util" = { };
#"nix-store" = { };
#"nix-fetchers" = { };
}
(pkgName: {}: {
# These attributes go right into `packages.<system>`.
"${pkgName}" = nixpkgsFor.${system}.native.nixComponents.${pkgName};
"${pkgName}-static" = nixpkgsFor.${system}.static.nixComponents.${pkgName};
}
// flatMapAttrs (lib.genAttrs crossSystems (_: { })) (crossSystem: {}: {
# These attributes go right into `packages.<system>`.
"${pkgName}-${crossSystem}" = nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName};
})
// flatMapAttrs (lib.genAttrs stdenvs (_: { })) (stdenvName: {}: {
# These attributes go right into `packages.<system>`.
"${pkgName}-${stdenvName}" = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".nixComponents.${pkgName};
})
)
// lib.optionalAttrs (builtins.elem system linux64BitSystems) {
dockerImage =
let
pkgs = nixpkgsFor.${system}.native;
image = import ./docker.nix { inherit pkgs; tag = version; };
in
pkgs.runCommand
"docker-image-tarball-${version}"
{ meta.description = "Docker image with Nix for ${system}"; }
''
mkdir -p $out/nix-support
image=$out/image.tar.gz
ln -s ${image} $image
echo "file binary-dist $image" >> $out/nix-support/hydra-build-products
'';
});
devShells = let
makeShell = pkgs: stdenv: (pkgs.nix.override { inherit stdenv; forDevShell = true; }).overrideAttrs (attrs:
let
modular = devFlake.getSystem stdenv.buildPlatform.system;
transformFlag = prefix: flag:
assert builtins.isString flag;
let
rest = builtins.substring 2 (builtins.stringLength flag) flag;
in
"-D${prefix}:${rest}";
havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix;
ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags;
in {
pname = "shell-for-" + attrs.pname;
# Remove the version suffix to avoid unnecessary attempts to substitute in nix develop
version = lib.fileContents ./.version;
name = attrs.pname;
installFlags = "sysconfdir=$(out)/etc";
shellHook = ''
PATH=$prefix/bin:$PATH
unset PYTHONPATH
export MANPATH=$out/share/man:$MANPATH
# Make bash completion work.
XDG_DATA_DIRS+=:$out/share
'';
# We use this shell with the local checkout, not unpackPhase.
src = null;
env = {
# Needed for Meson to find Boost.
# https://github.com/NixOS/nixpkgs/issues/86131.
BOOST_INCLUDEDIR = "${lib.getDev pkgs.nixDependencies.boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib pkgs.nixDependencies.boost}/lib";
# For `make format`, to work without installing pre-commit
_NIX_PRE_COMMIT_HOOKS_CONFIG =
"${(pkgs.formats.yaml { }).generate "pre-commit-config.yaml" modular.pre-commit.settings.rawConfig}";
};
mesonFlags =
map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents.nix-util.mesonFlags)
++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents.nix-store.mesonFlags)
++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents.nix-fetchers.mesonFlags)
++ lib.optionals havePerl (map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents.nix-perl-bindings.mesonFlags))
++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents.nix-expr.mesonFlags)
++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents.nix-cmd.mesonFlags)
;
nativeBuildInputs = attrs.nativeBuildInputs or []
++ pkgs.nixComponents.nix-util.nativeBuildInputs
++ pkgs.nixComponents.nix-store.nativeBuildInputs
++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs
++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs
++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs
++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs
++ lib.optional
(!stdenv.buildPlatform.canExecute stdenv.hostPlatform
# Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479
&& !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin)
&& stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages
&& lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages))
pkgs.buildPackages.mesonEmulatorHook
++ [
pkgs.buildPackages.cmake
pkgs.buildPackages.shellcheck
pkgs.buildPackages.changelog-d
modular.pre-commit.settings.package
(pkgs.writeScriptBin "pre-commit-hooks-install"
modular.pre-commit.settings.installationScript)
]
# TODO: Remove the darwin check once
# https://github.com/NixOS/nixpkgs/pull/291814 is available
++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear
++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) pkgs.buildPackages.clang-tools;
buildInputs = attrs.buildInputs or []
++ [
pkgs.gtest
pkgs.rapidcheck
]
++ lib.optional havePerl pkgs.perl
;
});
in
forAllSystems (system:
let
makeShells = prefix: pkgs:
lib.mapAttrs'
(k: v: lib.nameValuePair "${prefix}-${k}" v)
(forAllStdenvs (stdenvName: makeShell pkgs pkgs.${stdenvName}));
in
(makeShells "native" nixpkgsFor.${system}.native) //
(lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin)
(makeShells "static" nixpkgsFor.${system}.static) //
(forAllCrossSystems (crossSystem: let pkgs = nixpkgsFor.${system}.cross.${crossSystem}; in makeShell pkgs pkgs.stdenv))) //
//
flatMapAttrs
{
default = self.devShells.${system}.native-stdenvPackages;
# Components we'll iterate over in the upcoming lambda
"nix" = { };
# Temporarily disabled because GitHub Actions OOM issues. Once
# the old build system is gone and we are back to one build
# system, we should reenable these.
#"nix-util" = { };
#"nix-store" = { };
#"nix-fetchers" = { };
}
(
pkgName:
{ }:
{
# These attributes go right into `packages.<system>`.
"${pkgName}" = nixpkgsFor.${system}.native.nixComponents.${pkgName};
"${pkgName}-static" = nixpkgsFor.${system}.static.nixComponents.${pkgName};
}
// flatMapAttrs (lib.genAttrs crossSystems (_: { })) (
crossSystem:
{ }:
{
# These attributes go right into `packages.<system>`.
"${pkgName}-${crossSystem}" = nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName};
}
)
// flatMapAttrs (lib.genAttrs stdenvs (_: { })) (
stdenvName:
{ }:
{
# These attributes go right into `packages.<system>`.
"${pkgName}-${stdenvName}" =
nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".nixComponents.${pkgName};
}
)
)
// lib.optionalAttrs (builtins.elem system linux64BitSystems) {
dockerImage =
let
pkgs = nixpkgsFor.${system}.native;
image = import ./docker.nix {
inherit pkgs;
tag = version;
};
in
pkgs.runCommand "docker-image-tarball-${version}"
{ meta.description = "Docker image with Nix for ${system}"; }
''
mkdir -p $out/nix-support
image=$out/image.tar.gz
ln -s ${image} $image
echo "file binary-dist $image" >> $out/nix-support/hydra-build-products
'';
}
);
devShells =
let
makeShell =
pkgs: stdenv:
(pkgs.nix.override {
inherit stdenv;
forDevShell = true;
}).overrideAttrs
(
attrs:
let
modular = devFlake.getSystem stdenv.buildPlatform.system;
transformFlag =
prefix: flag:
assert builtins.isString flag;
let
rest = builtins.substring 2 (builtins.stringLength flag) flag;
in
"-D${prefix}:${rest}";
havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix;
ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags;
in
{
pname = "shell-for-" + attrs.pname;
# Remove the version suffix to avoid unnecessary attempts to substitute in nix develop
version = lib.fileContents ./.version;
name = attrs.pname;
installFlags = "sysconfdir=$(out)/etc";
shellHook = ''
PATH=$prefix/bin:$PATH
unset PYTHONPATH
export MANPATH=$out/share/man:$MANPATH
# Make bash completion work.
XDG_DATA_DIRS+=:$out/share
'';
# We use this shell with the local checkout, not unpackPhase.
src = null;
env = {
# Needed for Meson to find Boost.
# https://github.com/NixOS/nixpkgs/issues/86131.
BOOST_INCLUDEDIR = "${lib.getDev pkgs.nixDependencies.boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib pkgs.nixDependencies.boost}/lib";
# For `make format`, to work without installing pre-commit
_NIX_PRE_COMMIT_HOOKS_CONFIG = "${(pkgs.formats.yaml { }).generate "pre-commit-config.yaml"
modular.pre-commit.settings.rawConfig
}";
};
mesonFlags =
map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents.nix-util.mesonFlags)
++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents.nix-store.mesonFlags)
++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents.nix-fetchers.mesonFlags)
++ lib.optionals havePerl (
map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents.nix-perl-bindings.mesonFlags)
)
++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents.nix-expr.mesonFlags)
++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents.nix-cmd.mesonFlags);
nativeBuildInputs =
attrs.nativeBuildInputs or [ ]
++ pkgs.nixComponents.nix-util.nativeBuildInputs
++ pkgs.nixComponents.nix-store.nativeBuildInputs
++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs
++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs
++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs
++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs
++ lib.optional (
!stdenv.buildPlatform.canExecute stdenv.hostPlatform
# Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479
&& !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin)
&& stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages
&& lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages)
) pkgs.buildPackages.mesonEmulatorHook
++ [
pkgs.buildPackages.cmake
pkgs.buildPackages.shellcheck
pkgs.buildPackages.changelog-d
modular.pre-commit.settings.package
(pkgs.writeScriptBin "pre-commit-hooks-install" modular.pre-commit.settings.installationScript)
]
# TODO: Remove the darwin check once
# https://github.com/NixOS/nixpkgs/pull/291814 is available
++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear
++ lib.optional (
stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform
) pkgs.buildPackages.clang-tools;
buildInputs =
attrs.buildInputs or [ ]
++ [
pkgs.gtest
pkgs.rapidcheck
]
++ lib.optional havePerl pkgs.perl;
}
);
in
forAllSystems (
system:
let
makeShells =
prefix: pkgs:
lib.mapAttrs' (k: v: lib.nameValuePair "${prefix}-${k}" v) (
forAllStdenvs (stdenvName: makeShell pkgs pkgs.${stdenvName})
);
in
(makeShells "native" nixpkgsFor.${system}.native)
// (
lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin) (
makeShells "static" nixpkgsFor.${system}.static
)
// (forAllCrossSystems (
crossSystem:
let
pkgs = nixpkgsFor.${system}.cross.${crossSystem};
in
makeShell pkgs pkgs.stdenv
))
)
// {
default = self.devShells.${system}.native-stdenvPackages;
}
);
};
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,115 +1,116 @@
{ lib
, stdenv
, releaseTools
, autoconf-archive
, autoreconfHook
, aws-sdk-cpp
, boehmgc
, nlohmann_json
, bison
, boost
, brotli
, bzip2
, curl
, editline
, readline
, flex
, git
, gtest
, jq
, libarchive
, libcpuid
, libgit2
, libseccomp
, libsodium
, man
, darwin
, lowdown
, mdbook
, mdbook-linkcheck
, mercurial
, openssh
, openssl
, pkg-config
, rapidcheck
, sqlite
, toml11
, unixtools
, xz
{
lib,
stdenv,
releaseTools,
autoconf-archive,
autoreconfHook,
aws-sdk-cpp,
boehmgc,
nlohmann_json,
bison,
boost,
brotli,
bzip2,
curl,
editline,
readline,
flex,
git,
gtest,
jq,
libarchive,
libcpuid,
libgit2,
libseccomp,
libsodium,
man,
darwin,
lowdown,
mdbook,
mdbook-linkcheck,
mercurial,
openssh,
openssl,
pkg-config,
rapidcheck,
sqlite,
toml11,
unixtools,
xz,
, busybox-sandbox-shell ? null
busybox-sandbox-shell ? null,
# Configuration Options
#:
# This probably seems like too many degrees of freedom, but it
# faithfully reflects how the underlying configure + make build system
# work. The top-level flake.nix will choose useful combinations of these
# options to CI.
# Configuration Options
#:
# This probably seems like too many degrees of freedom, but it
# faithfully reflects how the underlying configure + make build system
# work. The top-level flake.nix will choose useful combinations of these
# options to CI.
, pname ? "nix"
pname ? "nix",
, versionSuffix ? ""
versionSuffix ? "",
# Whether to build Nix. Useful to skip for tasks like testing existing pre-built versions of Nix
, doBuild ? true
# Whether to build Nix. Useful to skip for tasks like testing existing pre-built versions of Nix
doBuild ? true,
# Run the unit tests as part of the build. See `installUnitTests` for an
# alternative to this.
, doCheck ? __forDefaults.canRunInstalled
# Run the unit tests as part of the build. See `installUnitTests` for an
# alternative to this.
doCheck ? __forDefaults.canRunInstalled,
# Run the functional tests as part of the build.
, doInstallCheck ? test-client != null || __forDefaults.canRunInstalled
# Run the functional tests as part of the build.
doInstallCheck ? test-client != null || __forDefaults.canRunInstalled,
# Check test coverage of Nix. Probably want to use with at least
# one of `doCHeck` or `doInstallCheck` enabled.
, withCoverageChecks ? false
# Check test coverage of Nix. Probably want to use with at least
# one of `doCHeck` or `doInstallCheck` enabled.
withCoverageChecks ? false,
# Whether to build the regular manual
, enableManual ? __forDefaults.canRunInstalled
# Whether to build the regular manual
enableManual ? __forDefaults.canRunInstalled,
# Whether to use garbage collection for the Nix language evaluator.
#
# If it is disabled, we just leak memory, but this is not as bad as it
# sounds so long as evaluation just takes places within short-lived
# processes. (When the process exits, the memory is reclaimed; it is
# only leaked *within* the process.)
#
# Temporarily disabled on Windows because the `GC_throw_bad_alloc`
# symbol is missing during linking.
#
# Disabled on OpenBSD because of missing `_data_start` symbol while linking
, enableGC ? !stdenv.hostPlatform.isWindows && !stdenv.hostPlatform.isOpenBSD
# Whether to use garbage collection for the Nix language evaluator.
#
# If it is disabled, we just leak memory, but this is not as bad as it
# sounds so long as evaluation just takes places within short-lived
# processes. (When the process exits, the memory is reclaimed; it is
# only leaked *within* the process.)
#
# Temporarily disabled on Windows because the `GC_throw_bad_alloc`
# symbol is missing during linking.
#
# Disabled on OpenBSD because of missing `_data_start` symbol while linking
enableGC ? !stdenv.hostPlatform.isWindows && !stdenv.hostPlatform.isOpenBSD,
# Whether to enable Markdown rendering in the Nix binary.
, enableMarkdown ? !stdenv.hostPlatform.isWindows
# Whether to enable Markdown rendering in the Nix binary.
enableMarkdown ? !stdenv.hostPlatform.isWindows,
# Which interactive line editor library to use for Nix's repl.
#
# Currently supported choices are:
#
# - editline (default)
# - readline
, readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline"
# Which interactive line editor library to use for Nix's repl.
#
# Currently supported choices are:
#
# - editline (default)
# - readline
readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline",
# Whether to install unit tests. This is useful when cross compiling
# since we cannot run them natively during the build, but can do so
# later.
, installUnitTests ? doBuild && !__forDefaults.canExecuteHost
# Whether to install unit tests. This is useful when cross compiling
# since we cannot run them natively during the build, but can do so
# later.
installUnitTests ? doBuild && !__forDefaults.canExecuteHost,
# For running the functional tests against a pre-built Nix. Probably
# want to use in conjunction with `doBuild = false;`.
, test-daemon ? null
, test-client ? null
# For running the functional tests against a pre-built Nix. Probably
# want to use in conjunction with `doBuild = false;`.
test-daemon ? null,
test-client ? null,
# Avoid setting things that would interfere with a functioning devShell
, forDevShell ? false
# Avoid setting things that would interfere with a functioning devShell
forDevShell ? false,
# Not a real argument, just the only way to approximate let-binding some
# stuff for argument defaults.
, __forDefaults ? {
# Not a real argument, just the only way to approximate let-binding some
# stuff for argument defaults.
__forDefaults ? {
canExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
canRunInstalled = doBuild && __forDefaults.canExecuteHost;
}
},
}:
let
@@ -125,250 +126,304 @@ let
};
mkDerivation =
if withCoverageChecks
then
if withCoverageChecks then
# TODO support `finalAttrs` args function in
# `releaseTools.coverageAnalysis`.
argsFun:
releaseTools.coverageAnalysis (let args = argsFun args; in args)
else stdenv.mkDerivation;
releaseTools.coverageAnalysis (
let
args = argsFun args;
in
args
)
else
stdenv.mkDerivation;
in
mkDerivation (finalAttrs: let
mkDerivation (
finalAttrs:
let
inherit (finalAttrs)
doCheck
doInstallCheck
;
inherit (finalAttrs)
doCheck
doInstallCheck
;
doBuild = !finalAttrs.dontBuild;
doBuild = !finalAttrs.dontBuild;
# Either running the unit tests during the build, or installing them
# to be run later, requiresthe unit tests to be built.
buildUnitTests = doCheck || installUnitTests;
# Either running the unit tests during the build, or installing them
# to be run later, requiresthe unit tests to be built.
buildUnitTests = doCheck || installUnitTests;
in {
inherit pname version;
in
{
inherit pname version;
src =
let
baseFiles = fileset.fileFilter (f: f.name != ".gitignore") ./.;
in
src =
let
baseFiles = fileset.fileFilter (f: f.name != ".gitignore") ./.;
in
fileset.toSource {
root = ./.;
fileset = fileset.intersection baseFiles (fileset.unions ([
# For configure
./.version
./configure.ac
./m4
# TODO: do we really need README.md? It doesn't seem used in the build.
./README.md
# This could be put behind a conditional
./maintainers/local.mk
# For make, regardless of what we are building
./local.mk
./Makefile
./Makefile.config.in
./mk
(fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts)
] ++ lib.optionals doBuild [
./doc
./misc
./precompiled-headers.h
(fileset.difference ./src ./src/perl)
./COPYING
./scripts/local.mk
] ++ lib.optionals enableManual [
./doc/manual
] ++ lib.optionals buildUnitTests [
./tests/unit
] ++ lib.optionals doInstallCheck [
./tests/functional
]));
fileset = fileset.intersection baseFiles (
fileset.unions (
[
# For configure
./.version
./configure.ac
./m4
# TODO: do we really need README.md? It doesn't seem used in the build.
./README.md
# This could be put behind a conditional
./maintainers/local.mk
# For make, regardless of what we are building
./local.mk
./Makefile
./Makefile.config.in
./mk
(fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts)
]
++ lib.optionals doBuild [
./doc
./misc
./precompiled-headers.h
(fileset.difference ./src ./src/perl)
./COPYING
./scripts/local.mk
]
++ lib.optionals enableManual [
./doc/manual
]
++ lib.optionals buildUnitTests [
./tests/unit
]
++ lib.optionals doInstallCheck [
./tests/functional
]
)
);
};
VERSION_SUFFIX = versionSuffix;
VERSION_SUFFIX = versionSuffix;
outputs = [ "out" ]
++ lib.optional doBuild "dev"
# If we are doing just build or just docs, the one thing will use
# "out". We only need additional outputs if we are doing both.
++ lib.optional (doBuild && enableManual) "doc"
++ lib.optional installUnitTests "check"
++ lib.optional doCheck "testresults"
;
outputs =
[ "out" ]
++ lib.optional doBuild "dev"
# If we are doing just build or just docs, the one thing will use
# "out". We only need additional outputs if we are doing both.
++ lib.optional (doBuild && enableManual) "doc"
++ lib.optional installUnitTests "check"
++ lib.optional doCheck "testresults";
nativeBuildInputs = [
autoconf-archive
autoreconfHook
pkg-config
] ++ lib.optionals doBuild [
bison
flex
] ++ lib.optionals enableManual [
(lib.getBin lowdown)
mdbook
mdbook-linkcheck
] ++ lib.optionals doInstallCheck [
git
mercurial
openssh
] ++ lib.optionals (doInstallCheck || enableManual) [
jq # Also for custom mdBook preprocessor.
] ++ lib.optionals enableManual [
man
] ++ lib.optional stdenv.hostPlatform.isStatic unixtools.hexdump
;
nativeBuildInputs =
[
autoconf-archive
autoreconfHook
pkg-config
]
++ lib.optionals doBuild [
bison
flex
]
++ lib.optionals enableManual [
(lib.getBin lowdown)
mdbook
mdbook-linkcheck
]
++ lib.optionals doInstallCheck [
git
mercurial
openssh
]
++ lib.optionals (doInstallCheck || enableManual) [
jq # Also for custom mdBook preprocessor.
]
++ lib.optionals enableManual [
man
]
++ lib.optional stdenv.hostPlatform.isStatic unixtools.hexdump;
buildInputs = lib.optionals doBuild (
[
brotli
bzip2
curl
libarchive
libgit2
libsodium
openssl
sqlite
toml11
xz
({ inherit readline editline; }.${readlineFlavor})
] ++ lib.optionals enableMarkdown [
lowdown
] ++ lib.optionals buildUnitTests [
gtest
rapidcheck
] ++ lib.optional stdenv.isLinux libseccomp
++ lib.optional stdenv.hostPlatform.isDarwin darwin.apple_sdk.libs.sandbox
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid
# There have been issues building these dependencies
++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin))
aws-sdk-cpp
);
buildInputs = lib.optionals doBuild (
[
brotli
bzip2
curl
libarchive
libgit2
libsodium
openssl
sqlite
toml11
xz
({ inherit readline editline; }.${readlineFlavor})
]
++ lib.optionals enableMarkdown [
lowdown
]
++ lib.optionals buildUnitTests [
gtest
rapidcheck
]
++ lib.optional stdenv.isLinux libseccomp
++ lib.optional stdenv.hostPlatform.isDarwin darwin.apple_sdk.libs.sandbox
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid
# There have been issues building these dependencies
++ lib.optional (
stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin)
) aws-sdk-cpp
);
propagatedBuildInputs = lib.optionals doBuild ([
boost
nlohmann_json
] ++ lib.optional enableGC boehmgc
);
propagatedBuildInputs = lib.optionals doBuild (
[
boost
nlohmann_json
]
++ lib.optional enableGC boehmgc
);
dontBuild = !attrs.doBuild;
doCheck = attrs.doCheck;
dontBuild = !attrs.doBuild;
doCheck = attrs.doCheck;
configureFlags = [
(lib.enableFeature doBuild "build")
(lib.enableFeature buildUnitTests "unit-tests")
(lib.enableFeature doInstallCheck "functional-tests")
(lib.enableFeature enableManual "doc-gen")
(lib.enableFeature enableGC "gc")
(lib.enableFeature enableMarkdown "markdown")
(lib.enableFeature installUnitTests "install-unit-tests")
(lib.withFeatureAs true "readline-flavor" readlineFlavor)
] ++ lib.optionals (!forDevShell) [
"--sysconfdir=/etc"
] ++ lib.optionals installUnitTests [
"--with-check-bin-dir=${builtins.placeholder "check"}/bin"
"--with-check-lib-dir=${builtins.placeholder "check"}/lib"
] ++ lib.optionals (doBuild) [
"--with-boost=${boost}/lib"
] ++ lib.optionals (doBuild && stdenv.isLinux) [
"--with-sandbox-shell=${busybox-sandbox-shell}/bin/busybox"
] ++ lib.optional (doBuild && stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
"LDFLAGS=-fuse-ld=gold"
++ lib.optional (doBuild && stdenv.hostPlatform.isStatic) "--enable-embedded-sandbox-shell"
;
configureFlags =
[
(lib.enableFeature doBuild "build")
(lib.enableFeature buildUnitTests "unit-tests")
(lib.enableFeature doInstallCheck "functional-tests")
(lib.enableFeature enableManual "doc-gen")
(lib.enableFeature enableGC "gc")
(lib.enableFeature enableMarkdown "markdown")
(lib.enableFeature installUnitTests "install-unit-tests")
(lib.withFeatureAs true "readline-flavor" readlineFlavor)
]
++ lib.optionals (!forDevShell) [
"--sysconfdir=/etc"
]
++ lib.optionals installUnitTests [
"--with-check-bin-dir=${builtins.placeholder "check"}/bin"
"--with-check-lib-dir=${builtins.placeholder "check"}/lib"
]
++ lib.optionals (doBuild) [
"--with-boost=${boost}/lib"
]
++ lib.optionals (doBuild && stdenv.isLinux) [
"--with-sandbox-shell=${busybox-sandbox-shell}/bin/busybox"
]
++ lib.optional (
doBuild && stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")
) "LDFLAGS=-fuse-ld=gold"
++ lib.optional (doBuild && stdenv.hostPlatform.isStatic) "--enable-embedded-sandbox-shell";
enableParallelBuilding = true;
enableParallelBuilding = true;
makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1";
makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1";
preCheck = ''
mkdir $testresults
'';
installTargets = lib.optional doBuild "install";
installFlags = "sysconfdir=$(out)/etc";
# In this case we are probably just running tests, and so there isn't
# anything to install, we just make an empty directory to signify tests
# succeeded.
installPhase = if finalAttrs.installTargets != [] then null else ''
mkdir -p $out
'';
postInstall = lib.optionalString doBuild (
lib.optionalString stdenv.hostPlatform.isStatic ''
mkdir -p $out/nix-support
echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products
''
) + lib.optionalString enableManual ''
mkdir -p ''${!outputDoc}/nix-support
echo "doc manual ''${!outputDoc}/share/doc/nix/manual" >> ''${!outputDoc}/nix-support/hydra-build-products
'';
# So the check output gets links for DLLs in the out output.
preFixup = lib.optionalString (stdenv.hostPlatform.isWindows && builtins.elem "check" finalAttrs.outputs) ''
ln -s "$check/lib/"*.dll "$check/bin"
ln -s "$out/bin/"*.dll "$check/bin"
'';
doInstallCheck = attrs.doInstallCheck;
installCheckFlags = "sysconfdir=$(out)/etc";
# Work around buggy detection in stdenv.
installCheckTarget = "installcheck";
# Work around weird bug where it doesn't think there is a Makefile.
installCheckPhase = if (!doBuild && doInstallCheck) then ''
runHook preInstallCheck
mkdir -p src/nix-channel
make installcheck -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES
'' else null;
# Needed for tests if we are not doing a build, but testing existing
# built Nix.
preInstallCheck =
lib.optionalString (! doBuild) ''
mkdir -p src/nix-channel
''
# See https://github.com/NixOS/nix/issues/2523
# Occurs often in tests since https://github.com/NixOS/nix/pull/9900
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
preCheck = ''
mkdir $testresults
'';
separateDebugInfo = !stdenv.hostPlatform.isStatic;
installTargets = lib.optional doBuild "install";
# TODO Always true after https://github.com/NixOS/nixpkgs/issues/318564
strictDeps = !withCoverageChecks;
installFlags = "sysconfdir=$(out)/etc";
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
# In this case we are probably just running tests, and so there isn't
# anything to install, we just make an empty directory to signify tests
# succeeded.
installPhase =
if finalAttrs.installTargets != [ ] then
null
else
''
mkdir -p $out
'';
meta = {
platforms = lib.platforms.unix ++ lib.platforms.windows;
mainProgram = "nix";
broken = !(lib.all (a: a) [
# We cannot run or install unit tests if we don't build them or
# Nix proper (which they depend on).
(installUnitTests -> doBuild)
(doCheck -> doBuild)
# The build process for the manual currently requires extracting
# data from the Nix executable we are trying to document.
(enableManual -> doBuild)
]);
};
postInstall =
lib.optionalString doBuild (
lib.optionalString stdenv.hostPlatform.isStatic ''
mkdir -p $out/nix-support
echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products
''
)
+ lib.optionalString enableManual ''
mkdir -p ''${!outputDoc}/nix-support
echo "doc manual ''${!outputDoc}/share/doc/nix/manual" >> ''${!outputDoc}/nix-support/hydra-build-products
'';
} // lib.optionalAttrs withCoverageChecks {
lcovFilter = [ "*/boost/*" "*-tab.*" ];
# So the check output gets links for DLLs in the out output.
preFixup =
lib.optionalString (stdenv.hostPlatform.isWindows && builtins.elem "check" finalAttrs.outputs)
''
ln -s "$check/lib/"*.dll "$check/bin"
ln -s "$out/bin/"*.dll "$check/bin"
'';
hardeningDisable = ["fortify"];
doInstallCheck = attrs.doInstallCheck;
NIX_CFLAGS_COMPILE = "-DCOVERAGE=1";
installCheckFlags = "sysconfdir=$(out)/etc";
# Work around buggy detection in stdenv.
installCheckTarget = "installcheck";
dontInstall = false;
} // lib.optionalAttrs (test-daemon != null) {
NIX_DAEMON_PACKAGE = test-daemon;
} // lib.optionalAttrs (test-client != null) {
NIX_CLIENT_PACKAGE = test-client;
})
# Work around weird bug where it doesn't think there is a Makefile.
installCheckPhase =
if (!doBuild && doInstallCheck) then
''
runHook preInstallCheck
mkdir -p src/nix-channel
make installcheck -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES
''
else
null;
# Needed for tests if we are not doing a build, but testing existing
# built Nix.
preInstallCheck =
lib.optionalString (!doBuild) ''
mkdir -p src/nix-channel
''
# See https://github.com/NixOS/nix/issues/2523
# Occurs often in tests since https://github.com/NixOS/nix/pull/9900
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
'';
separateDebugInfo = !stdenv.hostPlatform.isStatic;
# TODO Always true after https://github.com/NixOS/nixpkgs/issues/318564
strictDeps = !withCoverageChecks;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
meta = {
platforms = lib.platforms.unix ++ lib.platforms.windows;
mainProgram = "nix";
broken =
!(lib.all (a: a) [
# We cannot run or install unit tests if we don't build them or
# Nix proper (which they depend on).
(installUnitTests -> doBuild)
(doCheck -> doBuild)
# The build process for the manual currently requires extracting
# data from the Nix executable we are trying to document.
(enableManual -> doBuild)
]);
};
}
// lib.optionalAttrs withCoverageChecks {
lcovFilter = [
"*/boost/*"
"*-tab.*"
];
hardeningDisable = [ "fortify" ];
NIX_CFLAGS_COMPILE = "-DCOVERAGE=1";
dontInstall = false;
}
// lib.optionalAttrs (test-daemon != null) {
NIX_DAEMON_PACKAGE = test-daemon;
}
// lib.optionalAttrs (test-client != null) {
NIX_CLIENT_PACKAGE = test-client;
}
)

View File

@@ -20,9 +20,7 @@ let
root = ../.;
stdenv = if prevStdenv.isDarwin && prevStdenv.isx86_64
then darwinStdenv
else prevStdenv;
stdenv = if prevStdenv.isDarwin && prevStdenv.isx86_64 then darwinStdenv else prevStdenv;
# Fix the following error with the default x86_64-darwin SDK:
#
@@ -39,7 +37,8 @@ let
# Indirection for Nixpkgs to override when package.nix files are vendored
filesetToSource = lib.fileset.toSource;
localSourceLayer = finalAttrs: prevAttrs:
localSourceLayer =
finalAttrs: prevAttrs:
let
workDirPath =
# Ideally we'd pick finalAttrs.workDir, but for now `mkDerivation` has
@@ -48,8 +47,13 @@ let
prevAttrs.workDir;
workDirSubpath = lib.path.removePrefix root workDirPath;
sources = assert prevAttrs.fileset._type == "fileset"; prevAttrs.fileset;
src = lib.fileset.toSource { fileset = sources; inherit root; };
sources =
assert prevAttrs.fileset._type == "fileset";
prevAttrs.fileset;
src = lib.fileset.toSource {
fileset = sources;
inherit root;
};
in
{
@@ -63,30 +67,35 @@ let
# Work around weird `--as-needed` linker behavior with BSD, see
# https://github.com/mesonbuild/meson/issues/3593
bsdNoLinkAsNeeded = finalAttrs: prevAttrs:
bsdNoLinkAsNeeded =
finalAttrs: prevAttrs:
lib.optionalAttrs stdenv.hostPlatform.isBSD {
mesonFlags = [ (lib.mesonBool "b_asneeded" false) ] ++ prevAttrs.mesonFlags or [];
mesonFlags = [ (lib.mesonBool "b_asneeded" false) ] ++ prevAttrs.mesonFlags or [ ];
};
miscGoodPractice = finalAttrs: prevAttrs:
{
strictDeps = prevAttrs.strictDeps or true;
enableParallelBuilding = true;
};
miscGoodPractice = finalAttrs: prevAttrs: {
strictDeps = prevAttrs.strictDeps or true;
enableParallelBuilding = true;
};
in
scope: {
inherit stdenv versionSuffix;
version = lib.fileContents ../.version + versionSuffix;
aws-sdk-cpp = (pkgs.aws-sdk-cpp.override {
apis = [ "s3" "transfer" ];
customMemoryManagement = false;
}).overrideAttrs {
# only a stripped down version is built, which takes a lot less resources
# to build, so we don't need a "big-parallel" machine.
requiredSystemFeatures = [ ];
};
aws-sdk-cpp =
(pkgs.aws-sdk-cpp.override {
apis = [
"s3"
"transfer"
];
customMemoryManagement = false;
}).overrideAttrs
{
# only a stripped down version is built, which takes a lot less resources
# to build, so we don't need a "big-parallel" machine.
requiredSystemFeatures = [ ];
};
libseccomp = pkgs.libseccomp.overrideAttrs (_: rec {
version = "2.5.5";
@@ -101,48 +110,50 @@ scope: {
};
# TODO Hack until https://github.com/NixOS/nixpkgs/issues/45462 is fixed.
boost = (pkgs.boost.override {
extraB2Args = [
"--with-container"
"--with-context"
"--with-coroutine"
];
}).overrideAttrs (old: {
# Need to remove `--with-*` to use `--with-libraries=...`
buildPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.buildPhase;
installPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.installPhase;
});
boost =
(pkgs.boost.override {
extraB2Args = [
"--with-container"
"--with-context"
"--with-coroutine"
];
}).overrideAttrs
(old: {
# Need to remove `--with-*` to use `--with-libraries=...`
buildPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.buildPhase;
installPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.installPhase;
});
libgit2 = pkgs.libgit2.overrideAttrs (attrs: {
src = inputs.libgit2;
version = inputs.libgit2.lastModifiedDate;
cmakeFlags = attrs.cmakeFlags or []
++ [ "-DUSE_SSH=exec" ];
cmakeFlags = attrs.cmakeFlags or [ ] ++ [ "-DUSE_SSH=exec" ];
});
busybox-sandbox-shell = pkgs.busybox-sandbox-shell or (pkgs.busybox.override {
useMusl = true;
enableStatic = true;
enableMinimal = true;
extraConfig = ''
CONFIG_FEATURE_FANCY_ECHO y
CONFIG_FEATURE_SH_MATH y
CONFIG_FEATURE_SH_MATH_64 y
busybox-sandbox-shell =
pkgs.busybox-sandbox-shell or (pkgs.busybox.override {
useMusl = true;
enableStatic = true;
enableMinimal = true;
extraConfig = ''
CONFIG_FEATURE_FANCY_ECHO y
CONFIG_FEATURE_SH_MATH y
CONFIG_FEATURE_SH_MATH_64 y
CONFIG_ASH y
CONFIG_ASH_OPTIMIZE_FOR_SIZE y
CONFIG_ASH y
CONFIG_ASH_OPTIMIZE_FOR_SIZE y
CONFIG_ASH_ALIAS y
CONFIG_ASH_BASH_COMPAT y
CONFIG_ASH_CMDCMD y
CONFIG_ASH_ECHO y
CONFIG_ASH_GETOPTS y
CONFIG_ASH_INTERNAL_GLOB y
CONFIG_ASH_JOB_CONTROL y
CONFIG_ASH_PRINTF y
CONFIG_ASH_TEST y
'';
});
CONFIG_ASH_ALIAS y
CONFIG_ASH_BASH_COMPAT y
CONFIG_ASH_CMDCMD y
CONFIG_ASH_ECHO y
CONFIG_ASH_GETOPTS y
CONFIG_ASH_INTERNAL_GLOB y
CONFIG_ASH_JOB_CONTROL y
CONFIG_ASH_PRINTF y
CONFIG_ASH_TEST y
'';
});
# TODO change in Nixpkgs, Windows works fine. First commit of
# https://github.com/NixOS/nixpkgs/pull/322977 backported will fix.
@@ -152,14 +163,14 @@ scope: {
inherit resolvePath filesetToSource;
mkMesonDerivation = f: let
exts = [
miscGoodPractice
bsdNoLinkAsNeeded
localSourceLayer
];
in stdenv.mkDerivation
(lib.extends
(lib.foldr lib.composeExtensions (_: _: {}) exts)
f);
mkMesonDerivation =
f:
let
exts = [
miscGoodPractice
bsdNoLinkAsNeeded
localSourceLayer
];
in
stdenv.mkDerivation (lib.extends (lib.foldr lib.composeExtensions (_: _: { }) exts) f);
}

View File

@@ -1,28 +1,31 @@
{ inputs
, binaryTarball
, forAllCrossSystems
, forAllSystems
, lib
, linux64BitSystems
, nixpkgsFor
, self
{
inputs,
binaryTarball,
forAllCrossSystems,
forAllSystems,
lib,
linux64BitSystems,
nixpkgsFor,
self,
}:
let
inherit (inputs) nixpkgs nixpkgs-regression;
installScriptFor = tarballs:
installScriptFor =
tarballs:
nixpkgsFor.x86_64-linux.native.callPackage ../scripts/installer.nix {
inherit tarballs;
};
testNixVersions = pkgs: client: daemon:
testNixVersions =
pkgs: client: daemon:
pkgs.callPackage ../package.nix {
pname =
"nix-tests"
+ lib.optionalString
(lib.versionAtLeast daemon.version "2.4pre20211005" &&
lib.versionAtLeast client.version "2.4pre20211005")
"-${client.version}-against-${daemon.version}";
+ lib.optionalString (
lib.versionAtLeast daemon.version "2.4pre20211005"
&& lib.versionAtLeast client.version "2.4pre20211005"
) "-${client.version}-against-${daemon.version}";
test-client = client;
test-daemon = daemon;
@@ -59,27 +62,35 @@ let
in
{
# Binary package for various platforms.
build = forAllPackages (pkgName:
forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.${pkgName}));
build = forAllPackages (
pkgName: forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.${pkgName})
);
shellInputs = forAllSystems (system: self.devShells.${system}.default.inputDerivation);
buildStatic = forAllPackages (pkgName:
lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName}));
buildCross = forAllPackages (pkgName:
forAllCrossSystems (crossSystem:
lib.genAttrs [ "x86_64-linux" ] (system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName})));
buildNoGc = forAllSystems (system:
self.packages.${system}.nix.override { enableGC = false; }
buildStatic = forAllPackages (
pkgName:
lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName})
);
buildCross = forAllPackages (
pkgName:
forAllCrossSystems (
crossSystem:
lib.genAttrs [ "x86_64-linux" ] (
system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName}
)
)
);
buildNoGc = forAllSystems (system: self.packages.${system}.nix.override { enableGC = false; });
buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nix_noTests);
# Toggles some settings for better coverage. Windows needs these
# library combinations, and Debian build Nix with GNU readline too.
buildReadlineNoMarkdown = forAllSystems (system:
buildReadlineNoMarkdown = forAllSystems (
system:
self.packages.${system}.nix.override {
enableMarkdown = false;
readlineFlavor = "readline";
@@ -92,13 +103,18 @@ in
# Binary tarball for various platforms, containing a Nix store
# with the closure of 'nix' package, and the second half of
# the installation script.
binaryTarball = forAllSystems (system: binaryTarball nixpkgsFor.${system}.native.nix nixpkgsFor.${system}.native);
binaryTarball = forAllSystems (
system: binaryTarball nixpkgsFor.${system}.native.nix nixpkgsFor.${system}.native
);
binaryTarballCross = lib.genAttrs [ "x86_64-linux" ] (system:
forAllCrossSystems (crossSystem:
binaryTarball
nixpkgsFor.${system}.cross.${crossSystem}.nix
nixpkgsFor.${system}.cross.${crossSystem}));
binaryTarballCross = lib.genAttrs [ "x86_64-linux" ] (
system:
forAllCrossSystems (
crossSystem:
binaryTarball nixpkgsFor.${system}.cross.${crossSystem}.nix
nixpkgsFor.${system}.cross.${crossSystem}
)
);
# The first half of the installation script. This is uploaded
# to https://nixos.org/nix/install. It downloads the binary
@@ -117,9 +133,12 @@ in
self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu"
];
installerScriptForGHA = forAllSystems (system: nixpkgsFor.${system}.native.callPackage ../scripts/installer.nix {
tarballs = [ self.hydraJobs.binaryTarball.${system} ];
});
installerScriptForGHA = forAllSystems (
system:
nixpkgsFor.${system}.native.callPackage ../scripts/installer.nix {
tarballs = [ self.hydraJobs.binaryTarball.${system} ];
}
);
# docker image with Nix inside
dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage);
@@ -137,16 +156,24 @@ in
external-api-docs = nixpkgsFor.x86_64-linux.native.nixComponents.nix-external-api-docs;
# System tests.
tests = import ../tests/nixos { inherit lib nixpkgs nixpkgsFor self; } // {
tests =
import ../tests/nixos {
inherit
lib
nixpkgs
nixpkgsFor
self
;
}
// {
# Make sure that nix-env still produces the exact same result
# on a particular version of Nixpkgs.
evalNixpkgs =
let
inherit (nixpkgsFor.x86_64-linux.native) runCommand nix;
in
runCommand "eval-nixos" { buildInputs = [ nix ]; }
''
# Make sure that nix-env still produces the exact same result
# on a particular version of Nixpkgs.
evalNixpkgs =
let
inherit (nixpkgsFor.x86_64-linux.native) runCommand nix;
in
runCommand "eval-nixos" { buildInputs = [ nix ]; } ''
type -p nix-env
# Note: we're filtering out nixos-install-tools because https://github.com/NixOS/nixpkgs/pull/153594#issuecomment-1020530593.
(
@@ -157,36 +184,36 @@ in
mkdir $out
'';
nixpkgsLibTests =
forAllSystems (system:
import (nixpkgs + "/lib/tests/test-with-nix.nix")
{
lib = nixpkgsFor.${system}.native.lib;
nix = self.packages.${system}.nix;
pkgs = nixpkgsFor.${system}.native;
}
nixpkgsLibTests = forAllSystems (
system:
import (nixpkgs + "/lib/tests/test-with-nix.nix") {
lib = nixpkgsFor.${system}.native.lib;
nix = self.packages.${system}.nix;
pkgs = nixpkgsFor.${system}.native;
}
);
};
};
metrics.nixpkgs = import "${nixpkgs-regression}/pkgs/top-level/metrics.nix" {
pkgs = nixpkgsFor.x86_64-linux.native;
nixpkgs = nixpkgs-regression;
};
installTests = forAllSystems (system:
let pkgs = nixpkgsFor.${system}.native; in
pkgs.runCommand "install-tests"
{
againstSelf = testNixVersions pkgs pkgs.nix pkgs.pkgs.nix;
againstCurrentLatest =
# FIXME: temporarily disable this on macOS because of #3605.
if system == "x86_64-linux"
then testNixVersions pkgs pkgs.nix pkgs.nixVersions.latest
else null;
# Disabled because the latest stable version doesn't handle
# `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work
# againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable;
} "touch $out");
installTests = forAllSystems (
system:
let
pkgs = nixpkgsFor.${system}.native;
in
pkgs.runCommand "install-tests" {
againstSelf = testNixVersions pkgs pkgs.nix pkgs.pkgs.nix;
againstCurrentLatest =
# FIXME: temporarily disable this on macOS because of #3605.
if system == "x86_64-linux" then testNixVersions pkgs pkgs.nix pkgs.nixVersions.latest else null;
# Disabled because the latest stable version doesn't handle
# `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work
# againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable;
} "touch $out"
);
installerTests = import ../tests/installer {
binaryTarballs = self.hydraJobs.binaryTarball;

View File

@@ -1,14 +1,18 @@
{ runCommand
, system
, buildPackages
, cacert
, nix
{
runCommand,
system,
buildPackages,
cacert,
nix,
}:
let
installerClosureInfo = buildPackages.closureInfo {
rootPaths = [ nix cacert ];
rootPaths = [
nix
cacert
];
};
inherit (nix) version;

View File

@@ -1,36 +1,42 @@
{ lib
, runCommand
, nix
, tarballs
{
lib,
runCommand,
nix,
tarballs,
}:
runCommand "installer-script" {
buildInputs = [ nix ];
} ''
mkdir -p $out/nix-support
# Converts /nix/store/50p3qk8k...-nix-2.4pre20201102_550e11f/bin/nix to 50p3qk8k.../bin/nix.
tarballPath() {
# Remove the store prefix
local path=''${1#${builtins.storeDir}/}
# Get the path relative to the derivation root
local rest=''${path#*/}
# Get the derivation hash
local drvHash=''${path%%-*}
echo "$drvHash/$rest"
runCommand "installer-script"
{
buildInputs = [ nix ];
}
''
mkdir -p $out/nix-support
substitute ${./install.in} $out/install \
${lib.concatMapStrings
(tarball: let
inherit (tarball.stdenv.hostPlatform) system;
in '' \
--replace '@tarballHash_${system}@' $(nix --experimental-features nix-command hash-file --base16 --type sha256 ${tarball}/*.tar.xz) \
--replace '@tarballPath_${system}@' $(tarballPath ${tarball}/*.tar.xz) \
''
)
tarballs
} --replace '@nixVersion@' ${nix.version}
# Converts /nix/store/50p3qk8k...-nix-2.4pre20201102_550e11f/bin/nix to 50p3qk8k.../bin/nix.
tarballPath() {
# Remove the store prefix
local path=''${1#${builtins.storeDir}/}
# Get the path relative to the derivation root
local rest=''${path#*/}
# Get the derivation hash
local drvHash=''${path%%-*}
echo "$drvHash/$rest"
}
echo "file installer $out/install" >> $out/nix-support/hydra-build-products
''
substitute ${./install.in} $out/install \
${
lib.concatMapStrings (
tarball:
let
inherit (tarball.stdenv.hostPlatform) system;
in
''
\
--replace '@tarballHash_${system}@' $(nix --experimental-features nix-command hash-file --base16 --type sha256 ${tarball}/*.tar.xz) \
--replace '@tarballPath_${system}@' $(tarballPath ${tarball}/*.tar.xz) \
''
) tarballs
} --replace '@nixVersion@' ${nix.version}
echo "file installer $out/install" >> $out/nix-support/hydra-build-products
''

View File

@@ -1,7 +1,7 @@
# Only execute this file once per shell.
# This file is tested by tests/installer/default.nix.
if [ -n "${__ETC_PROFILE_NIX_SOURCED:-}" ]; then return; fi
__ETC_PROFILE_NIX_SOURCED=1
export __ETC_PROFILE_NIX_SOURCED=1
NIX_LINK=$HOME/.nix-profile
if [ -n "${XDG_STATE_HOME-}" ]; then

View File

@@ -1,13 +1,14 @@
{ lib
, mkMesonDerivation
{
lib,
mkMesonDerivation,
, meson
, ninja
, doxygen
meson,
ninja,
doxygen,
# Configuration Options
# Configuration Options
, version
version,
}:
let
@@ -42,11 +43,10 @@ mkMesonDerivation (finalAttrs: {
doxygen
];
preConfigure =
''
chmod u+w ./.version
echo ${finalAttrs.version} > ./.version
'';
preConfigure = ''
chmod u+w ./.version
echo ${finalAttrs.version} > ./.version
'';
postInstall = ''
mkdir -p ''${!outputDoc}/nix-support

View File

@@ -1,13 +1,14 @@
{ lib
, mkMesonDerivation
{
lib,
mkMesonDerivation,
, meson
, ninja
, doxygen
meson,
ninja,
doxygen,
# Configuration Options
# Configuration Options
, version
version,
}:
let
@@ -19,17 +20,19 @@ mkMesonDerivation (finalAttrs: {
inherit version;
workDir = ./.;
fileset = let
cpp = fileset.fileFilter (file: file.hasExt "cc" || file.hasExt "hh");
in fileset.unions [
./.version
../../.version
./meson.build
./doxygen.cfg.in
# Source is not compiled, but still must be available for Doxygen
# to gather comments.
(cpp ../.)
];
fileset =
let
cpp = fileset.fileFilter (file: file.hasExt "cc" || file.hasExt "hh");
in
fileset.unions [
./.version
../../.version
./meson.build
./doxygen.cfg.in
# Source is not compiled, but still must be available for Doxygen
# to gather comments.
(cpp ../.)
];
nativeBuildInputs = [
meson
@@ -37,11 +40,10 @@ mkMesonDerivation (finalAttrs: {
doxygen
];
preConfigure =
''
chmod u+w ./.version
echo ${finalAttrs.version} > ./.version
'';
preConfigure = ''
chmod u+w ./.version
echo ${finalAttrs.version} > ./.version
'';
postInstall = ''
mkdir -p ''${!outputDoc}/nix-support

View File

@@ -1,37 +1,38 @@
{ lib
, stdenv
, mkMesonDerivation
, releaseTools
{
lib,
stdenv,
mkMesonDerivation,
releaseTools,
, meson
, ninja
, pkg-config
meson,
ninja,
pkg-config,
, nix-util
, nix-store
, nix-fetchers
, nix-expr
, nix-flake
, nix-main
, editline
, readline
, lowdown
, nlohmann_json
nix-util,
nix-store,
nix-fetchers,
nix-expr,
nix-flake,
nix-main,
editline,
readline,
lowdown,
nlohmann_json,
# Configuration Options
# Configuration Options
, version
version,
# Whether to enable Markdown rendering in the Nix binary.
, enableMarkdown ? !stdenv.hostPlatform.isWindows
# Whether to enable Markdown rendering in the Nix binary.
enableMarkdown ? !stdenv.hostPlatform.isWindows,
# Which interactive line editor library to use for Nix's repl.
#
# Currently supported choices are:
#
# - editline (default)
# - readline
, readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline"
# Which interactive line editor library to use for Nix's repl.
#
# Currently supported choices are:
#
# - editline (default)
# - readline
readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline",
}:
let
@@ -54,7 +55,10 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];
outputs = [ "out" "dev" ];
outputs = [
"out"
"dev"
];
nativeBuildInputs = [
meson
@@ -89,9 +93,12 @@ mkMesonDerivation (finalAttrs: {
(lib.mesonOption "readline-flavor" readlineFlavor)
];
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -157,16 +157,13 @@ static std::ostream & showDebugTrace(std::ostream & out, const PosTable & positi
out << ANSI_RED "error: " << ANSI_NORMAL;
out << dt.hint.str() << "\n";
// prefer direct pos, but if noPos then try the expr.
auto pos = dt.pos
? dt.pos
: positions[dt.expr.getPos() ? dt.expr.getPos() : noPos];
auto pos = dt.getPos(positions);
if (pos) {
out << *pos;
if (auto loc = pos->getCodeLines()) {
out << pos;
if (auto loc = pos.getCodeLines()) {
out << "\n";
printCodeLines(out, "", *pos, *loc);
printCodeLines(out, "", pos, *loc);
out << "\n";
}
}

View File

@@ -619,12 +619,8 @@ nix_realised_string * nix_string_realise(nix_c_context * context, EvalState * st
context->last_err_code = NIX_OK;
try {
auto & v = check_value_in(value);
nix::NixStringContext stringContext;
auto rawStr = state->state.coerceToString(nix::noPos, v, stringContext, "while realising a string").toOwned();
nix::StorePathSet storePaths;
auto rewrites = state->state.realiseContext(stringContext, &storePaths);
auto s = nix::rewriteStrings(rawStr, rewrites);
auto s = state->state.realiseString(v, &storePaths, isIFD);
// Convert to the C API StorePath type and convert to vector for index-based access
std::vector<StorePath> vec;

View File

@@ -1,17 +1,18 @@
{ lib
, stdenv
, mkMesonDerivation
{
lib,
stdenv,
mkMesonDerivation,
, meson
, ninja
, pkg-config
meson,
ninja,
pkg-config,
, nix-store-c
, nix-expr
nix-store-c,
nix-expr,
# Configuration Options
# Configuration Options
, version
version,
}:
let
@@ -35,7 +36,10 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "h") ./.)
];
outputs = [ "out" "dev" ];
outputs = [
"out"
"dev"
];
nativeBuildInputs = [
meson
@@ -59,9 +63,12 @@ mkMesonDerivation (finalAttrs: {
mesonFlags = [
];
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -17,69 +17,69 @@ let
# Resolve a input spec into a node name. An input spec is
# either a node name, or a 'follows' path from the root
# node.
resolveInput = inputSpec:
if builtins.isList inputSpec
then getInputByPath lockFile.root inputSpec
else inputSpec;
resolveInput =
inputSpec: if builtins.isList inputSpec then getInputByPath lockFile.root inputSpec else inputSpec;
# Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the
# root node, returning the final node.
getInputByPath = nodeName: path:
if path == []
then nodeName
getInputByPath =
nodeName: path:
if path == [ ] then
nodeName
else
getInputByPath
# Since this could be a 'follows' input, call resolveInput.
(resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path})
(builtins.tail path);
allNodes =
builtins.mapAttrs
(key: node:
let
allNodes = builtins.mapAttrs (
key: node:
let
sourceInfo =
if overrides ? ${key}
then
overrides.${key}.sourceInfo
else
# FIXME: remove obsolete node.info.
fetchTree (node.info or {} // removeAttrs node.locked ["dir"]);
sourceInfo =
if overrides ? ${key} then
overrides.${key}.sourceInfo
else
# FIXME: remove obsolete node.info.
fetchTree (node.info or { } // removeAttrs node.locked [ "dir" ]);
subdir = overrides.${key}.dir or node.locked.dir or "";
subdir = overrides.${key}.dir or node.locked.dir or "";
outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir);
outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir);
flake = import (outPath + "/flake.nix");
flake = import (outPath + "/flake.nix");
inputs = builtins.mapAttrs
(inputName: inputSpec: allNodes.${resolveInput inputSpec})
(node.inputs or {});
inputs = builtins.mapAttrs (inputName: inputSpec: allNodes.${resolveInput inputSpec}) (
node.inputs or { }
);
outputs = flake.outputs (inputs // { self = result; });
outputs = flake.outputs (inputs // { self = result; });
result =
outputs
# We add the sourceInfo attribute for its metadata, as they are
# relevant metadata for the flake. However, the outPath of the
# sourceInfo does not necessarily match the outPath of the flake,
# as the flake may be in a subdirectory of a source.
# This is shadowed in the next //
// sourceInfo
// {
# This shadows the sourceInfo.outPath
inherit outPath;
result =
outputs
# We add the sourceInfo attribute for its metadata, as they are
# relevant metadata for the flake. However, the outPath of the
# sourceInfo does not necessarily match the outPath of the flake,
# as the flake may be in a subdirectory of a source.
# This is shadowed in the next //
// sourceInfo
// {
# This shadows the sourceInfo.outPath
inherit outPath;
inherit inputs; inherit outputs; inherit sourceInfo; _type = "flake";
};
inherit inputs;
inherit outputs;
inherit sourceInfo;
_type = "flake";
};
in
if node.flake or true then
assert builtins.isFunction flake.outputs;
result
else
sourceInfo
)
lockFile.nodes;
in
if node.flake or true then
assert builtins.isFunction flake.outputs;
result
else
sourceInfo
) lockFile.nodes;
in allNodes.${lockFile.root}
in
allNodes.${lockFile.root}

View File

@@ -45,7 +45,7 @@ EvalErrorBuilder<T> & EvalErrorBuilder<T>::withFrame(const Env & env, const Expr
// TODO: check compatibility with nested debugger calls.
// TODO: What side-effects??
error.state.debugTraces.push_front(DebugTrace{
.pos = error.state.positions[expr.getPos()],
.pos = expr.getPos(),
.expr = expr,
.env = env,
.hint = HintFmt("Fake frame for debugging purposes"),

View File

@@ -57,7 +57,7 @@ Strings EvalSettings::getDefaultNixPath()
{
Strings res;
auto add = [&](const Path & p, const std::string & s = std::string()) {
if (pathAccessible(p)) {
if (std::filesystem::exists(p)) {
if (s.empty()) {
res.push_back(p);
} else {

View File

@@ -756,18 +756,26 @@ void EvalState::runDebugRepl(const Error * error, const Env & env, const Expr &
if (!debugRepl || inDebugger)
return;
auto dts =
error && expr.getPos()
? std::make_unique<DebugTraceStacker>(
*this,
DebugTrace {
.pos = error->info().pos ? error->info().pos : positions[expr.getPos()],
auto dts = [&]() -> std::unique_ptr<DebugTraceStacker> {
if (error && expr.getPos()) {
auto trace = DebugTrace{
.pos = [&]() -> std::variant<Pos, PosIdx> {
if (error->info().pos) {
if (auto * pos = error->info().pos.get())
return *pos;
return noPos;
}
return expr.getPos();
}(),
.expr = expr,
.env = env,
.hint = error->info().msg,
.isError = true
})
: nullptr;
.isError = true};
return std::make_unique<DebugTraceStacker>(*this, std::move(trace));
}
return nullptr;
}();
if (error)
{
@@ -812,7 +820,7 @@ static std::unique_ptr<DebugTraceStacker> makeDebugTraceStacker(
EvalState & state,
Expr & expr,
Env & env,
std::shared_ptr<Pos> && pos,
std::variant<Pos, PosIdx> pos,
const Args & ... formatArgs)
{
return std::make_unique<DebugTraceStacker>(state,
@@ -1088,7 +1096,7 @@ void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial)
*this,
*e,
this->baseEnv,
e->getPos() ? std::make_shared<Pos>(positions[e->getPos()]) : nullptr,
e->getPos(),
"while evaluating the file '%1%':", resolvedPath.to_string())
: nullptr;
@@ -1314,9 +1322,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
state,
*this,
env2,
getPos()
? std::make_shared<Pos>(state.positions[getPos()])
: nullptr,
getPos(),
"while evaluating a '%1%' expression",
"let"
)
@@ -1385,7 +1391,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
state,
*this,
env,
state.positions[getPos()],
getPos(),
"while evaluating the attribute '%1%'",
showAttrPath(state, env, attrPath))
: nullptr;
@@ -1603,7 +1609,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
try {
auto dts = debugRepl
? makeDebugTraceStacker(
*this, *lambda.body, env2, positions[lambda.pos],
*this, *lambda.body, env2, lambda.pos,
"while calling %s",
lambda.name
? concatStrings("'", symbols[lambda.name], "'")
@@ -1742,9 +1748,7 @@ void ExprCall::eval(EvalState & state, Env & env, Value & v)
state,
*this,
env,
getPos()
? std::make_shared<Pos>(state.positions[getPos()])
: nullptr,
getPos(),
"while calling a function"
)
: nullptr;
@@ -2122,7 +2126,7 @@ void EvalState::forceValueDeep(Value & v)
try {
// If the value is a thunk, we're evaling. Otherwise no trace necessary.
auto dts = debugRepl && i.value->isThunk()
? makeDebugTraceStacker(*this, *i.value->payload.thunk.expr, *i.value->payload.thunk.env, positions[i.pos],
? makeDebugTraceStacker(*this, *i.value->payload.thunk.expr, *i.value->payload.thunk.env, i.pos,
"while evaluating the attribute '%1%'", symbols[i.name])
: nullptr;
@@ -2400,7 +2404,7 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat
: [&]() {
auto dstPath = fetchToStore(
*store,
path.resolveSymlinks(),
path.resolveSymlinks(SymlinkResolution::Ancestors),
settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy,
path.baseName(),
ContentAddressMethod::Raw::NixArchive,
@@ -3084,8 +3088,11 @@ std::optional<std::string> EvalState::resolveLookupPathPath(const LookupPath::Pa
auto i = lookupPathResolved.find(value);
if (i != lookupPathResolved.end()) return i->second;
auto finish = [&](std::string res) {
debug("resolved search path element '%s' to '%s'", value, res);
auto finish = [&](std::optional<std::string> res) {
if (res)
debug("resolved search path element '%s' to '%s'", value, *res);
else
debug("failed to resolve search path element '%s'", value);
lookupPathResolved.emplace(value, res);
return res;
};
@@ -3137,9 +3144,7 @@ std::optional<std::string> EvalState::resolveLookupPathPath(const LookupPath::Pa
}
}
debug("failed to resolve search path element '%s'", value);
return std::nullopt;
return finish(std::nullopt);
}

View File

@@ -155,11 +155,28 @@ struct RegexCache;
std::shared_ptr<RegexCache> makeRegexCache();
struct DebugTrace {
std::shared_ptr<Pos> pos;
/* WARNING: Converting PosIdx -> Pos should be done with extra care. This is
due to the fact that operator[] of PosTable is incredibly expensive. */
std::variant<Pos, PosIdx> pos;
const Expr & expr;
const Env & env;
HintFmt hint;
bool isError;
Pos getPos(const PosTable & table) const
{
return std::visit(
overloaded{
[&](PosIdx idx) {
// Prefer direct pos, but if noPos then try the expr.
if (!idx)
idx = expr.getPos();
return table[idx];
},
[&](Pos pos) { return pos; },
},
pos);
}
};
class EvalState : public std::enable_shared_from_this<EvalState>
@@ -786,6 +803,15 @@ public:
*/
[[nodiscard]] StringMap realiseContext(const NixStringContext & context, StorePathSet * maybePaths = nullptr, bool isIFD = true);
/**
* Realise the given string with context, and return the string with outputs instead of downstream output placeholders.
* @param[in] str the string to realise
* @param[out] paths all referenced store paths will be added to this set
* @return the realised string
* @throw EvalError if the value is not a string, path or derivation (see `coerceToString`)
*/
std::string realiseString(Value & str, StorePathSet * storePathsOutMaybe, bool isIFD = true, const PosIdx pos = noPos);
/* Call the binary path filter predicate used builtins.path etc. */
bool callPathFilter(
Value * filterFun,

View File

@@ -1,40 +1,72 @@
{ system ? "" # obsolete
, url
, hash ? "" # an SRI hash
{
system ? "", # obsolete
url,
hash ? "", # an SRI hash
# Legacy hash specification
, md5 ? "", sha1 ? "", sha256 ? "", sha512 ? ""
, outputHash ?
if hash != "" then hash else if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256
, outputHashAlgo ?
if hash != "" then "" else if sha512 != "" then "sha512" else if sha1 != "" then "sha1" else if md5 != "" then "md5" else "sha256"
# Legacy hash specification
md5 ? "",
sha1 ? "",
sha256 ? "",
sha512 ? "",
outputHash ?
if hash != "" then
hash
else if sha512 != "" then
sha512
else if sha1 != "" then
sha1
else if md5 != "" then
md5
else
sha256,
outputHashAlgo ?
if hash != "" then
""
else if sha512 != "" then
"sha512"
else if sha1 != "" then
"sha1"
else if md5 != "" then
"md5"
else
"sha256",
, executable ? false
, unpack ? false
, name ? baseNameOf (toString url)
, impure ? false
executable ? false,
unpack ? false,
name ? baseNameOf (toString url),
impure ? false,
}:
derivation ({
builder = "builtin:fetchurl";
derivation (
{
builder = "builtin:fetchurl";
# New-style output content requirements.
outputHashMode = if unpack || executable then "recursive" else "flat";
# New-style output content requirements.
outputHashMode = if unpack || executable then "recursive" else "flat";
inherit name url executable unpack;
inherit
name
url
executable
unpack
;
system = "builtin";
system = "builtin";
# No need to double the amount of network traffic
preferLocalBuild = true;
# No need to double the amount of network traffic
preferLocalBuild = true;
# This attribute does nothing; it's here to avoid changing evaluation results.
impureEnvVars = [
"http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy"
];
# This attribute does nothing; it's here to avoid changing evaluation results.
impureEnvVars = [
"http_proxy"
"https_proxy"
"ftp_proxy"
"all_proxy"
"no_proxy"
];
# To make "nix-prefetch-url" work.
urls = [ url ];
} // (if impure
then { __impure = true; }
else { inherit outputHashAlgo outputHash; }))
# To make "nix-prefetch-url" work.
urls = [ url ];
}
// (if impure then { __impure = true; } else { inherit outputHashAlgo outputHash; })
)

View File

@@ -1,21 +1,27 @@
attrs @ { drvPath, outputs, name, ... }:
attrs@{
drvPath,
outputs,
name,
...
}:
let
commonAttrs = (builtins.listToAttrs outputsList) //
{ all = map (x: x.value) outputsList;
inherit drvPath name;
type = "derivation";
};
commonAttrs = (builtins.listToAttrs outputsList) // {
all = map (x: x.value) outputsList;
inherit drvPath name;
type = "derivation";
};
outputToAttrListElement = outputName:
{ name = outputName;
value = commonAttrs // {
outPath = builtins.getAttr outputName attrs;
inherit outputName;
};
outputToAttrListElement = outputName: {
name = outputName;
value = commonAttrs // {
outPath = builtins.getAttr outputName attrs;
inherit outputName;
};
};
outputsList = map outputToAttrListElement outputs;
in (builtins.head outputsList).value
in
(builtins.head outputsList).value

View File

@@ -175,8 +175,6 @@ headers = [config_h] + files(
# internal: 'lexer-helpers.hh',
'nixexpr.hh',
'parser-state.hh',
'pos-idx.hh',
'pos-table.hh',
'primops.hh',
'print-ambiguous.hh',
'print-options.hh',

View File

@@ -601,41 +601,6 @@ void ExprLambda::setDocComment(DocComment docComment) {
}
};
/* Position table. */
Pos PosTable::operator[](PosIdx p) const
{
auto origin = resolve(p);
if (!origin)
return {};
const auto offset = origin->offsetOf(p);
Pos result{0, 0, origin->origin};
auto lines = this->lines.lock();
auto linesForInput = (*lines)[origin->offset];
if (linesForInput.empty()) {
auto source = result.getSource().value_or("");
const char * begin = source.data();
for (Pos::LinesIterator it(source), end; it != end; it++)
linesForInput.push_back(it->data() - begin);
if (linesForInput.empty())
linesForInput.push_back(0);
}
// as above: the first line starts at byte 0 and is always present
auto lineStartOffset = std::prev(
std::upper_bound(linesForInput.begin(), linesForInput.end(), offset));
result.line = 1 + (lineStartOffset - linesForInput.begin());
result.column = 1 + (offset - *lineStartOffset);
return result;
}
/* Symbol table. */
size_t SymbolTable::totalSize() const

View File

@@ -1,37 +1,38 @@
{ lib
, stdenv
, mkMesonDerivation
, releaseTools
{
lib,
stdenv,
mkMesonDerivation,
releaseTools,
, meson
, ninja
, pkg-config
, bison
, flex
, cmake # for resolving toml11 dep
meson,
ninja,
pkg-config,
bison,
flex,
cmake, # for resolving toml11 dep
, nix-util
, nix-store
, nix-fetchers
, boost
, boehmgc
, nlohmann_json
, toml11
nix-util,
nix-store,
nix-fetchers,
boost,
boehmgc,
nlohmann_json,
toml11,
# Configuration Options
# Configuration Options
, version
version,
# Whether to use garbage collection for the Nix language evaluator.
#
# If it is disabled, we just leak memory, but this is not as bad as it
# sounds so long as evaluation just takes places within short-lived
# processes. (When the process exits, the memory is reclaimed; it is
# only leaked *within* the process.)
#
# Temporarily disabled on Windows because the `GC_throw_bad_alloc`
# symbol is missing during linking.
, enableGC ? !stdenv.hostPlatform.isWindows
# Whether to use garbage collection for the Nix language evaluator.
#
# If it is disabled, we just leak memory, but this is not as bad as it
# sounds so long as evaluation just takes places within short-lived
# processes. (When the process exits, the memory is reclaimed; it is
# only leaked *within* the process.)
#
# Temporarily disabled on Windows because the `GC_throw_bad_alloc`
# symbol is missing during linking.
enableGC ? !stdenv.hostPlatform.isWindows,
}:
let
@@ -58,7 +59,10 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "nix") ./.)
];
outputs = [ "out" "dev" ];
outputs = [
"out"
"dev"
];
nativeBuildInputs = [
meson
@@ -93,14 +97,18 @@ mkMesonDerivation (finalAttrs: {
(lib.mesonEnable "gc" enableGC)
];
env = {
# Needed for Meson to find Boost.
# https://github.com/NixOS/nixpkgs/issues/86131.
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
} // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
{
# Needed for Meson to find Boost.
# https://github.com/NixOS/nixpkgs/issues/86131.
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
}
// lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -40,6 +40,15 @@ namespace nix {
* Miscellaneous
*************************************************************/
std::string EvalState::realiseString(Value & s, StorePathSet * storePathsOutMaybe, bool isIFD, const PosIdx pos)
{
nix::NixStringContext stringContext;
auto rawStr = coerceToString(pos, s, stringContext, "while realising a string").toOwned();
auto rewrites = realiseContext(stringContext, storePathsOutMaybe, isIFD);
return nix::rewriteStrings(rawStr, rewrites);
}
StringMap EvalState::realiseContext(const NixStringContext & context, StorePathSet * maybePathsOut, bool isIFD)
{
std::vector<DerivedPath::Built> drvs;

View File

@@ -26,27 +26,34 @@
Note that `derivation` is very bare-bones, and provides almost no commands during the build.
Most likely, you'll want to use functions like `stdenv.mkDerivation` in Nixpkgs to set up a basic environment.
*/
drvAttrs @ { outputs ? [ "out" ], ... }:
drvAttrs@{
outputs ? [ "out" ],
...
}:
let
strict = derivationStrict drvAttrs;
commonAttrs = drvAttrs // (builtins.listToAttrs outputsList) //
{ all = map (x: x.value) outputsList;
commonAttrs =
drvAttrs
// (builtins.listToAttrs outputsList)
// {
all = map (x: x.value) outputsList;
inherit drvAttrs;
};
outputToAttrListElement = outputName:
{ name = outputName;
value = commonAttrs // {
outPath = builtins.getAttr outputName strict;
drvPath = strict.drvPath;
type = "derivation";
inherit outputName;
};
outputToAttrListElement = outputName: {
name = outputName;
value = commonAttrs // {
outPath = builtins.getAttr outputName strict;
drvPath = strict.drvPath;
type = "derivation";
inherit outputName;
};
};
outputsList = map outputToAttrListElement outputs;
in (builtins.head outputsList).value
in
(builtins.head outputsList).value

View File

@@ -4,6 +4,21 @@
namespace nix {
fetchers::Cache::Key makeFetchToStoreCacheKey(
const std::string &name,
const std::string &fingerprint,
ContentAddressMethod method,
const std::string &path)
{
return fetchers::Cache::Key{"fetchToStore", {
{"name", name},
{"fingerprint", fingerprint},
{"method", std::string{method.render()}},
{"path", path}
}};
}
StorePath fetchToStore(
Store & store,
const SourcePath & path,
@@ -19,12 +34,7 @@ StorePath fetchToStore(
std::optional<fetchers::Cache::Key> cacheKey;
if (!filter && path.accessor->fingerprint) {
cacheKey = fetchers::Cache::Key{"fetchToStore", {
{"name", std::string{name}},
{"fingerprint", *path.accessor->fingerprint},
{"method", std::string{method.render()}},
{"path", path.path.abs()}
}};
cacheKey = makeFetchToStoreCacheKey(std::string{name}, *path.accessor->fingerprint, method, path.path.abs());
if (auto res = fetchers::getCache()->lookupStorePath(*cacheKey, store)) {
debug("store path cache hit for '%s'", path);
return res->storePath;

View File

@@ -5,6 +5,7 @@
#include "file-system.hh"
#include "repair-flag.hh"
#include "file-content-address.hh"
#include "cache.hh"
namespace nix {
@@ -22,4 +23,7 @@ StorePath fetchToStore(
PathFilter * filter = nullptr,
RepairFlag repair = NoRepair);
fetchers::Cache::Key makeFetchToStoreCacheKey(
const std::string & name, const std::string & fingerprint, ContentAddressMethod method, const std::string & path);
}

View File

@@ -159,7 +159,8 @@ static Object peelToTreeOrBlob(git_object * obj)
return peelObject<Object>(obj, GIT_OBJECT_TREE);
}
static void initRepoAtomically(std::filesystem::path &path, bool bare) {
static void initRepoAtomically(std::filesystem::path &path, bool bare)
{
if (pathExists(path.string())) return;
Path tmpDir = createTempDir(std::filesystem::path(path).parent_path());
@@ -416,13 +417,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
// then use code that was removed in this commit (see blame)
auto dir = this->path;
Strings gitArgs;
if (shallow) {
gitArgs = { "-C", dir.string(), "fetch", "--quiet", "--force", "--depth", "1", "--", url, refspec };
}
else {
gitArgs = { "-C", dir.string(), "fetch", "--quiet", "--force", "--", url, refspec };
}
Strings gitArgs{"-C", dir.string(), "--git-dir", ".", "fetch", "--quiet", "--force"};
if (shallow)
append(gitArgs, {"--depth", "1"});
append(gitArgs, {std::string("--"), url, refspec});
runProgram(RunOptions {
.program = "git",

View File

@@ -1,21 +1,22 @@
{ lib
, stdenv
, mkMesonDerivation
, releaseTools
{
lib,
stdenv,
mkMesonDerivation,
releaseTools,
, meson
, ninja
, pkg-config
meson,
ninja,
pkg-config,
, nix-util
, nix-store
, nlohmann_json
, libgit2
, man
nix-util,
nix-store,
nlohmann_json,
libgit2,
man,
# Configuration Options
# Configuration Options
, version
version,
}:
let
@@ -37,7 +38,10 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];
outputs = [ "out" "dev" ];
outputs = [
"out"
"dev"
];
nativeBuildInputs = [
meson
@@ -63,9 +67,12 @@ mkMesonDerivation (finalAttrs: {
echo ${version} > ../../.version
'';
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -2,6 +2,7 @@
#include "store-api.hh"
#include "archive.hh"
#include "store-path-accessor.hh"
#include "fetch-to-store.hh"
namespace nix::fetchers {
@@ -157,6 +158,15 @@ struct PathInputScheme : InputScheme
});
storePath = store->addToStoreFromDump(*src, "source");
}
// To avoid copying the path again to the /nix/store, we need to add a cache entry.
ContentAddressMethod method = ContentAddressMethod::Raw::NixArchive;
auto fp = getFingerprint(store, input);
if (fp) {
auto cacheKey = makeFetchToStoreCacheKey(input.getName(), *fp, method, "/");
fetchers::getCache()->upsert(cacheKey, *store, {}, *storePath);
}
input.attrs.insert_or_assign("lastModified", uint64_t(mtime));
return {makeStorePathAccessor(store, *storePath), std::move(input)};

View File

@@ -1,23 +1,24 @@
{ lib
, stdenv
, mkMesonDerivation
, releaseTools
{
lib,
stdenv,
mkMesonDerivation,
releaseTools,
, meson
, ninja
, pkg-config
meson,
ninja,
pkg-config,
, nix-util
, nix-store
, nix-fetchers
, nix-expr
, nlohmann_json
, libgit2
, man
nix-util,
nix-store,
nix-fetchers,
nix-expr,
nlohmann_json,
libgit2,
man,
# Configuration Options
# Configuration Options
, version
version,
}:
let
@@ -39,7 +40,10 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];
outputs = [ "out" "dev" ];
outputs = [
"out"
"dev"
];
nativeBuildInputs = [
meson
@@ -63,9 +67,12 @@ mkMesonDerivation (finalAttrs: {
echo ${version} > ../../.version
'';
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -1,20 +1,21 @@
{ lib
, stdenv
, mkMesonDerivation
, releaseTools
{
lib,
stdenv,
mkMesonDerivation,
releaseTools,
, meson
, ninja
, pkg-config
meson,
ninja,
pkg-config,
, nix-util-c
, nix-store
, nix-store-c
, nix-main
nix-util-c,
nix-store,
nix-store-c,
nix-main,
# Configuration Options
# Configuration Options
, version
version,
}:
let
@@ -38,7 +39,10 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "h") ./.)
];
outputs = [ "out" "dev" ];
outputs = [
"out"
"dev"
];
nativeBuildInputs = [
meson
@@ -64,9 +68,12 @@ mkMesonDerivation (finalAttrs: {
mesonFlags = [
];
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -1,20 +1,21 @@
{ lib
, stdenv
, mkMesonDerivation
, releaseTools
{
lib,
stdenv,
mkMesonDerivation,
releaseTools,
, meson
, ninja
, pkg-config
meson,
ninja,
pkg-config,
, openssl
openssl,
, nix-util
, nix-store
nix-util,
nix-store,
# Configuration Options
# Configuration Options
, version
version,
}:
let
@@ -36,7 +37,10 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];
outputs = [ "out" "dev" ];
outputs = [
"out"
"dev"
];
nativeBuildInputs = [
meson
@@ -58,9 +62,12 @@ mkMesonDerivation (finalAttrs: {
echo ${version} > ../../.version
'';
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -1,18 +1,19 @@
{ lib
, stdenv
, mkMesonDerivation
, releaseTools
{
lib,
stdenv,
mkMesonDerivation,
releaseTools,
, meson
, ninja
, pkg-config
meson,
ninja,
pkg-config,
, nix-util-c
, nix-store
nix-util-c,
nix-store,
# Configuration Options
# Configuration Options
, version
version,
}:
let
@@ -36,7 +37,10 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "h") ./.)
];
outputs = [ "out" "dev" ];
outputs = [
"out"
"dev"
];
nativeBuildInputs = [
meson
@@ -60,9 +64,12 @@ mkMesonDerivation (finalAttrs: {
mesonFlags = [
];
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -23,11 +23,7 @@ void builtinUnpackChannel(
throw Error("channelName is not allowed to contain filesystem separators, got %1%", channelName);
}
try {
fs::create_directories(out);
} catch (fs::filesystem_error &) {
throw SysError("creating directory '%1%'", out.string());
}
createDirs(out);
unpackTarfile(src, out);

View File

@@ -1025,6 +1025,7 @@ void processConnection(
{
#ifndef _WIN32 // TODO need graceful async exit support on Windows?
auto monitor = !recursive ? std::make_unique<MonitorFdHup>(from.fd) : nullptr;
(void) monitor; // suppress warning
#endif
/* Exchange the greeting. */

View File

@@ -298,6 +298,14 @@ struct curlFileTransfer : public FileTransfer
return ((TransferItem *) userp)->readCallback(buffer, size, nitems);
}
#if !defined(_WIN32) && LIBCURL_VERSION_NUM >= 0x071000
static int cloexec_callback(void *, curl_socket_t curlfd, curlsocktype purpose) {
unix::closeOnExec(curlfd);
vomit("cloexec set for fd %i", curlfd);
return CURL_SOCKOPT_OK;
}
#endif
void init()
{
if (!req) req = curl_easy_init();
@@ -357,6 +365,10 @@ struct curlFileTransfer : public FileTransfer
curl_easy_setopt(req, CURLOPT_SSL_VERIFYHOST, 0);
}
#if !defined(_WIN32) && LIBCURL_VERSION_NUM >= 0x071000
curl_easy_setopt(req, CURLOPT_SOCKOPTFUNCTION, cloexec_callback);
#endif
curl_easy_setopt(req, CURLOPT_CONNECTTIMEOUT, fileTransferSettings.connectTimeout.get());
curl_easy_setopt(req, CURLOPT_LOW_SPEED_LIMIT, 1L);

View File

@@ -213,7 +213,7 @@ LocalStore::LocalStore(
state->stmts = std::make_unique<State::Stmts>();
/* Create missing state directories if they don't already exist. */
createDirs(realStoreDir);
createDirs(realStoreDir.get());
if (readOnly) {
experimentalFeatureSettings.require(Xp::ReadOnlyLocalStore);
} else {
@@ -233,7 +233,12 @@ LocalStore::LocalStore(
for (auto & perUserDir : {profilesDir + "/per-user", gcRootsDir + "/per-user"}) {
createDirs(perUserDir);
if (!readOnly) {
if (chmod(perUserDir.c_str(), 0755) == -1)
auto st = lstat(perUserDir);
// Skip chmod call if the directory already has the correct permissions (0755).
// This is to avoid failing when the executing user lacks permissions to change the directory's permissions
// even if it would be no-op.
if ((st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) != 0755 && chmod(perUserDir.c_str(), 0755) == -1)
throw SysError("could not set permissions on '%s' to 755", perUserDir);
}
}
@@ -340,7 +345,7 @@ LocalStore::LocalStore(
else if (curSchema == 0) { /* new store */
curSchema = nixSchemaVersion;
openDB(*state, true);
writeFile(schemaPath, fmt("%1%", nixSchemaVersion), 0666, true);
writeFile(schemaPath, fmt("%1%", curSchema), 0666, true);
}
else if (curSchema < nixSchemaVersion) {

View File

@@ -1,29 +1,30 @@
{ lib
, stdenv
, mkMesonDerivation
, releaseTools
{
lib,
stdenv,
mkMesonDerivation,
releaseTools,
, meson
, ninja
, pkg-config
, unixtools
, darwin
meson,
ninja,
pkg-config,
unixtools,
darwin,
, nix-util
, boost
, curl
, aws-sdk-cpp
, libseccomp
, nlohmann_json
, sqlite
nix-util,
boost,
curl,
aws-sdk-cpp,
libseccomp,
nlohmann_json,
sqlite,
, busybox-sandbox-shell ? null
busybox-sandbox-shell ? null,
# Configuration Options
# Configuration Options
, version
version,
, embeddedSandboxShell ? stdenv.hostPlatform.isStatic
embeddedSandboxShell ? stdenv.hostPlatform.isStatic,
}:
let
@@ -52,7 +53,10 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "sql") ./.)
];
outputs = [ "out" "dev" ];
outputs = [
"out"
"dev"
];
nativeBuildInputs = [
meson
@@ -60,16 +64,18 @@ mkMesonDerivation (finalAttrs: {
pkg-config
] ++ lib.optional embeddedSandboxShell unixtools.hexdump;
buildInputs = [
boost
curl
sqlite
] ++ lib.optional stdenv.hostPlatform.isLinux libseccomp
buildInputs =
[
boost
curl
sqlite
]
++ lib.optional stdenv.hostPlatform.isLinux libseccomp
# There have been issues building these dependencies
++ lib.optional stdenv.hostPlatform.isDarwin darwin.apple_sdk.libs.sandbox
++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin))
aws-sdk-cpp
;
++ lib.optional (
stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin)
) aws-sdk-cpp;
propagatedBuildInputs = [
nix-util
@@ -84,21 +90,27 @@ mkMesonDerivation (finalAttrs: {
echo ${version} > ../../.version
'';
mesonFlags = [
(lib.mesonEnable "seccomp-sandboxing" stdenv.hostPlatform.isLinux)
(lib.mesonBool "embedded-sandbox-shell" embeddedSandboxShell)
] ++ lib.optionals stdenv.hostPlatform.isLinux [
(lib.mesonOption "sandbox-shell" "${busybox-sandbox-shell}/bin/busybox")
];
mesonFlags =
[
(lib.mesonEnable "seccomp-sandboxing" stdenv.hostPlatform.isLinux)
(lib.mesonBool "embedded-sandbox-shell" embeddedSandboxShell)
]
++ lib.optionals stdenv.hostPlatform.isLinux [
(lib.mesonOption "sandbox-shell" "${busybox-sandbox-shell}/bin/busybox")
];
env = {
# Needed for Meson to find Boost.
# https://github.com/NixOS/nixpkgs/issues/86131.
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
} // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
{
# Needed for Meson to find Boost.
# https://github.com/NixOS/nixpkgs/issues/86131.
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
}
// lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -539,11 +539,21 @@ void RemoteStore::addMultipleToStore(
RepairFlag repair,
CheckSigsFlag checkSigs)
{
// `addMultipleToStore` is single threaded
size_t bytesExpected = 0;
for (auto & [pathInfo, _] : pathsToCopy) {
bytesExpected += pathInfo.narSize;
}
act.setExpected(actCopyPath, bytesExpected);
auto source = sinkToSource([&](Sink & sink) {
sink << pathsToCopy.size();
size_t nrTotal = pathsToCopy.size();
sink << nrTotal;
// Reverse, so we can release memory at the original start
std::reverse(pathsToCopy.begin(), pathsToCopy.end());
while (!pathsToCopy.empty()) {
act.progress(nrTotal - pathsToCopy.size(), nrTotal, size_t(1), size_t(0));
auto & [pathInfo, pathSource] = pathsToCopy.back();
WorkerProto::Serialise<ValidPathInfo>::write(*this,
WorkerProto::WriteConn {

View File

@@ -242,8 +242,8 @@ void Store::addMultipleToStore(
storePathsToAdd.insert(thingToAdd.first.path);
}
auto showProgress = [&]() {
act.progress(nrDone, pathsToCopy.size(), nrRunning, nrFailed);
auto showProgress = [&, nrTotal = pathsToCopy.size()]() {
act.progress(nrDone, nrTotal, nrRunning, nrFailed);
};
processGraph<StorePath>(
@@ -1104,9 +1104,6 @@ std::map<StorePath, StorePath> copyPaths(
return storePathForDst;
};
// total is accessed by each copy, which are each handled in separate threads
std::atomic<uint64_t> total = 0;
for (auto & missingPath : sortedMissing) {
auto info = srcStore.queryPathInfo(missingPath);
@@ -1116,9 +1113,10 @@ std::map<StorePath, StorePath> copyPaths(
ValidPathInfo infoForDst = *info;
infoForDst.path = storePathForDst;
auto source = sinkToSource([&](Sink & sink) {
auto source = sinkToSource([&, narSize = info->narSize](Sink & sink) {
// We can reasonably assume that the copy will happen whenever we
// read the path, so log something about that at that point
uint64_t total = 0;
auto srcUri = srcStore.getUri();
auto dstUri = dstStore.getUri();
auto storePathS = srcStore.printStorePath(missingPath);
@@ -1129,13 +1127,13 @@ std::map<StorePath, StorePath> copyPaths(
LambdaSink progressSink([&](std::string_view data) {
total += data.size();
act.progress(total, info->narSize);
act.progress(total, narSize);
});
TeeSink tee { sink, progressSink };
srcStore.narFromPath(missingPath, tee);
});
pathsToCopy.push_back(std::pair{infoForDst, std::move(source)});
pathsToCopy.emplace_back(std::move(infoForDst), std::move(source));
}
dstStore.addMultipleToStore(std::move(pathsToCopy), act, repair, checkSigs);

View File

@@ -2100,7 +2100,18 @@ void LocalDerivationGoal::runChild()
without file-write* allowed, access() incorrectly returns EPERM
*/
sandboxProfile += "(allow file-read* file-write* process-exec\n";
// We create multiple allow lists, to avoid exceeding a limit in the darwin sandbox interpreter.
// See https://github.com/NixOS/nix/issues/4119
// We split our allow groups approximately at half the actual limit, 1 << 16
const int breakpoint = sandboxProfile.length() + (1 << 14);
for (auto & i : pathsInChroot) {
if (sandboxProfile.length() >= breakpoint) {
debug("Sandbox break: %d %d", sandboxProfile.length(), breakpoint);
sandboxProfile += ")\n(allow file-read* file-write* process-exec\n";
}
if (i.first != i.second.source)
throw Error(
"can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin",
@@ -2614,10 +2625,14 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
wanted.to_string(HashFormat::SRI, true),
got.to_string(HashFormat::SRI, true)));
}
if (!newInfo0.references.empty())
if (!newInfo0.references.empty()) {
auto numViolations = newInfo.references.size();
delayedException = std::make_exception_ptr(
BuildError("illegal path references in fixed-output derivation '%s'",
worker.store.printStorePath(drvPath)));
BuildError("fixed-output derivations must not reference store paths: '%s' references %d distinct paths, e.g. '%s'",
worker.store.printStorePath(drvPath),
numViolations,
worker.store.printStorePath(*newInfo.references.begin())));
}
return newInfo0;
},

View File

@@ -1,17 +1,18 @@
{ lib
, stdenv
, mkMesonDerivation
, releaseTools
{
lib,
stdenv,
mkMesonDerivation,
releaseTools,
, meson
, ninja
, pkg-config
meson,
ninja,
pkg-config,
, nix-util
nix-util,
# Configuration Options
# Configuration Options
, version
version,
}:
let
@@ -35,7 +36,10 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "h") ./.)
];
outputs = [ "out" "dev" ];
outputs = [
"out"
"dev"
];
nativeBuildInputs = [
meson
@@ -58,9 +62,12 @@ mkMesonDerivation (finalAttrs: {
mesonFlags = [
];
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -0,0 +1,18 @@
#include "util.hh"
#include "monitor-fd.hh"
#include <sys/file.h>
#include <gtest/gtest.h>
namespace nix {
TEST(MonitorFdHup, shouldNotBlock)
{
Pipe p;
p.create();
{
// when monitor gets destroyed it should cancel the
// background thread and do not block
MonitorFdHup monitor(p.readSide.get());
}
}
}

View File

@@ -50,6 +50,14 @@ struct LinesOfCode {
std::optional<std::string> nextLineOfCode;
};
/* NOTE: position.hh recursively depends on source-path.hh -> source-accessor.hh
-> hash.hh -> config.hh -> experimental-features.hh -> error.hh -> Pos.
There are other such cycles.
Thus, Pos has to be an incomplete type in this header. But since ErrorInfo/Trace
have to refer to Pos, they have to use pointer indirection via std::shared_ptr
to break the recursive header dependency.
FIXME: Untangle this mess. Should there be AbstractPos as there used to be before
4feb7d9f71? */
struct Pos;
void printCodeLines(std::ostream & out,

View File

@@ -419,12 +419,12 @@ void createDir(const Path & path, mode_t mode)
throw SysError("creating directory '%1%'", path);
}
void createDirs(const Path & path)
void createDirs(const fs::path & path)
{
try {
fs::create_directories(path);
} catch (fs::filesystem_error & e) {
throw SysError("creating directory '%1%'", path);
throw SysError("creating directory '%1%'", path.string());
}
}

View File

@@ -171,12 +171,10 @@ void deletePath(const std::filesystem::path & path, uint64_t & bytesFreed);
/**
* Create a directory and all its parents, if necessary.
*
* Wrapper around `std::filesystem::create_directories` to handle exceptions.
*/
void createDirs(const Path & path);
inline void createDirs(PathView path)
{
return createDirs(Path(path));
}
void createDirs(const std::filesystem::path & path);
/**
* Create a single directory.

View File

@@ -33,7 +33,7 @@ std::optional<Mode> decodeMode(RawMode m) {
static std::string getStringUntil(Source & source, char byte)
{
std::string s;
char n[1];
char n[1] = { 0 };
source(std::string_view { n, 1 });
while (*n != byte) {
s += *n;

View File

@@ -146,6 +146,7 @@ sources = files(
'logging.cc',
'memory-source-accessor.cc',
'position.cc',
'pos-table.cc',
'posix-source-accessor.cc',
'references.cc',
'serialise.cc',
@@ -207,6 +208,8 @@ headers = [config_h] + files(
'memory-source-accessor.hh',
'muxable-pipe.hh',
'pool.hh',
'pos-idx.hh',
'pos-table.hh',
'position.hh',
'posix-source-accessor.hh',
'processes.hh',

View File

@@ -1,23 +1,24 @@
{ lib
, stdenv
, mkMesonDerivation
, releaseTools
{
lib,
stdenv,
mkMesonDerivation,
releaseTools,
, meson
, ninja
, pkg-config
meson,
ninja,
pkg-config,
, boost
, brotli
, libarchive
, libcpuid
, libsodium
, nlohmann_json
, openssl
boost,
brotli,
libarchive,
libcpuid,
libsodium,
nlohmann_json,
openssl,
# Configuration Options
# Configuration Options
, version
version,
}:
let
@@ -43,7 +44,10 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];
outputs = [ "out" "dev" ];
outputs = [
"out"
"dev"
];
nativeBuildInputs = [
meson
@@ -55,8 +59,7 @@ mkMesonDerivation (finalAttrs: {
brotli
libsodium
openssl
] ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid
;
] ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid;
propagatedBuildInputs = [
boost
@@ -79,14 +82,18 @@ mkMesonDerivation (finalAttrs: {
(lib.mesonEnable "cpuid" stdenv.hostPlatform.isx86_64)
];
env = {
# Needed for Meson to find Boost.
# https://github.com/NixOS/nixpkgs/issues/86131.
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
} // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
{
# Needed for Meson to find Boost.
# https://github.com/NixOS/nixpkgs/issues/86131.
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
}
// lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -1,4 +1,5 @@
#pragma once
///@file
#include <cinttypes>
#include <functional>

37
src/libutil/pos-table.cc Normal file
View File

@@ -0,0 +1,37 @@
#include "pos-table.hh"
#include <algorithm>
namespace nix {
/* Position table. */
Pos PosTable::operator[](PosIdx p) const
{
auto origin = resolve(p);
if (!origin)
return {};
const auto offset = origin->offsetOf(p);
Pos result{0, 0, origin->origin};
auto lines = this->lines.lock();
auto linesForInput = (*lines)[origin->offset];
if (linesForInput.empty()) {
auto source = result.getSource().value_or("");
const char * begin = source.data();
for (Pos::LinesIterator it(source), end; it != end; it++)
linesForInput.push_back(it->data() - begin);
if (linesForInput.empty())
linesForInput.push_back(0);
}
// as above: the first line starts at byte 0 and is always present
auto lineStartOffset = std::prev(std::upper_bound(linesForInput.begin(), linesForInput.end(), offset));
result.line = 1 + (lineStartOffset - linesForInput.begin());
result.column = 1 + (offset - *lineStartOffset);
return result;
}
}

View File

@@ -1,4 +1,5 @@
#pragma once
///@file
#include <cstdint>
#include <vector>
@@ -18,9 +19,12 @@ public:
private:
uint32_t offset;
Origin(Pos::Origin origin, uint32_t offset, size_t size):
offset(offset), origin(origin), size(size)
{}
Origin(Pos::Origin origin, uint32_t offset, size_t size)
: offset(offset)
, origin(origin)
, size(size)
{
}
public:
const Pos::Origin origin;
@@ -72,6 +76,17 @@ public:
return PosIdx(1 + origin.offset + offset);
}
/**
* Convert a byte-offset PosIdx into a Pos with line/column information.
*
* @param p Byte offset into the virtual concatenation of all parsed contents
* @return Position
*
* @warning Very expensive to call, as this has to read the entire source
* into memory each time. Call this only if absolutely necessary. Prefer
* to keep PosIdx around instead of needlessly converting it into Pos by
* using this lookup method.
*/
Pos operator[](PosIdx p) const;
Pos::Origin originOf(PosIdx p) const

View File

@@ -66,6 +66,13 @@ std::optional<std::string> Pos::getSource() const
}, origin);
}
std::optional<SourcePath> Pos::getSourcePath() const
{
if (auto * path = std::get_if<SourcePath>(&origin))
return *path;
return std::nullopt;
}
void Pos::print(std::ostream & out, bool showOrigin) const
{
if (showOrigin) {

View File

@@ -50,6 +50,7 @@ struct Pos
explicit operator bool() const { return line > 0; }
/* TODO: Why std::shared_ptr<Pos> and not std::shared_ptr<const Pos>? */
operator std::shared_ptr<Pos>() const;
/**
@@ -69,9 +70,7 @@ struct Pos
/**
* Get the SourcePath, if the source was loaded from a file.
*/
std::optional<SourcePath> getSourcePath() const {
return *std::get_if<SourcePath>(&origin);
}
std::optional<SourcePath> getSourcePath() const;
struct LinesIterator {
using difference_type = size_t;

View File

@@ -166,7 +166,7 @@ void unpackTarfile(Source & source, const fs::path & destDir)
{
auto archive = TarArchive(source);
fs::create_directories(destDir);
createDirs(destDir);
extract_archive(archive, destDir);
}
@@ -174,7 +174,7 @@ void unpackTarfile(const fs::path & tarFile, const fs::path & destDir)
{
auto archive = TarArchive(tarFile);
fs::create_directories(destDir);
createDirs(destDir);
extract_archive(archive, destDir);
}

View File

@@ -14,35 +14,74 @@
namespace nix {
class MonitorFdHup
{
private:
std::thread thread;
Pipe notifyPipe;
public:
MonitorFdHup(int fd)
{
thread = std::thread([fd]() {
notifyPipe.create();
thread = std::thread([this, fd]() {
while (true) {
/* Wait indefinitely until a POLLHUP occurs. */
struct pollfd fds[1];
fds[0].fd = fd;
/* Polling for no specific events (i.e. just waiting
for an error/hangup) doesn't work on macOS
anymore. So wait for read events and ignore
them. */
fds[0].events =
#ifdef __APPLE__
POLLRDNORM
#else
// There is a POSIX violation on macOS: you have to listen for
// at least POLLHUP to receive HUP events for a FD. POSIX says
// this is not so, and you should just receive them regardless.
// However, as of our testing on macOS 14.5, the events do not
// get delivered if in the all-bits-unset case, but do get
// delivered if `POLLHUP` is set.
//
// This bug filed as rdar://37537852
// (https://openradar.appspot.com/37537852).
//
// macOS's own man page
// (https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/poll.2.html)
// additionally says that `POLLHUP` is ignored as an input. It
// seems the likely order of events here was
//
// 1. macOS did not follow the POSIX spec
//
// 2. Somebody ninja-fixed this other spec violation to make
// sure `POLLHUP` was not forgotten about, even though they
// "fixed" this issue in a spec-non-compliant way. Whatever,
// we'll use the fix.
//
// Relevant code, current version, which shows the :
// https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/sys_generic.c#L1751-L1758
//
// The `POLLHUP` detection was added in
// https://github.com/apple-oss-distributions/xnu/commit/e13b1fa57645afc8a7b2e7d868fe9845c6b08c40#diff-a5aa0b0e7f4d866ca417f60702689fc797e9cdfe33b601b05ccf43086c35d395R1468
// That means added in 2007 or earlier. Should be good enough
// for us.
short hangup_events =
#ifdef __APPLE__
POLLHUP
#else
0
#endif
#endif
;
auto count = poll(fds, 1, -1);
if (count == -1)
unreachable();
/* Wait indefinitely until a POLLHUP occurs. */
constexpr size_t num_fds = 2;
struct pollfd fds[num_fds] = {
{
.fd = fd,
.events = hangup_events,
},
{
.fd = notifyPipe.readSide.get(),
.events = hangup_events,
},
};
auto count = poll(fds, num_fds, -1);
if (count == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
throw SysError("failed to poll() in MonitorFdHup");
}
/* This shouldn't happen, but can on macOS due to a bug.
See rdar://37550628.
@@ -50,25 +89,42 @@ public:
coordination with the main thread if spinning proves
too harmful.
*/
if (count == 0) continue;
if (count == 0)
continue;
if (fds[0].revents & POLLHUP) {
unix::triggerInterrupt();
break;
}
/* This will only happen on macOS. We sleep a bit to
avoid waking up too often if the client is sending
input. */
sleep(1);
if (fds[1].revents & POLLHUP) {
break;
}
// On macOS, (jade thinks that) it is possible (although not
// observed on macOS 14.5) that in some limited cases on buggy
// kernel versions, all the non-POLLHUP events for the socket
// get delivered.
//
// We could sleep to avoid pointlessly spinning a thread on
// those, but this opens up a different problem, which is that
// if do sleep, it will be longer before the daemon fork for a
// client exits. Imagine a sequential shell script, running Nix
// commands, each of which talk to the daemon. If the previous
// command registered a temp root, exits, and then the next
// command issues a delete request before the temp root is
// cleaned up, that delete request might fail.
//
// Not sleeping doesn't actually fix the race condition --- we
// would need to block on the old connections' tempt roots being
// cleaned up in in the new connection --- but it does make it
// much less likely.
}
});
};
~MonitorFdHup()
{
pthread_cancel(thread.native_handle());
notifyPipe.writeSide.close();
thread.join();
}
};
}

View File

@@ -295,6 +295,17 @@ std::optional<typename T::value_type> pop(T & c)
}
/**
* Append items to a container. TODO: remove this once we can use
* C++23's `append_range()`.
*/
template<class C, typename T>
void append(C & c, std::initializer_list<T> l)
{
c.insert(c.end(), l.begin(), l.end());
}
template<typename T>
class Callback;

View File

@@ -1,4 +1,8 @@
{ name, channelName, src }:
{
name,
channelName,
src,
}:
derivation {
builder = "builtin:unpack-channel";

View File

@@ -8,13 +8,15 @@ derivation {
inherit manifest;
# !!! grmbl, need structured data for passing this in a clean way.
derivations =
map (d:
[ (d.meta.active or "true")
(d.meta.priority or 5)
(builtins.length d.outputs)
] ++ map (output: builtins.getAttr output d) d.outputs)
derivations;
derivations = map (
d:
[
(d.meta.active or "true")
(d.meta.priority or 5)
(builtins.length d.outputs)
]
++ map (output: builtins.getAttr output d) d.outputs
) derivations;
# Building user environments remotely just causes huge amounts of
# network traffic, so don't do that.

View File

@@ -1,24 +1,25 @@
{ lib
, stdenv
, mkMesonDerivation
, releaseTools
{
lib,
stdenv,
mkMesonDerivation,
releaseTools,
, meson
, ninja
, pkg-config
meson,
ninja,
pkg-config,
, nix-store
, nix-expr
, nix-main
, nix-cmd
nix-store,
nix-expr,
nix-main,
nix-cmd,
, rapidcheck
, gtest
, runCommand
rapidcheck,
gtest,
runCommand,
# Configuration Options
# Configuration Options
, version
version,
}:
let
@@ -30,58 +31,61 @@ mkMesonDerivation (finalAttrs: {
inherit version;
workDir = ./.;
fileset = fileset.unions ([
../../build-utils-meson
./build-utils-meson
../../.version
./.version
./meson.build
# ./meson.options
# Symbolic links to other dirs
./build-remote
./doc
./nix-build
./nix-channel
./nix-collect-garbage
./nix-copy-closure
./nix-env
./nix-instantiate
./nix-store
# Doc nix files for --help
../../doc/manual/generate-manpage.nix
../../doc/manual/utils.nix
../../doc/manual/generate-settings.nix
../../doc/manual/generate-store-info.nix
# Other files to be included as string literals
../nix-channel/unpack-channel.nix
../nix-env/buildenv.nix
./get-env.sh
./help-stores.md
../../doc/manual/src/store/types/index.md.in
./profiles.md
../../doc/manual/src/command-ref/files/profiles.md
# Files
] ++ lib.concatMap
(dir: [
(fileset.fileFilter (file: file.hasExt "cc") dir)
(fileset.fileFilter (file: file.hasExt "hh") dir)
(fileset.fileFilter (file: file.hasExt "md") dir)
])
fileset = fileset.unions (
[
./.
../build-remote
../nix-build
../nix-channel
../nix-collect-garbage
../nix-copy-closure
../nix-env
../nix-instantiate
../nix-store
../../build-utils-meson
./build-utils-meson
../../.version
./.version
./meson.build
# ./meson.options
# Symbolic links to other dirs
./build-remote
./doc
./nix-build
./nix-channel
./nix-collect-garbage
./nix-copy-closure
./nix-env
./nix-instantiate
./nix-store
# Doc nix files for --help
../../doc/manual/generate-manpage.nix
../../doc/manual/utils.nix
../../doc/manual/generate-settings.nix
../../doc/manual/generate-store-info.nix
# Other files to be included as string literals
../nix-channel/unpack-channel.nix
../nix-env/buildenv.nix
./get-env.sh
./help-stores.md
../../doc/manual/src/store/types/index.md.in
./profiles.md
../../doc/manual/src/command-ref/files/profiles.md
# Files
]
++
lib.concatMap
(dir: [
(fileset.fileFilter (file: file.hasExt "cc") dir)
(fileset.fileFilter (file: file.hasExt "hh") dir)
(fileset.fileFilter (file: file.hasExt "md") dir)
])
[
./.
../build-remote
../nix-build
../nix-channel
../nix-collect-garbage
../nix-copy-closure
../nix-env
../nix-instantiate
../nix-store
]
);
nativeBuildInputs = [
@@ -108,9 +112,12 @@ mkMesonDerivation (finalAttrs: {
mesonFlags = [
];
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
env =
lib.optionalAttrs
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
{
LDFLAGS = "-fuse-ld=gold";
};
separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@@ -1,77 +1,83 @@
{ lib
, stdenv
, mkMesonDerivation
, perl
, perlPackages
, meson
, ninja
, pkg-config
, nix-store
, darwin
, version
, curl
, bzip2
, libsodium
{
lib,
stdenv,
mkMesonDerivation,
perl,
perlPackages,
meson,
ninja,
pkg-config,
nix-store,
darwin,
version,
curl,
bzip2,
libsodium,
}:
let
inherit (lib) fileset;
in
perl.pkgs.toPerlModule (mkMesonDerivation (finalAttrs: {
pname = "nix-perl";
inherit version;
perl.pkgs.toPerlModule (
mkMesonDerivation (finalAttrs: {
pname = "nix-perl";
inherit version;
workDir = ./.;
fileset = fileset.unions ([
./.version
../../.version
./MANIFEST
./lib
./meson.build
./meson.options
] ++ lib.optionals finalAttrs.doCheck [
./.yath.rc.in
./t
]);
workDir = ./.;
fileset = fileset.unions (
[
./.version
../../.version
./MANIFEST
./lib
./meson.build
./meson.options
]
++ lib.optionals finalAttrs.doCheck [
./.yath.rc.in
./t
]
);
nativeBuildInputs = [
meson
ninja
pkg-config
perl
curl
];
nativeBuildInputs = [
meson
ninja
pkg-config
perl
curl
];
buildInputs = [
nix-store
bzip2
libsodium
];
buildInputs = [
nix-store
bzip2
libsodium
];
# `perlPackages.Test2Harness` is marked broken for Darwin
doCheck = !stdenv.isDarwin;
# `perlPackages.Test2Harness` is marked broken for Darwin
doCheck = !stdenv.isDarwin;
nativeCheckInputs = [
perlPackages.Test2Harness
];
nativeCheckInputs = [
perlPackages.Test2Harness
];
preConfigure =
# "Inline" .version so its not a symlink, and includes the suffix
''
chmod u+w .version
echo ${finalAttrs.version} > .version
'';
preConfigure =
# "Inline" .version so its not a symlink, and includes the suffix
''
chmod u+w .version
echo ${finalAttrs.version} > .version
'';
mesonFlags = [
(lib.mesonOption "dbi_path" "${perlPackages.DBI}/${perl.libPrefix}")
(lib.mesonOption "dbd_sqlite_path" "${perlPackages.DBDSQLite}/${perl.libPrefix}")
(lib.mesonEnable "tests" finalAttrs.doCheck)
];
mesonFlags = [
(lib.mesonOption "dbi_path" "${perlPackages.DBI}/${perl.libPrefix}")
(lib.mesonOption "dbd_sqlite_path" "${perlPackages.DBDSQLite}/${perl.libPrefix}")
(lib.mesonEnable "tests" finalAttrs.doCheck)
];
mesonCheckFlags = [
"--print-errorlogs"
];
mesonCheckFlags = [
"--print-errorlogs"
];
strictDeps = false;
}))
strictDeps = false;
})
)

View File

@@ -1,6 +1,25 @@
let
sixteenBytes = "0123456789abcdef";
times16 = s: builtins.concatStringsSep "" [s s s s s s s s s s s s s s s s];
times16 =
s:
builtins.concatStringsSep "" [
s
s
s
s
s
s
s
s
s
s
s
s
s
s
s
s
];
exp = n: x: if n == 1 then x else times16 (exp (n - 1) x);
sixteenMegabyte = exp 6 sixteenBytes;
in

View File

@@ -4,24 +4,39 @@ with import ./config.nix;
let
mkDerivation = args:
derivation ({
inherit system;
builder = busybox;
args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" ''
if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi;
eval "$buildCommand"
'')];
outputHashMode = "recursive";
outputHashAlgo = "sha256";
} // removeAttrs args ["builder" "meta" "passthru"])
// { meta = args.meta or {}; passthru = args.passthru or {}; };
mkDerivation =
args:
derivation (
{
inherit system;
builder = busybox;
args = [
"sh"
"-e"
args.builder or (builtins.toFile "builder-${args.name}.sh" ''
if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi;
eval "$buildCommand"
'')
];
outputHashMode = "recursive";
outputHashAlgo = "sha256";
}
// removeAttrs args [
"builder"
"meta"
"passthru"
]
)
// {
meta = args.meta or { };
passthru = args.passthru or { };
};
input1 = mkDerivation {
shell = busybox;
name = "build-remote-input-1";
buildCommand = "echo hi-input1; echo FOO > $out";
requiredSystemFeatures = ["foo"];
requiredSystemFeatures = [ "foo" ];
outputHash = "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=";
};
@@ -29,7 +44,7 @@ let
shell = busybox;
name = "build-remote-input-2";
buildCommand = "echo hi; echo BAR > $out";
requiredSystemFeatures = ["bar"];
requiredSystemFeatures = [ "bar" ];
outputHash = "sha256-XArauVH91AVwP9hBBQNlkX9ccuPpSYx9o0zeIHb6e+Q=";
};
@@ -41,21 +56,20 @@ let
read x < ${input2}
echo $x BAZ > $out
'';
requiredSystemFeatures = ["baz"];
requiredSystemFeatures = [ "baz" ];
outputHash = "sha256-daKAcPp/+BYMQsVi/YYMlCKoNAxCNDsaivwSHgQqD2s=";
};
in
mkDerivation {
shell = busybox;
name = "build-remote";
passthru = { inherit input1 input2 input3; };
buildCommand =
''
read x < ${input1}
read y < ${input3}
echo "$x $y" > $out
'';
outputHash = "sha256-5SxbkUw6xe2l9TE1uwCvTtTDysD1vhRor38OtDF0LqQ=";
}
mkDerivation {
shell = busybox;
name = "build-remote";
passthru = { inherit input1 input2 input3; };
buildCommand = ''
read x < ${input1}
read y < ${input3}
echo "$x $y" > $out
'';
outputHash = "sha256-5SxbkUw6xe2l9TE1uwCvTtTDysD1vhRor38OtDF0LqQ=";
}

View File

@@ -1,39 +1,61 @@
{ busybox, contentAddressed ? false }:
{
busybox,
contentAddressed ? false,
}:
with import ./config.nix;
let
caArgs = if contentAddressed then {
outputHashMode = "recursive";
outputHashAlgo = "sha256";
__contentAddressed = true;
} else {};
caArgs =
if contentAddressed then
{
outputHashMode = "recursive";
outputHashAlgo = "sha256";
__contentAddressed = true;
}
else
{ };
mkDerivation = args:
derivation ({
inherit system;
builder = busybox;
args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" ''
if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi;
eval "$buildCommand"
'')];
} // removeAttrs args ["builder" "meta" "passthru"]
// caArgs)
// { meta = args.meta or {}; passthru = args.passthru or {}; };
mkDerivation =
args:
derivation (
{
inherit system;
builder = busybox;
args = [
"sh"
"-e"
args.builder or (builtins.toFile "builder-${args.name}.sh" ''
if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi;
eval "$buildCommand"
'')
];
}
// removeAttrs args [
"builder"
"meta"
"passthru"
]
// caArgs
)
// {
meta = args.meta or { };
passthru = args.passthru or { };
};
input1 = mkDerivation {
shell = busybox;
name = "build-remote-input-1";
buildCommand = "echo hi-input1; echo FOO > $out";
requiredSystemFeatures = ["foo"];
requiredSystemFeatures = [ "foo" ];
};
input2 = mkDerivation {
shell = busybox;
name = "build-remote-input-2";
buildCommand = "echo hi; echo BAR > $out";
requiredSystemFeatures = ["bar"];
requiredSystemFeatures = [ "bar" ];
};
input3 = mkDerivation {
@@ -44,19 +66,18 @@ let
read x < ${input2}
echo $x BAZ > $out
'';
requiredSystemFeatures = ["baz"];
requiredSystemFeatures = [ "baz" ];
};
in
mkDerivation {
shell = busybox;
name = "build-remote";
passthru = { inherit input1 input2 input3; };
buildCommand =
''
read x < ${input1}
read y < ${input3}
echo "$x $y" > $out
'';
}
mkDerivation {
shell = busybox;
name = "build-remote";
passthru = { inherit input1 input2 input3; };
buildCommand = ''
read x < ${input1}
read y < ${input3}
echo "$x $y" > $out
'';
}

View File

@@ -1 +1,5 @@
{ inNixShell ? false, ... }@args: import ./shell.nix (args // { contentAddressed = true; })
{
inNixShell ? false,
...
}@args:
import ./shell.nix (args // { contentAddressed = true; })

View File

@@ -1,13 +1,21 @@
with import ./config.nix;
let mkCADerivation = args: mkDerivation ({
__contentAddressed = true;
outputHashMode = "recursive";
outputHashAlgo = "sha256";
} // args);
let
mkCADerivation =
args:
mkDerivation (
{
__contentAddressed = true;
outputHashMode = "recursive";
outputHashAlgo = "sha256";
}
// args
);
in
{ seed ? 0 }:
{
seed ? 0,
}:
# A simple content-addressed derivation.
# The derivation can be arbitrarily modified by passing a different `seed`,
# but the output will always be the same
@@ -23,7 +31,11 @@ rec {
};
rootCA = mkCADerivation {
name = "rootCA";
outputs = [ "out" "dev" "foo" ];
outputs = [
"out"
"dev"
"foo"
];
buildCommand = ''
echo "building a CA derivation"
echo "The seed is ${toString seed}"

View File

@@ -1,3 +1,3 @@
{
outputs = { self }: import ./content-addressed.nix {};
outputs = { self }: import ./content-addressed.nix { };
}

View File

@@ -1,10 +1,16 @@
with import ./config.nix;
let mkCADerivation = args: mkDerivation ({
__contentAddressed = true;
outputHashMode = "recursive";
outputHashAlgo = "sha256";
} // args);
let
mkCADerivation =
args:
mkDerivation (
{
__contentAddressed = true;
outputHashMode = "recursive";
outputHashAlgo = "sha256";
}
// args
);
in
rec {
@@ -15,13 +21,15 @@ rec {
echo $(date) > $out/current-time
'';
};
dep = seed: mkCADerivation {
name = "dep";
inherit seed;
buildCommand = ''
echo ${currentTime} > $out
'';
};
dep =
seed:
mkCADerivation {
name = "dep";
inherit seed;
buildCommand = ''
echo ${currentTime} > $out
'';
};
dep1 = dep 1;
dep2 = dep 2;
toplevel = mkCADerivation {
@@ -32,4 +40,3 @@ rec {
'';
};
}

View File

@@ -1,7 +1,6 @@
# A derivation that would certainly fail if several builders tried to
# build it at once.
with import ./config.nix;
mkDerivation {

View File

@@ -2,11 +2,16 @@ with import ./config.nix;
rec {
dep = import ./dependencies.nix {};
dep = import ./dependencies.nix { };
makeTest = nr: args: mkDerivation ({
name = "check-refs-" + toString nr;
} // args);
makeTest =
nr: args:
mkDerivation (
{
name = "check-refs-" + toString nr;
}
// args
);
src = builtins.toFile "aux-ref" "bla bla";
@@ -22,31 +27,31 @@ rec {
test3 = makeTest 3 {
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link";
allowedReferences = [];
allowedReferences = [ ];
inherit dep;
};
test4 = makeTest 4 {
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link";
allowedReferences = [dep];
allowedReferences = [ dep ];
inherit dep;
};
test5 = makeTest 5 {
builder = builtins.toFile "builder.sh" "mkdir $out";
allowedReferences = [];
allowedReferences = [ ];
inherit dep;
};
test6 = makeTest 6 {
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $out $out/link";
allowedReferences = [];
allowedReferences = [ ];
inherit dep;
};
test7 = makeTest 7 {
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $out $out/link";
allowedReferences = ["out"];
allowedReferences = [ "out" ];
inherit dep;
};
@@ -58,19 +63,19 @@ rec {
test9 = makeTest 9 {
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link";
inherit dep;
disallowedReferences = [dep];
disallowedReferences = [ dep ];
};
test10 = makeTest 10 {
builder = builtins.toFile "builder.sh" "mkdir $out; echo $test5; ln -s $dep $out/link";
inherit dep test5;
disallowedReferences = [test5];
disallowedReferences = [ test5 ];
};
test11 = makeTest 11 {
__structuredAttrs = true;
unsafeDiscardReferences.out = true;
outputChecks.out.allowedReferences = [];
outputChecks.out.allowedReferences = [ ];
buildCommand = ''echo ${dep} > "''${outputs[out]}"'';
};

View File

@@ -22,36 +22,48 @@ rec {
'';
};
makeTest = nr: allowreqs: mkDerivation {
name = "check-reqs-" + toString nr;
inherit deps;
builder = builtins.toFile "builder.sh" ''
mkdir $out
ln -s $deps $out/depdir1
'';
allowedRequisites = allowreqs;
};
makeTest =
nr: allowreqs:
mkDerivation {
name = "check-reqs-" + toString nr;
inherit deps;
builder = builtins.toFile "builder.sh" ''
mkdir $out
ln -s $deps $out/depdir1
'';
allowedRequisites = allowreqs;
};
# When specifying all the requisites, the build succeeds.
test1 = makeTest 1 [ dep1 dep2 deps ];
test1 = makeTest 1 [
dep1
dep2
deps
];
# But missing anything it fails.
test2 = makeTest 2 [ dep2 deps ];
test3 = makeTest 3 [ dep1 deps ];
test2 = makeTest 2 [
dep2
deps
];
test3 = makeTest 3 [
dep1
deps
];
test4 = makeTest 4 [ deps ];
test5 = makeTest 5 [];
test5 = makeTest 5 [ ];
test6 = mkDerivation {
name = "check-reqs";
inherit deps;
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $deps $out/depdir1";
disallowedRequisites = [dep1];
disallowedRequisites = [ dep1 ];
};
test7 = mkDerivation {
name = "check-reqs";
inherit deps;
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $deps $out/depdir1";
disallowedRequisites = [test1];
disallowedRequisites = [ test1 ];
};
}

View File

@@ -1,4 +1,6 @@
{checkBuildId ? 0}:
{
checkBuildId ? 0,
}:
with import ./config.nix;
@@ -6,41 +8,38 @@ with import ./config.nix;
nondeterministic = mkDerivation {
inherit checkBuildId;
name = "nondeterministic";
buildCommand =
''
mkdir $out
date +%s.%N > $out/date
echo "CHECK_TMPDIR=$TMPDIR"
echo "checkBuildId=$checkBuildId"
echo "$checkBuildId" > $TMPDIR/checkBuildId
'';
buildCommand = ''
mkdir $out
date +%s.%N > $out/date
echo "CHECK_TMPDIR=$TMPDIR"
echo "checkBuildId=$checkBuildId"
echo "$checkBuildId" > $TMPDIR/checkBuildId
'';
};
deterministic = mkDerivation {
inherit checkBuildId;
name = "deterministic";
buildCommand =
''
mkdir $out
echo date > $out/date
echo "CHECK_TMPDIR=$TMPDIR"
echo "checkBuildId=$checkBuildId"
echo "$checkBuildId" > $TMPDIR/checkBuildId
'';
buildCommand = ''
mkdir $out
echo date > $out/date
echo "CHECK_TMPDIR=$TMPDIR"
echo "checkBuildId=$checkBuildId"
echo "$checkBuildId" > $TMPDIR/checkBuildId
'';
};
failed = mkDerivation {
inherit checkBuildId;
name = "failed";
buildCommand =
''
mkdir $out
echo date > $out/date
echo "CHECK_TMPDIR=$TMPDIR"
echo "checkBuildId=$checkBuildId"
echo "$checkBuildId" > $TMPDIR/checkBuildId
false
'';
buildCommand = ''
mkdir $out
echo date > $out/date
echo "CHECK_TMPDIR=$TMPDIR"
echo "checkBuildId=$checkBuildId"
echo "$checkBuildId" > $TMPDIR/checkBuildId
false
'';
};
hashmismatch = import <nix/fetchurl.nix> {

View File

@@ -122,7 +122,7 @@ startDaemon() {
die "startDaemon: not supported when testing on NixOS. Is it really needed? If so add conditionals; e.g. if ! isTestOnNixOS; then ..."
fi
# Dont start the daemon twice, as this would just make it loop indefinitely
# Don't start the daemon twice, as this would just make it loop indefinitely.
if [[ "${_NIX_TEST_DAEMON_PID-}" != '' ]]; then
return
fi
@@ -131,15 +131,19 @@ startDaemon() {
PATH=$DAEMON_PATH nix --extra-experimental-features 'nix-command' daemon &
_NIX_TEST_DAEMON_PID=$!
export _NIX_TEST_DAEMON_PID
for ((i = 0; i < 300; i++)); do
for ((i = 0; i < 60; i++)); do
if [[ -S $NIX_DAEMON_SOCKET_PATH ]]; then
DAEMON_STARTED=1
break;
fi
if ! kill -0 "$_NIX_TEST_DAEMON_PID"; then
echo "daemon died unexpectedly" >&2
exit 1
fi
sleep 0.1
done
if [[ -z ${DAEMON_STARTED+x} ]]; then
fail "Didnt manage to start the daemon"
fail "Didn't manage to start the daemon"
fi
trap "killDaemon" EXIT
# Save for if daemon is killed
@@ -152,7 +156,7 @@ killDaemon() {
die "killDaemon: not supported when testing on NixOS. Is it really needed? If so add conditionals; e.g. if ! isTestOnNixOS; then ..."
fi
# Dont fail trying to stop a non-existant daemon twice
# Don't fail trying to stop a non-existant daemon twice.
if [[ "${_NIX_TEST_DAEMON_PID-}" == '' ]]; then
return
fi
@@ -277,7 +281,7 @@ assertStderr() {
needLocalStore() {
if [[ "$NIX_REMOTE" == "daemon" ]]; then
skipTest "Cant run through the daemon ($1)"
skipTest "Can't run through the daemon ($1)"
fi
}

View File

@@ -1,4 +1,6 @@
{ hashInvalidator ? "" }:
{
hashInvalidator ? "",
}:
with import ./config.nix;
let

View File

@@ -2,5 +2,8 @@ derivation {
name = "advanced-attributes-defaults";
system = "my-system";
builder = "/bin/bash";
args = [ "-c" "echo hello > $out" ];
args = [
"-c"
"echo hello > $out"
];
}

View File

@@ -2,7 +2,13 @@ derivation {
name = "advanced-attributes-structured-attrs-defaults";
system = "my-system";
builder = "/bin/bash";
args = [ "-c" "echo hello > $out" ];
outputs = [ "out" "dev" ];
args = [
"-c"
"echo hello > $out"
];
outputs = [
"out"
"dev"
];
__structuredAttrs = true;
}

View File

@@ -4,42 +4,58 @@ let
inherit system;
name = "foo";
builder = "/bin/bash";
args = ["-c" "echo foo > $out"];
args = [
"-c"
"echo foo > $out"
];
};
bar = derivation {
inherit system;
name = "bar";
builder = "/bin/bash";
args = ["-c" "echo bar > $out"];
args = [
"-c"
"echo bar > $out"
];
};
in
derivation {
inherit system;
name = "advanced-attributes-structured-attrs";
builder = "/bin/bash";
args = [ "-c" "echo hello > $out" ];
args = [
"-c"
"echo hello > $out"
];
__sandboxProfile = "sandcastle";
__noChroot = true;
__impureHostDeps = ["/usr/bin/ditto"];
impureEnvVars = ["UNICORN"];
__impureHostDeps = [ "/usr/bin/ditto" ];
impureEnvVars = [ "UNICORN" ];
__darwinAllowLocalNetworking = true;
outputs = [ "out" "bin" "dev" ];
outputs = [
"out"
"bin"
"dev"
];
__structuredAttrs = true;
outputChecks = {
out = {
allowedReferences = [foo];
allowedRequisites = [foo];
allowedReferences = [ foo ];
allowedRequisites = [ foo ];
};
bin = {
disallowedReferences = [bar];
disallowedRequisites = [bar];
disallowedReferences = [ bar ];
disallowedRequisites = [ bar ];
};
dev = {
maxSize = 789;
maxClosureSize = 5909;
};
};
requiredSystemFeatures = ["rainbow" "uid-range"];
requiredSystemFeatures = [
"rainbow"
"uid-range"
];
preferLocalBuild = true;
allowSubstitutes = false;
}

View File

@@ -4,30 +4,42 @@ let
inherit system;
name = "foo";
builder = "/bin/bash";
args = ["-c" "echo foo > $out"];
args = [
"-c"
"echo foo > $out"
];
};
bar = derivation {
inherit system;
name = "bar";
builder = "/bin/bash";
args = ["-c" "echo bar > $out"];
args = [
"-c"
"echo bar > $out"
];
};
in
derivation {
inherit system;
name = "advanced-attributes";
builder = "/bin/bash";
args = [ "-c" "echo hello > $out" ];
args = [
"-c"
"echo hello > $out"
];
__sandboxProfile = "sandcastle";
__noChroot = true;
__impureHostDeps = ["/usr/bin/ditto"];
impureEnvVars = ["UNICORN"];
__impureHostDeps = [ "/usr/bin/ditto" ];
impureEnvVars = [ "UNICORN" ];
__darwinAllowLocalNetworking = true;
allowedReferences = [foo];
allowedRequisites = [foo];
disallowedReferences = [bar];
disallowedRequisites = [bar];
requiredSystemFeatures = ["rainbow" "uid-range"];
allowedReferences = [ foo ];
allowedRequisites = [ foo ];
disallowedReferences = [ bar ];
disallowedRequisites = [ bar ];
requiredSystemFeatures = [
"rainbow"
"uid-range"
];
preferLocalBuild = true;
allowSubstitutes = false;
}

View File

@@ -1,6 +1,8 @@
with import ./config.nix;
let innerName = "foo"; in
let
innerName = "foo";
in
mkDerivation rec {
name = "${innerName}.drv";

View File

@@ -2,28 +2,33 @@ with import ./config.nix;
rec {
printRefs =
''
echo $exportReferencesGraph
while read path; do
read drv
read nrRefs
echo "$path has $nrRefs references"
echo "$path" >> $out
for ((n = 0; n < $nrRefs; n++)); do read ref; echo "ref $ref"; test -e "$ref"; done
done < refs
'';
printRefs = ''
echo $exportReferencesGraph
while read path; do
read drv
read nrRefs
echo "$path has $nrRefs references"
echo "$path" >> $out
for ((n = 0; n < $nrRefs; n++)); do read ref; echo "ref $ref"; test -e "$ref"; done
done < refs
'';
foo."bar.runtimeGraph" = mkDerivation {
name = "dependencies";
builder = builtins.toFile "build-graph-builder" "${printRefs}";
exportReferencesGraph = ["refs" (import ./dependencies.nix {})];
exportReferencesGraph = [
"refs"
(import ./dependencies.nix { })
];
};
foo."bar.buildGraph" = mkDerivation {
name = "dependencies";
builder = builtins.toFile "build-graph-builder" "${printRefs}";
exportReferencesGraph = ["refs" (import ./dependencies.nix {}).drvPath];
exportReferencesGraph = [
"refs"
(import ./dependencies.nix { }).drvPath
];
};
}

View File

@@ -2,16 +2,29 @@
with import ./config.nix;
let
mkDerivation = args:
derivation ({
inherit system;
builder = busybox;
args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" ''
if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi;
eval "$buildCommand"
'')];
} // removeAttrs args ["builder" "meta"])
// { meta = args.meta or {}; };
mkDerivation =
args:
derivation (
{
inherit system;
builder = busybox;
args = [
"sh"
"-e"
args.builder or (builtins.toFile "builder-${args.name}.sh" ''
if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi;
eval "$buildCommand"
'')
];
}
// removeAttrs args [
"builder"
"meta"
]
)
// {
meta = args.meta or { };
};
in
{

View File

@@ -4,9 +4,12 @@ mkDerivation {
name = "filter";
builder = builtins.toFile "builder" "ln -s $input $out";
input =
let filter = path: type:
type != "symlink"
&& baseNameOf path != "foo"
&& !((import ./lang/lib.nix).hasSuffix ".bak" (baseNameOf path));
in builtins.filterSource filter ((builtins.getEnv "TEST_ROOT") + "/filterin");
let
filter =
path: type:
type != "symlink"
&& baseNameOf path != "foo"
&& !((import ./lang/lib.nix).hasSuffix ".bak" (baseNameOf path));
in
builtins.filterSource filter ((builtins.getEnv "TEST_ROOT") + "/filterin");
}

View File

@@ -2,15 +2,20 @@ with import ./config.nix;
rec {
f2 = dummy: builder: mode: algo: hash: mkDerivation {
name = "fixed";
inherit builder;
outputHashMode = mode;
outputHashAlgo = algo;
outputHash = hash;
inherit dummy;
impureEnvVars = ["IMPURE_VAR1" "IMPURE_VAR2"];
};
f2 =
dummy: builder: mode: algo: hash:
mkDerivation {
name = "fixed";
inherit builder;
outputHashMode = mode;
outputHashAlgo = algo;
outputHash = hash;
inherit dummy;
impureEnvVars = [
"IMPURE_VAR1"
"IMPURE_VAR2"
];
};
f = f2 "";
@@ -37,7 +42,8 @@ rec {
];
sameAsAdd =
f ./fixed.builder2.sh "recursive" "sha256" "1ixr6yd3297ciyp9im522dfxpqbkhcw0pylkb2aab915278fqaik";
f ./fixed.builder2.sh "recursive" "sha256"
"1ixr6yd3297ciyp9im522dfxpqbkhcw0pylkb2aab915278fqaik";
bad = [
(f ./fixed.builder1.sh "flat" "md5" "0ddd8be4b179a529afa5f2ffae4b9858")

View File

@@ -2,38 +2,34 @@ with import ./config.nix;
rec {
x1 = mkDerivation {
name = "x1";
builder = builtins.toFile "builder.sh"
''
echo $name > $out
'';
builder = builtins.toFile "builder.sh" ''
echo $name > $out
'';
outputHashMode = "recursive";
outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
x2 = mkDerivation {
name = "x2";
builder = builtins.toFile "builder.sh"
''
echo $name > $out
'';
builder = builtins.toFile "builder.sh" ''
echo $name > $out
'';
outputHashMode = "recursive";
outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
x3 = mkDerivation {
name = "x3";
builder = builtins.toFile "builder.sh"
''
echo $name > $out
'';
builder = builtins.toFile "builder.sh" ''
echo $name > $out
'';
outputHashMode = "recursive";
outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
x4 = mkDerivation {
name = "x4";
inherit x2 x3;
builder = builtins.toFile "builder.sh"
''
echo $x2 $x3
exit 1
'';
builder = builtins.toFile "builder.sh" ''
echo $x2 $x3
exit 1
'';
};
}

View File

@@ -1,6 +1,8 @@
with import ./config.nix;
{ lockFifo ? null }:
{
lockFifo ? null,
}:
rec {

2
tests/functional/git-hashing/simple.sh Normal file → Executable file
View File

@@ -1,3 +1,5 @@
#!/usr/bin/env bash
source common.sh
repo="$TEST_ROOT/scratch"

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