Merge remote-tracking branch 'origin/master' into flake-substitution

This commit is contained in:
Eelco Dolstra 2024-11-08 16:42:12 +01:00
commit ecb418e163
157 changed files with 881 additions and 670 deletions

View File

@ -214,4 +214,4 @@ jobs:
path: flake-regressions/tests
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
- run: nix build --out-link ./new-nix && PATH=$(pwd)/new-nix/bin:$PATH scripts/flake-regressions.sh
- run: nix build --out-link ./new-nix && PATH=$(pwd)/new-nix/bin:$PATH MAX_FLAKES=25 flake-regressions/eval-all.sh

View File

@ -91,6 +91,7 @@ ifdef HOST_WINDOWS
#
# TODO do not do this, and instead do fine-grained export annotations.
GLOBAL_LDFLAGS += -Wl,--export-all-symbols
GLOBAL_CXXFLAGS += -D_WIN32_WINNT=0x0602
endif
GLOBAL_CXXFLAGS += -g -Wall -Wdeprecated-copy -Wignored-qualifiers -Wimplicit-fallthrough -Werror=unused-result -Werror=suggest-override -include $(buildprefix)config.h -std=c++2a -I src

View File

@ -0,0 +1,8 @@
# Check if -latomic is needed
# This is needed for std::atomic on some platforms
# We did not manage to test this reliably on all platforms, so we hardcode
# it for now.
if host_machine.cpu_family() == 'arm'
deps_other += cxx.find_library('atomic')
endif

View File

@ -0,0 +1,6 @@
if host_machine.system() == 'windows'
# https://learn.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170
# #define _WIN32_WINNT_WIN8 0x0602
# We currently don't use any API which requires higher than this.
add_project_arguments([ '-D_WIN32_WINNT=0x0602' ], language: 'cpp')
endif

View File

@ -1,25 +0,0 @@
---
synopsis: Show package descriptions with `nix flake show`
issues: [10977]
prs: [10980]
---
`nix flake show` will now display a package's `meta.description` if it exists. If the description does not fit in the terminal it will be truncated to fit the terminal width. If the size of the terminal width is unknown the description will be capped at 80 characters.
```
$ nix flake show
└───packages
└───x86_64-linux
├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix build environment'
└───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-runner executable'
```
In a narrower terminal:
```
$ nix flake show
└───packages
└───x86_64-linux
├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix b...
└───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-run...
```

View File

@ -121,6 +121,7 @@
- [Development](development/index.md)
- [Building](development/building.md)
- [Testing](development/testing.md)
- [Debugging](development/debugging.md)
- [Documentation](development/documentation.md)
- [CLI guideline](development/cli-guideline.md)
- [JSON guideline](development/json-guideline.md)

View File

@ -0,0 +1,62 @@
# Debugging Nix
This section shows how to build and debug Nix with debug symbols enabled.
## Building Nix with Debug Symbols
In the development shell, set the `mesonBuildType` environment variable to `debug` before configuring the build:
```console
[nix-shell]$ export mesonBuildType=debugoptimized
```
Then, proceed to build Nix as described in [Building Nix](./building.md).
This will build Nix with debug symbols, which are essential for effective debugging.
## Debugging the Nix Binary
Obtain your preferred debugger within the development shell:
```console
[nix-shell]$ nix-shell -p gdb
```
On macOS, use `lldb`:
```console
[nix-shell]$ nix-shell -p lldb
```
### Launching the Debugger
To debug the Nix binary, run:
```console
[nix-shell]$ gdb --args ../outputs/out/bin/nix
```
On macOS, use `lldb`:
```console
[nix-shell]$ lldb -- ../outputs/out/bin/nix
```
### Using the Debugger
Inside the debugger, you can set breakpoints, run the program, and inspect variables.
```gdb
(gdb) break main
(gdb) run <arguments>
```
Refer to the [GDB Documentation](https://www.gnu.org/software/gdb/documentation/) for comprehensive usage instructions.
On macOS, use `lldb`:
```lldb
(lldb) breakpoint set --name main
(lldb) process launch -- <arguments>
```
Refer to the [LLDB Tutorial](https://lldb.llvm.org/use/tutorial.html) for comprehensive usage instructions.

View File

@ -29,7 +29,7 @@ The unit tests are defined using the [googletest] and [rapidcheck] frameworks.
> ```
> src
> ├── libexpr
> │ ├── local.mk
> │ ├── meson.build
> │ ├── value/context.hh
> │ ├── value/context.cc
> │ …
@ -37,25 +37,24 @@ The unit tests are defined using the [googletest] and [rapidcheck] frameworks.
> ├── tests
> │ │
> │ …
> │ └── unit
> │ ├── libutil
> │ │ ├── local.mk
> │ │ …
> │ │ └── data
> │ │ ├── git/tree.txt
> │ │ …
> │ │
> │ ├── libexpr-support
> │ │ ├── local.mk
> │ │ └── tests
> │ │ ├── value/context.hh
> │ │ ├── value/context.cc
> │ │ …
> │ │
> │ ├── libexpr
> │ … ├── local.mk
> │ ├── value/context.cc
> │ …
> │ ├── libutil-tests
> │ │ ├── meson.build
> │ │ …
> │ │ └── data
> │ │ ├── git/tree.txt
> │ │ …
> │ │
> │ ├── libexpr-test-support
> │ │ ├── meson.build
> │ │ └── tests
> │ │ ├── value/context.hh
> │ │ ├── value/context.cc
> │ │ …
> │ │
> │ ├── libexpr-tests
> │ … ├── meson.build
> │ ├── value/context.cc
> │ …
> …
> ```
@ -128,7 +127,7 @@ On other platforms they wouldn't be run at all.
## Functional tests
The functional tests reside under the `tests/functional` directory and are listed in `tests/functional/local.mk`.
The functional tests reside under the `tests/functional` directory and are listed in `tests/functional/meson.build`.
Each test is a bash script.
Functional tests are run during `installCheck` in the `nix` package build, as well as separately from the build, in VM tests.

View File

@ -102,7 +102,7 @@ The `+` operator is overloaded to also work on strings and paths.
>
> *string* `+` *string*
Concatenate two [strings][string] and merge their string contexts.
Concatenate two [strings][string] and merge their [string contexts](./string-context.md).
[String concatenation]: #string-concatenation
@ -128,7 +128,7 @@ The result is a path.
> **Note**
>
> The string must not have a string context that refers to a [store path].
> The string must not have a [string context](./string-context.md) that refers to a [store path].
[Path and string concatenation]: #path-and-string-concatenation

119
flake.nix
View File

@ -294,109 +294,24 @@
});
devShells = let
makeShell = pkgs: stdenv: (pkgs.nix.override { inherit stdenv; forDevShell = true; }).overrideAttrs (attrs:
let
buildCanExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
modular = devFlake.getSystem stdenv.buildPlatform.system;
transformFlag = prefix: flag:
assert builtins.isString flag;
let
rest = builtins.substring 2 (builtins.stringLength flag) flag;
in
"-D${prefix}:${rest}";
havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix;
ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags;
in {
pname = "shell-for-" + attrs.pname;
# Remove the version suffix to avoid unnecessary attempts to substitute in nix develop
version = lib.fileContents ./.version;
name = attrs.pname;
installFlags = "sysconfdir=$(out)/etc";
shellHook = ''
PATH=$prefix/bin:$PATH
unset PYTHONPATH
export MANPATH=$out/share/man:$MANPATH
# Make bash completion work.
XDG_DATA_DIRS+=:$out/share
'';
# We use this shell with the local checkout, not unpackPhase.
src = null;
env = {
# Needed for Meson to find Boost.
# https://github.com/NixOS/nixpkgs/issues/86131.
BOOST_INCLUDEDIR = "${lib.getDev pkgs.nixDependencies.boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib pkgs.nixDependencies.boost}/lib";
# For `make format`, to work without installing pre-commit
_NIX_PRE_COMMIT_HOOKS_CONFIG =
"${(pkgs.formats.yaml { }).generate "pre-commit-config.yaml" modular.pre-commit.settings.rawConfig}";
};
mesonFlags =
map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents.nix-util.mesonFlags)
++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents.nix-store.mesonFlags)
++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents.nix-fetchers.mesonFlags)
++ lib.optionals havePerl (map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents.nix-perl-bindings.mesonFlags))
++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents.nix-expr.mesonFlags)
++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents.nix-cmd.mesonFlags)
;
nativeBuildInputs = attrs.nativeBuildInputs or []
++ pkgs.nixComponents.nix-util.nativeBuildInputs
++ pkgs.nixComponents.nix-store.nativeBuildInputs
++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs
++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs
++ lib.optionals buildCanExecuteHost pkgs.nixComponents.nix-manual.externalNativeBuildInputs
++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs
++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs
++ pkgs.nixComponents.nix-functional-tests.externalNativeBuildInputs
++ lib.optional
(!buildCanExecuteHost
# Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479
&& !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin)
&& stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages
&& lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages))
pkgs.buildPackages.mesonEmulatorHook
++ [
pkgs.buildPackages.cmake
pkgs.buildPackages.shellcheck
pkgs.buildPackages.changelog-d
modular.pre-commit.settings.package
(pkgs.writeScriptBin "pre-commit-hooks-install"
modular.pre-commit.settings.installationScript)
]
# TODO: Remove the darwin check once
# https://github.com/NixOS/nixpkgs/pull/291814 is available
++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear
++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) (lib.hiPrio pkgs.buildPackages.clang-tools);
buildInputs = attrs.buildInputs or []
++ [
pkgs.gtest
pkgs.rapidcheck
]
++ lib.optional havePerl pkgs.perl
;
});
in
makeShell = import ./packaging/dev-shell.nix { inherit lib devFlake; };
prefixAttrs = prefix: lib.concatMapAttrs (k: v: { "${prefix}-${k}" = v; });
in
forAllSystems (system:
let
makeShells = prefix: pkgs:
lib.mapAttrs'
(k: v: lib.nameValuePair "${prefix}-${k}" v)
(forAllStdenvs (stdenvName: makeShell pkgs pkgs.${stdenvName}));
in
(makeShells "native" nixpkgsFor.${system}.native) //
(lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin)
(makeShells "static" nixpkgsFor.${system}.static) //
(forAllCrossSystems (crossSystem: let pkgs = nixpkgsFor.${system}.cross.${crossSystem}; in makeShell pkgs pkgs.stdenv))) //
{
default = self.devShells.${system}.native-stdenvPackages;
}
prefixAttrs "native" (forAllStdenvs (stdenvName: makeShell {
pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages";
})) //
lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin) (
prefixAttrs "static" (forAllStdenvs (stdenvName: makeShell {
pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsStatic;
})) //
prefixAttrs "cross" (forAllCrossSystems (crossSystem: makeShell {
pkgs = nixpkgsFor.${system}.cross.${crossSystem};
}))
) //
{
default = self.devShells.${system}.native-stdenvPackages;
}
);
};
}

View File

@ -28,8 +28,6 @@
''^src/build-remote/build-remote\.cc$''
''^src/libcmd/built-path\.cc$''
''^src/libcmd/built-path\.hh$''
''^src/libcmd/command\.cc$''
''^src/libcmd/command\.hh$''
''^src/libcmd/common-eval-args\.cc$''
''^src/libcmd/common-eval-args\.hh$''
''^src/libcmd/editor-for\.cc$''
@ -547,7 +545,6 @@
''^tests/functional/flakes/absolute-paths\.sh$''
''^tests/functional/flakes/check\.sh$''
''^tests/functional/flakes/config\.sh$''
''^tests/functional/flakes/develop\.sh$''
''^tests/functional/flakes/flakes\.sh$''
''^tests/functional/flakes/follow-paths\.sh$''
''^tests/functional/flakes/prefetch\.sh$''

View File

@ -22,10 +22,12 @@ subproject('libcmd')
subproject('nix')
# Docs
subproject('internal-api-docs')
subproject('external-api-docs')
if not meson.is_cross_build()
subproject('nix-manual')
if get_option('doc-gen')
subproject('internal-api-docs')
subproject('external-api-docs')
if not meson.is_cross_build()
subproject('nix-manual')
endif
endif
# External C wrapper libraries
@ -35,17 +37,19 @@ subproject('libexpr-c')
subproject('libmain-c')
# Language Bindings
if not meson.is_cross_build()
if get_option('bindings') and not meson.is_cross_build()
subproject('perl')
endif
# Testing
subproject('libutil-test-support')
subproject('libutil-tests')
subproject('libstore-test-support')
subproject('libstore-tests')
subproject('libfetchers-tests')
subproject('libexpr-test-support')
subproject('libexpr-tests')
subproject('libflake-tests')
if get_option('unit-tests')
subproject('libutil-test-support')
subproject('libutil-tests')
subproject('libstore-test-support')
subproject('libstore-tests')
subproject('libfetchers-tests')
subproject('libexpr-test-support')
subproject('libexpr-tests')
subproject('libflake-tests')
endif
subproject('nix-functional-tests')

13
meson.options Normal file
View File

@ -0,0 +1,13 @@
# vim: filetype=meson
option('doc-gen', type : 'boolean', value : true,
description : 'Generate documentation',
)
option('unit-tests', type : 'boolean', value : true,
description : 'Build unit tests',
)
option('bindings', type : 'boolean', value : true,
description : 'Build language bindings (e.g. Perl)',
)

View File

@ -9,13 +9,21 @@ test_name=$(echo -n "${test?must be defined by caller (test runner)}" | sed \
-e "s|\.sh$||" \
)
# Layer violation, but I am not inclined to care too much, as this code
# is about to be deleted.
src_dir=$(realpath tests/functional)
# shellcheck disable=SC2016
TESTS_ENVIRONMENT=(
"TEST_NAME=$test_name"
'NIX_REMOTE='
'PS4=+(${BASH_SOURCE[0]-$0}:$LINENO) '
"_NIX_TEST_SOURCE_DIR=${src_dir}"
"_NIX_TEST_BUILD_DIR=${src_dir}"
)
unset src_dir
read -r -a bash <<< "${BASH:-/usr/bin/env bash}"
run () {

96
packaging/dev-shell.nix Normal file
View File

@ -0,0 +1,96 @@
{ lib, devFlake }:
{ pkgs }:
(pkgs.nix.override { forDevShell = true; }).overrideAttrs (attrs:
let
stdenv = pkgs.nixDependencies.stdenv;
buildCanExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
modular = devFlake.getSystem stdenv.buildPlatform.system;
transformFlag = prefix: flag:
assert builtins.isString flag;
let
rest = builtins.substring 2 (builtins.stringLength flag) flag;
in
"-D${prefix}:${rest}";
havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix;
ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags;
in {
pname = "shell-for-" + attrs.pname;
# Remove the version suffix to avoid unnecessary attempts to substitute in nix develop
version = lib.fileContents ../.version;
name = attrs.pname;
installFlags = "sysconfdir=$(out)/etc";
shellHook = ''
PATH=$prefix/bin:$PATH
unset PYTHONPATH
export MANPATH=$out/share/man:$MANPATH
# Make bash completion work.
XDG_DATA_DIRS+=:$out/share
'';
# We use this shell with the local checkout, not unpackPhase.
src = null;
env = {
# Needed for Meson to find Boost.
# https://github.com/NixOS/nixpkgs/issues/86131.
BOOST_INCLUDEDIR = "${lib.getDev pkgs.nixDependencies.boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib pkgs.nixDependencies.boost}/lib";
# For `make format`, to work without installing pre-commit
_NIX_PRE_COMMIT_HOOKS_CONFIG =
"${(pkgs.formats.yaml { }).generate "pre-commit-config.yaml" modular.pre-commit.settings.rawConfig}";
};
mesonFlags =
map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents.nix-util.mesonFlags)
++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents.nix-store.mesonFlags)
++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents.nix-fetchers.mesonFlags)
++ lib.optionals havePerl (map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents.nix-perl-bindings.mesonFlags))
++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents.nix-expr.mesonFlags)
++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents.nix-cmd.mesonFlags)
;
nativeBuildInputs = attrs.nativeBuildInputs or []
++ pkgs.nixComponents.nix-util.nativeBuildInputs
++ pkgs.nixComponents.nix-store.nativeBuildInputs
++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs
++ pkgs.nixComponents.nix-expr.nativeBuildInputs
++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs
++ lib.optionals buildCanExecuteHost pkgs.nixComponents.nix-manual.externalNativeBuildInputs
++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs
++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs
++ pkgs.nixComponents.nix-functional-tests.externalNativeBuildInputs
++ lib.optional
(!buildCanExecuteHost
# Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479
&& !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin)
&& stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages
&& lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages))
pkgs.buildPackages.mesonEmulatorHook
++ [
pkgs.buildPackages.cmake
pkgs.buildPackages.shellcheck
pkgs.buildPackages.changelog-d
modular.pre-commit.settings.package
(pkgs.writeScriptBin "pre-commit-hooks-install"
modular.pre-commit.settings.installationScript)
]
# TODO: Remove the darwin check once
# https://github.com/NixOS/nixpkgs/pull/291814 is available
++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear
++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) (lib.hiPrio pkgs.buildPackages.clang-tools);
buildInputs = attrs.buildInputs or []
++ pkgs.nixComponents.nix-util.buildInputs
++ pkgs.nixComponents.nix-store.buildInputs
++ pkgs.nixComponents.nix-fetchers.buildInputs
++ pkgs.nixComponents.nix-expr.buildInputs
++ pkgs.nixComponents.nix-store-tests.externalBuildInputs
++ lib.optional havePerl pkgs.perl
;
})

View File

@ -16,25 +16,16 @@ let
inherit tarballs;
};
testNixVersions = pkgs: client: daemon:
pkgs.nixComponents.callPackage ../package.nix {
testNixVersions = pkgs: daemon:
pkgs.nixComponents.nix-functional-tests.override {
pname =
"nix-tests"
+ lib.optionalString
(lib.versionAtLeast daemon.version "2.4pre20211005" &&
lib.versionAtLeast client.version "2.4pre20211005")
"-${client.version}-against-${daemon.version}";
lib.versionAtLeast pkgs.nix.version "2.4pre20211005")
"-${pkgs.nix.version}-against-${daemon.version}";
test-client = client;
test-daemon = daemon;
doBuild = false;
# This could be more accurate, but a shorter version will match the
# fine version with rev. This functionality is already covered in
# the normal test, so it's fine.
version = pkgs.nixComponents.version;
versionSuffix = pkgs.nixComponents.versionSuffix;
};
# Technically we could just return `pkgs.nixComponents`, but for Hydra it's
@ -71,7 +62,9 @@ in
build = forAllPackages (pkgName:
forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.${pkgName}));
shellInputs = forAllSystems (system: self.devShells.${system}.default.inputDerivation);
shellInputs = removeAttrs
(forAllSystems (system: self.devShells.${system}.default.inputDerivation))
[ "i686-linux" ];
buildStatic = forAllPackages (pkgName:
lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName}));
@ -82,20 +75,28 @@ in
(forAllCrossSystems (crossSystem:
lib.genAttrs [ "x86_64-linux" ] (system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName}))));
buildNoGc = forAllSystems (system:
self.packages.${system}.nix.override { enableGC = false; }
);
buildNoGc = let
components = forAllSystems (system:
nixpkgsFor.${system}.native.nixComponents.overrideScope (self: super: {
nix-expr = super.nix-expr.override { enableGC = false; };
})
);
in forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName}));
buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-cli);
# Toggles some settings for better coverage. Windows needs these
# library combinations, and Debian build Nix with GNU readline too.
buildReadlineNoMarkdown = forAllSystems (system:
self.packages.${system}.nix.override {
enableMarkdown = false;
readlineFlavor = "readline";
}
);
buildReadlineNoMarkdown = let
components = forAllSystems (system:
nixpkgsFor.${system}.native.nixComponents.overrideScope (self: super: {
nix-cmd = super.nix-cmd.override {
enableMarkdown = false;
readlineFlavor = "readline";
};
})
);
in forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName}));
# Perl bindings for various platforms.
perlBindings = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-perl-bindings);
@ -196,15 +197,15 @@ in
let pkgs = nixpkgsFor.${system}.native; in
pkgs.runCommand "install-tests"
{
againstSelf = testNixVersions pkgs pkgs.nix pkgs.pkgs.nix;
againstSelf = testNixVersions pkgs pkgs.nix;
againstCurrentLatest =
# FIXME: temporarily disable this on macOS because of #3605.
if system == "x86_64-linux"
then testNixVersions pkgs pkgs.nix pkgs.nixVersions.latest
then testNixVersions pkgs pkgs.nixVersions.latest
else null;
# Disabled because the latest stable version doesn't handle
# `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work
# againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable;
# againstLatestStable = testNixVersions pkgs pkgs.nixStable;
} "touch $out");
installerTests = import ../tests/installer {

View File

@ -1,27 +0,0 @@
#! /usr/bin/env bash
set -e
echo "Nix version:"
nix --version
cd flake-regressions
status=0
flakes=$(find tests -mindepth 3 -maxdepth 3 -type d -not -path '*/.*' | sort | head -n25)
echo "Running flake tests..."
for flake in $flakes; do
if ! REGENERATE=0 ./eval-flake.sh "$flake"; then
status=1
echo "$flake"
else
echo "$flake"
fi
done
exit "$status"

View File

@ -1,3 +1,4 @@
#include <algorithm>
#include <nlohmann/json.hpp>
#include "command.hh"
@ -9,8 +10,7 @@
#include "profiles.hh"
#include "repl.hh"
#include "strings.hh"
extern char * * environ __attribute__((weak));
#include "environment-variables.hh"
namespace nix {
@ -23,7 +23,8 @@ nix::Commands RegisterCommand::getCommandsFor(const std::vector<std::string> & p
if (name.size() == prefix.size() + 1) {
bool equal = true;
for (size_t i = 0; i < prefix.size(); ++i)
if (name[i] != prefix[i]) equal = false;
if (name[i] != prefix[i])
equal = false;
if (equal)
res.insert_or_assign(name[prefix.size()], command);
}
@ -42,16 +43,16 @@ void NixMultiCommand::run()
std::set<std::string> subCommandTextLines;
for (auto & [name, _] : commands)
subCommandTextLines.insert(fmt("- `%s`", name));
std::string markdownError = fmt("`nix %s` requires a sub-command. Available sub-commands:\n\n%s\n",
commandName, concatStringsSep("\n", subCommandTextLines));
std::string markdownError =
fmt("`nix %s` requires a sub-command. Available sub-commands:\n\n%s\n",
commandName,
concatStringsSep("\n", subCommandTextLines));
throw UsageError(renderMarkdownToTerminal(markdownError));
}
command->second->run();
}
StoreCommand::StoreCommand()
{
}
StoreCommand::StoreCommand() {}
ref<Store> StoreCommand::getStore()
{
@ -126,10 +127,8 @@ ref<Store> EvalCommand::getEvalStore()
ref<EvalState> EvalCommand::getEvalState()
{
if (!evalState) {
evalState =
std::allocate_shared<EvalState>(
traceable_allocator<EvalState>(),
lookupPath, getEvalStore(), fetchSettings, evalSettings, getStore());
evalState = std::allocate_shared<EvalState>(
traceable_allocator<EvalState>(), lookupPath, getEvalStore(), fetchSettings, evalSettings, getStore());
evalState->repair = repair;
@ -144,7 +143,8 @@ MixOperateOnOptions::MixOperateOnOptions()
{
addFlag({
.longName = "derivation",
.description = "Operate on the [store derivation](@docroot@/glossary.md#gloss-store-derivation) rather than its outputs.",
.description =
"Operate on the [store derivation](@docroot@/glossary.md#gloss-store-derivation) rather than its outputs.",
.category = installablesCategory,
.handler = {&operateOn, OperateOn::Derivation},
});
@ -233,46 +233,48 @@ void StorePathCommand::run(ref<Store> store, StorePaths && storePaths)
MixProfile::MixProfile()
{
addFlag({
.longName = "profile",
.description = "The profile to operate on.",
.labels = {"path"},
.handler = {&profile},
.completer = completePath
});
addFlag(
{.longName = "profile",
.description = "The profile to operate on.",
.labels = {"path"},
.handler = {&profile},
.completer = completePath});
}
void MixProfile::updateProfile(const StorePath & storePath)
{
if (!profile) return;
if (!profile)
return;
auto store = getStore().dynamic_pointer_cast<LocalFSStore>();
if (!store) throw Error("'--profile' is not supported for this Nix store");
if (!store)
throw Error("'--profile' is not supported for this Nix store");
auto profile2 = absPath(*profile);
switchLink(profile2,
createGeneration(*store, profile2, storePath));
switchLink(profile2, createGeneration(*store, profile2, storePath));
}
void MixProfile::updateProfile(const BuiltPaths & buildables)
{
if (!profile) return;
if (!profile)
return;
StorePaths result;
for (auto & buildable : buildables) {
std::visit(overloaded {
[&](const BuiltPath::Opaque & bo) {
result.push_back(bo.path);
std::visit(
overloaded{
[&](const BuiltPath::Opaque & bo) { result.push_back(bo.path); },
[&](const BuiltPath::Built & bfd) {
for (auto & output : bfd.outputs) {
result.push_back(output.second);
}
},
},
[&](const BuiltPath::Built & bfd) {
for (auto & output : bfd.outputs) {
result.push_back(output.second);
}
},
}, buildable.raw());
buildable.raw());
}
if (result.size() != 1)
throw UsageError("'--profile' requires that the arguments produce a single store path, but there are %d", result.size());
throw UsageError(
"'--profile' requires that the arguments produce a single store path, but there are %d", result.size());
updateProfile(result[0]);
}
@ -282,51 +284,85 @@ MixDefaultProfile::MixDefaultProfile()
profile = getDefaultProfile();
}
MixEnvironment::MixEnvironment() : ignoreEnvironment(false)
MixEnvironment::MixEnvironment()
: ignoreEnvironment(false)
{
addFlag({
.longName = "ignore-environment",
.longName = "ignore-env",
.aliases = {"ignore-environment"},
.shortName = 'i',
.description = "Clear the entire environment (except those specified with `--keep`).",
.description = "Clear the entire environment, except for those specified with `--keep-env-var`.",
.category = environmentVariablesCategory,
.handler = {&ignoreEnvironment, true},
});
addFlag({
.longName = "keep",
.longName = "keep-env-var",
.aliases = {"keep"},
.shortName = 'k',
.description = "Keep the environment variable *name*.",
.description = "Keep the environment variable *name*, when using `--ignore-env`.",
.category = environmentVariablesCategory,
.labels = {"name"},
.handler = {[&](std::string s) { keep.insert(s); }},
.handler = {[&](std::string s) { keepVars.insert(s); }},
});
addFlag({
.longName = "unset",
.longName = "unset-env-var",
.aliases = {"unset"},
.shortName = 'u',
.description = "Unset the environment variable *name*.",
.category = environmentVariablesCategory,
.labels = {"name"},
.handler = {[&](std::string s) { unset.insert(s); }},
.handler = {[&](std::string name) {
if (setVars.contains(name))
throw UsageError("Cannot unset environment variable '%s' that is set with '%s'", name, "--set-env-var");
unsetVars.insert(name);
}},
});
addFlag({
.longName = "set-env-var",
.shortName = 's',
.description = "Sets an environment variable *name* with *value*.",
.category = environmentVariablesCategory,
.labels = {"name", "value"},
.handler = {[&](std::string name, std::string value) {
if (unsetVars.contains(name))
throw UsageError(
"Cannot set environment variable '%s' that is unset with '%s'", name, "--unset-env-var");
if (setVars.contains(name))
throw UsageError(
"Duplicate definition of environment variable '%s' with '%s' is ambiguous", name, "--set-env-var");
setVars.insert_or_assign(name, value);
}},
});
}
void MixEnvironment::setEnviron() {
if (ignoreEnvironment) {
if (!unset.empty())
throw UsageError("--unset does not make sense with --ignore-environment");
void MixEnvironment::setEnviron()
{
if (ignoreEnvironment && !unsetVars.empty())
throw UsageError("--unset-env-var does not make sense with --ignore-env");
for (const auto & var : keep) {
auto val = getenv(var.c_str());
if (val) stringsEnv.emplace_back(fmt("%s=%s", var.c_str(), val));
}
if (!ignoreEnvironment && !keepVars.empty())
throw UsageError("--keep-env-var does not make sense without --ignore-env");
vectorEnv = stringsToCharPtrs(stringsEnv);
environ = vectorEnv.data();
} else {
if (!keep.empty())
throw UsageError("--keep does not make sense without --ignore-environment");
auto env = getEnv();
for (const auto & var : unset)
unsetenv(var.c_str());
}
if (ignoreEnvironment)
std::erase_if(env, [&](const auto & var) { return !keepVars.contains(var.first); });
for (const auto & [name, value] : setVars)
env[name] = value;
if (!unsetVars.empty())
std::erase_if(env, [&](const auto & var) { return unsetVars.contains(var.first); });
replaceEnv(env);
return;
}
}

View File

@ -13,7 +13,7 @@ namespace nix {
extern std::string programPath;
extern char * * savedArgv;
extern char ** savedArgv;
class EvalState;
struct Pos;
@ -24,7 +24,8 @@ static constexpr Command::Category catSecondary = 100;
static constexpr Command::Category catUtility = 101;
static constexpr Command::Category catNixInstallation = 102;
static constexpr auto installablesCategory = "Options that change the interpretation of [installables](@docroot@/command-ref/new-cli/nix.md#installables)";
static constexpr auto installablesCategory =
"Options that change the interpretation of [installables](@docroot@/command-ref/new-cli/nix.md#installables)";
struct NixMultiCommand : MultiCommand, virtual Command
{
@ -112,7 +113,9 @@ struct MixFlakeOptions : virtual Args, EvalCommand
* arguments) so that the completions for these flags can use them.
*/
virtual std::vector<FlakeRef> getFlakeRefsForCompletion()
{ return {}; }
{
return {};
}
};
struct SourceExprCommand : virtual Args, MixFlakeOptions
@ -122,11 +125,9 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions
SourceExprCommand();
Installables parseInstallables(
ref<Store> store, std::vector<std::string> ss);
Installables parseInstallables(ref<Store> store, std::vector<std::string> ss);
ref<Installable> parseInstallable(
ref<Store> store, const std::string & installable);
ref<Installable> parseInstallable(ref<Store> store, const std::string & installable);
virtual Strings getDefaultFlakeAttrPaths();
@ -272,10 +273,10 @@ struct RegisterCommand
typedef std::map<std::vector<std::string>, std::function<ref<Command>()>> Commands;
static Commands * commands;
RegisterCommand(std::vector<std::string> && name,
std::function<ref<Command>()> command)
RegisterCommand(std::vector<std::string> && name, std::function<ref<Command>()> command)
{
if (!commands) commands = new Commands;
if (!commands)
commands = new Commands;
commands->emplace(name, command);
}
@ -285,13 +286,13 @@ struct RegisterCommand
template<class T>
static RegisterCommand registerCommand(const std::string & name)
{
return RegisterCommand({name}, [](){ return make_ref<T>(); });
return RegisterCommand({name}, []() { return make_ref<T>(); });
}
template<class T>
static RegisterCommand registerCommand2(std::vector<std::string> && name)
{
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
return RegisterCommand(std::move(name), []() { return make_ref<T>(); });
}
struct MixProfile : virtual StoreCommand
@ -313,19 +314,21 @@ struct MixDefaultProfile : MixProfile
MixDefaultProfile();
};
struct MixEnvironment : virtual Args {
struct MixEnvironment : virtual Args
{
StringSet keep, unset;
Strings stringsEnv;
std::vector<char*> vectorEnv;
StringSet keepVars;
StringSet unsetVars;
std::map<std::string, std::string> setVars;
bool ignoreEnvironment;
MixEnvironment();
/***
* Modify global environ based on `ignoreEnvironment`, `keep`, and
* `unset`. It's expected that exec will be called before this class
* goes out of scope, otherwise `environ` will become invalid.
* Modify global environ based on `ignoreEnvironment`, `keep`,
* `unset`, and `added`. It's expected that exec will be called
* before this class goes out of scope, otherwise `environ` will
* become invalid.
*/
void setEnviron();
};
@ -349,9 +352,6 @@ void completeFlakeRefWithFragment(
std::string showVersions(const std::set<std::string> & versions);
void printClosureDiff(
ref<Store> store,
const StorePath & beforePath,
const StorePath & afterPath,
std::string_view indent);
ref<Store> store, const StorePath & beforePath, const StorePath & afterPath, std::string_view indent);
}

View File

@ -75,6 +75,7 @@ headers = [config_h] + files(
headers += files('nix_api_expr_internal.h')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library(
'nixexprc',

View File

@ -56,6 +56,7 @@ headers = files(
)
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library(
'nix-expr-test-support',

View File

@ -28,6 +28,7 @@ subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
rapidcheck = dependency('rapidcheck')
deps_private += rapidcheck

View File

@ -2834,7 +2834,9 @@ void EvalState::printStatistics()
#endif
#if HAVE_BOEHMGC
{GC_is_incremental_mode() ? "gcNonIncremental" : "gc", gcFullOnlyTime},
#ifndef _WIN32 // TODO implement
{GC_is_incremental_mode() ? "gcNonIncrementalFraction" : "gcFraction", gcFullOnlyTime / cpuTime},
#endif
#endif
};
topObj["envs"] = {

View File

@ -27,6 +27,7 @@ subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
rapidcheck = dependency('rapidcheck')
deps_private += rapidcheck

View File

@ -217,8 +217,12 @@ static void initRepoAtomically(std::filesystem::path &path, bool bare) {
try {
std::filesystem::rename(tmpDir, path);
} catch (std::filesystem::filesystem_error & e) {
if (e.code() == std::errc::file_exists) // Someone might race us to create the repository.
// Someone may race us to create the repository.
if (e.code() == std::errc::file_exists
// `path` may be attempted to be deleted by s::f::rename, in which case the code is:
|| e.code() == std::errc::directory_not_empty) {
return;
}
else
throw SysError("moving temporary git repository from %s to %s", tmpDir, path);
}

View File

@ -27,6 +27,7 @@ subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
rapidcheck = dependency('rapidcheck')
deps_private += rapidcheck

View File

@ -68,6 +68,7 @@ headers = [config_h] + files(
)
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library(
'nixmainc',

View File

@ -543,7 +543,7 @@ public:
auto state(state_.lock());
if (!state->active) return {};
std::cerr << fmt("\r\e[K%s ", msg);
auto s = trim(readLine(STDIN_FILENO));
auto s = trim(readLine(getStandardInput(), true));
if (s.size() != 1) return {};
draw(*state);
return s[0];

View File

@ -67,6 +67,7 @@ headers = [config_h] + files(
headers += files('nix_api_store_internal.h')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library(
'nixstorec',

View File

@ -58,6 +58,7 @@ headers = files(
)
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library(
'nix-store-test-support',

View File

@ -28,6 +28,7 @@ subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
sqlite = dependency('sqlite3', 'sqlite', version : '>=3.6.19')
deps_private += sqlite

View File

@ -38,15 +38,19 @@ mkMesonExecutable (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];
buildInputs = [
nix-store
nix-store-c
nix-store-test-support
# Hack for sake of the dev shell
passthru.externalBuildInputs = [
sqlite
rapidcheck
gtest
];
buildInputs = finalAttrs.passthru.externalBuildInputs ++ [
nix-store
nix-store-c
nix-store-test-support
];
preConfigure =
# "Inline" .version so it's not a symlink, and includes the suffix.
# Do the meson utils, without modification.

View File

@ -459,21 +459,14 @@ TEST_F(ServeProtoTest, handshake_client_truncated_replay_throws)
CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) {
for (size_t len = 0; len < toClientLog.size(); ++len) {
NullBufferedSink nullSink;
StringSource in {
// truncate
toClientLog.substr(0, len)
};
auto substring = toClientLog.substr(0, len);
StringSource in{substring};
if (len < 8) {
EXPECT_THROW(
ServeProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion, "blah"),
EndOfFile);
ServeProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, "blah"), EndOfFile);
} else {
// Not sure why cannot keep on checking for `EndOfFile`.
EXPECT_THROW(
ServeProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion, "blah"),
Error);
EXPECT_THROW(ServeProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, "blah"), Error);
}
}
});

View File

@ -725,21 +725,14 @@ TEST_F(WorkerProtoTest, handshake_client_truncated_replay_throws)
CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) {
for (size_t len = 0; len < toClientLog.size(); ++len) {
NullBufferedSink nullSink;
StringSource in {
// truncate
toClientLog.substr(0, len)
};
auto substring = toClientLog.substr(0, len);
StringSource in{substring};
if (len < 8) {
EXPECT_THROW(
WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion, {}),
EndOfFile);
WorkerProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, {}), EndOfFile);
} else {
// Not sure why cannot keep on checking for `EndOfFile`.
EXPECT_THROW(
WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion, {}),
Error);
EXPECT_THROW(WorkerProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, {}), Error);
}
}
});

View File

@ -34,6 +34,8 @@ subdir('build-utils-meson/subprojects')
run_command('ln', '-s',
meson.project_build_root() / '__nothing_link_target',
meson.project_build_root() / '__nothing_symlink',
# native doesn't allow dangling symlinks, which the tests require
env : { 'MSYS' : 'winsymlinks:lnk' },
check : true,
)
can_link_symlink = run_command('ln',
@ -74,6 +76,12 @@ if host_machine.system() == 'darwin'
deps_other += [sandbox]
endif
if host_machine.system() == 'windows'
wsock32 = cxx.find_library('wsock32')
deps_other += [wsock32]
endif
subdir('build-utils-meson/libatomic')
subdir('build-utils-meson/threads')
boost = dependency(
@ -410,6 +418,7 @@ foreach name, value : cpp_str_defines
endforeach
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library(
'nixstore',

View File

@ -63,6 +63,7 @@ headers = [config_h] + files(
headers += files('nix_api_util_internal.h')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library(
'nixutilc',

View File

@ -53,6 +53,7 @@ headers = files(
)
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library(
'nix-util-test-support',

View File

@ -28,6 +28,7 @@ subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
rapidcheck = dependency('rapidcheck')
deps_private += rapidcheck

View File

@ -7,6 +7,8 @@
#include <gtest/gtest.h>
#include <memory>
namespace nixC {
TEST_F(nix_api_util_context, nix_context_error)
@ -57,6 +59,14 @@ struct MySettings : nix::Config
MySettings mySettings;
static nix::GlobalConfig::Register rs(&mySettings);
static auto createOwnedNixContext()
{
return std::unique_ptr<nix_c_context, decltype([](nix_c_context * ctx) {
if (ctx)
nix_c_context_free(ctx);
})>(nix_c_context_create(), {});
}
TEST_F(nix_api_util_context, nix_setting_get)
{
ASSERT_EQ(ctx->last_err_code, NIX_OK);
@ -97,7 +107,8 @@ TEST_F(nix_api_util_context, nix_err_msg)
// advanced usage
unsigned int sz;
err_msg = nix_err_msg(nix_c_context_create(), ctx, &sz);
auto new_ctx = createOwnedNixContext();
err_msg = nix_err_msg(new_ctx.get(), ctx, &sz);
ASSERT_EQ(sz, err_msg.size());
}
@ -113,7 +124,8 @@ TEST_F(nix_api_util_context, nix_err_info_msg)
} catch (...) {
nix_context_error(ctx);
}
nix_err_info_msg(nix_c_context_create(), ctx, OBSERVE_STRING(err_info));
auto new_ctx = createOwnedNixContext();
nix_err_info_msg(new_ctx.get(), ctx, OBSERVE_STRING(err_info));
ASSERT_STREQ("testing error", err_info.c_str());
}
@ -130,7 +142,8 @@ TEST_F(nix_api_util_context, nix_err_name)
} catch (...) {
nix_context_error(ctx);
}
nix_err_name(nix_c_context_create(), ctx, OBSERVE_STRING(err_name));
auto new_ctx = createOwnedNixContext();
nix_err_name(new_ctx.get(), ctx, OBSERVE_STRING(err_name));
ASSERT_EQ(std::string(err_name), "nix::Error");
}

View File

@ -13,6 +13,8 @@
namespace nix {
static constexpr auto environmentVariablesCategory = "Options that change environment variables";
/**
* @return an environment variable.
*/

View File

@ -77,8 +77,13 @@ void writeFull(Descriptor fd, std::string_view s, bool allowInterrupts = true);
/**
* Read a line from a file descriptor.
*
* @param fd The file descriptor to read from
* @param eofOk If true, return an unterminated line if EOF is reached. (e.g. the empty string)
*
* @return A line of text ending in `\n`, or a string without `\n` if `eofOk` is true and EOF is reached.
*/
std::string readLine(Descriptor fd);
std::string readLine(Descriptor fd, bool eofOk = false);
/**
* Write a line to a file descriptor.
@ -101,8 +106,25 @@ void drainFD(
#endif
);
/**
* Get [Standard Input](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_(stdin))
*/
[[gnu::always_inline]]
inline Descriptor getStandardOut() {
inline Descriptor getStandardInput()
{
#ifndef _WIN32
return STDIN_FILENO;
#else
return GetStdHandle(STD_INPUT_HANDLE);
#endif
}
/**
* Get [Standard Output](https://en.wikipedia.org/wiki/Standard_streams#Standard_output_(stdout))
*/
[[gnu::always_inline]]
inline Descriptor getStandardOutput()
{
#ifndef _WIN32
return STDOUT_FILENO;
#else
@ -110,6 +132,19 @@ inline Descriptor getStandardOut() {
#endif
}
/**
* Get [Standard Error](https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr))
*/
[[gnu::always_inline]]
inline Descriptor getStandardError()
{
#ifndef _WIN32
return STDERR_FILENO;
#else
return GetStdHandle(STD_ERROR_HANDLE);
#endif
}
/**
* Automatic cleanup of resources.
*/

View File

@ -38,7 +38,7 @@ void Logger::warn(const std::string & msg)
void Logger::writeToStdout(std::string_view s)
{
Descriptor standard_out = getStandardOut();
Descriptor standard_out = getStandardOutput();
writeFull(standard_out, s);
writeFull(standard_out, "\n");
}
@ -118,11 +118,7 @@ void writeToStderr(std::string_view s)
{
try {
writeFull(
#ifdef _WIN32
GetStdHandle(STD_ERROR_HANDLE),
#else
STDERR_FILENO,
#endif
getStandardError(),
s, false);
} catch (SystemError & e) {
/* Ignore failing writes to stderr. We need to ignore write

View File

@ -53,16 +53,9 @@ endforeach
configdata.set('HAVE_DECL_AT_SYMLINK_NOFOLLOW', cxx.has_header_symbol('fcntl.h', 'AT_SYMLINK_NOFOLLOW').to_int())
subdir('build-utils-meson/libatomic')
subdir('build-utils-meson/threads')
# Check if -latomic is needed
# This is needed for std::atomic on some platforms
# We did not manage to test this reliably on all platforms, so we hardcode
# it for now.
if host_machine.cpu_family() == 'arm'
deps_other += cxx.find_library('atomic')
endif
if host_machine.system() == 'windows'
socket = cxx.find_library('ws2_32')
deps_other += socket
@ -265,6 +258,7 @@ else
endif
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library(
'nixutil',

View File

@ -7,8 +7,8 @@
namespace nix {
PosixSourceAccessor::PosixSourceAccessor(std::filesystem::path && root)
: root(std::move(root))
PosixSourceAccessor::PosixSourceAccessor(std::filesystem::path && argRoot)
: root(std::move(argRoot))
{
assert(root.empty() || root.is_absolute());
displayPrefix = root.string();

View File

@ -2,6 +2,7 @@
///@file
#include <memory>
#include <type_traits>
#include "types.hh"
#include "util.hh"
@ -202,7 +203,14 @@ struct StringSource : Source
{
std::string_view s;
size_t pos;
// NOTE: Prevent unintentional dangling views when an implicit conversion
// from std::string -> std::string_view occurs when the string is passed
// by rvalue.
StringSource(std::string &&) = delete;
StringSource(std::string_view s) : s(s), pos(0) { }
StringSource(const std::string& str): StringSource(std::string_view(str)) {}
size_t read(char * data, size_t len) override;
};

View File

@ -47,7 +47,7 @@ void writeFull(int fd, std::string_view s, bool allowInterrupts)
}
std::string readLine(int fd)
std::string readLine(int fd, bool eofOk)
{
std::string s;
while (1) {
@ -58,8 +58,12 @@ std::string readLine(int fd)
if (rd == -1) {
if (errno != EINTR)
throw SysError("reading a line");
} else if (rd == 0)
throw EndOfFile("unexpected EOF reading a line");
} else if (rd == 0) {
if (eofOk)
return s;
else
throw EndOfFile("unexpected EOF reading a line");
}
else {
if (ch == '\n') return s;
s += ch;

View File

@ -61,7 +61,7 @@ void writeFull(HANDLE handle, std::string_view s, bool allowInterrupts)
}
std::string readLine(HANDLE handle)
std::string readLine(HANDLE handle, bool eofOk)
{
std::string s;
while (1) {
@ -71,8 +71,12 @@ std::string readLine(HANDLE handle)
DWORD rd;
if (!ReadFile(handle, &ch, 1, &rd, NULL)) {
throw WinError("reading a line");
} else if (rd == 0)
throw EndOfFile("unexpected EOF reading a line");
} else if (rd == 0) {
if (eofOk)
return s;
else
throw EndOfFile("unexpected EOF reading a line");
}
else {
if (ch == '\n') return s;
s += ch;

View File

@ -536,7 +536,7 @@ static void main_nix_build(int argc, char * * argv)
env["__ETC_PROFILE_SOURCED"] = "1";
}
env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDir.path();
env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDir.path().string();
env["NIX_STORE"] = store->storeDir;
env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores);

View File

@ -694,7 +694,7 @@ static void opDump(Strings opFlags, Strings opArgs)
if (!opFlags.empty()) throw UsageError("unknown flag");
if (opArgs.size() != 1) throw UsageError("only one argument allowed");
FdSink sink(getStandardOut());
FdSink sink(getStandardOutput());
std::string path = *opArgs.begin();
dumpPath(path, sink);
sink.flush();
@ -722,7 +722,7 @@ static void opExport(Strings opFlags, Strings opArgs)
for (auto & i : opArgs)
paths.insert(store->followLinksToStorePath(i));
FdSink sink(getStandardOut());
FdSink sink(getStandardOutput());
store->exportPaths(paths, sink);
sink.flush();
}
@ -835,7 +835,7 @@ static void opServe(Strings opFlags, Strings opArgs)
if (!opArgs.empty()) throw UsageError("no arguments expected");
FdSource in(STDIN_FILENO);
FdSink out(getStandardOut());
FdSink out(getStandardOutput());
/* Exchange the greeting. */
ServeProto::Version clientVersion =

View File

@ -16,7 +16,7 @@ struct MixCat : virtual Args
throw Error("path '%1%' is not a regular file", path);
stopProgressBar();
writeFull(getStandardOut(), accessor->readFile(CanonPath(path)));
writeFull(getStandardOutput(), accessor->readFile(CanonPath(path)));
}
};

View File

@ -20,7 +20,7 @@ struct CmdDumpPath : StorePathCommand
void run(ref<Store> store, const StorePath & storePath) override
{
FdSink sink(getStandardOut());
FdSink sink(getStandardOutput());
store->narFromPath(storePath, sink);
sink.flush();
}
@ -55,7 +55,7 @@ struct CmdDumpPath2 : Command
void run() override
{
FdSink sink(getStandardOut());
FdSink sink(getStandardOutput());
dumpPath(path, sink);
sink.flush();
}

View File

@ -115,7 +115,7 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption
else if (raw) {
stopProgressBar();
writeFull(getStandardOut(), *state->coerceToString(noPos, *v, context, "while generating the eval command output"));
writeFull(getStandardOutput(), *state->coerceToString(noPos, *v, context, "while generating the eval command output"));
}
else if (json) {

View File

@ -17,7 +17,6 @@
#include "eval-cache.hh"
#include "markdown.hh"
#include "users.hh"
#include "terminal.hh"
#include <filesystem>
#include <nlohmann/json.hpp>
@ -1275,97 +1274,25 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
auto showDerivation = [&]()
{
auto name = visitor.getAttr(state->sName)->getString();
std::optional<std::string> description;
if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) {
if (auto aDescription = aMeta->maybeGetAttr(state->sDescription))
description = aDescription->getString();
}
if (json) {
std::optional<std::string> description;
if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) {
if (auto aDescription = aMeta->maybeGetAttr(state->sDescription))
description = aDescription->getString();
}
j.emplace("type", "derivation");
j.emplace("name", name);
j.emplace("description", description ? *description : "");
} else {
auto type =
logger->cout("%s: %s '%s'",
headerPrefix,
attrPath.size() == 2 && attrPathS[0] == "devShell" ? "development environment" :
attrPath.size() >= 2 && attrPathS[0] == "devShells" ? "development environment" :
attrPath.size() == 3 && attrPathS[0] == "checks" ? "derivation" :
attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" :
"package";
if (description && !description->empty()) {
// Takes a string and returns the # of characters displayed
auto columnLengthOfString = [](std::string_view s) -> unsigned int {
unsigned int columnCount = 0;
for (auto i = s.begin(); i < s.end();) {
// Test first character to determine if it is one of
// treeConn, treeLast, treeLine
if (*i == -30) {
i += 3;
++columnCount;
}
// Escape sequences
// https://en.wikipedia.org/wiki/ANSI_escape_code
else if (*i == '\e') {
// Eat '['
if (*(++i) == '[') {
++i;
// Eat parameter bytes
while(*i >= 0x30 && *i <= 0x3f) ++i;
// Eat intermediate bytes
while(*i >= 0x20 && *i <= 0x2f) ++i;
// Eat final byte
if(*i >= 0x40 && *i <= 0x73) ++i;
}
else {
// Eat Fe Escape sequence
if (*i >= 0x40 && *i <= 0x5f) ++i;
}
}
else {
++i;
++columnCount;
}
}
return columnCount;
};
// Maximum length to print
size_t maxLength = getWindowSize().second > 0 ? getWindowSize().second : 80;
// Trim the description and only use the first line
auto trimmed = trim(*description);
auto newLinePos = trimmed.find('\n');
auto length = newLinePos != std::string::npos ? newLinePos : trimmed.length();
auto beginningOfLine = fmt("%s: %s '%s'", headerPrefix, type, name);
auto line = fmt("%s: %s '%s' - '%s'", headerPrefix, type, name, trimmed.substr(0, length));
// If we are already over the maximum length then do not trim
// and don't print the description (preserves existing behavior)
if (columnLengthOfString(beginningOfLine) >= maxLength) {
logger->cout("%s", beginningOfLine);
}
// If the entire line fits then print that
else if (columnLengthOfString(line) < maxLength) {
logger->cout("%s", line);
}
// Otherwise we need to truncate
else {
auto lineLength = columnLengthOfString(line);
auto chopOff = lineLength - maxLength;
line.resize(line.length() - chopOff);
line = line.replace(line.length() - 3, 3, "...");
logger->cout("%s", line);
}
}
else {
logger->cout("%s: %s '%s'", headerPrefix, type, name);
}
"package",
name);
}
};

View File

@ -57,7 +57,7 @@ struct CmdLog : InstallableCommand
if (!log) continue;
stopProgressBar();
printInfo("got build log for '%s' from '%s'", installable->what(), logSub.getUri());
writeFull(getStandardOut(), *log);
writeFull(getStandardOutput(), *log);
return;
}

View File

@ -35,6 +35,7 @@ subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
configdata = configuration_data()
@ -229,6 +230,8 @@ foreach linkname : nix_symlinks
t = custom_target(
command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'],
output: linkname + executable_suffix,
# native doesn't allow dangling symlinks, but the target executable often doesn't exist at this time
env : { 'MSYS' : 'winsymlinks:lnk' },
# TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working)
build_by_default: true
)
@ -247,6 +250,8 @@ install_symlink(
custom_target(
command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'],
output: 'build-remote' + executable_suffix,
# native doesn't allow dangling symlinks, but the target executable often doesn't exist at this time
env : { 'MSYS' : 'winsymlinks:lnk' },
# TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working)
build_by_default: true
)

View File

@ -177,7 +177,7 @@ struct CmdKeyGenerateSecret : Command
throw UsageError("required argument '--key-name' is missing");
stopProgressBar();
writeFull(getStandardOut(), SecretKey::generate(*keyName).to_string());
writeFull(getStandardOutput(), SecretKey::generate(*keyName).to_string());
}
};
@ -199,7 +199,7 @@ struct CmdKeyConvertSecretToPublic : Command
{
SecretKey secretKey(drainFD(STDIN_FILENO));
stopProgressBar();
writeFull(getStandardOut(), secretKey.toPublicKey().to_string());
writeFull(getStandardOutput(), secretKey.toPublicKey().to_string());
}
};

View File

@ -238,7 +238,7 @@ clearCache
# preserve quotes variables in the single-quoted string
# shellcheck disable=SC2016
outPath=$(nix-build --no-out-link -E '
with import ./config.nix;
with import '"${config_nix}"';
mkDerivation {
name = "nar-listing";
buildCommand = "mkdir $out; echo foo > $out/bar; ln -s xyzzy $out/link";
@ -258,7 +258,7 @@ clearCache
# preserve quotes variables in the single-quoted string
# shellcheck disable=SC2016
outPath=$(nix-build --no-out-link -E '
with import ./config.nix;
with import '"${config_nix}"';
mkDerivation {
name = "debug-info";
buildCommand = "mkdir -p $out/lib/debug/.build-id/02; echo foo > $out/lib/debug/.build-id/02/623eda209c26a59b1a8638ff7752f6b945c26b.debug";
@ -276,7 +276,7 @@ diff -u \
# preserve quotes variables in the single-quoted string
# shellcheck disable=SC2016
expr='
with import ./config.nix;
with import '"${config_nix}"';
mkDerivation {
name = "multi-output";
buildCommand = "mkdir -p $out; echo foo > $doc; echo $doc > $out/docref";

View File

@ -1,6 +1,6 @@
{ busybox }:
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
let

View File

@ -1,6 +1,6 @@
{ busybox, contentAddressed ? false }:
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
let

View File

@ -1,4 +1,4 @@
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix";
let mkCADerivation = args: mkDerivation ({
__contentAddressed = true;

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash
#
source common.sh
export NIX_TESTS_CA_BY_DEFAULT=1

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash
source ./common.sh
source common.sh
requireDaemonNewerThan "2.4pre20210625"

View File

@ -1,3 +1,5 @@
#!/usr/bin/env bash
source common.sh
export NIX_TESTS_CA_BY_DEFAULT=1

View File

@ -29,5 +29,5 @@ suites += {
'substitute.sh',
'why-depends.sh',
],
'workdir': meson.current_build_dir(),
'workdir': meson.current_source_dir(),
}

View File

@ -1,3 +1,5 @@
#!/usr/bin/env bash
source common.sh
export NIX_TESTS_CA_BY_DEFAULT=1

View File

@ -2,6 +2,11 @@
source common.sh
FLAKE_PATH=path:$PWD
flakeDir="$TEST_HOME/flake"
mkdir -p "${flakeDir}"
cp flake.nix "${_NIX_TEST_BUILD_DIR}/ca/config.nix" content-addressed.nix "${flakeDir}"
nix run --no-write-lock-file "$FLAKE_PATH#runnable"
# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake.
removeBuildDirRef "$flakeDir"/*.nix
nix run --no-write-lock-file "path:${flakeDir}#runnable"

View File

@ -5,4 +5,3 @@ source common.sh
CONTENT_ADDRESSED=true
cd ..
source ./nix-shell.sh

View File

@ -1,4 +1,4 @@
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix";
let mkCADerivation = args: mkDerivation ({
__contentAddressed = true;

View File

@ -2,7 +2,7 @@
# build it at once.
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix";
mkDerivation {
name = "simple";

View File

@ -1,3 +1,5 @@
#!/usr/bin/env bash
source common.sh
export NIX_TESTS_CA_BY_DEFAULT=1

View File

@ -1,3 +1,5 @@
#!/usr/bin/env bash
source common.sh
export NIX_TESTS_CA_BY_DEFAULT=1

View File

@ -1,4 +1,4 @@
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
rec {

View File

@ -1,4 +1,4 @@
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
rec {
dep1 = mkDerivation {

View File

@ -1,6 +1,6 @@
{checkBuildId ? 0}:
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
{
nondeterministic = mkDerivation {

View File

@ -37,7 +37,10 @@ if canUseSandbox; then
}
EOF
cp simple.nix shell.nix simple.builder.sh config.nix "$flakeDir/"
cp simple.nix shell.nix simple.builder.sh "${config_nix}" "$flakeDir/"
# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake.
removeBuildDirRef "$flakeDir"/*.nix
TODO_NixOS

View File

@ -343,6 +343,15 @@ count() {
echo $#
}
# Sometimes, e.g. due to pure eval, restricted eval, or sandboxing, we
# cannot look up `config.nix` in the build dir, and have to instead get
# it from the current directory. (In this case, the current directly
# will be somewhere in `$TEST_ROOT`.)
removeBuildDirRef() {
# shellcheck disable=SC2016 # The ${} in this is Nix, not shell
sed -i -e 's,"${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/[^ ]*config.nix",./config.nix,' "$@"
}
trap onError ERR
fi # COMMON_FUNCTIONS_SH_SOURCED

View File

@ -19,7 +19,7 @@ EOF
# When we're doing everything in the same store, we need to bring
# dependencies into context.
sed -i "$(dirname "${BASH_SOURCE[0]}")"/../config.nix \
sed -i "${_NIX_TEST_BUILD_DIR}/config.nix" \
-e 's^\(shell\) = "/nix/store/\([^/]*\)/\(.*\)";^\1 = builtins.appendContext "/nix/store/\2" { "/nix/store/\2".path = true; } + "/\3";^' \
-e 's^\(path\) = "/nix/store/\([^/]*\)/\(.*\)";^\1 = builtins.appendContext "/nix/store/\2" { "/nix/store/\2".path = true; } + "/\3";^' \
;

View File

@ -8,11 +8,10 @@ COMMON_PATHS_SH_SOURCED=1
commonDir="$(readlink -f "$(dirname "${BASH_SOURCE[0]-$0}")")"
# Since these are generated files
# shellcheck disable=SC1091
# Just for `isTestOnNixOS`
source "$commonDir/functions.sh"
# shellcheck disable=SC1091
source "$commonDir/subst-vars.sh"
source "${_NIX_TEST_BUILD_DIR}/common/subst-vars.sh"
# Make sure shellcheck knows this will be defined by the above generated snippet
: "${bash?}" "${bindir?}"

View File

@ -1,4 +1,4 @@
# NOTE: instances of @variable@ are substituted as defined in /mk/templates.mk
# NOTE: instances of @variable@ are substituted by the build system
if [[ -z "${COMMON_SUBST_VARS_SH_SOURCED-}" ]]; then

View File

@ -6,11 +6,14 @@ if [[ -z "${COMMON_VARS_SH_SOURCED-}" ]]; then
COMMON_VARS_SH_SOURCED=1
_NIX_TEST_SOURCE_DIR=$(realpath "${_NIX_TEST_SOURCE_DIR}")
_NIX_TEST_BUILD_DIR=$(realpath "${_NIX_TEST_BUILD_DIR}")
commonDir="$(readlink -f "$(dirname "${BASH_SOURCE[0]-$0}")")"
# Since this is a generated file
# shellcheck disable=SC1091
source "$commonDir/subst-vars.sh"
source "${_NIX_TEST_BUILD_DIR}/common/subst-vars.sh"
# Make sure shellcheck knows all these will be defined by the above generated snippet
: "${bindir?} ${coreutils?} ${dot?} ${SHELL?} ${busybox?} ${version?} ${system?}"
export coreutils dot busybox version system
@ -69,4 +72,9 @@ if [[ $(uname) == Linux ]] && [[ -L /proc/self/ns/user ]] && unshare --user true
_canUseSandbox=1
fi
# Very common, shorthand helps
# Used in other files
# shellcheck disable=SC2034
config_nix="${_NIX_TEST_BUILD_DIR}/config.nix"
fi # COMMON_VARS_SH_SOURCED

View File

@ -1,5 +1,5 @@
{ hashInvalidator ? "" }:
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
let {

View File

@ -15,5 +15,5 @@ suites += {
'dep-built-drv.sh',
'old-daemon-error-hack.sh',
],
'workdir': meson.current_build_dir(),
'workdir': meson.current_source_dir(),
}

View File

@ -1,4 +1,4 @@
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix";
# A simple content-addressed derivation.
# The derivation can be arbitrarily modified by passing a different `seed`,

View File

@ -1,4 +1,4 @@
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix";
let innerName = "foo"; in

View File

@ -1,4 +1,4 @@
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix";
# A simple content-addressed derivation.
# The derivation can be arbitrarily modified by passing a different `seed`,

View File

@ -45,7 +45,7 @@ printf 123 > "$TEST_ROOT/xyzzy/default.nix"
[[ $(nix eval --impure --expr "import $TEST_ROOT/foo/bar") = 123 ]]
# Test --arg-from-file.
[[ "$(nix eval --raw --arg-from-file foo config.nix --expr '{ foo }: { inherit foo; }' foo)" = "$(cat config.nix)" ]]
[[ "$(nix eval --raw --arg-from-file foo "${config_nix}" --expr '{ foo }: { inherit foo; }' foo)" = "$(cat "${config_nix}")" ]]
# Check that special(-ish) files are drained.
if [[ -e /proc/version ]]; then

View File

@ -1,4 +1,4 @@
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
rec {

View File

@ -1,6 +1,6 @@
{ destFile, seed }:
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
mkDerivation {
name = "simple";

View File

@ -1,5 +1,5 @@
{ busybox }:
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
let
mkDerivation = args:

View File

@ -1,4 +1,4 @@
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
mkDerivation {
name = "filter";

View File

@ -1,4 +1,4 @@
with import ./config.nix;
with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
rec {

View File

@ -79,7 +79,7 @@ cat > "$flake1Dir"/flake.nix <<EOF
}
EOF
cp ../simple.nix ../simple.builder.sh ../config.nix "$flake1Dir/"
cp ../simple.nix ../simple.builder.sh "${config_nix}" "$flake1Dir/"
echo bar > "$flake1Dir/foo"

View File

@ -2,7 +2,10 @@
source common.sh
cp ../simple.nix ../simple.builder.sh ../config.nix "$TEST_HOME"
cp ../simple.nix ../simple.builder.sh "${config_nix}" "$TEST_HOME"
# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake.
removeBuildDirRef "$TEST_HOME"/*.nix
cd "$TEST_HOME"

View File

@ -34,7 +34,10 @@ writeSimpleFlake() {
}
EOF
cp ../simple.nix ../shell.nix ../simple.builder.sh ../config.nix "$flakeDir/"
cp ../simple.nix ../shell.nix ../simple.builder.sh "${config_nix}" "$flakeDir/"
# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake.
removeBuildDirRef "$flakeDir"/*.nix
}
createSimpleGitFlake() {

View File

@ -2,7 +2,8 @@
source common.sh
cp ../simple.nix ../simple.builder.sh ../config.nix $TEST_HOME
cp ../simple.nix ../simple.builder.sh "${config_nix}" $TEST_HOME
removeBuildDirRef "$TEST_HOME/simple.nix"
cd $TEST_HOME
@ -26,7 +27,17 @@ cat <<EOF > flake.nix
EOF
# Without --accept-flake-config, the post hook should not run.
# To test variations in stderr tty-ness, we run the command in different ways,
# none of which should block on stdin or accept the `nixConfig`s.
nix build < /dev/null
nix build < /dev/null 2>&1 | cat
# EOF counts as no, even when interactive (throw EOF error before)
if type -p script >/dev/null && script -q -c true /dev/null; then
echo "script is available and GNU-like, so we can ensure a tty"
script -q -c 'nix build < /dev/null' /dev/null
else
echo "script is not available or not GNU-like, so we skip testing with an added tty"
fi
(! [[ -f post-hook-ran ]])
TODO_NixOS
clearStore

View File

@ -5,11 +5,11 @@ source ../common.sh
TODO_NixOS
clearStore
rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local
rm -rf "$TEST_HOME/.cache" "$TEST_HOME/.config" "$TEST_HOME/.local"
# Create flake under test.
cp ../shell-hello.nix ../config.nix $TEST_HOME/
cat <<EOF >$TEST_HOME/flake.nix
cp ../shell-hello.nix "$config_nix" "$TEST_HOME/"
cat <<EOF >"$TEST_HOME/flake.nix"
{
inputs.nixpkgs.url = "$TEST_HOME/nixpkgs";
outputs = {self, nixpkgs}: {
@ -24,9 +24,13 @@ cat <<EOF >$TEST_HOME/flake.nix
EOF
# Create fake nixpkgs flake.
mkdir -p $TEST_HOME/nixpkgs
cp ../config.nix ../shell.nix $TEST_HOME/nixpkgs
cat <<EOF >$TEST_HOME/nixpkgs/flake.nix
mkdir -p "$TEST_HOME/nixpkgs"
cp "${config_nix}" ../shell.nix "$TEST_HOME/nixpkgs"
# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake.
removeBuildDirRef "$TEST_HOME/nixpkgs"/*.nix
cat <<EOF >"$TEST_HOME/nixpkgs/flake.nix"
{
outputs = {self}: {
legacyPackages.$system.bashInteractive = (import ./shell.nix {}).bashInteractive;
@ -34,7 +38,7 @@ cat <<EOF >$TEST_HOME/nixpkgs/flake.nix
}
EOF
cd $TEST_HOME
cd "$TEST_HOME"
# Test whether `nix develop` passes through environment variables.
[[ "$(
@ -43,13 +47,86 @@ echo "\$ENVVAR"
EOF
)" = "a" ]]
# Test whether `nix develop --ignore-environment` does _not_ pass through environment variables.
# Test whether `nix develop --ignore-env` does _not_ pass through environment variables.
[[ -z "$(
ENVVAR=a nix develop --ignore-environment --no-write-lock-file .#hello <<EOF
ENVVAR=a nix develop --ignore-env --no-write-lock-file .#hello <<EOF
echo "\$ENVVAR"
EOF
)" ]]
# Test wether `--keep-env-var` keeps the environment variable.
(
expect='BAR'
got="$(FOO='BAR' nix develop --ignore-env --keep-env-var FOO --no-write-lock-file .#hello <<EOF
echo "\$FOO"
EOF
)"
[[ "$got" == "$expect" ]]
)
# Test wether duplicate `--keep-env-var` keeps the environment variable.
(
expect='BAR'
got="$(FOO='BAR' nix develop --ignore-env --keep-env-var FOO --keep-env-var FOO --no-write-lock-file .#hello <<EOF
echo "\$FOO"
EOF
)"
[[ "$got" == "$expect" ]]
)
# Test wether `--set-env-var` sets the environment variable.
(
expect='BAR'
got="$(nix develop --ignore-env --set-env-var FOO 'BAR' --no-write-lock-file .#hello <<EOF
echo "\$FOO"
EOF
)"
[[ "$got" == "$expect" ]]
)
# Test that `--set-env-var` overwrites previously set variables.
(
expect='BLA'
got="$(FOO='BAR' nix develop --set-env-var FOO 'BLA' --no-write-lock-file .#hello <<EOF
echo "\$FOO"
EOF
)"
[[ "$got" == "$expect" ]]
)
# Test that multiple `--set-env-var` work.
(
expect='BARFOO'
got="$(nix develop --set-env-var FOO 'BAR' --set-env-var BAR 'FOO' --no-write-lock-file .#hello <<EOF | tr -d '\n'
echo "\$FOO"
echo "\$BAR"
EOF
)"
[[ "$got" == "$expect" ]]
)
# Check that we throw an error when `--keep-env-var` is used without `--ignore-env`.
expectStderr 1 nix develop --keep-env-var FOO .#hello |
grepQuiet "error: --keep-env-var does not make sense without --ignore-env"
# Check that we throw an error when `--unset-env-var` is used with `--ignore-env`.
expectStderr 1 nix develop --ignore-env --unset-env-var FOO .#hello |
grepQuiet "error: --unset-env-var does not make sense with --ignore-env"
# Test wether multiple occurances of `--set-env-var` throws.
expectStderr 1 nix develop --set-env-var FOO 'BAR' --set-env-var FOO 'BLA' --no-write-lock-file .#hello |
grepQuiet "error: Duplicate definition of environment variable 'FOO' with '--set-env-var' is ambiguous"
# Test wether similar `--unset-env-var` and `--set-env-var` throws.
expectStderr 1 nix develop --set-env-var FOO 'BAR' --unset-env-var FOO --no-write-lock-file .#hello |
grepQuiet "error: Cannot unset environment variable 'FOO' that is set with '--set-env-var'"
expectStderr 1 nix develop --unset-env-var FOO --set-env-var FOO 'BAR' --no-write-lock-file .#hello |
grepQuiet "error: Cannot set environment variable 'FOO' that is unset with '--unset-env-var'"
# Check that multiple `--ignore-env`'s are okay.
expectStderr 0 nix develop --ignore-env --set-env-var FOO 'BAR' --ignore-env .#hello
# Determine the bashInteractive executable.
nix build --no-write-lock-file './nixpkgs#bashInteractive' --out-link ./bash-interactive
BASH_INTERACTIVE_EXECUTABLE="$PWD/bash-interactive/bin/bash"
@ -63,7 +140,7 @@ EOF
# Test whether `nix develop` with ignore environment sets `SHELL` to nixpkgs#bashInteractive shell.
[[ "$(
SHELL=custom nix develop --ignore-environment --no-write-lock-file .#hello <<EOF
SHELL=custom nix develop --ignore-env --no-write-lock-file .#hello <<EOF
echo "\$SHELL"
EOF
)" -ef "$BASH_INTERACTIVE_EXECUTABLE" ]]

View File

@ -7,7 +7,7 @@ requireGit
flake1Dir="$TEST_ROOT/eval-cache-flake"
createGitRepo "$flake1Dir" ""
cp ../simple.nix ../simple.builder.sh ../config.nix "$flake1Dir/"
cp ../simple.nix ../simple.builder.sh "${config_nix}" "$flake1Dir/"
git -C "$flake1Dir" add simple.nix simple.builder.sh config.nix
git -C "$flake1Dir" commit -m "config.nix"

View File

@ -390,7 +390,7 @@ cat > "$flake3Dir/flake.nix" <<EOF
}
EOF
cp ../config.nix "$flake3Dir"
cp "${config_nix}" "$flake3Dir"
git -C "$flake3Dir" add flake.nix config.nix
git -C "$flake3Dir" commit -m 'Add nonFlakeInputs'

View File

@ -25,5 +25,5 @@ suites += {
'show.sh',
'dubious-query.sh',
],
'workdir': meson.current_build_dir(),
'workdir': meson.current_source_dir(),
}

View File

@ -6,7 +6,10 @@ TODO_NixOS
clearStore
rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local
cp ../shell-hello.nix ../config.nix $TEST_HOME
cp ../shell-hello.nix "${config_nix}" $TEST_HOME
# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake.
removeBuildDirRef "$TEST_HOME"/*.nix
cd $TEST_HOME
cat <<EOF > flake.nix

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