Compare commits

..

2 Commits

Author SHA1 Message Date
regnat
cc711c6956 Add aliases for the old flake commands
Requires reworking a bit the existing alias mechanism to allow aliases
to be composite commands themselves
2021-11-25 21:42:55 +01:00
regnat
401b09b7fe Move nix flake {new,init} at toplevel
Fix #4502
2021-11-25 21:42:55 +01:00
79 changed files with 462 additions and 898 deletions

View File

@@ -1,7 +0,0 @@
**Release Notes**
Please include relevant [release notes](https://github.com/NixOS/nix/blob/master/doc/manual/src/release-notes/rl-next.md) as needed.
**Testing**
If this issue is a regression or something that should block release, please consider including a test either in the [testsuite](https://github.com/NixOS/nix/tree/master/tests) or as a [hydraJob]( https://github.com/NixOS/nix/blob/master/flake.nix#L396) so that it can be part of the [automatic checks](https://hydra.nixos.org/jobset/nix/master).

View File

@@ -1,16 +0,0 @@
name: Hydra status
on:
schedule:
- cron: "12,42 * * * *"
workflow_dispatch:
jobs:
check_hydra_status:
name: Check Hydra status
if: github.repository_owner == 'NixOS'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.4.0
with:
fetch-depth: 0
- run: bash scripts/check-hydra-status.sh

View File

@@ -1 +1 @@
2.5.1
2.5

View File

@@ -188,24 +188,17 @@ PKG_CHECK_MODULES([EDITLINE], [libeditline], [CXXFLAGS="$EDITLINE_CFLAGS $CXXFLA
[AC_MSG_ERROR([Nix requires libeditline; it was not found via pkg-config, but via its header, but required functions do not work. Maybe it is too old? >= 1.14 is required.])])
])
# Look for libsodium.
# Look for libsodium, an optional dependency.
PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"])
# Look for libbrotli{enc,dec}.
PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec], [CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"])
# Look for libcpuid.
have_libcpuid=
if test "$machine_name" = "x86_64"; then
AC_ARG_ENABLE([cpuid],
AS_HELP_STRING([--disable-cpuid], [Do not determine microarchitecture levels with libcpuid (relevant to x86_64 only)]))
if test "x$enable_cpuid" != "xno"; then
PKG_CHECK_MODULES([LIBCPUID], [libcpuid],
[CXXFLAGS="$LIBCPUID_CFLAGS $CXXFLAGS"
have_libcpuid=1
AC_DEFINE([HAVE_LIBCPUID], [1], [Use libcpuid])]
)
fi
PKG_CHECK_MODULES([LIBCPUID], [libcpuid], [CXXFLAGS="$LIBCPUID_CFLAGS $CXXFLAGS"])
have_libcpuid=1
AC_DEFINE([HAVE_LIBCPUID], [1], [Use libcpuid])
fi
AC_SUBST(HAVE_LIBCPUID, [$have_libcpuid])

View File

@@ -8,19 +8,17 @@ concatStrings (map
let option = options.${name}; in
" - `${name}` \n\n"
+ concatStrings (map (s: " ${s}\n") (splitLines option.description)) + "\n\n"
+ (if option.documentDefault
then " **Default:** " + (
if option.value == "" || option.value == []
then "*empty*"
else if isBool option.value
then (if option.value then "`true`" else "`false`")
else
# n.b. 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 isAttrs option.value then "`\"\"`"
else "`" + toString option.value + "`")) + "\n\n"
else " **Default:** *machine-specific*")
+ " **Default:** " + (
if option.value == "" || option.value == []
then "*empty*"
else if isBool option.value
then (if option.value then "`true`" else "`false`")
else
# n.b. 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 isAttrs option.value then "`\"\"`"
else "`" + toString option.value + "`")) + "\n\n"
+ (if option.aliases != []
then " **Deprecated alias:** " + (concatStringsSep ", " (map (s: "`${s}`") option.aliases)) + "\n\n"
else "")

View File

@@ -12,13 +12,11 @@ man-pages := $(foreach n, \
clean-files += $(d)/*.1 $(d)/*.5 $(d)/*.8
# Provide a dummy environment for nix, so that it will not access files outside the macOS sandbox.
# Set cores to 0 because otherwise nix show-config resolves the cores based on the current machine
dummy-env = env -i \
HOME=/dummy \
NIX_CONF_DIR=/dummy \
NIX_SSL_CERT_FILE=/dummy/no-ca-bundle.crt \
NIX_STATE_DIR=/dummy \
NIX_CONFIG='cores = 0'
NIX_STATE_DIR=/dummy
nix-eval = $(dummy-env) $(bindir)/nix eval --experimental-features nix-command -I nix/corepkgs=corepkgs --store dummy:// --impure --raw

View File

@@ -71,7 +71,7 @@
- [Hacking](contributing/hacking.md)
- [CLI guideline](contributing/cli-guideline.md)
- [Release Notes](release-notes/release-notes.md)
- [Release 2.5 (2021-12-13)](release-notes/rl-2.5.md)
- [Release X.Y (202?-??-??)](release-notes/rl-next.md)
- [Release 2.4 (2021-11-01)](release-notes/rl-2.4.md)
- [Release 2.3 (2019-09-04)](release-notes/rl-2.3.md)
- [Release 2.2 (2019-01-11)](release-notes/rl-2.2.md)

View File

@@ -53,8 +53,8 @@ example, the following command allows you to build a derivation for
$ uname
Linux
$ nix build --impure \
--expr '(with import <nixpkgs> { system = "x86_64-darwin"; }; runCommand "foo" {} "uname > $out")' \
$ nix build \
'(with import <nixpkgs> { system = "x86_64-darwin"; }; runCommand "foo" {} "uname > $out")' \
--builders 'ssh://mac x86_64-darwin'
[1/0/1 built, 0.0 MiB DL] building foo on ssh://mac

View File

@@ -35,25 +35,6 @@ variables are set up so that those dependencies can be found:
$ nix-shell
```
or if you have a flake-enabled nix:
```console
$ nix develop
```
To get a shell with a different compilation environment (e.g. stdenv,
gccStdenv, clangStdenv, clang11Stdenv):
```console
$ nix-shell -A devShells.x86_64-linux.clang11StdenvPackages
```
or if you have a flake-enabled nix:
```console
$ nix develop .#clang11StdenvPackages
```
To build Nix itself in this shell:
```console

View File

@@ -47,7 +47,7 @@
the store object at `P` contains the path `Q` somewhere. The
*references* of a store path are the set of store paths to which it
has a reference.
A derivation can reference other derivations and sources (but not
output paths), whereas an output path only references other output
paths.
@@ -66,7 +66,7 @@
is necessary to deploy whole closures, since otherwise at runtime
files could be missing. The command `nix-store -qR` prints out
closures of store paths.
As an example, if the store object at path `P` contains a reference
to path `Q`, then `Q` is in the closure of `P`. Further, if `Q`
references `R` then `R` is also in the closure of `P`.
@@ -98,7 +98,3 @@
store. It can contain regular files, directories and symbolic
links. NARs are generated and unpacked using `nix-store --dump`
and `nix-store --restore`.
- `∅` \
The empty set symbol. In the context of profile history, this denotes a package is not present in a particular version of the profile.
- `ε` \
The epsilon symbol. In the context of a package, this means the version is empty. More precisely, the derivation does not have a version attribute.

View File

@@ -119,30 +119,6 @@ this to run the installer, but it may help if you run into trouble:
- update `/etc/synthetic.conf` to direct macOS to create a "synthetic"
empty root directory to mount your volume
- specify mount options for the volume in `/etc/fstab`
- `rw`: read-write
- `noauto`: prevent the system from auto-mounting the volume (so the
LaunchDaemon mentioned below can control mounting it, and to avoid
masking problems with that mounting service).
- `nobrowse`: prevent the Nix Store volume from showing up on your
desktop; also keeps Spotlight from spending resources to index
this volume
<!-- TODO:
- `suid`: honor setuid? surely not? ...
- `owners`: honor file ownership on the volume
For now I'll avoid pretending to understand suid/owners more
than I do. There've been some vague reports of file-ownership
and permission issues, particularly in cloud/VM/headless setups.
My pet theory is that this has something to do with these setups
not having a token that gets delegated to initial/admin accounts
on macOS. See scripts/create-darwin-volume.sh for a little more.
In any case, by Dec 4 2021, it _seems_ like some combination of
suid, owners, and calling diskutil enableOwnership have stopped
new reports from coming in. But I hesitate to celebrate because we
haven't really named and catalogued the behavior, understood what
we're fixing, and validated that all 3 components are essential.
-->
- if you have FileVault enabled
- generate an encryption password
- put it in your system Keychain

View File

@@ -3,7 +3,7 @@
To run the latest stable release of Nix with Docker run the following command:
```console
$ docker run -ti nixos/nix
$ docker -ti run nixos/nix
Unable to find image 'nixos/nix:latest' locally
latest: Pulling from nixos/nix
5843afab3874: Pull complete

View File

@@ -44,11 +44,6 @@
obtained from the its repository
<https://github.com/troglobit/editline>.
- The `libsodium` library for verifying cryptographic signatures
of contents fetched from binary caches.
It can be obtained from the official web site
<https://libsodium.org>.
- Recent versions of Bison and Flex to build the parser. (This is
because Nix needs GLR support in Bison and reentrancy support in
Flex.) For Bison, you need version 2.6, which can be obtained from
@@ -63,11 +58,3 @@
`--disable-seccomp-sandboxing` option to the `configure` script (Not
recommended unless your system doesn't support `libseccomp`). To get
the library, visit <https://github.com/seccomp/libseccomp>.
- On 64-bit x86 machines only, `libcpuid` library
is used to determine which microarchitecture levels are supported
(e.g., as whether to have `x86_64-v2-linux` among additional system types).
The library is available from its homepage
<http://libcpuid.sourceforge.net>.
This is an optional dependency and can be disabled
by providing a `--disable-cpuid` to the `configure` script.

View File

@@ -40,7 +40,7 @@ $ nix-channel --update
>
> On NixOS, youre automatically subscribed to a NixOS channel
> corresponding to your NixOS major release (e.g.
> <http://nixos.org/channels/nixos-21.11>). A NixOS channel is identical
> <http://nixos.org/channels/nixos-14.12>). A NixOS channel is identical
> to the Nixpkgs channel, except that it contains only Linux binaries
> and is updated only if a set of regression tests succeed.

View File

@@ -276,9 +276,6 @@ more than 2800 commits from 195 contributors since release 2.3.
* Plugins can now register `nix` subcommands.
* The `--indirect` flag to `nix-store --add-root` has become a no-op.
`--add-root` will always generate indirect GC roots from now on.
## Incompatible changes
* The `nix` command is now marked as an experimental feature. This

View File

@@ -1,16 +0,0 @@
# Release 2.5 (2021-12-13)
* The garbage collector no longer blocks new builds, so the message
`waiting for the big garbage collector lock...` is a thing of the
past.
* Binary cache stores now have a setting `compression-level`.
* `nix develop` now has a flag `--unpack` to run `unpackPhase`.
* Lists can now be compared lexicographically using the `<` operator.
* New built-in function: `builtins.groupBy`, with the same functionality as
Nixpkgs' `lib.groupBy`, but faster.
* `nix repl` now has a `:log` command.

View File

@@ -1 +1,7 @@
# Release X.Y (202?-??-??)
# Release 2.5 (2021-XX-XX)
* Binary cache stores now have a setting `compression-level`.
* `nix develop` now has a flag `--unpack` to run `unpackPhase`.
* Lists can now be compared lexicographically using the `<` operator.

View File

@@ -14,7 +14,7 @@
then ""
else "pre${builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}_${self.shortRev or "dirty"}";
officialRelease = true;
officialRelease = false;
linux64BitSystems = [ "x86_64-linux" "aarch64-linux" ];
linuxSystems = linux64BitSystems ++ [ "i686-linux" ];
@@ -22,36 +22,15 @@
crossSystems = [ "armv6l-linux" "armv7l-linux" ];
stdenvs = [ "gccStdenv" "clangStdenv" "clang11Stdenv" "stdenv" ];
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system);
forAllSystemsAndStdenvs = f: forAllSystems (system:
nixpkgs.lib.listToAttrs
(map
(n:
nixpkgs.lib.nameValuePair "${n}Packages" (
f system n
)) stdenvs
)
);
forAllStdenvs = stdenvs: f: nixpkgs.lib.genAttrs stdenvs (stdenv: f stdenv);
# Memoize nixpkgs for different platforms for efficiency.
nixpkgsFor =
let stdenvsPackages = forAllSystemsAndStdenvs
(system: stdenv:
import nixpkgs {
inherit system;
overlays = [
(overlayFor (p: p.${stdenv}))
];
}
);
in
# Add the `stdenvPackages` at toplevel, both because these are the ones
# we want most of the time and for backwards compatibility
forAllSystems (system: stdenvsPackages.${system} // stdenvsPackages.${system}.stdenvPackages);
nixpkgsFor = forAllSystems (system:
import nixpkgs {
inherit system;
overlays = [ self.overlay ];
}
);
commonDeps = pkgs: with pkgs; rec {
# Use "busybox-sandbox-shell" if present,
@@ -276,15 +255,18 @@
$(cat ${installerClosureInfo}/store-paths)
'';
overlayFor = getStdenv: final: prev:
let currentStdenv = getStdenv final; in
{
in {
# A Nixpkgs overlay that overrides the 'nix' and
# 'nix.perl-bindings' packages.
overlay = final: prev: {
nixStable = prev.nix;
# Forward from the previous stage as we dont want it to pick the lowdown override
nixUnstable = prev.nixUnstable;
nix = with final; with commonDeps pkgs; currentStdenv.mkDerivation {
nix = with final; with commonDeps pkgs; stdenv.mkDerivation {
name = "nix-${version}";
inherit version;
@@ -306,9 +288,9 @@
mkdir -p $out/lib
cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib
rm -f $out/lib/*.a
${lib.optionalString currentStdenv.isLinux ''
${lib.optionalString stdenv.isLinux ''
chmod u+w $out/lib/*.so.*
patchelf --set-rpath $out/lib:${currentStdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.*
patchelf --set-rpath $out/lib:${stdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.*
''}
'';
@@ -335,7 +317,7 @@
strictDeps = true;
passthru.perl-bindings = with final; currentStdenv.mkDerivation {
passthru.perl-bindings = with final; stdenv.mkDerivation {
name = "nix-perl-${version}";
src = self;
@@ -354,8 +336,8 @@
pkgs.perl
boost
]
++ lib.optional (currentStdenv.isLinux || currentStdenv.isDarwin) libsodium
++ lib.optional currentStdenv.isDarwin darwin.apple_sdk.frameworks.Security;
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security;
configureFlags = ''
--with-dbi=${perlPackages.DBI}/${pkgs.perl.libPrefix}
@@ -369,7 +351,7 @@
};
lowdown-nix = with final; currentStdenv.mkDerivation rec {
lowdown-nix = with final; stdenv.mkDerivation rec {
name = "lowdown-0.9.0";
src = lowdown-src;
@@ -379,20 +361,15 @@
nativeBuildInputs = [ buildPackages.which ];
configurePhase = ''
${if (currentStdenv.isDarwin && currentStdenv.isAarch64) then "echo \"HAVE_SANDBOX_INIT=false\" > configure.local" else ""}
${if (stdenv.isDarwin && stdenv.isAarch64) then "echo \"HAVE_SANDBOX_INIT=false\" > configure.local" else ""}
./configure \
PREFIX=${placeholder "dev"} \
BINDIR=${placeholder "bin"}/bin
'';
'';
};
};
in {
# A Nixpkgs overlay that overrides the 'nix' and
# 'nix.perl-bindings' packages.
overlay = overlayFor (p: p.stdenv);
hydraJobs = {
# Binary package for various platforms.
@@ -633,22 +610,15 @@
doInstallCheck = true;
installCheckFlags = "sysconfdir=$(out)/etc";
};
}) crossSystems)) // (builtins.listToAttrs (map (stdenvName:
nixpkgsFor.${system}.lib.nameValuePair
"nix-${stdenvName}"
nixpkgsFor.${system}."${stdenvName}Packages".nix
) stdenvs))
);
}) crossSystems)));
defaultPackage = forAllSystems (system: self.packages.${system}.nix);
devShell = forAllSystems (system: self.devShells.${system}.stdenvPackages);
devShells = forAllSystemsAndStdenvs (system: stdenv:
devShell = forAllSystems (system:
with nixpkgsFor.${system};
with commonDeps pkgs;
nixpkgsFor.${system}.${stdenv}.mkDerivation {
stdenv.mkDerivation {
name = "nix";
outputs = [ "out" "dev" "doc" ];

View File

@@ -25,10 +25,5 @@
<string>/var/log/nix-daemon.log</string>
<key>StandardOutPath</key>
<string>/dev/null</string>
<key>SoftResourceLimits</key>
<dict>
<key>NumberOfFiles</key>
<integer>4096</integer>
</dict>
</dict>
</plist>

View File

@@ -41,7 +41,7 @@ perlarchname=$($perl -e 'use Config; print $Config{archname};')
AC_SUBST(perllibdir, [${libdir}/perl5/site_perl/$perlversion/$perlarchname])
AC_MSG_RESULT($perllibdir)
# Look for libsodium.
# Look for libsodium, an optional dependency.
PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"])
# Check for the required Perl dependencies (DBI and DBD::SQLite).

View File

@@ -1,28 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# set -x
# mapfile BUILDS_FOR_LATEST_EVAL < <(
# curl -H 'Accept: application/json' https://hydra.nixos.org/jobset/nix/master/evals | \
# jq -r '.evals[0].builds[] | @sh')
BUILDS_FOR_LATEST_EVAL=$(
curl -sS -H 'Accept: application/json' https://hydra.nixos.org/jobset/nix/master/evals | \
jq -r '.evals[0].builds[]')
someBuildFailed=0
for buildId in $BUILDS_FOR_LATEST_EVAL; do
buildInfo=$(curl -sS -H 'Accept: application/json' "https://hydra.nixos.org/build/$buildId")
buildStatus=$(echo "$buildInfo" | \
jq -r '.buildstatus')
if [[ "$buildStatus" -ne 0 ]]; then
someBuildFailed=1
echo "Job “$(echo "$buildInfo" | jq -r '.job')” failed on hydra"
fi
done
exit "$someBuildFailed"

View File

@@ -440,22 +440,7 @@ add_nix_vol_fstab_line() {
# shellcheck disable=SC1003,SC2026
local escaped_mountpoint="${NIX_ROOT/ /'\\\'040}"
shift
# wrap `ex` to work around a problem with vim plugins breaking exit codes;
# (see https://github.com/NixOS/nix/issues/5468)
# we'd prefer EDITOR="/usr/bin/ex --noplugin" but vifs doesn't word-split
# the EDITOR env.
#
# TODO: at some point we should switch to `--clean`, but it wasn't added
# until https://github.com/vim/vim/releases/tag/v8.0.1554 while the macOS
# minver 10.12.6 seems to have released with vim 7.4
cat > "$SCRATCH/ex_cleanroom_wrapper" <<EOF
#!/bin/sh
/usr/bin/ex --noplugin "\$@"
EOF
chmod 755 "$SCRATCH/ex_cleanroom_wrapper"
EDITOR="$SCRATCH/ex_cleanroom_wrapper" _sudo "to add nix to fstab" "$@" <<EOF
EDITOR="/usr/bin/ex" _sudo "to add nix to fstab" "$@" <<EOF
:a
UUID=$uuid $escaped_mountpoint apfs rw,noauto,nobrowse,suid,owners
.
@@ -646,7 +631,7 @@ EOF
# technically /etc/synthetic.d/nix is supported in Big Sur+
# but handling both takes even more code...
_sudo "to add Nix to /etc/synthetic.conf" \
/usr/bin/ex --noplugin /etc/synthetic.conf <<EOF
/usr/bin/ex /etc/synthetic.conf <<EOF
:a
${NIX_ROOT:1}
.
@@ -809,7 +794,7 @@ setup_volume_daemon() {
local volume_uuid="$2"
if ! test_voldaemon; then
task "Configuring LaunchDaemon to mount '$NIX_VOLUME_LABEL'" >&2
_sudo "to install the Nix volume mounter" /usr/bin/ex --noplugin "$NIX_VOLUME_MOUNTD_DEST" <<EOF
_sudo "to install the Nix volume mounter" /usr/bin/ex "$NIX_VOLUME_MOUNTD_DEST" <<EOF
:a
$(generate_mount_daemon "$cmd_type" "$volume_uuid")
.

View File

@@ -218,7 +218,7 @@ EOF
setup_darwin_volume
fi
if [ "$(/usr/sbin/diskutil info -plist /nix | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]" -)" = "<false/>" ]; then
failure "This script needs a /nix volume with global permissions! This may require running sudo /usr/sbin/diskutil enableOwnership /nix."
if [ "$(diskutil info -plist /nix | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]" -)" = "<false/>" ]; then
failure "This script needs a /nix volume with global permissions! This may require running sudo diskutil enableOwnership /nix."
fi
}

View File

@@ -377,11 +377,6 @@ cure_artifacts() {
}
validate_starting_assumptions() {
task "Checking for artifacts of previous installs"
cat <<EOF
Before I try to install, I'll check for signs Nix already is or has
been installed on this system.
EOF
if type nix-env 2> /dev/null >&2; then
warning <<EOF
Nix already appears to be installed. This installer may run into issues.
@@ -391,11 +386,6 @@ $(uninstall_directions)
EOF
fi
# TODO: I think it would be good for this step to accumulate more
# knowledge of older obsolete artifacts, if there are any.
# We could issue a "reminder" here that the user might want
# to clean them up?
for profile_target in "${PROFILE_TARGETS[@]}"; do
# TODO: I think it would be good to accumulate a list of all
# of the copies so that people don't hit this 2 or 3x in

View File

@@ -38,7 +38,7 @@ fi
# Determine if we could use the multi-user installer or not
if [ "$(uname -s)" = "Linux" ]; then
echo "Note: a multi-user installation is possible. See https://nixos.org/manual/nix/stable/installation/installing-binary.html#multi-user-installation" >&2
echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2
fi
case "$(uname -s)" in
@@ -98,7 +98,7 @@ while [ $# -gt 0 ]; do
echo " providing multi-user support and better isolation for local builds."
echo " Both for security and reproducibility, this method is recommended if"
echo " supported on your platform."
echo " See https://nixos.org/manual/nix/stable/installation/installing-binary.html#multi-user-installation"
echo " See https://nixos.org/nix/manual/#sect-multi-user-installation"
echo ""
echo " --no-daemon: Simple, single-user installation that does not require root and is"
echo " trivial to uninstall."
@@ -144,7 +144,7 @@ if ! [ -e "$dest" ]; then
fi
if ! [ -w "$dest" ]; then
echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see https://nixos.org/manual/nix/stable/installation/multi-user.html. If you wish to continue with a single-user install for $USER please run 'chown -R $USER $dest' as root." >&2
echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see https://nixos.org/nix/manual/#ssec-multi-user. If you wish to continue with a single-user install for $USER please run 'chown -R $USER $dest' as root." >&2
exit 1
fi

View File

@@ -73,13 +73,8 @@ ref<Store> EvalCommand::getEvalStore()
ref<EvalState> EvalCommand::getEvalState()
{
if (!evalState) evalState =
#if HAVE_BOEHMGC
std::allocate_shared<EvalState>(traceable_allocator<EvalState>(),
#else
std::make_shared<EvalState>(
#endif
searchPath, getEvalStore(), getStore());
if (!evalState)
evalState = std::make_shared<EvalState>(searchPath, getEvalStore(), getStore());
return ref<EvalState>(evalState);
}

View File

@@ -291,9 +291,6 @@ void completeFlakeRefWithFragment(
void completeFlakeRef(ref<Store> store, std::string_view prefix)
{
if (!settings.isExperimentalFeatureEnabled(Xp::Flakes))
return;
if (prefix == "")
completions->add(".");

View File

@@ -1656,7 +1656,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
bool first = !forceString;
ValueType firstType = nString;
for (auto & [i_pos, i] : *es) {
for (auto & i : *es) {
Value vTmp;
i->eval(state, env, vTmp);
@@ -1677,19 +1677,19 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
nf = n;
nf += vTmp.fpoint;
} else
throwEvalError(i_pos, "cannot add %1% to an integer", showType(vTmp));
throwEvalError(pos, "cannot add %1% to an integer", showType(vTmp));
} else if (firstType == nFloat) {
if (vTmp.type() == nInt) {
nf += vTmp.integer;
} else if (vTmp.type() == nFloat) {
nf += vTmp.fpoint;
} else
throwEvalError(i_pos, "cannot add %1% to a float", showType(vTmp));
throwEvalError(pos, "cannot add %1% to a float", showType(vTmp));
} else
/* skip canonization of first path, which would only be not
canonized in the first place if it's coming from a ./${foo} type
path */
s << state.coerceToString(i_pos, vTmp, context, false, firstType == nString, !first);
s << state.coerceToString(pos, vTmp, context, false, firstType == nString, !first);
first = false;
}

View File

@@ -480,16 +480,11 @@ LockedFlake lockFlake(
}
}
LockParent newParent {
.path = inputPath,
.absolute = false
};
computeLocks(
mustRefetch
? getFlake(state, oldLock->lockedRef, false, flakeCache).inputs
: fakeInputs,
childNode, inputPath, oldLock, newParent, parentPath);
childNode, inputPath, oldLock, parent, parentPath);
} else {
/* We need to create a new lock file entry. So fetch

View File

@@ -191,7 +191,7 @@ void ExprConcatStrings::show(std::ostream & str) const
str << "(";
for (auto & i : *es) {
if (first) first = false; else str << " + ";
str << i.second;
str << *i;
}
str << ")";
}
@@ -439,7 +439,7 @@ void ExprOpNot::bindVars(const StaticEnv & env)
void ExprConcatStrings::bindVars(const StaticEnv & env)
{
for (auto & i : *es)
i.second->bindVars(env);
i->bindVars(env);
}
void ExprPos::bindVars(const StaticEnv & env)

View File

@@ -332,8 +332,8 @@ struct ExprConcatStrings : Expr
{
Pos pos;
bool forceString;
vector<std::pair<Pos, Expr *> > * es;
ExprConcatStrings(const Pos & pos, bool forceString, vector<std::pair<Pos, Expr *> > * es)
vector<Expr *> * es;
ExprConcatStrings(const Pos & pos, bool forceString, vector<Expr *> * es)
: pos(pos), forceString(forceString), es(es) { };
COMMON_METHODS
};

View File

@@ -152,7 +152,7 @@ static void addFormal(const Pos & pos, Formals * formals, const Formal & formal)
}
static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<std::pair<Pos, Expr *> > & es)
static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Expr *> & es)
{
if (es.empty()) return new ExprString(symbols.create(""));
@@ -162,7 +162,7 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<st
bool atStartOfLine = true; /* = seen only whitespace in the current line */
size_t minIndent = 1000000;
size_t curIndent = 0;
for (auto & [i_pos, i] : es) {
for (auto & i : es) {
ExprIndStr * e = dynamic_cast<ExprIndStr *>(i);
if (!e) {
/* Anti-quotations end the current start-of-line whitespace. */
@@ -192,12 +192,12 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<st
}
/* Strip spaces from each line. */
vector<std::pair<Pos, Expr *> > * es2 = new vector<std::pair<Pos, Expr *> >;
vector<Expr *> * es2 = new vector<Expr *>;
atStartOfLine = true;
size_t curDropped = 0;
size_t n = es.size();
for (vector<std::pair<Pos, Expr *> >::iterator i = es.begin(); i != es.end(); ++i, --n) {
ExprIndStr * e = dynamic_cast<ExprIndStr *>(i->second);
for (vector<Expr *>::iterator i = es.begin(); i != es.end(); ++i, --n) {
ExprIndStr * e = dynamic_cast<ExprIndStr *>(*i);
if (!e) {
atStartOfLine = false;
curDropped = 0;
@@ -234,11 +234,11 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<st
s2 = string(s2, 0, p + 1);
}
es2->emplace_back(i->first, new ExprString(symbols.create(s2)));
es2->push_back(new ExprString(symbols.create(s2)));
}
/* If this is a single string, then don't do a concatenation. */
return es2->size() == 1 && dynamic_cast<ExprString *>((*es2)[0].second) ? (*es2)[0].second : new ExprConcatStrings(pos, true, es2);
return es2->size() == 1 && dynamic_cast<ExprString *>((*es2)[0]) ? (*es2)[0] : new ExprConcatStrings(pos, true, es2);
}
@@ -277,7 +277,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err
char * path;
char * uri;
std::vector<nix::AttrName> * attrNames;
std::vector<std::pair<nix::Pos, nix::Expr *> > * string_parts;
std::vector<nix::Expr *> * string_parts;
}
%type <e> start expr expr_function expr_if expr_op
@@ -364,7 +364,7 @@ expr_op
| expr_op UPDATE expr_op { $$ = new ExprOpUpdate(CUR_POS, $1, $3); }
| expr_op '?' attrpath { $$ = new ExprOpHasAttr($1, *$3); }
| expr_op '+' expr_op
{ $$ = new ExprConcatStrings(CUR_POS, false, new vector<std::pair<Pos, Expr *> >({{makeCurPos(@1, data), $1}, {makeCurPos(@3, data), $3}})); }
{ $$ = new ExprConcatStrings(CUR_POS, false, new vector<Expr *>({$1, $3})); }
| expr_op '-' expr_op { $$ = new ExprCall(CUR_POS, new ExprVar(data->symbols.create("__sub")), {$1, $3}); }
| expr_op '*' expr_op { $$ = new ExprCall(CUR_POS, new ExprVar(data->symbols.create("__mul")), {$1, $3}); }
| expr_op '/' expr_op { $$ = new ExprCall(CUR_POS, new ExprVar(data->symbols.create("__div")), {$1, $3}); }
@@ -410,7 +410,7 @@ expr_simple
}
| path_start PATH_END { $$ = $1; }
| path_start string_parts_interpolated PATH_END {
$2->insert($2->begin(), {makeCurPos(@1, data), $1});
$2->insert($2->begin(), $1);
$$ = new ExprConcatStrings(CUR_POS, false, $2);
}
| SPATH {
@@ -448,13 +448,13 @@ string_parts
;
string_parts_interpolated
: string_parts_interpolated STR { $$ = $1; $1->emplace_back(makeCurPos(@2, data), $2); }
| string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = $1; $1->emplace_back(makeCurPos(@2, data), $3); }
| DOLLAR_CURLY expr '}' { $$ = new vector<std::pair<Pos, Expr *> >; $$->emplace_back(makeCurPos(@1, data), $2); }
: string_parts_interpolated STR { $$ = $1; $1->push_back($2); }
| string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = $1; $1->push_back($3); }
| DOLLAR_CURLY expr '}' { $$ = new vector<Expr *>; $$->push_back($2); }
| STR DOLLAR_CURLY expr '}' {
$$ = new vector<std::pair<Pos, Expr *> >;
$$->emplace_back(makeCurPos(@1, data), $1);
$$->emplace_back(makeCurPos(@2, data), $3);
$$ = new vector<Expr *>;
$$->push_back($1);
$$->push_back($3);
}
;
@@ -473,9 +473,9 @@ path_start
;
ind_string_parts
: ind_string_parts IND_STR { $$ = $1; $1->emplace_back(makeCurPos(@2, data), $2); }
| ind_string_parts DOLLAR_CURLY expr '}' { $$ = $1; $1->emplace_back(makeCurPos(@2, data), $3); }
| { $$ = new vector<std::pair<Pos, Expr *> >; }
: ind_string_parts IND_STR { $$ = $1; $1->push_back($2); }
| ind_string_parts DOLLAR_CURLY expr '}' { $$ = $1; $1->push_back($3); }
| { $$ = new vector<Expr *>; }
;
binds

View File

@@ -2928,56 +2928,6 @@ static RegisterPrimOp primop_partition({
.fun = prim_partition,
});
static void prim_groupBy(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceFunction(*args[0], pos);
state.forceList(*args[1], pos);
ValueVectorMap attrs;
for (auto vElem : args[1]->listItems()) {
Value res;
state.callFunction(*args[0], *vElem, res, pos);
string name = state.forceStringNoCtx(res, pos);
Symbol sym = state.symbols.create(name);
auto vector = attrs.try_emplace(sym, ValueVector()).first;
vector->second.push_back(vElem);
}
state.mkAttrs(v, attrs.size());
for (auto & i : attrs) {
Value * list = state.allocAttr(v, i.first);
auto size = i.second.size();
state.mkList(*list, size);
memcpy(list->listElems(), i.second.data(), sizeof(Value *) * size);
}
}
static RegisterPrimOp primop_groupBy({
.name = "__groupBy",
.args = {"f", "list"},
.doc = R"(
Groups elements of *list* together by the string returned from the
function *f* called on each element. It returns an attribute set
where each attribute value contains the elements of *list* that are
mapped to the same corresponding attribute name returned by *f*.
For example,
```nix
builtins.groupBy (builtins.substring 0 1) ["foo" "bar" "baz"]
```
evaluates to
```nix
{ b = [ "bar" "baz" ]; f = [ "foo" ]; }
```
)",
.fun = prim_groupBy,
});
static void prim_concatMap(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceFunction(*args[0], pos);
@@ -3782,7 +3732,7 @@ void EvalState::createBaseEnv()
.fun = primOp.fun,
.arity = std::max(primOp.args.size(), primOp.arity),
.name = symbols.create(primOp.name),
.args = primOp.args,
.args = std::move(primOp.args),
.doc = primOp.doc,
});

View File

@@ -425,11 +425,9 @@ void mkPath(Value & v, const char * s);
#if HAVE_BOEHMGC
typedef std::vector<Value *, traceable_allocator<Value *> > ValueVector;
typedef std::map<Symbol, Value *, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, Value *> > > ValueMap;
typedef std::map<Symbol, ValueVector, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, ValueVector> > > ValueVectorMap;
#else
typedef std::vector<Value *> ValueVector;
typedef std::map<Symbol, Value *> ValueMap;
typedef std::map<Symbol, ValueVector> ValueVectorMap;
#endif

View File

@@ -97,7 +97,7 @@ struct PathInputScheme : InputScheme
// for security, ensure that if the parent is a store path, it's inside it
if (store->isInStore(parent)) {
auto storePath = store->printStorePath(store->toStorePath(parent).first);
if (!isDirOrInDir(absPath, storePath))
if (!isInDir(absPath, storePath))
throw BadStorePath("relative path '%s' points outside of its parent's store path '%s'", path, storePath);
}
} else

View File

@@ -176,7 +176,6 @@ struct TarballInputScheme : InputScheme
if (!hasSuffix(url.path, ".zip")
&& !hasSuffix(url.path, ".tar")
&& !hasSuffix(url.path, ".tgz")
&& !hasSuffix(url.path, ".tar.gz")
&& !hasSuffix(url.path, ".tar.xz")
&& !hasSuffix(url.path, ".tar.bz2")

View File

@@ -11,7 +11,7 @@
namespace nix {
static std::string_view getS(const std::vector<Logger::Field> & fields, size_t n)
static std::string getS(const std::vector<Logger::Field> & fields, size_t n)
{
assert(n < fields.size());
assert(fields[n].type == Logger::Field::tString);

View File

@@ -145,10 +145,10 @@ static void preloadNSS() {
*
* All other platforms are unaffected.
*/
if (!dlopen(LIBNSS_DNS_SO, RTLD_NOW))
warn("unable to load nss_dns backend");
// FIXME: get hosts entry from nsswitch.conf.
__nss_configure_lookup("hosts", "files dns");
if (dlopen (LIBNSS_DNS_SO, RTLD_NOW) == NULL) {
printMsg(Verbosity::lvlWarn, fmt("Unable to load nss_dns backend"));
}
__nss_configure_lookup ("hosts", "dns");
#endif
});
}
@@ -427,7 +427,7 @@ RunPager::RunPager()
});
pid.setKillSignal(SIGINT);
stdout = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0);
if (dup2(toPager.writeSide.get(), STDOUT_FILENO) == -1)
throw SysError("dupping stdout");
}
@@ -438,7 +438,7 @@ RunPager::~RunPager()
try {
if (pid != -1) {
std::cout.flush();
dup2(stdout, STDOUT_FILENO);
close(STDOUT_FILENO);
pid.wait();
}
} catch (...) {

View File

@@ -88,7 +88,6 @@ public:
private:
Pid pid;
int stdout;
};
extern volatile ::sig_atomic_t blockInt;

View File

@@ -655,7 +655,7 @@ void DerivationGoal::tryLocalBuild() {
throw Error(
"unable to build with a primary store that isn't a local store; "
"either pass a different '--store' or enable remote builds."
"\nhttps://nixos.org/manual/nix/stable/advanced-topics/distributed-builds.html");
"\nhttps://nixos.org/nix/manual/#chap-distributed-builds");
}

View File

@@ -1779,14 +1779,11 @@ void LocalDerivationGoal::runChild()
i686-linux build on an x86_64-linux machine. */
struct utsname utsbuf;
uname(&utsbuf);
if ((drv->platform == "i686-linux"
&& (settings.thisSystem == "x86_64-linux"
|| (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64"))))
|| drv->platform == "armv7l-linux"
|| drv->platform == "armv6l-linux")
{
if (drv->platform == "i686-linux" &&
(settings.thisSystem == "x86_64-linux" ||
(!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64")))) {
if (personality(PER_LINUX32) == -1)
throw SysError("cannot set 32-bit personality");
throw SysError("cannot set i686-linux personality");
}
/* Impersonate a Linux 2.6 machine to get some determinism in

View File

@@ -281,11 +281,11 @@ void Worker::run(const Goals & _topGoals)
if (getMachines().empty())
throw Error("unable to start any build; either increase '--max-jobs' "
"or enable remote builds."
"\nhttps://nixos.org/manual/nix/stable/advanced-topics/distributed-builds.html");
"\nhttps://nixos.org/nix/manual/#chap-distributed-builds");
else
throw Error("unable to start any build; remote machines may not have "
"all required system features."
"\nhttps://nixos.org/manual/nix/stable/advanced-topics/distributed-builds.html");
"\nhttps://nixos.org/nix/manual/#chap-distributed-builds");
}
assert(!awake.empty());

View File

@@ -431,30 +431,25 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
hashAlgo = parseHashType(hashAlgoRaw);
}
auto dumpSource = sinkToSource([&](Sink & saved) {
if (method == FileIngestionMethod::Recursive) {
/* We parse the NAR dump through into `saved` unmodified,
so why all this extra work? We still parse the NAR so
that we aren't sending arbitrary data to `saved`
unwittingly`, and we know when the NAR ends so we don't
consume the rest of `from` and can't parse another
command. (We don't trust `addToStoreFromDump` to not
eagerly consume the entire stream it's given, past the
length of the Nar. */
TeeSource savedNARSource(from, saved);
ParseSink sink; /* null sink; just parse the NAR */
parseDump(sink, savedNARSource);
} else {
/* Incrementally parse the NAR file, stripping the
metadata, and streaming the sole file we expect into
`saved`. */
RetrieveRegularNARSink savedRegular { saved };
parseDump(savedRegular, from);
if (!savedRegular.regular) throw Error("regular file expected");
}
});
StringSink saved;
TeeSource savedNARSource(from, saved);
RetrieveRegularNARSink savedRegular { saved };
if (method == FileIngestionMethod::Recursive) {
/* Get the entire NAR dump from the client and save it to
a string so that we can pass it to
addToStoreFromDump(). */
ParseSink sink; /* null sink; just parse the NAR */
parseDump(sink, savedNARSource);
} else
parseDump(savedRegular, from);
logger->startWork();
auto path = store->addToStoreFromDump(*dumpSource, baseName, method, hashAlgo);
if (!savedRegular.regular) throw Error("regular file expected");
// FIXME: try to stream directly from `from`.
StringSource dumpSource { *saved.s };
auto path = store->addToStoreFromDump(dumpSource, baseName, method, hashAlgo);
logger->stopWork();
to << store->printStorePath(path);
@@ -956,7 +951,7 @@ void processConnection(
Finally finally([&]() {
_isInterrupted = false;
printMsgUsing(prevLogger, lvlDebug, "%d operations", opCount);
prevLogger->log(lvlDebug, fmt("%d operations", opCount));
});
if (GET_PROTOCOL_MINOR(clientVersion) >= 14 && readInt(from)) {
@@ -989,8 +984,6 @@ void processConnection(
break;
}
printMsgUsing(prevLogger, lvlDebug, "received daemon op %d", op);
opCount++;
try {

View File

@@ -544,7 +544,13 @@ struct curlFileTransfer : public FileTransfer
stopWorkerThread();
});
unshareFilesystem();
#ifdef __linux__
/* Cause this thread to not share any FS attributes with the main thread,
because this causes setns() in restoreMountNamespace() to fail.
Ideally, this would happen in the std::thread() constructor. */
if (unshare(CLONE_FS) != 0)
throw SysError("unsharing filesystem state in download thread");
#endif
std::map<CURL *, std::shared_ptr<TransferItem>> items;

View File

@@ -126,17 +126,7 @@ void LocalStore::addTempRoot(const StorePath & path)
auto socketPath = stateDir.get() + gcSocketPath;
debug("connecting to '%s'", socketPath);
state->fdRootsSocket = createUnixDomainSocket();
try {
nix::connect(state->fdRootsSocket.get(), socketPath);
} catch (SysError & e) {
/* The garbage collector may have exited, so we need to
restart. */
if (e.errNo == ECONNREFUSED) {
debug("GC socket connection refused");
state->fdRootsSocket.close();
goto restart;
}
}
nix::connect(state->fdRootsSocket.get(), socketPath);
}
try {
@@ -533,8 +523,6 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
AutoCloseFD fdClient = accept(fdServer.get(), nullptr, nullptr);
if (!fdClient) continue;
debug("GC roots server accepted new client");
/* Process the connection in a separate thread. */
auto fdClient_ = fdClient.get();
std::thread clientThread([&, fdClient = std::move(fdClient)]() {
@@ -547,12 +535,6 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
}
});
/* On macOS, accepted sockets inherit the
non-blocking flag from the server socket, so
explicitly make it blocking. */
if (fcntl(fdServer.get(), F_SETFL, fcntl(fdServer.get(), F_GETFL) & ~O_NONBLOCK) == -1)
abort();
while (true) {
try {
auto path = readLine(fdClient.get());
@@ -577,10 +559,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
} else
printError("received garbage instead of a root from client");
writeFull(fdClient.get(), "1", false);
} catch (Error & e) {
debug("reading GC root from client: %s", e.msg());
break;
}
} catch (Error &) { break; }
}
});

View File

@@ -21,7 +21,7 @@ struct MaxBuildJobsSetting : public BaseSetting<unsigned int>
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {})
: BaseSetting<unsigned int>(def, true, name, description, aliases)
: BaseSetting<unsigned int>(def, name, description, aliases)
{
options->addSetting(this);
}
@@ -38,7 +38,7 @@ struct PluginFilesSetting : public BaseSetting<Paths>
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {})
: BaseSetting<Paths>(def, true, name, description, aliases)
: BaseSetting<Paths>(def, name, description, aliases)
{
options->addSetting(this);
}
@@ -130,9 +130,7 @@ public:
{"build-max-jobs"}};
Setting<unsigned int> buildCores{
this,
getDefaultCores(),
"cores",
this, getDefaultCores(), "cores",
R"(
Sets the value of the `NIX_BUILD_CORES` environment variable in the
invocation of builders. Builders can use this variable at their
@@ -143,7 +141,7 @@ public:
command line switch and defaults to `1`. The value `0` means that
the builder should use all available CPU cores in the system.
)",
{"build-cores"}, false};
{"build-cores"}};
/* Read-only mode. Don't copy stuff to the store, don't change
the database. */
@@ -585,11 +583,10 @@ public:
platform and generate incompatible code, so you may wish to
cross-check the results of using this option against proper
natively-built versions of your derivations.
)", {}, false};
)"};
Setting<StringSet> systemFeatures{
this,
getDefaultSystemFeatures(),
this, getDefaultSystemFeatures(),
"system-features",
R"(
A set of system features supported by this machine, e.g. `kvm`.
@@ -605,7 +602,7 @@ public:
This setting by default includes `kvm` if `/dev/kvm` is accessible,
and the pseudo-features `nixos-test`, `benchmark` and `big-parallel`
that are used in Nixpkgs to route builds to specific machines.
)", {}, false};
)"};
Setting<Strings> substituters{
this,
@@ -800,15 +797,6 @@ public:
may be useful in certain scenarios (e.g. to spin up containers or
set up userspace network interfaces in tests).
)"};
Setting<StringSet> ignoredAcls{
this, {"security.selinux", "system.nfs4_acl"}, "ignored-acls",
R"(
A list of ACLs that should be ignored, normally Nix attempts to
remove all ACLs from files and directories in the Nix store, but
some ACLs like `security.selinux` or `system.nfs4_acl` can't be
removed even by root. Therefore it's best to just ignore them.
)"};
#endif
Setting<Strings> hashedMirrors{

View File

@@ -8,7 +8,6 @@
#include "references.hh"
#include "callback.hh"
#include "topo-sort.hh"
#include "finally.hh"
#include <iostream>
#include <algorithm>
@@ -590,7 +589,9 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
throw SysError("querying extended attributes of '%s'", path);
for (auto & eaName: tokenizeString<Strings>(std::string(eaBuf.data(), eaSize), std::string("\000", 1))) {
if (settings.ignoredAcls.get().count(eaName)) continue;
/* Ignore SELinux security labels since these cannot be
removed even by root. */
if (eaName == "security.selinux") continue;
if (lremovexattr(path.c_str(), eaName.c_str()) == -1)
throw SysError("removing extended attribute '%s' from '%s'", eaName, path);
}
@@ -1332,15 +1333,13 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, const string & name,
auto want = std::min(chunkSize, settings.narBufferSize - oldSize);
dump.resize(oldSize + want);
auto got = 0;
Finally cleanup([&]() {
dump.resize(oldSize + got);
});
try {
got = source.read(dump.data() + oldSize, want);
} catch (EndOfFile &) {
inMemory = true;
break;
}
dump.resize(oldSize + got);
}
std::unique_ptr<AutoDelete> delTempDir;

View File

@@ -7,7 +7,6 @@
#include "topo-sort.hh"
#include "callback.hh"
#include "closure.hh"
#include "filetransfer.hh"
namespace nix {
@@ -101,8 +100,7 @@ void Store::queryMissing(const std::vector<DerivedPath> & targets,
downloadSize_ = narSize_ = 0;
// FIXME: make async.
ThreadPool pool(fileTransferSettings.httpConnections);
ThreadPool pool;
struct State
{

View File

@@ -42,7 +42,7 @@ DrvName::~DrvName()
{ }
bool DrvName::matches(const DrvName & n)
bool DrvName::matches(DrvName & n)
{
if (name != "*") {
if (!regex) {

View File

@@ -19,7 +19,7 @@ struct DrvName
DrvName(std::string_view s);
~DrvName();
bool matches(const DrvName & n);
bool matches(DrvName & n);
private:
std::unique_ptr<Regex> regex;

View File

@@ -684,14 +684,6 @@ void RemoteStore::queryRealisationUncached(const DrvOutput & id,
Callback<std::shared_ptr<const Realisation>> callback) noexcept
{
auto conn(getConnection());
if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 27) {
warn("the daemon is too old to support content-addressed derivations, please upgrade it to 2.4");
try {
callback(nullptr);
} catch (...) { return callback.rethrow(); }
}
conn->to << wopQueryRealisation;
conn->to << id.to_string();
conn.processStderr();

View File

@@ -1079,7 +1079,7 @@ std::map<StorePath, StorePath> copyPaths(
nrFailed++;
if (!settings.keepGoing)
throw e;
printMsg(lvlError, "could not copy %s: %s", dstStore.printStorePath(storePath), e.what());
logger->log(lvlError, fmt("could not copy %s: %s", dstStore.printStorePath(storePath), e.what()));
showProgress();
return;
}

View File

@@ -10,7 +10,6 @@ std::map<std::string, nlohmann::json> BaseSetting<T>::toJSONObject()
auto obj = AbstractSetting::toJSONObject();
obj.emplace("value", value);
obj.emplace("defaultValue", defaultValue);
obj.emplace("documentDefault", documentDefault);
return obj;
}
}

View File

@@ -232,19 +232,16 @@ protected:
T value;
const T defaultValue;
const bool documentDefault;
public:
BaseSetting(const T & def,
const bool documentDefault,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {})
: AbstractSetting(name, description, aliases)
, value(def)
, defaultValue(def)
, documentDefault(documentDefault)
{ }
operator const T &() const { return value; }
@@ -291,9 +288,8 @@ public:
const T & def,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {},
const bool documentDefault = true)
: BaseSetting<T>(def, documentDefault, name, description, aliases)
const std::set<std::string> & aliases = {})
: BaseSetting<T>(def, name, description, aliases)
{
options->addSetting(this);
}
@@ -315,7 +311,7 @@ public:
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {})
: BaseSetting<Path>(def, true, name, description, aliases)
: BaseSetting<Path>(def, name, description, aliases)
, allowEmpty(allowEmpty)
{
options->addSetting(this);

View File

@@ -189,14 +189,13 @@ extern Verbosity verbosity; /* suppress msgs > this */
/* Print a string message if the current log level is at least the specified
level. Note that this has to be implemented as a macro to ensure that the
arguments are evaluated lazily. */
#define printMsgUsing(loggerParam, level, args...) \
#define printMsg(level, args...) \
do { \
auto __lvl = level; \
if (__lvl <= nix::verbosity) { \
loggerParam->log(__lvl, fmt(args)); \
logger->log(__lvl, fmt(args)); \
} \
} while (0)
#define printMsg(level, args...) printMsgUsing(logger, level, args)
#define printError(args...) printMsg(lvlError, args)
#define notice(args...) printMsg(lvlNotice, args)

View File

@@ -93,16 +93,9 @@ static void extract_archive(TarArchive & archive, const Path & destDir)
else
archive.check(r);
archive_entry_copy_pathname(entry,
archive_entry_set_pathname(entry,
(destDir + "/" + name).c_str());
// Patch hardlink path
const char *original_hardlink = archive_entry_hardlink(entry);
if (original_hardlink) {
archive_entry_copy_hardlink(entry,
(destDir + "/" + original_hardlink).c_str());
}
archive.check(archive_read_extract(archive.archive, entry, flags));
}

View File

@@ -161,7 +161,7 @@ namespace nix {
Setting<std::string> setting{&config, "", "name-of-the-setting", "description"};
setting.assign("value");
ASSERT_EQ(config.toJSON().dump(), R"#({"name-of-the-setting":{"aliases":[],"defaultValue":"","description":"description\n","documentDefault":true,"value":"value"}})#");
ASSERT_EQ(config.toJSON().dump(), R"#({"name-of-the-setting":{"aliases":[],"defaultValue":"","description":"description\n","value":"value"}})#");
}
TEST(Config, setSettingAlias) {

View File

@@ -512,7 +512,6 @@ std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
AutoCloseFD fd(mkstemp((char *) tmpl.c_str()));
if (!fd)
throw SysError("creating temporary file '%s'", tmpl);
closeOnExec(fd.get());
return {std::move(fd), tmpl};
}
@@ -1660,14 +1659,6 @@ void restoreMountNamespace()
#endif
}
void unshareFilesystem()
{
#ifdef __linux__
if (unshare(CLONE_FS) != 0 && errno != EPERM)
throw SysError("unsharing filesystem state in download thread");
#endif
}
void restoreProcessContext(bool restoreMounts)
{
restoreSignals();

View File

@@ -11,7 +11,6 @@
#include <unistd.h>
#include <signal.h>
#include <atomic>
#include <functional>
#include <map>
#include <sstream>
@@ -311,11 +310,6 @@ void saveMountNamespace();
if saveMountNamespace() was never called. */
void restoreMountNamespace();
/* Cause this thread to not share any FS attributes with the main
thread, because this causes setns() in restoreMountNamespace() to
fail. */
void unshareFilesystem();
class ExecError : public Error
{

View File

@@ -359,7 +359,6 @@ static void main_nix_build(int argc, char * * argv)
is not set, then build bashInteractive from
<nixpkgs>. */
auto shell = getEnv("NIX_BUILD_SHELL");
std::optional<StorePath> shellDrv;
if (!shell) {
@@ -376,7 +375,8 @@ static void main_nix_build(int argc, char * * argv)
auto bashDrv = store->parseStorePath(drv->queryDrvPath());
pathsToBuild.push_back({bashDrv});
pathsToCopy.insert(bashDrv);
shellDrv = bashDrv;
shell = drv->queryOutPath() + "/bin/bash";
} catch (Error & e) {
logError(e.info());
@@ -402,11 +402,6 @@ static void main_nix_build(int argc, char * * argv)
if (dryRun) return;
if (shellDrv) {
auto shellDrvOutputs = store->queryPartialDerivationOutputMap(shellDrv.value());
shell = store->printStorePath(shellDrvOutputs.at("out").value()) + "/bin/bash";
}
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
auto resolvedDrv = drv.tryResolve(*store);
assert(resolvedDrv && "Successfully resolved the derivation");

View File

@@ -224,91 +224,6 @@ static void checkSelectorUse(DrvNames & selectors)
}
namespace {
std::set<std::string> searchByPrefix(const DrvInfos & allElems, std::string_view prefix) {
constexpr std::size_t maxResults = 3;
std::set<std::string> result;
for (const auto & drvInfo : allElems) {
const auto drvName = DrvName { drvInfo.queryName() };
if (hasPrefix(drvName.name, prefix)) {
result.emplace(drvName.name);
if (result.size() >= maxResults) {
break;
}
}
}
return result;
}
struct Match
{
DrvInfo drvInfo;
std::size_t index;
Match(DrvInfo drvInfo_, std::size_t index_)
: drvInfo{std::move(drvInfo_)}
, index{index_}
{}
};
/* If a selector matches multiple derivations
with the same name, pick the one matching the current
system. If there are still multiple derivations, pick the
one with the highest priority. If there are still multiple
derivations, pick the one with the highest version.
Finally, if there are still multiple derivations,
arbitrarily pick the first one. */
std::vector<Match> pickNewestOnly(EvalState & state, std::vector<Match> matches) {
/* Map from package names to derivations. */
std::map<std::string, Match> newest;
StringSet multiple;
for (auto & match : matches) {
auto & oneDrv = match.drvInfo;
const auto drvName = DrvName { oneDrv.queryName() };
long comparison = 1;
const auto itOther = newest.find(drvName.name);
if (itOther != newest.end()) {
auto & newestDrv = itOther->second.drvInfo;
comparison =
oneDrv.querySystem() == newestDrv.querySystem() ? 0 :
oneDrv.querySystem() == settings.thisSystem ? 1 :
newestDrv.querySystem() == settings.thisSystem ? -1 : 0;
if (comparison == 0)
comparison = comparePriorities(state, oneDrv, newestDrv);
if (comparison == 0)
comparison = compareVersions(drvName.version, DrvName { newestDrv.queryName() }.version);
}
if (comparison > 0) {
newest.erase(drvName.name);
newest.emplace(drvName.name, match);
multiple.erase(drvName.fullName);
} else if (comparison == 0) {
multiple.insert(drvName.fullName);
}
}
matches.clear();
for (auto & [name, match] : newest) {
if (multiple.find(name) != multiple.end())
warn(
"there are multiple derivations named '%1%'; using the first one",
name);
matches.push_back(match);
}
return matches;
}
} // end namespace
static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
const Strings & args, bool newestOnly)
{
@@ -317,43 +232,80 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
selectors.emplace_back("*");
DrvInfos elems;
std::set<std::size_t> done;
set<unsigned int> done;
for (auto & selector : selectors) {
std::vector<Match> matches;
for (const auto & [index, drvInfo] : enumerate(allElems)) {
const auto drvName = DrvName { drvInfo.queryName() };
if (selector.matches(drvName)) {
++selector.hits;
matches.emplace_back(drvInfo, index);
for (auto & i : selectors) {
typedef list<std::pair<DrvInfo, unsigned int> > Matches;
Matches matches;
unsigned int n = 0;
for (DrvInfos::const_iterator j = allElems.begin();
j != allElems.end(); ++j, ++n)
{
DrvName drvName(j->queryName());
if (i.matches(drvName)) {
i.hits++;
matches.push_back(std::pair<DrvInfo, unsigned int>(*j, n));
}
}
/* If `newestOnly', if a selector matches multiple derivations
with the same name, pick the one matching the current
system. If there are still multiple derivations, pick the
one with the highest priority. If there are still multiple
derivations, pick the one with the highest version.
Finally, if there are still multiple derivations,
arbitrarily pick the first one. */
if (newestOnly) {
matches = pickNewestOnly(state, std::move(matches));
/* Map from package names to derivations. */
typedef map<string, std::pair<DrvInfo, unsigned int> > Newest;
Newest newest;
StringSet multiple;
for (auto & j : matches) {
DrvName drvName(j.first.queryName());
long d = 1;
Newest::iterator k = newest.find(drvName.name);
if (k != newest.end()) {
d = j.first.querySystem() == k->second.first.querySystem() ? 0 :
j.first.querySystem() == settings.thisSystem ? 1 :
k->second.first.querySystem() == settings.thisSystem ? -1 : 0;
if (d == 0)
d = comparePriorities(state, j.first, k->second.first);
if (d == 0)
d = compareVersions(drvName.version, DrvName(k->second.first.queryName()).version);
}
if (d > 0) {
newest.erase(drvName.name);
newest.insert(Newest::value_type(drvName.name, j));
multiple.erase(j.first.queryName());
} else if (d == 0) {
multiple.insert(j.first.queryName());
}
}
matches.clear();
for (auto & j : newest) {
if (multiple.find(j.second.first.queryName()) != multiple.end())
printInfo(
"warning: there are multiple derivations named '%1%'; using the first one",
j.second.first.queryName());
matches.push_back(j.second);
}
}
/* Insert only those elements in the final list that we
haven't inserted before. */
for (auto & match : matches)
if (done.insert(match.index).second)
elems.push_back(match.drvInfo);
if (selector.hits == 0 && selector.fullName != "*") {
const auto prefixHits = searchByPrefix(allElems, selector.name);
if (prefixHits.empty()) {
throw Error("selector '%1%' matches no derivations", selector.fullName);
} else {
std::string suggestionMessage = ", maybe you meant:";
for (const auto & drvName : prefixHits) {
suggestionMessage += fmt("\n%s", drvName);
}
throw Error("selector '%1%' matches no derivations" + suggestionMessage, selector.fullName);
}
}
for (auto & j : matches)
if (done.insert(j.second).second)
elems.push_back(j.first);
}
checkSelectorUse(selectors);
return elems;
}

View File

@@ -83,14 +83,11 @@ UnresolvedApp Installable::toApp(EvalState & state)
auto outPath = cursor->getAttr(state.sOutPath)->getString();
auto outputName = cursor->getAttr(state.sOutputName)->getString();
auto name = cursor->getAttr(state.sName)->getString();
auto aPname = cursor->maybeGetAttr("pname");
auto aMeta = cursor->maybeGetAttr("meta");
auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr;
auto mainProgram =
aMainProgram
? aMainProgram->getString()
: aPname
? aPname->getString()
: DrvName(name).name;
auto program = outPath + "/bin/" + mainProgram;
return UnresolvedApp { App {

View File

@@ -638,142 +638,6 @@ struct CmdFlakeCheck : FlakeCommand
}
};
struct CmdFlakeInitCommon : virtual Args, EvalCommand
{
std::string templateUrl = "templates";
Path destDir;
const Strings attrsPathPrefixes{"templates."};
const LockFlags lockFlags{ .writeLockFile = false };
CmdFlakeInitCommon()
{
addFlag({
.longName = "template",
.shortName = 't',
.description = "The template to use.",
.labels = {"template"},
.handler = {&templateUrl},
.completer = {[&](size_t, std::string_view prefix) {
completeFlakeRefWithFragment(
getEvalState(),
lockFlags,
attrsPathPrefixes,
{"defaultTemplate"},
prefix);
}}
});
}
void run(nix::ref<nix::Store> store) override
{
auto flakeDir = absPath(destDir);
auto evalState = getEvalState();
auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment(templateUrl, absPath("."));
auto installable = InstallableFlake(nullptr,
evalState, std::move(templateFlakeRef),
Strings{templateName == "" ? "defaultTemplate" : templateName},
Strings(attrsPathPrefixes), lockFlags);
auto [cursor, attrPath] = installable.getCursor(*evalState);
auto templateDir = cursor->getAttr("path")->getString();
assert(store->isInStore(templateDir));
std::vector<Path> files;
std::function<void(const Path & from, const Path & to)> copyDir;
copyDir = [&](const Path & from, const Path & to)
{
createDirs(to);
for (auto & entry : readDirectory(from)) {
auto from2 = from + "/" + entry.name;
auto to2 = to + "/" + entry.name;
auto st = lstat(from2);
if (S_ISDIR(st.st_mode))
copyDir(from2, to2);
else if (S_ISREG(st.st_mode)) {
auto contents = readFile(from2);
if (pathExists(to2)) {
auto contents2 = readFile(to2);
if (contents != contents2)
throw Error("refusing to overwrite existing file '%s'", to2);
} else
writeFile(to2, contents);
}
else if (S_ISLNK(st.st_mode)) {
auto target = readLink(from2);
if (pathExists(to2)) {
if (readLink(to2) != target)
throw Error("refusing to overwrite existing symlink '%s'", to2);
} else
createSymlink(target, to2);
}
else
throw Error("file '%s' has unsupported type", from2);
files.push_back(to2);
}
};
copyDir(templateDir, flakeDir);
if (pathExists(flakeDir + "/.git")) {
Strings args = { "-C", flakeDir, "add", "--intent-to-add", "--force", "--" };
for (auto & s : files) args.push_back(s);
runProgram("git", true, args);
}
}
};
struct CmdFlakeInit : CmdFlakeInitCommon
{
std::string description() override
{
return "create a flake in the current directory from a template";
}
std::string doc() override
{
return
#include "flake-init.md"
;
}
CmdFlakeInit()
{
destDir = ".";
}
};
struct CmdFlakeNew : CmdFlakeInitCommon
{
std::string description() override
{
return "create a flake in the specified directory from a template";
}
std::string doc() override
{
return
#include "flake-new.md"
;
}
CmdFlakeNew()
{
expectArgs({
.label = "dest-dir",
.handler = {&destDir},
.completer = completePath
});
}
};
struct CmdFlakeClone : FlakeCommand
{
Path destDir;
@@ -1125,8 +989,6 @@ struct CmdFlake : NixMultiCommand
{"metadata", []() { return make_ref<CmdFlakeMetadata>(); }},
{"info", []() { return make_ref<CmdFlakeInfo>(); }},
{"check", []() { return make_ref<CmdFlakeCheck>(); }},
{"init", []() { return make_ref<CmdFlakeInit>(); }},
{"new", []() { return make_ref<CmdFlakeNew>(); }},
{"clone", []() { return make_ref<CmdFlakeClone>(); }},
{"archive", []() { return make_ref<CmdFlakeArchive>(); }},
{"show", []() { return make_ref<CmdFlakeShow>(); }},

View File

@@ -106,26 +106,28 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
});
}
std::map<std::string, std::vector<std::string>> aliases = {
{"add-to-store", {"store", "add-path"}},
{"cat-nar", {"nar", "cat"}},
{"cat-store", {"store", "cat"}},
{"copy-sigs", {"store", "copy-sigs"}},
{"dev-shell", {"develop"}},
{"diff-closures", {"store", "diff-closures"}},
{"dump-path", {"store", "dump-path"}},
{"hash-file", {"hash", "file"}},
{"hash-path", {"hash", "path"}},
{"ls-nar", {"nar", "ls"}},
{"ls-store", {"store", "ls"}},
{"make-content-addressable", {"store", "make-content-addressable"}},
{"optimise-store", {"store", "optimise"}},
{"ping-store", {"store", "ping"}},
{"sign-paths", {"store", "sign"}},
{"to-base16", {"hash", "to-base16"}},
{"to-base32", {"hash", "to-base32"}},
{"to-base64", {"hash", "to-base64"}},
{"verify", {"store", "verify"}},
std::map<std::vector<std::string>, std::vector<std::string>> aliases = {
{{"add-to-store"}, {"store", "add-path"}},
{{"cat-nar"}, {"nar", "cat"}},
{{"cat-store"}, {"store", "cat"}},
{{"copy-sigs"}, {"store", "copy-sigs"}},
{{"dev-shell"}, {"develop"}},
{{"diff-closures"}, {"store", "diff-closures"}},
{{"dump-path"}, {"store", "dump-path"}},
{{"hash-file"}, {"hash", "file"}},
{{"hash-path"}, {"hash", "path"}},
{{"ls-nar"}, {"nar", "ls"}},
{{"ls-store"}, {"store", "ls"}},
{{"make-content-addressable"}, {"store", "make-content-addressable"}},
{{"optimise-store"}, {"store", "optimise"}},
{{"ping-store"}, {"store", "ping"}},
{{"sign-paths"}, {"store", "sign"}},
{{"to-base16"}, {"hash", "to-base16"}},
{{"to-base32"}, {"hash", "to-base32"}},
{{"to-base64"}, {"hash", "to-base64"}},
{{"verify"}, {"store", "verify"}},
{{"flake", "init"}, {"init"}},
{{"flake", "new"}, {"new"}},
};
bool aliasUsed = false;
@@ -134,14 +136,33 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
{
if (aliasUsed || command || pos == args.end()) return pos;
auto arg = *pos;
auto i = aliases.find(arg);
if (i == aliases.end()) return pos;
warn("'%s' is a deprecated alias for '%s'",
arg, concatStringsSep(" ", i->second));
pos = args.erase(pos);
for (auto j = i->second.rbegin(); j != i->second.rend(); ++j)
pos = args.insert(pos, *j);
aliasUsed = true;
// Loop through the aliases to see whether the current cli corresponds
// to one of them.
for (auto & [from, to] : aliases) {
auto i = pos;
bool isCurrentAlias = true;
// Is the current alias a prefix of the args?
for (auto & fromItem : from) {
if (i == args.end() || *i != fromItem) {
// The current alias doesnt match the args
isCurrentAlias = false;
break;
}
i++;
}
// If we went through to the end of the previous loop, then we match
// the currently considered alias.
// So rewrite the alias in the current args.
if (isCurrentAlias) {
warn("'%s' is a deprecated alias for '%s'",
concatStringsSep(" ", from), concatStringsSep(" ", to));
pos = args.erase(pos, i);
pos = args.insert(pos, to.begin(), to.end());
aliasUsed = true;
return pos;
}
}
return pos;
}

150
src/nix/new.cc Normal file
View File

@@ -0,0 +1,150 @@
#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "local-fs-store.hh"
#include "fs-accessor.hh"
#include "eval-cache.hh"
using namespace nix;
using namespace nix::flake;
struct CmdFlakeInitCommon : virtual Args, EvalCommand
{
std::string templateUrl = "templates";
Path destDir;
const Strings attrsPathPrefixes{"templates."};
const LockFlags lockFlags{ .writeLockFile = false };
CmdFlakeInitCommon()
{
addFlag({
.longName = "template",
.shortName = 't',
.description = "The template to use.",
.labels = {"template"},
.handler = {&templateUrl},
.completer = {[&](size_t, std::string_view prefix) {
completeFlakeRefWithFragment(
getEvalState(),
lockFlags,
attrsPathPrefixes,
{"defaultTemplate"},
prefix);
}}
});
}
void run(nix::ref<nix::Store> store) override
{
auto flakeDir = absPath(destDir);
auto evalState = getEvalState();
auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment(templateUrl, absPath("."));
auto installable = InstallableFlake(nullptr,
evalState, std::move(templateFlakeRef),
Strings{templateName == "" ? "defaultTemplate" : templateName},
Strings(attrsPathPrefixes), lockFlags);
auto [cursor, attrPath] = installable.getCursor(*evalState);
auto templateDir = cursor->getAttr("path")->getString();
assert(store->isInStore(templateDir));
std::vector<Path> files;
std::function<void(const Path & from, const Path & to)> copyDir;
copyDir = [&](const Path & from, const Path & to)
{
createDirs(to);
for (auto & entry : readDirectory(from)) {
auto from2 = from + "/" + entry.name;
auto to2 = to + "/" + entry.name;
auto st = lstat(from2);
if (S_ISDIR(st.st_mode))
copyDir(from2, to2);
else if (S_ISREG(st.st_mode)) {
auto contents = readFile(from2);
if (pathExists(to2)) {
auto contents2 = readFile(to2);
if (contents != contents2)
throw Error("refusing to overwrite existing file '%s'", to2);
} else
writeFile(to2, contents);
}
else if (S_ISLNK(st.st_mode)) {
auto target = readLink(from2);
if (pathExists(to2)) {
if (readLink(to2) != target)
throw Error("refusing to overwrite existing symlink '%s'", to2);
} else
createSymlink(target, to2);
}
else
throw Error("file '%s' has unsupported type", from2);
files.push_back(to2);
}
};
copyDir(templateDir, flakeDir);
if (pathExists(flakeDir + "/.git")) {
Strings args = { "-C", flakeDir, "add", "--intent-to-add", "--force", "--" };
for (auto & s : files) args.push_back(s);
runProgram("git", true, args);
}
}
};
struct CmdFlakeInit : CmdFlakeInitCommon
{
std::string description() override
{
return "create a flake in the current directory from a template";
}
std::string doc() override
{
return
#include "init.md"
;
}
CmdFlakeInit()
{
destDir = ".";
}
};
struct CmdFlakeNew : CmdFlakeInitCommon
{
std::string description() override
{
return "create a flake in the specified directory from a template";
}
std::string doc() override
{
return
#include "new.md"
;
}
CmdFlakeNew()
{
expectArgs({
.label = "dest-dir",
.handler = {&destDir},
.completer = completePath
});
}
};
static auto r0 = registerCommand<CmdFlakeInit>("init");
static auto r1 = registerCommand<CmdFlakeNew>("new");

View File

@@ -2,7 +2,7 @@ R""(
# Description
`nix registry` provides subcommands for managing *flake
`nix flake` provides subcommands for managing *flake
registries*. Flake registries are a convenience feature that allows
you to refer to flakes using symbolic identifiers such as `nixpkgs`,
rather than full URLs such as `git://github.com/NixOS/nixpkgs`. You

View File

@@ -279,7 +279,6 @@ bool NixRepl::getLine(string & input, const std::string &prompt)
};
setupSignals();
Finally resetTerminal([&]() { rl_deprep_terminal(); });
char * s = readline(prompt.c_str());
Finally doFree([&]() { free(s); });
restoreSignals();
@@ -357,8 +356,6 @@ StringSet NixRepl::completePrefix(string prefix)
// Quietly ignore evaluation errors.
} catch (UndefinedVarError & e) {
// Quietly ignore undefined variable errors.
} catch (BadURL & e) {
// Quietly ignore BadURL flake-related errors.
}
}
@@ -430,8 +427,7 @@ bool NixRepl::processLine(string line)
<< " :s <expr> Build dependencies of derivation, then start nix-shell\n"
<< " :t <expr> Describe result of evaluation\n"
<< " :u <expr> Build derivation, then start nix-shell\n"
<< " :doc <expr> Show documentation of a builtin function\n"
<< " :log <expr> Show logs for a derivation\n";
<< " :doc <expr> Show documentation of a builtin function\n";
}
else if (command == ":a" || command == ":add") {
@@ -501,7 +497,7 @@ bool NixRepl::processLine(string line)
runNix("nix-shell", {state->store->printStorePath(drvPath)});
}
else if (command == ":b" || command == ":i" || command == ":s" || command == ":log") {
else if (command == ":b" || command == ":i" || command == ":s") {
Value v;
evalString(arg, v);
StorePath drvPath = getDerivationPath(v);
@@ -515,27 +511,6 @@ bool NixRepl::processLine(string line)
logger->cout(" %s -> %s", outputName, state->store->printStorePath(outputPath));
} else if (command == ":i") {
runNix("nix-env", {"-i", drvPathRaw});
} else if (command == ":log") {
settings.readOnlyMode = true;
Finally roModeReset([&]() {
settings.readOnlyMode = false;
});
auto subs = getDefaultSubstituters();
subs.push_front(state->store);
bool foundLog = false;
RunPager pager;
for (auto & sub : subs) {
auto log = sub->getBuildLog(drvPath);
if (log) {
printInfo("got build log for '%s' from '%s'", drvPathRaw, sub->getUri());
logger->writeToStdout(*log);
foundLog = true;
break;
}
}
if (!foundLog) throw Error("build log of '%s' is not available", drvPathRaw);
} else {
runNix("nix-shell", {drvPathRaw});
}
@@ -672,8 +647,6 @@ void NixRepl::addVarToScope(const Symbol & name, Value & v)
{
if (displ >= envSize)
throw Error("environment full; cannot add more variables");
if (auto oldVar = staticEnv.find(name); oldVar != staticEnv.vars.end())
staticEnv.vars.erase(oldVar);
staticEnv.vars.emplace_back(name, displ);
staticEnv.sort();
env->values[displ++] = &v;

View File

@@ -35,17 +35,14 @@ R""(
nix-repl> emacs.drvPath
"/nix/store/lp0sjrhgg03y2n0l10n70rg0k7hhyz0l-emacs-27.1.drv"
nix-repl> drv = runCommand "hello" { buildInputs = [ hello ]; } "hello; hello > $out"
nix-repl> drv = runCommand "hello" { buildInputs = [ hello ]; } "hello > $out"
nix-repl> :b drv
nix-repl> :b x
this derivation produced the following outputs:
out -> /nix/store/0njwbgwmkwls0w5dv9mpc1pq5fj39q0l-hello
nix-repl> builtins.readFile drv
"Hello, world!\n"
nix-repl> :log drv
Hello, world!
```
# Description

View File

@@ -43,15 +43,10 @@ program specified by the app definition.
If *installable* evaluates to a derivation, it will try to execute the
program `<out>/bin/<name>`, where *out* is the primary output store
path of the derivation, and *name* is the first of the following that
exists:
* The `meta.mainProgram` attribute of the derivation.
* The `pname` attribute of the derivation.
* The name part of the value of the `name` attribute of the derivation.
For instance, if `name` is set to `hello-1.10`, `nix run` will run
`$out/bin/hello`.
path of the derivation and *name* is the `meta.mainProgram` attribute
of the derivation if it exists, and otherwise the name part of the
value of the `name` attribute of the derivation (e.g. if `name` is set
to `hello-1.10`, it will run `$out/bin/hello`).
# Flake output attributes

View File

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

View File

@@ -722,7 +722,6 @@ cat > $flakeFollowsB/flake.nix <<EOF
inputs = {
foobar.url = "path:$flakeFollowsA/flakeE";
nonFlake.url = "path:$nonFlakeDir";
goodoo.follows = "C/goodoo";
C = {
url = "path:./flakeC";
inputs.foobar.follows = "foobar";
@@ -737,7 +736,6 @@ cat > $flakeFollowsC/flake.nix <<EOF
description = "Flake C";
inputs = {
foobar.url = "path:$flakeFollowsA/flakeE";
goodoo.follows = "foobar";
};
outputs = { ... }: {};
}
@@ -762,18 +760,8 @@ EOF
git -C $flakeFollowsA add flake.nix flakeB/flake.nix \
flakeB/flakeC/flake.nix flakeD/flake.nix flakeE/flake.nix
nix flake update $flakeFollowsA
oldLock="$(cat "$flakeFollowsA/flake.lock")"
# Ensure that locking twice doesn't change anything
nix flake lock $flakeFollowsA
newLock="$(cat "$flakeFollowsA/flake.lock")"
diff <(echo "$newLock") <(echo "$oldLock")
[[ $(jq -c .nodes.B.inputs.C $flakeFollowsA/flake.lock) = '"C"' ]]
[[ $(jq -c .nodes.B.inputs.foobar $flakeFollowsA/flake.lock) = '["D"]' ]]
[[ $(jq -c .nodes.C.inputs.foobar $flakeFollowsA/flake.lock) = '["B","foobar"]' ]]

View File

@@ -19,7 +19,7 @@ pid=$!
sleep 2
outPath=$(nix-build --max-silent-time 60 -o "$TEST_ROOT/result" -E "
outPath=$(nix-build -o "$TEST_ROOT/result" -E "
with import ./config.nix;
mkDerivation {
name = \"non-blocking\";

View File

@@ -48,6 +48,7 @@ nix_tests = \
flakes.sh \
flake-local-settings.sh \
build.sh \
compute-levels.sh \
repl.sh ca/repl.sh \
ca/build.sh \
ca/build-with-garbage-path.sh \
@@ -62,10 +63,6 @@ nix_tests = \
eval-store.sh
# parallel.sh
ifeq ($(HAVE_LIBCPUID), 1)
nix_tests += compute-levels.sh
endif
install-tests += $(foreach x, $(nix_tests), tests/$(x))
tests-environment = NIX_REMOTE= $(bash) -e

View File

@@ -3,53 +3,59 @@ source common.sh
clearStore
if [[ -n ${CONTENT_ADDRESSED:-} ]]; then
shellDotNix="$PWD/ca-shell.nix"
else
shellDotNix="$PWD/shell.nix"
fi
nix-shell () {
command nix-shell --arg contentAddressed true "$@"
}
export NIX_PATH=nixpkgs="$shellDotNix"
nix_develop() {
nix develop --arg contentAddressed true "$@"
}
else
nix_develop() {
nix develop "$@"
}
fi
# Test nix-shell -A
export IMPURE_VAR=foo
export SELECTED_IMPURE_VAR=baz
output=$(nix-shell --pure "$shellDotNix" -A shellDrv --run \
export NIX_BUILD_SHELL=$SHELL
output=$(nix-shell --pure shell.nix -A shellDrv --run \
'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"')
[ "$output" = " - foo - bar - true" ]
# Test --keep
output=$(nix-shell --pure --keep SELECTED_IMPURE_VAR "$shellDotNix" -A shellDrv --run \
output=$(nix-shell --pure --keep SELECTED_IMPURE_VAR shell.nix -A shellDrv --run \
'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $SELECTED_IMPURE_VAR"')
[ "$output" = " - foo - bar - baz" ]
# Test nix-shell on a .drv
[[ $(nix-shell --pure $(nix-instantiate "$shellDotNix" -A shellDrv) --run \
[[ $(nix-shell --pure $(nix-instantiate shell.nix -A shellDrv) --run \
'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') = " - foo - bar - false" ]]
[[ $(nix-shell --pure $(nix-instantiate "$shellDotNix" -A shellDrv) --run \
[[ $(nix-shell --pure $(nix-instantiate shell.nix -A shellDrv) --run \
'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') = " - foo - bar - false" ]]
# Test nix-shell on a .drv symlink
# Legacy: absolute path and .drv extension required
nix-instantiate "$shellDotNix" -A shellDrv --add-root $TEST_ROOT/shell.drv
nix-instantiate shell.nix -A shellDrv --add-root $TEST_ROOT/shell.drv
[[ $(nix-shell --pure $TEST_ROOT/shell.drv --run \
'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]]
# New behaviour: just needs to resolve to a derivation in the store
nix-instantiate "$shellDotNix" -A shellDrv --add-root $TEST_ROOT/shell
nix-instantiate shell.nix -A shellDrv --add-root $TEST_ROOT/shell
[[ $(nix-shell --pure $TEST_ROOT/shell --run \
'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]]
# Test nix-shell -p
output=$(NIX_PATH=nixpkgs="$shellDotNix" nix-shell --pure -p foo bar --run 'echo "$(foo) $(bar)"')
output=$(NIX_PATH=nixpkgs=shell.nix nix-shell --pure -p foo bar --run 'echo "$(foo) $(bar)"')
[ "$output" = "foo bar" ]
# Test nix-shell -p --arg x y
output=$(NIX_PATH=nixpkgs="$shellDotNix" nix-shell --pure -p foo --argstr fooContents baz --run 'echo "$(foo)"')
output=$(NIX_PATH=nixpkgs=shell.nix nix-shell --pure -p foo --argstr fooContents baz --run 'echo "$(foo)"')
[ "$output" = "baz" ]
# Test nix-shell shebang mode
@@ -85,18 +91,18 @@ output=$($TEST_ROOT/spaced\ \\\'\"shell.shebang.rb abc ruby)
[ "$output" = '-e load(ARGV.shift) -- '"$TEST_ROOT"'/spaced \'\''"shell.shebang.rb abc ruby' ]
# Test 'nix develop'.
nix develop -f "$shellDotNix" shellDrv -c bash -c '[[ -n $stdenv ]]'
nix_develop -f shell.nix shellDrv -c bash -c '[[ -n $stdenv ]]'
# Ensure `nix develop -c` preserves stdin
echo foo | nix develop -f "$shellDotNix" shellDrv -c cat | grep -q foo
echo foo | nix develop -f shell.nix shellDrv -c cat | grep -q foo
# Ensure `nix develop -c` actually executes the command if stdout isn't a terminal
nix develop -f "$shellDotNix" shellDrv -c echo foo |& grep -q foo
nix_develop -f shell.nix shellDrv -c echo foo |& grep -q foo
# Test 'nix print-dev-env'.
[[ $(nix print-dev-env -f "$shellDotNix" shellDrv --json | jq -r .variables.arr1.value[2]) = '3 4' ]]
[[ $(nix print-dev-env -f shell.nix shellDrv --json | jq -r .variables.arr1.value[2]) = '3 4' ]]
source <(nix print-dev-env -f "$shellDotNix" shellDrv)
source <(nix print-dev-env -f shell.nix shellDrv)
[[ -n $stdenv ]]
[[ ${arr1[2]} = "3 4" ]]
[[ ${arr2[1]} = $'\n' ]]

View File

@@ -1,16 +1,8 @@
source common.sh
replCmds="
simple = 1
simple = import ./simple.nix
:b simple
:log simple
"
replFailingCmds="
failing = import ./simple-failing.nix
:b failing
:log failing
"
testRepl () {
@@ -20,12 +12,6 @@ testRepl () {
local outPath=$(echo "$replOutput" |&
grep -o -E "$NIX_STORE_DIR/\w*-simple")
nix path-info "${nixArgs[@]}" "$outPath"
# simple.nix prints a PATH during build
echo "$replOutput" | grep -qs 'PATH=' || fail "nix repl :log doesn't output logs"
local replOutput="$(nix repl "${nixArgs[@]}" <<< "$replFailingCmds")"
echo "$replOutput"
echo "$replOutput" | grep -qs 'This should fail' \
|| fail "nix repl :log doesn't output logs for a failed derivation"
}
# Simple test, try building a drv

View File

@@ -74,10 +74,6 @@ let pkgs = rec {
'';
bash = shell;
bashInteractive = runCommand "bash" {} ''
mkdir -p $out/bin
ln -s ${shell} $out/bin/bash
'';
# ruby "interpreter" that outputs "$@"
ruby = runCommand "ruby" {} ''

View File

@@ -1,12 +0,0 @@
with import ./config.nix;
mkDerivation {
name = "simple-failing";
builder = builtins.toFile "builder.sh"
''
echo "This should fail"
exit 1
'';
PATH = "";
goodPath = path;
}