mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-24 23:06:16 +02:00
Merge remote-tracking branch 'nixos/master'
This commit is contained in:
commit
9080d4c520
46 changed files with 670 additions and 153 deletions
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
name: Missing or incorrect documentation
|
||||
about:
|
||||
about: Help us improve the reference manual
|
||||
title: ''
|
||||
labels: 'documentation'
|
||||
labels: documentation
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
|
|
@ -1,97 +1,114 @@
|
|||
{ command }:
|
||||
{ toplevel }:
|
||||
|
||||
with builtins;
|
||||
with import ./utils.nix;
|
||||
|
||||
let
|
||||
|
||||
showCommand =
|
||||
{ command, def, filename }:
|
||||
''
|
||||
**Warning**: This program is **experimental** and its interface is subject to change.
|
||||
''
|
||||
+ "# Name\n\n"
|
||||
+ "`${command}` - ${def.description}\n\n"
|
||||
+ "# Synopsis\n\n"
|
||||
+ showSynopsis { inherit command; args = def.args; }
|
||||
+ (if def.commands or {} != {}
|
||||
then
|
||||
let
|
||||
categories = sort (x: y: x.id < y.id) (unique (map (cmd: cmd.category) (attrValues def.commands)));
|
||||
listCommands = cmds:
|
||||
concatStrings (map (name:
|
||||
"* "
|
||||
+ "[`${command} ${name}`](./${appendName filename name}.md)"
|
||||
+ " - ${cmds.${name}.description}\n")
|
||||
(attrNames cmds));
|
||||
in
|
||||
"where *subcommand* is one of the following:\n\n"
|
||||
# FIXME: group by category
|
||||
+ (if length categories > 1
|
||||
then
|
||||
concatStrings (map
|
||||
(cat:
|
||||
"**${toString cat.description}:**\n\n"
|
||||
+ listCommands (filterAttrs (n: v: v.category == cat) def.commands)
|
||||
+ "\n"
|
||||
) categories)
|
||||
+ "\n"
|
||||
else
|
||||
listCommands def.commands
|
||||
+ "\n")
|
||||
else "")
|
||||
+ (if def ? doc
|
||||
then def.doc + "\n\n"
|
||||
else "")
|
||||
+ (let s = showOptions def.flags; in
|
||||
if s != ""
|
||||
then "# Options\n\n${s}"
|
||||
else "")
|
||||
;
|
||||
showCommand = { command, details, filename, toplevel }:
|
||||
let
|
||||
result = ''
|
||||
> **Warning** \
|
||||
> This program is **experimental** and its interface is subject to change.
|
||||
|
||||
# Name
|
||||
|
||||
`${command}` - ${details.description}
|
||||
|
||||
# Synopsis
|
||||
|
||||
${showSynopsis command details.args}
|
||||
|
||||
${maybeSubcommands}
|
||||
|
||||
${maybeDocumentation}
|
||||
|
||||
${maybeOptions}
|
||||
'';
|
||||
showSynopsis = command: args:
|
||||
let
|
||||
showArgument = arg: "*${arg.label}*" + (if arg ? arity then "" else "...");
|
||||
arguments = concatStringsSep " " (map showArgument args);
|
||||
in ''
|
||||
`${command}` [*option*...] ${arguments}
|
||||
'';
|
||||
maybeSubcommands = if details ? commands && details.commands != {}
|
||||
then ''
|
||||
where *subcommand* is one of the following:
|
||||
|
||||
${subcommands}
|
||||
''
|
||||
else "";
|
||||
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)));
|
||||
listCategories = concatStrings (map showCategory categories);
|
||||
showCategory = cat: ''
|
||||
**${toString cat.description}:**
|
||||
|
||||
${listSubcommands (filterAttrs (n: v: v.category == cat) details.commands)}
|
||||
'';
|
||||
listSubcommands = cmds: concatStrings (attrValues (mapAttrs showSubcommand cmds));
|
||||
showSubcommand = name: subcmd: ''
|
||||
* [`${command} ${name}`](./${appendName filename name}.md) - ${subcmd.description}
|
||||
'';
|
||||
maybeDocumentation = if details ? doc then details.doc else "";
|
||||
maybeOptions = if details.flags == {} then "" else ''
|
||||
# Options
|
||||
|
||||
${showOptions details.flags toplevel.flags}
|
||||
'';
|
||||
showOptions = options: commonOptions:
|
||||
let
|
||||
allOptions = options // commonOptions;
|
||||
showCategory = cat: ''
|
||||
${if cat != "" then "**${cat}:**" else ""}
|
||||
|
||||
${listOptions (filterAttrs (n: v: v.category == cat) allOptions)}
|
||||
'';
|
||||
listOptions = opts: concatStringsSep "\n" (attrValues (mapAttrs showOption opts));
|
||||
showOption = name: option:
|
||||
let
|
||||
shortName = if option ? shortName then "/ `-${option.shortName}`" else "";
|
||||
labels = if option ? labels then (concatStringsSep " " (map (s: "*${s}*") option.labels)) else "";
|
||||
in trim ''
|
||||
- `--${name}` ${shortName} ${labels}
|
||||
|
||||
${option.description}
|
||||
'';
|
||||
categories = sort builtins.lessThan (unique (map (cmd: cmd.category) (attrValues allOptions)));
|
||||
in concatStrings (map showCategory categories);
|
||||
in squash result;
|
||||
|
||||
appendName = filename: name: (if filename == "nix" then "nix3" else filename) + "-" + name;
|
||||
|
||||
showOptions = flags:
|
||||
processCommand = { command, details, filename, toplevel }:
|
||||
let
|
||||
categories = sort builtins.lessThan (unique (map (cmd: cmd.category) (attrValues flags)));
|
||||
in
|
||||
concatStrings (map
|
||||
(cat:
|
||||
(if cat != ""
|
||||
then "**${cat}:**\n\n"
|
||||
else "")
|
||||
+ concatStrings
|
||||
(map (longName:
|
||||
let
|
||||
flag = flags.${longName};
|
||||
in
|
||||
" - `--${longName}`"
|
||||
+ (if flag ? shortName then " / `-${flag.shortName}`" else "")
|
||||
+ (if flag ? labels then " " + (concatStringsSep " " (map (s: "*${s}*") flag.labels)) else "")
|
||||
+ " \n"
|
||||
+ " " + flag.description + "\n\n"
|
||||
) (attrNames (filterAttrs (n: v: v.category == cat) flags))))
|
||||
categories);
|
||||
cmd = {
|
||||
inherit command;
|
||||
name = filename + ".md";
|
||||
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 {});
|
||||
|
||||
showSynopsis =
|
||||
{ command, args }:
|
||||
"`${command}` [*option*...] ${concatStringsSep " "
|
||||
(map (arg: "*${arg.label}*" + (if arg ? arity then "" else "...")) args)}\n\n";
|
||||
parsedToplevel = builtins.fromJSON toplevel;
|
||||
manpages = processCommand {
|
||||
command = "nix";
|
||||
details = parsedToplevel;
|
||||
filename = "nix";
|
||||
toplevel = parsedToplevel;
|
||||
};
|
||||
|
||||
processCommand = { command, def, filename }:
|
||||
[ { name = filename + ".md"; value = showCommand { inherit command def filename; }; inherit command; } ]
|
||||
++ concatMap
|
||||
(name: processCommand {
|
||||
filename = appendName filename name;
|
||||
command = command + " " + name;
|
||||
def = def.commands.${name};
|
||||
})
|
||||
(attrNames def.commands or {});
|
||||
tableOfContents = let
|
||||
showEntry = page:
|
||||
" - [${page.command}](command-ref/new-cli/${page.name})";
|
||||
in concatStringsSep "\n" (map showEntry manpages) + "\n";
|
||||
|
||||
in
|
||||
|
||||
let
|
||||
manpages = processCommand { filename = "nix"; command = "nix"; def = builtins.fromJSON command; };
|
||||
summary = concatStrings (map (manpage: " - [${manpage.command}](command-ref/new-cli/${manpage.name})\n") manpages);
|
||||
in
|
||||
(listToAttrs manpages) // { "SUMMARY.md" = summary; }
|
||||
in (listToAttrs manpages) // { "SUMMARY.md" = tableOfContents; }
|
||||
|
|
|
@ -50,7 +50,7 @@ $(d)/src/SUMMARY.md: $(d)/src/SUMMARY.md.in $(d)/src/command-ref/new-cli
|
|||
|
||||
$(d)/src/command-ref/new-cli: $(d)/nix.json $(d)/generate-manpage.nix $(bindir)/nix
|
||||
@rm -rf $@
|
||||
$(trace-gen) $(nix-eval) --write-to $@ --expr 'import doc/manual/generate-manpage.nix { command = builtins.readFile $<; }'
|
||||
$(trace-gen) $(nix-eval) --write-to $@ --expr 'import doc/manual/generate-manpage.nix { toplevel = builtins.readFile $<; }'
|
||||
|
||||
$(d)/src/command-ref/conf-file.md: $(d)/conf-file.json $(d)/generate-options.nix $(d)/src/command-ref/conf-file-prefix.md $(bindir)/nix
|
||||
@cat doc/manual/src/command-ref/conf-file-prefix.md > $@.tmp
|
||||
|
|
|
@ -30,8 +30,8 @@ Since `nix-copy-closure` calls `ssh`, you may be asked to type in the
|
|||
appropriate password or passphrase. In fact, you may be asked _twice_
|
||||
because `nix-copy-closure` currently connects twice to the remote
|
||||
machine, first to get the set of paths missing on the target machine,
|
||||
and second to send the dump of those paths. If this bothers you, use
|
||||
`ssh-agent`.
|
||||
and second to send the dump of those paths. When using public key
|
||||
authentication, you can avoid typing the passphrase with `ssh-agent`.
|
||||
|
||||
# Options
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ $ nix develop
|
|||
```
|
||||
|
||||
To get a shell with a different compilation environment (e.g. stdenv,
|
||||
gccStdenv, clangStdenv, clang11Stdenv):
|
||||
gccStdenv, clangStdenv, clang11Stdenv, ccacheStdenv):
|
||||
|
||||
```console
|
||||
$ nix-shell -A devShells.x86_64-linux.clang11StdenvPackages
|
||||
|
@ -54,6 +54,9 @@ or if you have a flake-enabled nix:
|
|||
$ nix develop .#clang11StdenvPackages
|
||||
```
|
||||
|
||||
Note: you can use `ccacheStdenv` to drastically improve rebuild
|
||||
time. By default, ccache keeps artifacts in `~/.cache/ccache/`.
|
||||
|
||||
To build Nix itself in this shell:
|
||||
|
||||
```console
|
||||
|
@ -83,9 +86,7 @@ by:
|
|||
$ nix develop
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Nix comes with three different flavors of tests: unit, functional and integration.
|
||||
## Running tests
|
||||
|
||||
### Unit-tests
|
||||
|
||||
|
@ -108,3 +109,72 @@ These tests include everything that needs to interact with external services or
|
|||
Because these tests are expensive and require more than what the standard github-actions setup provides, they only run on the master branch (on <https://hydra.nixos.org/jobset/nix/master>).
|
||||
|
||||
You can run them manually with `nix build .#hydraJobs.tests.{testName}` or `nix-build -A hydraJobs.tests.{testName}`
|
||||
|
||||
### Installer tests
|
||||
|
||||
After a one-time setup, the Nix repository's GitHub Actions continuous integration (CI) workflow can test the installer each time you push to a branch.
|
||||
|
||||
Creating a Cachix cache for your installer tests and adding its authorization token to GitHub enables [two installer-specific jobs in the CI workflow](https://github.com/NixOS/nix/blob/88a45d6149c0e304f6eb2efcc2d7a4d0d569f8af/.github/workflows/ci.yml#L50-L91):
|
||||
|
||||
- The `installer` job generates installers for the platforms below and uploads them to your Cachix cache:
|
||||
- `x86_64-linux`
|
||||
- `armv6l-linux`
|
||||
- `armv7l-linux`
|
||||
- `x86_64-darwin`
|
||||
|
||||
- The `installer_test` job (which runs on `ubuntu-latest` and `macos-latest`) will try to install Nix with the cached installer and run a trivial Nix command.
|
||||
|
||||
#### One-time setup
|
||||
|
||||
1. Have a GitHub account with a fork of the [Nix repository](https://github.com/NixOS/nix).
|
||||
2. At cachix.org:
|
||||
- Create or log in to an account.
|
||||
- Create a Cachix cache using the format `<github-username>-nix-install-tests`.
|
||||
- Navigate to the new cache > Settings > Auth Tokens.
|
||||
- Generate a new Cachix auth token and copy the generated value.
|
||||
3. At github.com:
|
||||
- Navigate to your Nix fork > Settings > Secrets > Actions > New repository secret.
|
||||
- Name the secret `CACHIX_AUTH_TOKEN`.
|
||||
- Paste the copied value of the Cachix cache auth token.
|
||||
|
||||
#### Using the CI-generated installer for manual testing
|
||||
|
||||
After the CI run completes, you can check the output to extract the installer URL:
|
||||
1. Click into the detailed view of the CI run.
|
||||
2. Click into any `installer_test` run (the URL you're here to extract will be the same in all of them).
|
||||
3. Click into the `Run cachix/install-nix-action@v...` step and click the detail triangle next to the first log line (it will also be `Run cachix/install-nix-action@v...`)
|
||||
4. Copy the value of `install_url`
|
||||
5. To generate an install command, plug this `install_url` and your GitHub username into this template:
|
||||
|
||||
```console
|
||||
sh <(curl -L <install_url>) --tarball-url-prefix https://<github-username>-nix-install-tests.cachix.org/serve
|
||||
```
|
||||
|
||||
<!-- #### Manually generating test installers
|
||||
|
||||
There's obviously a manual way to do this, and it's still the only way for
|
||||
platforms that lack GA runners.
|
||||
|
||||
I did do this back in Fall 2020 (before the GA approach encouraged here). I'll
|
||||
sketch what I recall in case it encourages someone to fill in detail, but: I
|
||||
didn't know what I was doing at the time and had to fumble/ask around a lot--
|
||||
so I don't want to uphold any of it as "right". It may have been dumb or
|
||||
the _hard_ way from the getgo. Fundamentals may have changed since.
|
||||
|
||||
Here's the build command I used to do this on and for x86_64-darwin:
|
||||
nix build --out-link /tmp/foo ".#checks.x86_64-darwin.binaryTarball"
|
||||
|
||||
I used the stable out-link to make it easier to script the next steps:
|
||||
link=$(readlink /tmp/foo)
|
||||
cp $link/*-darwin.tar.xz ~/somewheres
|
||||
|
||||
I've lost the last steps and am just going from memory:
|
||||
|
||||
From here, I think I had to extract and modify the `install` script to point
|
||||
it at this tarball (which I scped to my own site, but it might make more sense
|
||||
to just share them locally). I extracted this script once and then just
|
||||
search/replaced in it for each new build.
|
||||
|
||||
The installer now supports a `--tarball-url-prefix` flag which _may_ have
|
||||
solved this need?
|
||||
-->
|
||||
|
|
|
@ -7,10 +7,44 @@
|
|||
translated into low-level *store derivations* (implicitly by
|
||||
`nix-env` and `nix-build`, or explicitly by `nix-instantiate`).
|
||||
|
||||
- [content-addressed derivation]{#gloss-content-addressed-derivation}\
|
||||
A derivation which has the
|
||||
[`__contentAddressed`](language/advanced-attributes.md#adv-attr-__contentAddressed)
|
||||
attribute set to `true`.
|
||||
|
||||
- [fixed-output derivation]{#gloss-fixed-output-derivation}\
|
||||
A derivation which includes the
|
||||
[`outputHash`](language/advanced-attributes.md#adv-attr-outputHash) attribute.
|
||||
|
||||
- [store]{#gloss-store}\
|
||||
The location in the file system where store objects live. Typically
|
||||
`/nix/store`.
|
||||
|
||||
From the perspective of the location where Nix is
|
||||
invoked, the Nix store can be referred to
|
||||
as a "_local_" or a "_remote_" one:
|
||||
|
||||
+ A *local store* exists on the filesystem of
|
||||
the machine where Nix is invoked. You can use other
|
||||
local stores by passing the `--store` flag to the
|
||||
`nix` command. Local stores can be used for building derivations.
|
||||
|
||||
+ A *remote store* exists anywhere other than the
|
||||
local filesystem. One example is the `/nix/store`
|
||||
directory on another machine, accessed via `ssh` or
|
||||
served by the `nix-serve` Perl script.
|
||||
|
||||
- [chroot store]{#gloss-chroot-store}\
|
||||
A local store whose canonical path is anything other than `/nix/store`.
|
||||
|
||||
- [binary cache]{#gloss-binary-cache}\
|
||||
A *binary cache* is a Nix store which uses a different format: its
|
||||
metadata and signatures are kept in `.narinfo` files rather than in a
|
||||
Nix database. This different format simplifies serving store objects
|
||||
over the network, but cannot host builds. Examples of binary caches
|
||||
include S3 buckets and the [NixOS binary
|
||||
cache](https://cache.nixos.org).
|
||||
|
||||
- [store path]{#gloss-store-path}\
|
||||
The location in the file system of a store object, i.e., an
|
||||
immediate child of the Nix store directory.
|
||||
|
@ -22,6 +56,19 @@
|
|||
derivation outputs (objects produced by running a build action), or
|
||||
derivations (files describing a build action).
|
||||
|
||||
- [input-addressed store object]{#gloss-input-addressed-store-object}\
|
||||
A store object produced by building a
|
||||
non-[content-addressed](#gloss-content-addressed-derivation),
|
||||
non-[fixed-output](#gloss-fixed-output-derivation)
|
||||
derivation.
|
||||
|
||||
- [output-addressed store object]{#gloss-output-addressed-store-object}\
|
||||
A store object whose store path hashes its content. This
|
||||
includes derivations, the outputs of
|
||||
[content-addressed derivations](#gloss-content-addressed-derivation),
|
||||
and the outputs of
|
||||
[fixed-output derivations](#gloss-fixed-output-derivation).
|
||||
|
||||
- [substitute]{#gloss-substitute}\
|
||||
A substitute is a command invocation stored in the Nix database that
|
||||
describes how to build a store object, bypassing the normal build
|
||||
|
@ -29,6 +76,11 @@
|
|||
store object by downloading a pre-built version of the store object
|
||||
from some server.
|
||||
|
||||
- [substituter]{#gloss-substituter}\
|
||||
A *substituter* is an additional store from which Nix will
|
||||
copy store objects it doesn't have. For details, see the
|
||||
[`substituters` option](command-ref/conf-file.html#conf-substituters).
|
||||
|
||||
- [purity]{#gloss-purity}\
|
||||
The assumption that equal Nix derivations when run always produce
|
||||
the same output. This cannot be guaranteed in general (e.g., a
|
||||
|
|
|
@ -5,6 +5,32 @@ rec {
|
|||
|
||||
concatStrings = concatStringsSep "";
|
||||
|
||||
replaceStringsRec = from: to: string:
|
||||
# recursively replace occurrences of `from` with `to` within `string`
|
||||
# example:
|
||||
# replaceStringRec "--" "-" "hello-----world"
|
||||
# => "hello-world"
|
||||
let
|
||||
replaced = replaceStrings [ from ] [ to ] string;
|
||||
in
|
||||
if replaced == string then string else replaceStringsRec from to replaced;
|
||||
|
||||
squash = replaceStringsRec "\n\n\n" "\n\n";
|
||||
|
||||
trim = string:
|
||||
# trim trailing spaces and squash non-leading spaces
|
||||
let
|
||||
trimLine = line:
|
||||
let
|
||||
# separate leading spaces from the rest
|
||||
parts = split "(^ *)" line;
|
||||
spaces = head (elemAt parts 1);
|
||||
rest = elemAt parts 2;
|
||||
# drop trailing spaces
|
||||
body = head (split " *$" rest);
|
||||
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 ]) [];
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ let
|
|||
|
||||
root = {
|
||||
uid = 0;
|
||||
shell = "/bin/bash";
|
||||
shell = "${pkgs.bashInteractive}/bin/bash";
|
||||
home = "/root";
|
||||
gid = 0;
|
||||
};
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
crossSystems = [ "armv6l-linux" "armv7l-linux" ];
|
||||
|
||||
stdenvs = [ "gccStdenv" "gcc10Stdenv" "clangStdenv" "clang11Stdenv" "stdenv" "libcxxStdenv" ];
|
||||
stdenvs = [ "gccStdenv" "clangStdenv" "clang11Stdenv" "stdenv" "libcxxStdenv" "ccacheStdenv" ];
|
||||
|
||||
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system);
|
||||
forAllSystemsAndStdenvs = f: forAllSystems (system:
|
||||
|
@ -546,6 +546,11 @@
|
|||
# againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable;
|
||||
} "touch $out");
|
||||
|
||||
installerTests = import ./tests/installer {
|
||||
binaryTarballs = self.hydraJobs.binaryTarball;
|
||||
inherit nixpkgsFor;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
checks = forAllSystems (system: {
|
||||
|
|
|
@ -40,12 +40,12 @@ case "$(uname -s).$(uname -m)" in
|
|||
path=@tarballPath_aarch64-linux@
|
||||
system=aarch64-linux
|
||||
;;
|
||||
Linux.armv6l_linux)
|
||||
Linux.armv6l)
|
||||
hash=@tarballHash_armv6l-linux@
|
||||
path=@tarballPath_armv6l-linux@
|
||||
system=armv6l-linux
|
||||
;;
|
||||
Linux.armv7l_linux)
|
||||
Linux.armv7l)
|
||||
hash=@tarballHash_armv7l-linux@
|
||||
path=@tarballPath_armv7l-linux@
|
||||
system=armv7l-linux
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Only execute this file once per shell.
|
||||
if test -n "$__ETC_PROFILE_NIX_SOURCED"
|
||||
return
|
||||
exit
|
||||
end
|
||||
|
||||
set __ETC_PROFILE_NIX_SOURCED 1
|
||||
|
|
|
@ -88,7 +88,8 @@ EvalCommand::EvalCommand()
|
|||
{
|
||||
addFlag({
|
||||
.longName = "debugger",
|
||||
.description = "start an interactive environment if evaluation fails",
|
||||
.description = "Start an interactive environment if evaluation fails.",
|
||||
.category = MixEvalArgs::category,
|
||||
.handler = {&startReplOnEvalErrors, true},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@ namespace nix {
|
|||
|
||||
MixEvalArgs::MixEvalArgs()
|
||||
{
|
||||
auto category = "Common evaluation options";
|
||||
|
||||
addFlag({
|
||||
.longName = "arg",
|
||||
.description = "Pass the value *expr* as the argument *name* to Nix functions.",
|
||||
|
|
|
@ -10,6 +10,8 @@ class Bindings;
|
|||
|
||||
struct MixEvalArgs : virtual Args
|
||||
{
|
||||
static constexpr auto category = "Common evaluation options";
|
||||
|
||||
MixEvalArgs();
|
||||
|
||||
Bindings * getAutoArgs(EvalState & state);
|
||||
|
|
|
@ -242,7 +242,11 @@ void NixRepl::mainLoop()
|
|||
|
||||
// Allow nix-repl specific settings in .inputrc
|
||||
rl_readline_name = "nix-repl";
|
||||
createDirs(dirOf(historyFile));
|
||||
try {
|
||||
createDirs(dirOf(historyFile));
|
||||
} catch (SysError & e) {
|
||||
logWarning(e.info());
|
||||
}
|
||||
#ifndef READLINE
|
||||
el_hist_size = 1000;
|
||||
#endif
|
||||
|
@ -1046,7 +1050,7 @@ struct CmdRepl : InstallablesCommand
|
|||
evalSettings.pureEval = false;
|
||||
}
|
||||
|
||||
void prepare()
|
||||
void prepare() override
|
||||
{
|
||||
if (!settings.isExperimentalFeatureEnabled(Xp::ReplFlake) && !(file) && this->_installables.size() >= 1) {
|
||||
warn("future versions of Nix will require using `--file` to load a file");
|
||||
|
|
|
@ -68,7 +68,7 @@ void ConfigFile::apply()
|
|||
}
|
||||
}
|
||||
if (!trusted) {
|
||||
warn("ignoring untrusted flake configuration setting '%s'", name);
|
||||
warn("ignoring untrusted flake configuration setting '%s'.\nPass '%s' to trust it", name, "--accept-flake-config");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -483,12 +483,12 @@ LockedFlake lockFlake(
|
|||
} else if (auto follows = std::get_if<1>(&i.second)) {
|
||||
if (! trustLock) {
|
||||
// It is possible that the flake has changed,
|
||||
// so we must confirm all the follows that are in the lockfile are also in the flake.
|
||||
// so we must confirm all the follows that are in the lock file are also in the flake.
|
||||
auto overridePath(inputPath);
|
||||
overridePath.push_back(i.first);
|
||||
auto o = overrides.find(overridePath);
|
||||
// If the override disappeared, we have to refetch the flake,
|
||||
// since some of the inputs may not be present in the lockfile.
|
||||
// since some of the inputs may not be present in the lock file.
|
||||
if (o == overrides.end()) {
|
||||
mustRefetch = true;
|
||||
// There's no point populating the rest of the fake inputs,
|
||||
|
|
|
@ -36,7 +36,7 @@ LockedNode::LockedNode(const nlohmann::json & json)
|
|||
, isFlake(json.find("flake") != json.end() ? (bool) json["flake"] : true)
|
||||
{
|
||||
if (!lockedRef.input.isLocked())
|
||||
throw Error("lockfile contains mutable lock '%s'",
|
||||
throw Error("lock file contains mutable lock '%s'",
|
||||
fetchers::attrsToJSON(lockedRef.input.toAttrs()));
|
||||
}
|
||||
|
||||
|
|
|
@ -2454,8 +2454,8 @@ static RegisterPrimOp primop_intersectAttrs({
|
|||
.name = "__intersectAttrs",
|
||||
.args = {"e1", "e2"},
|
||||
.doc = R"(
|
||||
Return a set consisting of the attributes in the set *e2* that also
|
||||
exist in the set *e1*.
|
||||
Return a set consisting of the attributes in the set *e2* which have the
|
||||
same name as some attribute in *e1*.
|
||||
)",
|
||||
.fun = prim_intersectAttrs,
|
||||
});
|
||||
|
@ -3821,8 +3821,8 @@ static RegisterPrimOp primop_parseDrvName({
|
|||
.args = {"s"},
|
||||
.doc = R"(
|
||||
Split the string *s* into a package name and version. The package
|
||||
name is everything up to but not including the first dash followed
|
||||
by a digit, and the version is everything following that dash. The
|
||||
name is everything up to but not including the first dash not followed
|
||||
by a letter, and the version is everything following that dash. The
|
||||
result is returned in a set `{ name, version }`. Thus,
|
||||
`builtins.parseDrvName "nix-0.12pre12876"` returns `{ name =
|
||||
"nix"; version = "0.12pre12876"; }`.
|
||||
|
|
|
@ -32,6 +32,7 @@ MixCommonArgs::MixCommonArgs(const std::string & programName)
|
|||
addFlag({
|
||||
.longName = "option",
|
||||
.description = "Set the Nix configuration setting *name* to *value* (overriding `nix.conf`).",
|
||||
.category = miscCategory,
|
||||
.labels = {"name", "value"},
|
||||
.handler = {[](std::string name, std::string value) {
|
||||
try {
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace nix {
|
|||
|
||||
//static constexpr auto commonArgsCategory = "Miscellaneous common options";
|
||||
static constexpr auto loggingCategory = "Logging-related options";
|
||||
static constexpr auto miscCategory = "Miscellaneous global options";
|
||||
|
||||
class MixCommonArgs : public virtual Args
|
||||
{
|
||||
|
|
|
@ -503,7 +503,7 @@ public:
|
|||
return s[0];
|
||||
}
|
||||
|
||||
virtual void setPrintBuildLogs(bool printBuildLogs)
|
||||
void setPrintBuildLogs(bool printBuildLogs) override
|
||||
{
|
||||
this->printBuildLogs = printBuildLogs;
|
||||
}
|
||||
|
|
|
@ -113,5 +113,25 @@ struct PrintFreed
|
|||
/* Install a SIGSEGV handler to detect stack overflows. */
|
||||
void detectStackOverflow();
|
||||
|
||||
/* Pluggable behavior to run in case of a stack overflow.
|
||||
|
||||
Default value: defaultStackOverflowHandler.
|
||||
|
||||
This is called by the handler installed by detectStackOverflow().
|
||||
|
||||
This gives Nix library consumers a limit opportunity to report the error
|
||||
condition. The handler should exit the process.
|
||||
See defaultStackOverflowHandler() for a reference implementation.
|
||||
|
||||
NOTE: Use with diligence, because this runs in the signal handler, with very
|
||||
limited stack space and a potentially a corrupted heap, all while the failed
|
||||
thread is blocked indefinitely. All functions called must be reentrant. */
|
||||
extern std::function<void(siginfo_t * info, void * ctx)> stackOverflowHandler;
|
||||
|
||||
/* The default, robust implementation of stackOverflowHandler.
|
||||
|
||||
Prints an error message directly to stderr using a syscall instead of the
|
||||
logger. Exits the process immediately after. */
|
||||
void defaultStackOverflowHandler(siginfo_t * info, void * ctx);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "error.hh"
|
||||
#include "shared.hh"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstddef>
|
||||
|
@ -29,9 +30,7 @@ static void sigsegvHandler(int signo, siginfo_t * info, void * ctx)
|
|||
ptrdiff_t diff = (char *) info->si_addr - sp;
|
||||
if (diff < 0) diff = -diff;
|
||||
if (diff < 4096) {
|
||||
char msg[] = "error: stack overflow (possible infinite recursion)\n";
|
||||
[[gnu::unused]] auto res = write(2, msg, strlen(msg));
|
||||
_exit(1); // maybe abort instead?
|
||||
nix::stackOverflowHandler(info, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,5 +66,12 @@ void detectStackOverflow()
|
|||
#endif
|
||||
}
|
||||
|
||||
std::function<void(siginfo_t * info, void * ctx)> stackOverflowHandler(defaultStackOverflowHandler);
|
||||
|
||||
void defaultStackOverflowHandler(siginfo_t * info, void * ctx) {
|
||||
char msg[] = "error: stack overflow (possible infinite recursion)\n";
|
||||
[[gnu::unused]] auto res = write(2, msg, strlen(msg));
|
||||
_exit(1); // maybe abort instead?
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1594,6 +1594,8 @@ void LocalDerivationGoal::runChild()
|
|||
/* Warning: in the child we should absolutely not make any SQLite
|
||||
calls! */
|
||||
|
||||
bool sendException = true;
|
||||
|
||||
try { /* child */
|
||||
|
||||
commonChildInit(builderOut);
|
||||
|
@ -2050,6 +2052,8 @@ void LocalDerivationGoal::runChild()
|
|||
/* Indicate that we managed to set up the build environment. */
|
||||
writeFull(STDERR_FILENO, std::string("\2\n"));
|
||||
|
||||
sendException = false;
|
||||
|
||||
/* Execute the program. This should not return. */
|
||||
if (drv->isBuiltin()) {
|
||||
try {
|
||||
|
@ -2103,10 +2107,13 @@ void LocalDerivationGoal::runChild()
|
|||
throw SysError("executing '%1%'", drv->builder);
|
||||
|
||||
} catch (Error & e) {
|
||||
writeFull(STDERR_FILENO, "\1\n");
|
||||
FdSink sink(STDERR_FILENO);
|
||||
sink << e;
|
||||
sink.flush();
|
||||
if (sendException) {
|
||||
writeFull(STDERR_FILENO, "\1\n");
|
||||
FdSink sink(STDERR_FILENO);
|
||||
sink << e;
|
||||
sink.flush();
|
||||
} else
|
||||
std::cerr << e.msg();
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,6 +239,8 @@ struct ClientSettings
|
|||
else if (trusted
|
||||
|| name == settings.buildTimeout.name
|
||||
|| name == settings.buildRepeat.name
|
||||
|| name == settings.maxSilentTime.name
|
||||
|| name == settings.pollInterval.name
|
||||
|| name == "connect-timeout"
|
||||
|| (name == "builders" && value == ""))
|
||||
settings.set(name, value);
|
||||
|
|
|
@ -322,7 +322,6 @@ struct curlFileTransfer : public FileTransfer
|
|||
}
|
||||
|
||||
if (request.verifyTLS) {
|
||||
debug("verify TLS: Nix CA file = '%s'", settings.caFile);
|
||||
if (settings.caFile != "")
|
||||
curl_easy_setopt(req, CURLOPT_CAINFO, settings.caFile.c_str());
|
||||
} else {
|
||||
|
|
|
@ -154,13 +154,9 @@ StringSet Settings::getDefaultExtraPlatforms()
|
|||
// machines. Note that we can’t force processes from executing
|
||||
// x86_64 in aarch64 environments or vice versa since they can
|
||||
// always exec with their own binary preferences.
|
||||
if (pathExists("/Library/Apple/System/Library/LaunchDaemons/com.apple.oahd.plist") ||
|
||||
pathExists("/System/Library/LaunchDaemons/com.apple.oahd.plist")) {
|
||||
if (std::string{SYSTEM} == "x86_64-darwin")
|
||||
extraPlatforms.insert("aarch64-darwin");
|
||||
else if (std::string{SYSTEM} == "aarch64-darwin")
|
||||
extraPlatforms.insert("x86_64-darwin");
|
||||
}
|
||||
if (std::string{SYSTEM} == "aarch64-darwin" &&
|
||||
runProgram(RunOptions {.program = "arch", .args = {"-arch", "x86_64", "/usr/bin/true"}, .mergeStderrToStdout = true}).first == 0)
|
||||
extraPlatforms.insert("x86_64-darwin");
|
||||
#endif
|
||||
|
||||
return extraPlatforms;
|
||||
|
|
|
@ -560,9 +560,15 @@ public:
|
|||
R"(
|
||||
If set to `true` (the default), any non-content-addressed path added
|
||||
or copied to the Nix store (e.g. when substituting from a binary
|
||||
cache) must have a valid signature, that is, be signed using one of
|
||||
the keys listed in `trusted-public-keys` or `secret-key-files`. Set
|
||||
to `false` to disable signature checking.
|
||||
cache) must have a signature by a trusted key. A trusted key is one
|
||||
listed in `trusted-public-keys`, or a public key counterpart to a
|
||||
private key stored in a file listed in `secret-key-files`.
|
||||
|
||||
Set to `false` to disable signature checking and trust all
|
||||
non-content-addressed paths unconditionally.
|
||||
|
||||
(Content-addressed paths are inherently trustworthy and thus
|
||||
unaffected by this configuration option.)
|
||||
)"};
|
||||
|
||||
Setting<StringSet> extraPlatforms{
|
||||
|
@ -613,6 +619,14 @@ public:
|
|||
are tried based on their Priority value, which each substituter can set
|
||||
independently. Lower value means higher priority.
|
||||
The default is `https://cache.nixos.org`, with a Priority of 40.
|
||||
|
||||
Nix will copy a store path from a remote store only if one
|
||||
of the following is true:
|
||||
|
||||
- the store object is signed by one of the [`trusted-public-keys`](#conf-trusted-public-keys)
|
||||
- the substituter is in the [`trusted-substituters`](#conf-trusted-substituters) list
|
||||
- the [`require-sigs`](#conf-require-sigs) option has been set to `false`
|
||||
- the store object is [output-addressed](glossary.md#gloss-output-addressed-store-object)
|
||||
)",
|
||||
{"binary-caches"}};
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd)
|
|||
txn.commit();
|
||||
}
|
||||
|
||||
writeFile(schemaPath, fmt("%d", nixCASchemaVersion));
|
||||
writeFile(schemaPath, fmt("%d", nixCASchemaVersion), 0666, true);
|
||||
lockFile(lockFd.get(), ltRead, true);
|
||||
}
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ LocalStore::LocalStore(const Params & params)
|
|||
else if (curSchema == 0) { /* new store */
|
||||
curSchema = nixSchemaVersion;
|
||||
openDB(*state, true);
|
||||
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str());
|
||||
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str(), 0666, true);
|
||||
}
|
||||
|
||||
else if (curSchema < nixSchemaVersion) {
|
||||
|
@ -329,7 +329,7 @@ LocalStore::LocalStore(const Params & params)
|
|||
txn.commit();
|
||||
}
|
||||
|
||||
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str());
|
||||
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str(), 0666, true);
|
||||
|
||||
lockFile(globalLock.get(), ltRead, true);
|
||||
}
|
||||
|
@ -751,7 +751,7 @@ void LocalStore::registerDrvOutput(const Realisation & info, CheckSigsFlag check
|
|||
if (checkSigs == NoCheckSigs || !realisationIsUntrusted(info))
|
||||
registerDrvOutput(info);
|
||||
else
|
||||
throw Error("cannot register realisation '%s' because it lacks a valid signature", info.outPath.to_string());
|
||||
throw Error("cannot register realisation '%s' because it lacks a signature by a trusted key", info.outPath.to_string());
|
||||
}
|
||||
|
||||
void LocalStore::registerDrvOutput(const Realisation & info)
|
||||
|
@ -1266,7 +1266,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
|
|||
RepairFlag repair, CheckSigsFlag checkSigs)
|
||||
{
|
||||
if (checkSigs && pathInfoIsUntrusted(info))
|
||||
throw Error("cannot add path '%s' because it lacks a valid signature", printStorePath(info.path));
|
||||
throw Error("cannot add path '%s' because it lacks a signature by a trusted key", printStorePath(info.path));
|
||||
|
||||
addTempRoot(info.path);
|
||||
|
||||
|
|
|
@ -75,6 +75,9 @@ struct NarAccessor : public FSAccessor
|
|||
createMember(path, {FSAccessor::Type::tRegular, false, 0, 0});
|
||||
}
|
||||
|
||||
void closeRegularFile() override
|
||||
{ }
|
||||
|
||||
void isExecutable() override
|
||||
{
|
||||
parents.top()->isExecutable = true;
|
||||
|
|
|
@ -1363,9 +1363,9 @@ std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Para
|
|||
} catch (Error & e) {
|
||||
return std::make_shared<LocalStore>(params);
|
||||
}
|
||||
warn("'/nix' does not exist, so Nix will use '%s' as a chroot store", chrootStore);
|
||||
warn("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore);
|
||||
} else
|
||||
debug("'/nix' does not exist, so Nix will use '%s' as a chroot store", chrootStore);
|
||||
debug("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore);
|
||||
Store::Params params2;
|
||||
params2["root"] = chrootStore;
|
||||
return std::make_shared<LocalStore>(params2);
|
||||
|
|
|
@ -234,6 +234,7 @@ static void parse(ParseSink & sink, Source & source, const Path & path)
|
|||
|
||||
else if (s == "contents" && type == tpRegular) {
|
||||
parseContents(sink, source, path);
|
||||
sink.closeRegularFile();
|
||||
}
|
||||
|
||||
else if (s == "executable" && type == tpRegular) {
|
||||
|
@ -324,6 +325,12 @@ struct RestoreSink : ParseSink
|
|||
if (!fd) throw SysError("creating file '%1%'", p);
|
||||
}
|
||||
|
||||
void closeRegularFile() override
|
||||
{
|
||||
/* Call close explicitly to make sure the error is checked */
|
||||
fd.close();
|
||||
}
|
||||
|
||||
void isExecutable() override
|
||||
{
|
||||
struct stat st;
|
||||
|
|
|
@ -60,6 +60,7 @@ struct ParseSink
|
|||
virtual void createDirectory(const Path & path) { };
|
||||
|
||||
virtual void createRegularFile(const Path & path) { };
|
||||
virtual void closeRegularFile() { };
|
||||
virtual void isExecutable() { };
|
||||
virtual void preallocateContents(uint64_t size) { };
|
||||
virtual void receiveContents(std::string_view data) { };
|
||||
|
|
|
@ -353,7 +353,7 @@ void readFile(const Path & path, Sink & sink)
|
|||
}
|
||||
|
||||
|
||||
void writeFile(const Path & path, std::string_view s, mode_t mode)
|
||||
void writeFile(const Path & path, std::string_view s, mode_t mode, bool sync)
|
||||
{
|
||||
AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode);
|
||||
if (!fd)
|
||||
|
@ -364,10 +364,16 @@ void writeFile(const Path & path, std::string_view s, mode_t mode)
|
|||
e.addTrace({}, "writing file '%1%'", path);
|
||||
throw;
|
||||
}
|
||||
if (sync)
|
||||
fd.fsync();
|
||||
// Explicitly close to make sure exceptions are propagated.
|
||||
fd.close();
|
||||
if (sync)
|
||||
syncParent(path);
|
||||
}
|
||||
|
||||
|
||||
void writeFile(const Path & path, Source & source, mode_t mode)
|
||||
void writeFile(const Path & path, Source & source, mode_t mode, bool sync)
|
||||
{
|
||||
AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode);
|
||||
if (!fd)
|
||||
|
@ -386,6 +392,20 @@ void writeFile(const Path & path, Source & source, mode_t mode)
|
|||
e.addTrace({}, "writing file '%1%'", path);
|
||||
throw;
|
||||
}
|
||||
if (sync)
|
||||
fd.fsync();
|
||||
// Explicitly close to make sure exceptions are propagated.
|
||||
fd.close();
|
||||
if (sync)
|
||||
syncParent(path);
|
||||
}
|
||||
|
||||
void syncParent(const Path & path)
|
||||
{
|
||||
AutoCloseFD fd = open(dirOf(path).c_str(), O_RDONLY, 0);
|
||||
if (!fd)
|
||||
throw SysError("opening file '%1%'", path);
|
||||
fd.fsync();
|
||||
}
|
||||
|
||||
std::string readLine(int fd)
|
||||
|
@ -841,6 +861,20 @@ void AutoCloseFD::close()
|
|||
}
|
||||
}
|
||||
|
||||
void AutoCloseFD::fsync()
|
||||
{
|
||||
if (fd != -1) {
|
||||
int result;
|
||||
#if __APPLE__
|
||||
result = ::fcntl(fd, F_FULLFSYNC);
|
||||
#else
|
||||
result = ::fsync(fd);
|
||||
#endif
|
||||
if (result == -1)
|
||||
throw SysError("fsync file descriptor %1%", fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AutoCloseFD::operator bool() const
|
||||
{
|
||||
|
|
|
@ -115,9 +115,12 @@ std::string readFile(const Path & path);
|
|||
void readFile(const Path & path, Sink & sink);
|
||||
|
||||
/* Write a string to a file. */
|
||||
void writeFile(const Path & path, std::string_view s, mode_t mode = 0666);
|
||||
void writeFile(const Path & path, std::string_view s, mode_t mode = 0666, bool sync = false);
|
||||
|
||||
void writeFile(const Path & path, Source & source, mode_t mode = 0666);
|
||||
void writeFile(const Path & path, Source & source, mode_t mode = 0666, bool sync = false);
|
||||
|
||||
/* Flush a file's parent directory to disk */
|
||||
void syncParent(const Path & path);
|
||||
|
||||
/* Read a line from a file descriptor. */
|
||||
std::string readLine(int fd);
|
||||
|
@ -231,6 +234,7 @@ public:
|
|||
explicit operator bool() const;
|
||||
int release();
|
||||
void close();
|
||||
void fsync();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -85,7 +85,6 @@ static void main_nix_build(int argc, char * * argv)
|
|||
Strings attrPaths;
|
||||
Strings left;
|
||||
RepairFlag repair = NoRepair;
|
||||
Path gcRoot;
|
||||
BuildMode buildMode = bmNormal;
|
||||
bool readStdin = false;
|
||||
|
||||
|
@ -167,9 +166,6 @@ static void main_nix_build(int argc, char * * argv)
|
|||
else if (*arg == "--out-link" || *arg == "-o")
|
||||
outLink = getArg(*arg, arg, end);
|
||||
|
||||
else if (*arg == "--add-root")
|
||||
gcRoot = getArg(*arg, arg, end);
|
||||
|
||||
else if (*arg == "--dry-run")
|
||||
dryRun = true;
|
||||
|
||||
|
|
|
@ -246,6 +246,7 @@ struct Common : InstallableCommand, MixProfile
|
|||
"NIX_LOG_FD",
|
||||
"NIX_REMOTE",
|
||||
"PPID",
|
||||
"SHELL",
|
||||
"SHELLOPTS",
|
||||
"SSL_CERT_FILE", // FIXME: only want to ignore /no-cert-file.crt
|
||||
"TEMP",
|
||||
|
|
|
@ -74,6 +74,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
|
|||
addFlag({
|
||||
.longName = "help",
|
||||
.description = "Show usage information.",
|
||||
.category = miscCategory,
|
||||
.handler = {[&]() { throw HelpRequested(); }},
|
||||
});
|
||||
|
||||
|
@ -88,6 +89,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
|
|||
addFlag({
|
||||
.longName = "version",
|
||||
.description = "Show version information.",
|
||||
.category = miscCategory,
|
||||
.handler = {[&]() { showVersion = true; }},
|
||||
});
|
||||
|
||||
|
@ -95,12 +97,14 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
|
|||
.longName = "offline",
|
||||
.aliases = {"no-net"}, // FIXME: remove
|
||||
.description = "Disable substituters and consider all previously downloaded files up-to-date.",
|
||||
.category = miscCategory,
|
||||
.handler = {[&]() { useNet = false; }},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "refresh",
|
||||
.description = "Consider all previously downloaded files out-of-date.",
|
||||
.category = miscCategory,
|
||||
.handler = {[&]() { refresh = true; }},
|
||||
});
|
||||
}
|
||||
|
@ -187,7 +191,7 @@ static void showHelp(std::vector<std::string> subcommand, MultiCommand & topleve
|
|||
*vUtils);
|
||||
|
||||
auto attrs = state.buildBindings(16);
|
||||
attrs.alloc("command").mkString(toplevel.toJSON().dump());
|
||||
attrs.alloc("toplevel").mkString(toplevel.toJSON().dump());
|
||||
|
||||
auto vRes = state.allocValue();
|
||||
state.callFunction(*vGenerateManpage, state.allocValue()->mkAttrs(attrs), *vRes, noPos);
|
||||
|
|
|
@ -22,7 +22,7 @@ R""(
|
|||
|
||||
```console
|
||||
# nix copy --to /tmp/nix --trusted-public-keys '' nixpkgs#hello
|
||||
cannot add path '/nix/store/zy9wbxwcygrwnh8n2w9qbbcr6zk87m26-libunistring-0.9.10' because it lacks a valid signature
|
||||
cannot add path '/nix/store/zy9wbxwcygrwnh8n2w9qbbcr6zk87m26-libunistring-0.9.10' because it lacks a signature by a trusted key
|
||||
```
|
||||
|
||||
* Create a content-addressed representation of the current NixOS
|
||||
|
|
|
@ -41,7 +41,7 @@ struct CmdVerify : StorePathsCommand
|
|||
addFlag({
|
||||
.longName = "sigs-needed",
|
||||
.shortName = 'n',
|
||||
.description = "Require that each path has at least *n* valid signatures.",
|
||||
.description = "Require that each path is signed by at least *n* different keys.",
|
||||
.labels = {"n"},
|
||||
.handler = {&sigsNeeded}
|
||||
});
|
||||
|
|
|
@ -18,9 +18,6 @@ nix-build --no-out-link dependencies.nix --dry-run 2>&1 | grep "will be built"
|
|||
# Now new command:
|
||||
nix build -f dependencies.nix --dry-run 2>&1 | grep "will be built"
|
||||
|
||||
# TODO: XXX: FIXME: #1793
|
||||
# Disable this part of the test until the problem is resolved:
|
||||
if [ -n "$ISSUE_1795_IS_FIXED" ]; then
|
||||
clearStore
|
||||
clearCache
|
||||
|
||||
|
@ -28,7 +25,6 @@ clearCache
|
|||
nix build -f dependencies.nix --dry-run 2>&1 | grep "will be built"
|
||||
# Now old command:
|
||||
nix-build --no-out-link dependencies.nix --dry-run 2>&1 | grep "will be built"
|
||||
fi
|
||||
|
||||
###################################################
|
||||
# Check --dry-run doesn't create links with --dry-run
|
||||
|
|
220
tests/installer/default.nix
Normal file
220
tests/installer/default.nix
Normal file
|
@ -0,0 +1,220 @@
|
|||
{ binaryTarballs
|
||||
, nixpkgsFor
|
||||
}:
|
||||
|
||||
let
|
||||
|
||||
installScripts = {
|
||||
install-default = {
|
||||
script = ''
|
||||
tar -xf ./nix.tar.xz
|
||||
mv ./nix-* nix
|
||||
./nix/install --no-channel-add
|
||||
'';
|
||||
};
|
||||
|
||||
install-force-no-daemon = {
|
||||
script = ''
|
||||
tar -xf ./nix.tar.xz
|
||||
mv ./nix-* nix
|
||||
./nix/install --no-daemon
|
||||
'';
|
||||
};
|
||||
|
||||
install-force-daemon = {
|
||||
script = ''
|
||||
tar -xf ./nix.tar.xz
|
||||
mv ./nix-* nix
|
||||
./nix/install --daemon --no-channel-add
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
disableSELinux = "sudo setenforce 0";
|
||||
|
||||
images = {
|
||||
|
||||
/*
|
||||
"ubuntu-14-04" = {
|
||||
image = import <nix/fetchurl.nix> {
|
||||
url = "https://app.vagrantup.com/ubuntu/boxes/trusty64/versions/20190514.0.0/providers/virtualbox.box";
|
||||
hash = "sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8=";
|
||||
};
|
||||
rootDisk = "box-disk1.vmdk";
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
*/
|
||||
|
||||
"ubuntu-16-04" = {
|
||||
image = import <nix/fetchurl.nix> {
|
||||
url = "https://app.vagrantup.com/generic/boxes/ubuntu1604/versions/4.1.12/providers/libvirt.box";
|
||||
hash = "sha256-lO4oYQR2tCh5auxAYe6bPOgEqOgv3Y3GC1QM1tEEEU8=";
|
||||
};
|
||||
rootDisk = "box.img";
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
|
||||
"ubuntu-22-04" = {
|
||||
image = import <nix/fetchurl.nix> {
|
||||
url = "https://app.vagrantup.com/generic/boxes/ubuntu2204/versions/4.1.12/providers/libvirt.box";
|
||||
hash = "sha256-HNll0Qikw/xGIcogni5lz01vUv+R3o8xowP2EtqjuUQ=";
|
||||
};
|
||||
rootDisk = "box.img";
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
|
||||
"fedora-36" = {
|
||||
image = import <nix/fetchurl.nix> {
|
||||
url = "https://app.vagrantup.com/generic/boxes/fedora36/versions/4.1.12/providers/libvirt.box";
|
||||
hash = "sha256-rxPgnDnFkTDwvdqn2CV3ZUo3re9AdPtSZ9SvOHNvaks=";
|
||||
};
|
||||
rootDisk = "box.img";
|
||||
system = "x86_64-linux";
|
||||
postBoot = disableSELinux;
|
||||
};
|
||||
|
||||
# Currently fails with 'error while loading shared libraries:
|
||||
# libsodium.so.23: cannot stat shared object: Invalid argument'.
|
||||
/*
|
||||
"rhel-6" = {
|
||||
image = import <nix/fetchurl.nix> {
|
||||
url = "https://app.vagrantup.com/generic/boxes/rhel6/versions/4.1.12/providers/libvirt.box";
|
||||
hash = "sha256-QwzbvRoRRGqUCQptM7X/InRWFSP2sqwRt2HaaO6zBGM=";
|
||||
};
|
||||
rootDisk = "box.img";
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
*/
|
||||
|
||||
"rhel-7" = {
|
||||
image = import <nix/fetchurl.nix> {
|
||||
url = "https://app.vagrantup.com/generic/boxes/rhel7/versions/4.1.12/providers/libvirt.box";
|
||||
hash = "sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U=";
|
||||
};
|
||||
rootDisk = "box.img";
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
|
||||
"rhel-8" = {
|
||||
image = import <nix/fetchurl.nix> {
|
||||
url = "https://app.vagrantup.com/generic/boxes/rhel8/versions/4.1.12/providers/libvirt.box";
|
||||
hash = "sha256-zFOPjSputy1dPgrQRixBXmlyN88cAKjJ21VvjSWUCUY=";
|
||||
};
|
||||
rootDisk = "box.img";
|
||||
system = "x86_64-linux";
|
||||
postBoot = disableSELinux;
|
||||
};
|
||||
|
||||
"rhel-9" = {
|
||||
image = import <nix/fetchurl.nix> {
|
||||
url = "https://app.vagrantup.com/generic/boxes/rhel9/versions/4.1.12/providers/libvirt.box";
|
||||
hash = "sha256-vL/FbB3kK1rcSaR627nWmScYGKGk4seSmAdq6N5diMg=";
|
||||
};
|
||||
rootDisk = "box.img";
|
||||
system = "x86_64-linux";
|
||||
postBoot = disableSELinux;
|
||||
extraQemuOpts = "-cpu Westmere-v2";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
makeTest = imageName: testName:
|
||||
let image = images.${imageName}; in
|
||||
with nixpkgsFor.${image.system};
|
||||
runCommand
|
||||
"installer-test-${imageName}-${testName}"
|
||||
{ buildInputs = [ qemu_kvm openssh ];
|
||||
image = image.image;
|
||||
postBoot = image.postBoot or "";
|
||||
installScript = installScripts.${testName}.script;
|
||||
binaryTarball = binaryTarballs.${system};
|
||||
}
|
||||
''
|
||||
shopt -s nullglob
|
||||
|
||||
echo "Unpacking Vagrant box $image..."
|
||||
tar xvf $image
|
||||
|
||||
image_type=$(qemu-img info ${image.rootDisk} | sed 's/file format: \(.*\)/\1/; t; d')
|
||||
|
||||
qemu-img create -b ./${image.rootDisk} -F "$image_type" -f qcow2 ./disk.qcow2
|
||||
|
||||
extra_qemu_opts="${image.extraQemuOpts or ""}"
|
||||
|
||||
# Add the config disk, required by the Ubuntu images.
|
||||
config_drive=$(echo *configdrive.vmdk || true)
|
||||
if [[ -n $config_drive ]]; then
|
||||
extra_qemu_opts+=" -drive id=disk2,file=$config_drive,if=virtio"
|
||||
fi
|
||||
|
||||
echo "Starting qemu..."
|
||||
qemu-kvm -m 4096 -nographic \
|
||||
-drive id=disk1,file=./disk.qcow2,if=virtio \
|
||||
-netdev user,id=net0,restrict=yes,hostfwd=tcp::20022-:22 -device virtio-net-pci,netdev=net0 \
|
||||
$extra_qemu_opts &
|
||||
qemu_pid=$!
|
||||
trap "kill $qemu_pid" EXIT
|
||||
|
||||
if ! [ -e ./vagrant_insecure_key ]; then
|
||||
cp ${./vagrant_insecure_key} vagrant_insecure_key
|
||||
fi
|
||||
|
||||
chmod 0400 ./vagrant_insecure_key
|
||||
|
||||
ssh_opts="-o StrictHostKeyChecking=no -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedKeyTypes=+ssh-rsa -i ./vagrant_insecure_key"
|
||||
ssh="ssh -p 20022 -q $ssh_opts vagrant@localhost"
|
||||
|
||||
echo "Waiting for SSH..."
|
||||
for ((i = 0; i < 120; i++)); do
|
||||
echo "[ssh] Trying to connect..."
|
||||
if $ssh -- true; then
|
||||
echo "[ssh] Connected!"
|
||||
break
|
||||
fi
|
||||
if ! kill -0 $qemu_pid; then
|
||||
echo "qemu died unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [[ -n $postBoot ]]; then
|
||||
echo "Running post-boot commands..."
|
||||
$ssh "set -ex; $postBoot"
|
||||
fi
|
||||
|
||||
echo "Copying installer..."
|
||||
scp -P 20022 $ssh_opts $binaryTarball/nix-*.tar.xz vagrant@localhost:nix.tar.xz
|
||||
|
||||
echo "Running installer..."
|
||||
$ssh "set -eux; $installScript"
|
||||
|
||||
echo "Testing Nix installation..."
|
||||
$ssh <<EOF
|
||||
set -ex
|
||||
|
||||
# FIXME: get rid of this; ideally ssh should just work.
|
||||
source ~/.bash_profile || true
|
||||
source ~/.bash_login || true
|
||||
source ~/.profile || true
|
||||
source /etc/bashrc || true
|
||||
|
||||
nix-env --version
|
||||
nix --extra-experimental-features nix-command store ping
|
||||
|
||||
out=\$(nix-build --no-substitute -E 'derivation { name = "foo"; system = "x86_64-linux"; builder = "/bin/sh"; args = ["-c" "echo foobar > \$out"]; }')
|
||||
[[ \$(cat \$out) = foobar ]]
|
||||
EOF
|
||||
|
||||
echo "Done!"
|
||||
touch $out
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
builtins.mapAttrs (imageName: image:
|
||||
{ ${image.system} = builtins.mapAttrs (testName: test:
|
||||
makeTest imageName testName
|
||||
) installScripts;
|
||||
}
|
||||
) images
|
27
tests/installer/vagrant_insecure_key
Normal file
27
tests/installer/vagrant_insecure_key
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI
|
||||
w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP
|
||||
kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2
|
||||
hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO
|
||||
Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW
|
||||
yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd
|
||||
ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1
|
||||
Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf
|
||||
TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK
|
||||
iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A
|
||||
sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf
|
||||
4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP
|
||||
cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk
|
||||
EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN
|
||||
CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX
|
||||
3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG
|
||||
YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj
|
||||
3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+
|
||||
dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz
|
||||
6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC
|
||||
P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF
|
||||
llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ
|
||||
kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH
|
||||
+vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ
|
||||
NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s=
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -4,6 +4,7 @@ let
|
|||
name2 = "hello";
|
||||
name3 = "915resolution-0.5.2";
|
||||
name4 = "xf86-video-i810-1.7.4";
|
||||
name5 = "name-that-ends-with-dash--1.0";
|
||||
|
||||
eq = 0;
|
||||
lt = builtins.sub 0 1;
|
||||
|
@ -23,6 +24,8 @@ let
|
|||
((builtins.parseDrvName name3).version == "0.5.2")
|
||||
((builtins.parseDrvName name4).name == "xf86-video-i810")
|
||||
((builtins.parseDrvName name4).version == "1.7.4")
|
||||
((builtins.parseDrvName name5).name == "name-that-ends-with-dash")
|
||||
((builtins.parseDrvName name5).version == "-1.0")
|
||||
(versionTest "1.0" "2.3" lt)
|
||||
(versionTest "2.1" "2.3" lt)
|
||||
(versionTest "2.3" "2.3" eq)
|
||||
|
|
|
@ -81,7 +81,7 @@ info=$(nix path-info --store file://$cacheDir --json $outPath2)
|
|||
[[ $info =~ 'cache1.example.org' ]]
|
||||
[[ $info =~ 'cache2.example.org' ]]
|
||||
|
||||
# Copying to a diverted store should fail due to a lack of valid signatures.
|
||||
# Copying to a diverted store should fail due to a lack of signatures by trusted keys.
|
||||
chmod -R u+w $TEST_ROOT/store0 || true
|
||||
rm -rf $TEST_ROOT/store0
|
||||
(! nix copy --to $TEST_ROOT/store0 $outPath)
|
||||
|
|
Loading…
Reference in a new issue