1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-25 10:41:16 +02:00

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 path: flake-regressions/tests
- uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-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. # TODO do not do this, and instead do fine-grained export annotations.
GLOBAL_LDFLAGS += -Wl,--export-all-symbols GLOBAL_LDFLAGS += -Wl,--export-all-symbols
GLOBAL_CXXFLAGS += -D_WIN32_WINNT=0x0602
endif 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 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) - [Development](development/index.md)
- [Building](development/building.md) - [Building](development/building.md)
- [Testing](development/testing.md) - [Testing](development/testing.md)
- [Debugging](development/debugging.md)
- [Documentation](development/documentation.md) - [Documentation](development/documentation.md)
- [CLI guideline](development/cli-guideline.md) - [CLI guideline](development/cli-guideline.md)
- [JSON guideline](development/json-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 > src
> ├── libexpr > ├── libexpr
> │ ├── local.mk > │ ├── meson.build
> │ ├── value/context.hh > │ ├── value/context.hh
> │ ├── value/context.cc > │ ├── value/context.cc
> │ … > │ …
@ -37,25 +37,24 @@ The unit tests are defined using the [googletest] and [rapidcheck] frameworks.
> ├── tests > ├── tests
> │ │ > │ │
> │ … > │ …
> │ └── unit > │ ├── libutil-tests
> │ ├── libutil > │ │ ├── meson.build
> │ │ ├── local.mk > │ │ …
> │ │ … > │ │ └── data
> │ │ └── data > │ │ ├── git/tree.txt
> │ │ ├── git/tree.txt > │ │ …
> │ │ … > │ │
> │ │ > │ ├── libexpr-test-support
> │ ├── libexpr-support > │ │ ├── meson.build
> │ │ ├── local.mk > │ │ └── tests
> │ │ └── tests > │ │ ├── value/context.hh
> │ │ ├── value/context.hh > │ │ ├── value/context.cc
> │ │ ├── value/context.cc > │ │ …
> │ │ … > │ │
> │ │ > │ ├── libexpr-tests
> │ ├── libexpr > │ … ├── meson.build
> │ … ├── local.mk > │ ├── value/context.cc
> │ ├── value/context.cc > │ …
> │ …
> … > …
> ``` > ```
@ -128,7 +127,7 @@ On other platforms they wouldn't be run at all.
## Functional tests ## 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. 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. 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* > *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 [String concatenation]: #string-concatenation
@ -128,7 +128,7 @@ The result is a path.
> **Note** > **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 [Path and string concatenation]: #path-and-string-concatenation

119
flake.nix
View file

@ -294,109 +294,24 @@
}); });
devShells = let devShells = let
makeShell = pkgs: stdenv: (pkgs.nix.override { inherit stdenv; forDevShell = true; }).overrideAttrs (attrs: makeShell = import ./packaging/dev-shell.nix { inherit lib devFlake; };
let prefixAttrs = prefix: lib.concatMapAttrs (k: v: { "${prefix}-${k}" = v; });
buildCanExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform; in
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
forAllSystems (system: forAllSystems (system:
let prefixAttrs "native" (forAllStdenvs (stdenvName: makeShell {
makeShells = prefix: pkgs: pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages";
lib.mapAttrs' })) //
(k: v: lib.nameValuePair "${prefix}-${k}" v) lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin) (
(forAllStdenvs (stdenvName: makeShell pkgs pkgs.${stdenvName})); prefixAttrs "static" (forAllStdenvs (stdenvName: makeShell {
in pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsStatic;
(makeShells "native" nixpkgsFor.${system}.native) // })) //
(lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin) prefixAttrs "cross" (forAllCrossSystems (crossSystem: makeShell {
(makeShells "static" nixpkgsFor.${system}.static) // pkgs = nixpkgsFor.${system}.cross.${crossSystem};
(forAllCrossSystems (crossSystem: let pkgs = nixpkgsFor.${system}.cross.${crossSystem}; in makeShell pkgs pkgs.stdenv))) // }))
{ ) //
default = self.devShells.${system}.native-stdenvPackages; {
} default = self.devShells.${system}.native-stdenvPackages;
}
); );
}; };
} }

View file

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

View file

@ -22,10 +22,12 @@ subproject('libcmd')
subproject('nix') subproject('nix')
# Docs # Docs
subproject('internal-api-docs') if get_option('doc-gen')
subproject('external-api-docs') subproject('internal-api-docs')
if not meson.is_cross_build() subproject('external-api-docs')
subproject('nix-manual') if not meson.is_cross_build()
subproject('nix-manual')
endif
endif endif
# External C wrapper libraries # External C wrapper libraries
@ -35,17 +37,19 @@ subproject('libexpr-c')
subproject('libmain-c') subproject('libmain-c')
# Language Bindings # Language Bindings
if not meson.is_cross_build() if get_option('bindings') and not meson.is_cross_build()
subproject('perl') subproject('perl')
endif endif
# Testing # Testing
subproject('libutil-test-support') if get_option('unit-tests')
subproject('libutil-tests') subproject('libutil-test-support')
subproject('libstore-test-support') subproject('libutil-tests')
subproject('libstore-tests') subproject('libstore-test-support')
subproject('libfetchers-tests') subproject('libstore-tests')
subproject('libexpr-test-support') subproject('libfetchers-tests')
subproject('libexpr-tests') subproject('libexpr-test-support')
subproject('libflake-tests') subproject('libexpr-tests')
subproject('libflake-tests')
endif
subproject('nix-functional-tests') 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$||" \ -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 # shellcheck disable=SC2016
TESTS_ENVIRONMENT=( TESTS_ENVIRONMENT=(
"TEST_NAME=$test_name" "TEST_NAME=$test_name"
'NIX_REMOTE=' 'NIX_REMOTE='
'PS4=+(${BASH_SOURCE[0]-$0}:$LINENO) ' '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}" read -r -a bash <<< "${BASH:-/usr/bin/env bash}"
run () { 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; inherit tarballs;
}; };
testNixVersions = pkgs: client: daemon: testNixVersions = pkgs: daemon:
pkgs.nixComponents.callPackage ../package.nix { pkgs.nixComponents.nix-functional-tests.override {
pname = pname =
"nix-tests" "nix-tests"
+ lib.optionalString + lib.optionalString
(lib.versionAtLeast daemon.version "2.4pre20211005" && (lib.versionAtLeast daemon.version "2.4pre20211005" &&
lib.versionAtLeast client.version "2.4pre20211005") lib.versionAtLeast pkgs.nix.version "2.4pre20211005")
"-${client.version}-against-${daemon.version}"; "-${pkgs.nix.version}-against-${daemon.version}";
test-client = client;
test-daemon = daemon; 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 # Technically we could just return `pkgs.nixComponents`, but for Hydra it's
@ -71,7 +62,9 @@ in
build = forAllPackages (pkgName: build = forAllPackages (pkgName:
forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.${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: buildStatic = forAllPackages (pkgName:
lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName})); lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName}));
@ -82,20 +75,28 @@ in
(forAllCrossSystems (crossSystem: (forAllCrossSystems (crossSystem:
lib.genAttrs [ "x86_64-linux" ] (system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName})))); lib.genAttrs [ "x86_64-linux" ] (system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName}))));
buildNoGc = forAllSystems (system: buildNoGc = let
self.packages.${system}.nix.override { enableGC = false; } 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); buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-cli);
# Toggles some settings for better coverage. Windows needs these # Toggles some settings for better coverage. Windows needs these
# library combinations, and Debian build Nix with GNU readline too. # library combinations, and Debian build Nix with GNU readline too.
buildReadlineNoMarkdown = forAllSystems (system: buildReadlineNoMarkdown = let
self.packages.${system}.nix.override { components = forAllSystems (system:
enableMarkdown = false; nixpkgsFor.${system}.native.nixComponents.overrideScope (self: super: {
readlineFlavor = "readline"; nix-cmd = super.nix-cmd.override {
} enableMarkdown = false;
); readlineFlavor = "readline";
};
})
);
in forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName}));
# Perl bindings for various platforms. # Perl bindings for various platforms.
perlBindings = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-perl-bindings); perlBindings = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-perl-bindings);
@ -196,15 +197,15 @@ in
let pkgs = nixpkgsFor.${system}.native; in let pkgs = nixpkgsFor.${system}.native; in
pkgs.runCommand "install-tests" pkgs.runCommand "install-tests"
{ {
againstSelf = testNixVersions pkgs pkgs.nix pkgs.pkgs.nix; againstSelf = testNixVersions pkgs pkgs.nix;
againstCurrentLatest = againstCurrentLatest =
# FIXME: temporarily disable this on macOS because of #3605. # FIXME: temporarily disable this on macOS because of #3605.
if system == "x86_64-linux" if system == "x86_64-linux"
then testNixVersions pkgs pkgs.nix pkgs.nixVersions.latest then testNixVersions pkgs pkgs.nixVersions.latest
else null; else null;
# Disabled because the latest stable version doesn't handle # Disabled because the latest stable version doesn't handle
# `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work # `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"); } "touch $out");
installerTests = import ../tests/installer { 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 <nlohmann/json.hpp>
#include "command.hh" #include "command.hh"
@ -9,8 +10,7 @@
#include "profiles.hh" #include "profiles.hh"
#include "repl.hh" #include "repl.hh"
#include "strings.hh" #include "strings.hh"
#include "environment-variables.hh"
extern char * * environ __attribute__((weak));
namespace nix { namespace nix {
@ -23,7 +23,8 @@ nix::Commands RegisterCommand::getCommandsFor(const std::vector<std::string> & p
if (name.size() == prefix.size() + 1) { if (name.size() == prefix.size() + 1) {
bool equal = true; bool equal = true;
for (size_t i = 0; i < prefix.size(); ++i) 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) if (equal)
res.insert_or_assign(name[prefix.size()], command); res.insert_or_assign(name[prefix.size()], command);
} }
@ -42,16 +43,16 @@ void NixMultiCommand::run()
std::set<std::string> subCommandTextLines; std::set<std::string> subCommandTextLines;
for (auto & [name, _] : commands) for (auto & [name, _] : commands)
subCommandTextLines.insert(fmt("- `%s`", name)); subCommandTextLines.insert(fmt("- `%s`", name));
std::string markdownError = fmt("`nix %s` requires a sub-command. Available sub-commands:\n\n%s\n", std::string markdownError =
commandName, concatStringsSep("\n", subCommandTextLines)); fmt("`nix %s` requires a sub-command. Available sub-commands:\n\n%s\n",
commandName,
concatStringsSep("\n", subCommandTextLines));
throw UsageError(renderMarkdownToTerminal(markdownError)); throw UsageError(renderMarkdownToTerminal(markdownError));
} }
command->second->run(); command->second->run();
} }
StoreCommand::StoreCommand() StoreCommand::StoreCommand() {}
{
}
ref<Store> StoreCommand::getStore() ref<Store> StoreCommand::getStore()
{ {
@ -126,10 +127,8 @@ ref<Store> EvalCommand::getEvalStore()
ref<EvalState> EvalCommand::getEvalState() ref<EvalState> EvalCommand::getEvalState()
{ {
if (!evalState) { if (!evalState) {
evalState = evalState = std::allocate_shared<EvalState>(
std::allocate_shared<EvalState>( traceable_allocator<EvalState>(), lookupPath, getEvalStore(), fetchSettings, evalSettings, getStore());
traceable_allocator<EvalState>(),
lookupPath, getEvalStore(), fetchSettings, evalSettings, getStore());
evalState->repair = repair; evalState->repair = repair;
@ -144,7 +143,8 @@ MixOperateOnOptions::MixOperateOnOptions()
{ {
addFlag({ addFlag({
.longName = "derivation", .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, .category = installablesCategory,
.handler = {&operateOn, OperateOn::Derivation}, .handler = {&operateOn, OperateOn::Derivation},
}); });
@ -233,46 +233,48 @@ void StorePathCommand::run(ref<Store> store, StorePaths && storePaths)
MixProfile::MixProfile() MixProfile::MixProfile()
{ {
addFlag({ addFlag(
.longName = "profile", {.longName = "profile",
.description = "The profile to operate on.", .description = "The profile to operate on.",
.labels = {"path"}, .labels = {"path"},
.handler = {&profile}, .handler = {&profile},
.completer = completePath .completer = completePath});
});
} }
void MixProfile::updateProfile(const StorePath & storePath) void MixProfile::updateProfile(const StorePath & storePath)
{ {
if (!profile) return; if (!profile)
return;
auto store = getStore().dynamic_pointer_cast<LocalFSStore>(); 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); auto profile2 = absPath(*profile);
switchLink(profile2, switchLink(profile2, createGeneration(*store, profile2, storePath));
createGeneration(*store, profile2, storePath));
} }
void MixProfile::updateProfile(const BuiltPaths & buildables) void MixProfile::updateProfile(const BuiltPaths & buildables)
{ {
if (!profile) return; if (!profile)
return;
StorePaths result; StorePaths result;
for (auto & buildable : buildables) { for (auto & buildable : buildables) {
std::visit(overloaded { std::visit(
[&](const BuiltPath::Opaque & bo) { overloaded{
result.push_back(bo.path); [&](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) { buildable.raw());
for (auto & output : bfd.outputs) {
result.push_back(output.second);
}
},
}, buildable.raw());
} }
if (result.size() != 1) 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]); updateProfile(result[0]);
} }
@ -282,51 +284,85 @@ MixDefaultProfile::MixDefaultProfile()
profile = getDefaultProfile(); profile = getDefaultProfile();
} }
MixEnvironment::MixEnvironment() : ignoreEnvironment(false) MixEnvironment::MixEnvironment()
: ignoreEnvironment(false)
{ {
addFlag({ addFlag({
.longName = "ignore-environment", .longName = "ignore-env",
.aliases = {"ignore-environment"},
.shortName = 'i', .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}, .handler = {&ignoreEnvironment, true},
}); });
addFlag({ addFlag({
.longName = "keep", .longName = "keep-env-var",
.aliases = {"keep"},
.shortName = 'k', .shortName = 'k',
.description = "Keep the environment variable *name*.", .description = "Keep the environment variable *name*, when using `--ignore-env`.",
.category = environmentVariablesCategory,
.labels = {"name"}, .labels = {"name"},
.handler = {[&](std::string s) { keep.insert(s); }}, .handler = {[&](std::string s) { keepVars.insert(s); }},
}); });
addFlag({ addFlag({
.longName = "unset", .longName = "unset-env-var",
.aliases = {"unset"},
.shortName = 'u', .shortName = 'u',
.description = "Unset the environment variable *name*.", .description = "Unset the environment variable *name*.",
.category = environmentVariablesCategory,
.labels = {"name"}, .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() { void MixEnvironment::setEnviron()
if (ignoreEnvironment) { {
if (!unset.empty()) if (ignoreEnvironment && !unsetVars.empty())
throw UsageError("--unset does not make sense with --ignore-environment"); throw UsageError("--unset-env-var does not make sense with --ignore-env");
for (const auto & var : keep) { if (!ignoreEnvironment && !keepVars.empty())
auto val = getenv(var.c_str()); throw UsageError("--keep-env-var does not make sense without --ignore-env");
if (val) stringsEnv.emplace_back(fmt("%s=%s", var.c_str(), val));
}
vectorEnv = stringsToCharPtrs(stringsEnv); auto env = getEnv();
environ = vectorEnv.data();
} else {
if (!keep.empty())
throw UsageError("--keep does not make sense without --ignore-environment");
for (const auto & var : unset) if (ignoreEnvironment)
unsetenv(var.c_str()); 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 std::string programPath;
extern char * * savedArgv; extern char ** savedArgv;
class EvalState; class EvalState;
struct Pos; struct Pos;
@ -24,7 +24,8 @@ static constexpr Command::Category catSecondary = 100;
static constexpr Command::Category catUtility = 101; static constexpr Command::Category catUtility = 101;
static constexpr Command::Category catNixInstallation = 102; 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 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. * arguments) so that the completions for these flags can use them.
*/ */
virtual std::vector<FlakeRef> getFlakeRefsForCompletion() virtual std::vector<FlakeRef> getFlakeRefsForCompletion()
{ return {}; } {
return {};
}
}; };
struct SourceExprCommand : virtual Args, MixFlakeOptions struct SourceExprCommand : virtual Args, MixFlakeOptions
@ -122,11 +125,9 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions
SourceExprCommand(); SourceExprCommand();
Installables parseInstallables( Installables parseInstallables(ref<Store> store, std::vector<std::string> ss);
ref<Store> store, std::vector<std::string> ss);
ref<Installable> parseInstallable( ref<Installable> parseInstallable(ref<Store> store, const std::string & installable);
ref<Store> store, const std::string & installable);
virtual Strings getDefaultFlakeAttrPaths(); virtual Strings getDefaultFlakeAttrPaths();
@ -272,10 +273,10 @@ struct RegisterCommand
typedef std::map<std::vector<std::string>, std::function<ref<Command>()>> Commands; typedef std::map<std::vector<std::string>, std::function<ref<Command>()>> Commands;
static Commands * commands; static Commands * commands;
RegisterCommand(std::vector<std::string> && name, RegisterCommand(std::vector<std::string> && name, std::function<ref<Command>()> command)
std::function<ref<Command>()> command)
{ {
if (!commands) commands = new Commands; if (!commands)
commands = new Commands;
commands->emplace(name, command); commands->emplace(name, command);
} }
@ -285,13 +286,13 @@ struct RegisterCommand
template<class T> template<class T>
static RegisterCommand registerCommand(const std::string & name) static RegisterCommand registerCommand(const std::string & name)
{ {
return RegisterCommand({name}, [](){ return make_ref<T>(); }); return RegisterCommand({name}, []() { return make_ref<T>(); });
} }
template<class T> template<class T>
static RegisterCommand registerCommand2(std::vector<std::string> && name) 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 struct MixProfile : virtual StoreCommand
@ -313,19 +314,21 @@ struct MixDefaultProfile : MixProfile
MixDefaultProfile(); MixDefaultProfile();
}; };
struct MixEnvironment : virtual Args { struct MixEnvironment : virtual Args
{
StringSet keep, unset; StringSet keepVars;
Strings stringsEnv; StringSet unsetVars;
std::vector<char*> vectorEnv; std::map<std::string, std::string> setVars;
bool ignoreEnvironment; bool ignoreEnvironment;
MixEnvironment(); MixEnvironment();
/*** /***
* Modify global environ based on `ignoreEnvironment`, `keep`, and * Modify global environ based on `ignoreEnvironment`, `keep`,
* `unset`. It's expected that exec will be called before this class * `unset`, and `added`. It's expected that exec will be called
* goes out of scope, otherwise `environ` will become invalid. * before this class goes out of scope, otherwise `environ` will
* become invalid.
*/ */
void setEnviron(); void setEnviron();
}; };
@ -349,9 +352,6 @@ void completeFlakeRefWithFragment(
std::string showVersions(const std::set<std::string> & versions); std::string showVersions(const std::set<std::string> & versions);
void printClosureDiff( void printClosureDiff(
ref<Store> store, ref<Store> store, const StorePath & beforePath, const StorePath & afterPath, std::string_view indent);
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') headers += files('nix_api_expr_internal.h')
subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library( this_library = library(
'nixexprc', 'nixexprc',

View file

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

View file

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

View file

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

View file

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

View file

@ -217,8 +217,12 @@ static void initRepoAtomically(std::filesystem::path &path, bool bare) {
try { try {
std::filesystem::rename(tmpDir, path); std::filesystem::rename(tmpDir, path);
} catch (std::filesystem::filesystem_error & e) { } 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; return;
}
else else
throw SysError("moving temporary git repository from %s to %s", tmpDir, path); 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/threads')
subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
rapidcheck = dependency('rapidcheck') rapidcheck = dependency('rapidcheck')
deps_private += 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/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library( this_library = library(
'nixmainc', 'nixmainc',

View file

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

View file

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

View file

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

View file

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

View file

@ -38,15 +38,19 @@ mkMesonExecutable (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.) (fileset.fileFilter (file: file.hasExt "hh") ./.)
]; ];
buildInputs = [ # Hack for sake of the dev shell
nix-store passthru.externalBuildInputs = [
nix-store-c
nix-store-test-support
sqlite sqlite
rapidcheck rapidcheck
gtest gtest
]; ];
buildInputs = finalAttrs.passthru.externalBuildInputs ++ [
nix-store
nix-store-c
nix-store-test-support
];
preConfigure = preConfigure =
# "Inline" .version so it's not a symlink, and includes the suffix. # "Inline" .version so it's not a symlink, and includes the suffix.
# Do the meson utils, without modification. # 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) { CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) {
for (size_t len = 0; len < toClientLog.size(); ++len) { for (size_t len = 0; len < toClientLog.size(); ++len) {
NullBufferedSink nullSink; NullBufferedSink nullSink;
StringSource in { auto substring = toClientLog.substr(0, len);
// truncate StringSource in{substring};
toClientLog.substr(0, len)
};
if (len < 8) { if (len < 8) {
EXPECT_THROW( EXPECT_THROW(
ServeProto::BasicClientConnection::handshake( ServeProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, "blah"), EndOfFile);
nullSink, in, defaultVersion, "blah"),
EndOfFile);
} else { } else {
// Not sure why cannot keep on checking for `EndOfFile`. // Not sure why cannot keep on checking for `EndOfFile`.
EXPECT_THROW( EXPECT_THROW(ServeProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, "blah"), Error);
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) { CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) {
for (size_t len = 0; len < toClientLog.size(); ++len) { for (size_t len = 0; len < toClientLog.size(); ++len) {
NullBufferedSink nullSink; NullBufferedSink nullSink;
StringSource in { auto substring = toClientLog.substr(0, len);
// truncate StringSource in{substring};
toClientLog.substr(0, len)
};
if (len < 8) { if (len < 8) {
EXPECT_THROW( EXPECT_THROW(
WorkerProto::BasicClientConnection::handshake( WorkerProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, {}), EndOfFile);
nullSink, in, defaultVersion, {}),
EndOfFile);
} else { } else {
// Not sure why cannot keep on checking for `EndOfFile`. // Not sure why cannot keep on checking for `EndOfFile`.
EXPECT_THROW( EXPECT_THROW(WorkerProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, {}), Error);
WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion, {}),
Error);
} }
} }
}); });

View file

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

View file

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

View file

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

View file

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

View file

@ -7,6 +7,8 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <memory>
namespace nixC { namespace nixC {
TEST_F(nix_api_util_context, nix_context_error) TEST_F(nix_api_util_context, nix_context_error)
@ -57,6 +59,14 @@ struct MySettings : nix::Config
MySettings mySettings; MySettings mySettings;
static nix::GlobalConfig::Register rs(&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) TEST_F(nix_api_util_context, nix_setting_get)
{ {
ASSERT_EQ(ctx->last_err_code, NIX_OK); ASSERT_EQ(ctx->last_err_code, NIX_OK);
@ -97,7 +107,8 @@ TEST_F(nix_api_util_context, nix_err_msg)
// advanced usage // advanced usage
unsigned int sz; 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()); ASSERT_EQ(sz, err_msg.size());
} }
@ -113,7 +124,8 @@ TEST_F(nix_api_util_context, nix_err_info_msg)
} catch (...) { } catch (...) {
nix_context_error(ctx); 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()); ASSERT_STREQ("testing error", err_info.c_str());
} }
@ -130,7 +142,8 @@ TEST_F(nix_api_util_context, nix_err_name)
} catch (...) { } catch (...) {
nix_context_error(ctx); 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"); ASSERT_EQ(std::string(err_name), "nix::Error");
} }

View file

@ -13,6 +13,8 @@
namespace nix { namespace nix {
static constexpr auto environmentVariablesCategory = "Options that change environment variables";
/** /**
* @return an environment variable. * @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. * 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. * Write a line to a file descriptor.
@ -101,8 +106,25 @@ void drainFD(
#endif #endif
); );
/**
* Get [Standard Input](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_(stdin))
*/
[[gnu::always_inline]] [[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 #ifndef _WIN32
return STDOUT_FILENO; return STDOUT_FILENO;
#else #else
@ -110,6 +132,19 @@ inline Descriptor getStandardOut() {
#endif #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. * Automatic cleanup of resources.
*/ */

View file

@ -38,7 +38,7 @@ void Logger::warn(const std::string & msg)
void Logger::writeToStdout(std::string_view s) void Logger::writeToStdout(std::string_view s)
{ {
Descriptor standard_out = getStandardOut(); Descriptor standard_out = getStandardOutput();
writeFull(standard_out, s); writeFull(standard_out, s);
writeFull(standard_out, "\n"); writeFull(standard_out, "\n");
} }
@ -118,11 +118,7 @@ void writeToStderr(std::string_view s)
{ {
try { try {
writeFull( writeFull(
#ifdef _WIN32 getStandardError(),
GetStdHandle(STD_ERROR_HANDLE),
#else
STDERR_FILENO,
#endif
s, false); s, false);
} catch (SystemError & e) { } catch (SystemError & e) {
/* Ignore failing writes to stderr. We need to ignore write /* 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()) 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') 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' if host_machine.system() == 'windows'
socket = cxx.find_library('ws2_32') socket = cxx.find_library('ws2_32')
deps_other += socket deps_other += socket
@ -265,6 +258,7 @@ else
endif endif
subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library( this_library = library(
'nixutil', 'nixutil',

View file

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

View file

@ -2,6 +2,7 @@
///@file ///@file
#include <memory> #include <memory>
#include <type_traits>
#include "types.hh" #include "types.hh"
#include "util.hh" #include "util.hh"
@ -202,7 +203,14 @@ struct StringSource : Source
{ {
std::string_view s; std::string_view s;
size_t pos; 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(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; 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; std::string s;
while (1) { while (1) {
@ -58,8 +58,12 @@ std::string readLine(int fd)
if (rd == -1) { if (rd == -1) {
if (errno != EINTR) if (errno != EINTR)
throw SysError("reading a line"); throw SysError("reading a line");
} else if (rd == 0) } else if (rd == 0) {
throw EndOfFile("unexpected EOF reading a line"); if (eofOk)
return s;
else
throw EndOfFile("unexpected EOF reading a line");
}
else { else {
if (ch == '\n') return s; if (ch == '\n') return s;
s += ch; 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; std::string s;
while (1) { while (1) {
@ -71,8 +71,12 @@ std::string readLine(HANDLE handle)
DWORD rd; DWORD rd;
if (!ReadFile(handle, &ch, 1, &rd, NULL)) { if (!ReadFile(handle, &ch, 1, &rd, NULL)) {
throw WinError("reading a line"); throw WinError("reading a line");
} else if (rd == 0) } else if (rd == 0) {
throw EndOfFile("unexpected EOF reading a line"); if (eofOk)
return s;
else
throw EndOfFile("unexpected EOF reading a line");
}
else { else {
if (ch == '\n') return s; if (ch == '\n') return s;
s += ch; s += ch;

View file

@ -536,7 +536,7 @@ static void main_nix_build(int argc, char * * argv)
env["__ETC_PROFILE_SOURCED"] = "1"; 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_STORE"] = store->storeDir;
env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores); 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 (!opFlags.empty()) throw UsageError("unknown flag");
if (opArgs.size() != 1) throw UsageError("only one argument allowed"); if (opArgs.size() != 1) throw UsageError("only one argument allowed");
FdSink sink(getStandardOut()); FdSink sink(getStandardOutput());
std::string path = *opArgs.begin(); std::string path = *opArgs.begin();
dumpPath(path, sink); dumpPath(path, sink);
sink.flush(); sink.flush();
@ -722,7 +722,7 @@ static void opExport(Strings opFlags, Strings opArgs)
for (auto & i : opArgs) for (auto & i : opArgs)
paths.insert(store->followLinksToStorePath(i)); paths.insert(store->followLinksToStorePath(i));
FdSink sink(getStandardOut()); FdSink sink(getStandardOutput());
store->exportPaths(paths, sink); store->exportPaths(paths, sink);
sink.flush(); sink.flush();
} }
@ -835,7 +835,7 @@ static void opServe(Strings opFlags, Strings opArgs)
if (!opArgs.empty()) throw UsageError("no arguments expected"); if (!opArgs.empty()) throw UsageError("no arguments expected");
FdSource in(STDIN_FILENO); FdSource in(STDIN_FILENO);
FdSink out(getStandardOut()); FdSink out(getStandardOutput());
/* Exchange the greeting. */ /* Exchange the greeting. */
ServeProto::Version clientVersion = ServeProto::Version clientVersion =

View file

@ -16,7 +16,7 @@ struct MixCat : virtual Args
throw Error("path '%1%' is not a regular file", path); throw Error("path '%1%' is not a regular file", path);
stopProgressBar(); 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 void run(ref<Store> store, const StorePath & storePath) override
{ {
FdSink sink(getStandardOut()); FdSink sink(getStandardOutput());
store->narFromPath(storePath, sink); store->narFromPath(storePath, sink);
sink.flush(); sink.flush();
} }
@ -55,7 +55,7 @@ struct CmdDumpPath2 : Command
void run() override void run() override
{ {
FdSink sink(getStandardOut()); FdSink sink(getStandardOutput());
dumpPath(path, sink); dumpPath(path, sink);
sink.flush(); sink.flush();
} }

View file

@ -115,7 +115,7 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption
else if (raw) { else if (raw) {
stopProgressBar(); 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) { else if (json) {

View file

@ -17,7 +17,6 @@
#include "eval-cache.hh" #include "eval-cache.hh"
#include "markdown.hh" #include "markdown.hh"
#include "users.hh" #include "users.hh"
#include "terminal.hh"
#include <filesystem> #include <filesystem>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
@ -1275,97 +1274,25 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
auto showDerivation = [&]() auto showDerivation = [&]()
{ {
auto name = visitor.getAttr(state->sName)->getString(); 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) { 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("type", "derivation");
j.emplace("name", name); j.emplace("name", name);
j.emplace("description", description ? *description : ""); j.emplace("description", description ? *description : "");
} else { } else {
auto type = logger->cout("%s: %s '%s'",
headerPrefix,
attrPath.size() == 2 && attrPathS[0] == "devShell" ? "development environment" : attrPath.size() == 2 && attrPathS[0] == "devShell" ? "development environment" :
attrPath.size() >= 2 && attrPathS[0] == "devShells" ? "development environment" : attrPath.size() >= 2 && attrPathS[0] == "devShells" ? "development environment" :
attrPath.size() == 3 && attrPathS[0] == "checks" ? "derivation" : attrPath.size() == 3 && attrPathS[0] == "checks" ? "derivation" :
attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" : attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" :
"package"; "package",
if (description && !description->empty()) { name);
// 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);
}
} }
}; };

View file

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

View file

@ -35,6 +35,7 @@ subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads') subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
configdata = configuration_data() configdata = configuration_data()
@ -229,6 +230,8 @@ foreach linkname : nix_symlinks
t = custom_target( t = custom_target(
command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'], command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'],
output: linkname + executable_suffix, 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) # TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working)
build_by_default: true build_by_default: true
) )
@ -247,6 +250,8 @@ install_symlink(
custom_target( custom_target(
command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'], command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'],
output: 'build-remote' + executable_suffix, 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) # TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working)
build_by_default: true build_by_default: true
) )

View file

@ -177,7 +177,7 @@ struct CmdKeyGenerateSecret : Command
throw UsageError("required argument '--key-name' is missing"); throw UsageError("required argument '--key-name' is missing");
stopProgressBar(); 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)); SecretKey secretKey(drainFD(STDIN_FILENO));
stopProgressBar(); 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 # preserve quotes variables in the single-quoted string
# shellcheck disable=SC2016 # shellcheck disable=SC2016
outPath=$(nix-build --no-out-link -E ' outPath=$(nix-build --no-out-link -E '
with import ./config.nix; with import '"${config_nix}"';
mkDerivation { mkDerivation {
name = "nar-listing"; name = "nar-listing";
buildCommand = "mkdir $out; echo foo > $out/bar; ln -s xyzzy $out/link"; 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 # preserve quotes variables in the single-quoted string
# shellcheck disable=SC2016 # shellcheck disable=SC2016
outPath=$(nix-build --no-out-link -E ' outPath=$(nix-build --no-out-link -E '
with import ./config.nix; with import '"${config_nix}"';
mkDerivation { mkDerivation {
name = "debug-info"; name = "debug-info";
buildCommand = "mkdir -p $out/lib/debug/.build-id/02; echo foo > $out/lib/debug/.build-id/02/623eda209c26a59b1a8638ff7752f6b945c26b.debug"; 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 # preserve quotes variables in the single-quoted string
# shellcheck disable=SC2016 # shellcheck disable=SC2016
expr=' expr='
with import ./config.nix; with import '"${config_nix}"';
mkDerivation { mkDerivation {
name = "multi-output"; name = "multi-output";
buildCommand = "mkdir -p $out; echo foo > $doc; echo $doc > $out/docref"; buildCommand = "mkdir -p $out; echo foo > $doc; echo $doc > $out/docref";

View file

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

View file

@ -1,6 +1,6 @@
{ busybox, contentAddressed ? false }: { busybox, contentAddressed ? false }:
with import ./config.nix; with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix";
let 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 ({ let mkCADerivation = args: mkDerivation ({
__contentAddressed = true; __contentAddressed = true;

View file

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

View file

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

View file

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

View file

@ -29,5 +29,5 @@ suites += {
'substitute.sh', 'substitute.sh',
'why-depends.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 source common.sh
export NIX_TESTS_CA_BY_DEFAULT=1 export NIX_TESTS_CA_BY_DEFAULT=1

View file

@ -2,6 +2,11 @@
source common.sh 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 CONTENT_ADDRESSED=true
cd .. cd ..
source ./nix-shell.sh 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 ({ let mkCADerivation = args: mkDerivation ({
__contentAddressed = true; __contentAddressed = true;

View file

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

View file

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

View file

@ -1,3 +1,5 @@
#!/usr/bin/env bash
source common.sh source common.sh
export NIX_TESTS_CA_BY_DEFAULT=1 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 { rec {

View file

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

View file

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

View file

@ -37,7 +37,10 @@ if canUseSandbox; then
} }
EOF 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 TODO_NixOS

View file

@ -343,6 +343,15 @@ count() {
echo $# 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 trap onError ERR
fi # COMMON_FUNCTIONS_SH_SOURCED 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 # When we're doing everything in the same store, we need to bring
# dependencies into context. # 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^\(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";^' \ -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}")")" commonDir="$(readlink -f "$(dirname "${BASH_SOURCE[0]-$0}")")"
# Since these are generated files # Just for `isTestOnNixOS`
# shellcheck disable=SC1091
source "$commonDir/functions.sh" source "$commonDir/functions.sh"
# shellcheck disable=SC1091 # 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 # Make sure shellcheck knows this will be defined by the above generated snippet
: "${bash?}" "${bindir?}" : "${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 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 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}")")" commonDir="$(readlink -f "$(dirname "${BASH_SOURCE[0]-$0}")")"
# Since this is a generated file # Since this is a generated file
# shellcheck disable=SC1091 # 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 # Make sure shellcheck knows all these will be defined by the above generated snippet
: "${bindir?} ${coreutils?} ${dot?} ${SHELL?} ${busybox?} ${version?} ${system?}" : "${bindir?} ${coreutils?} ${dot?} ${SHELL?} ${busybox?} ${version?} ${system?}"
export coreutils dot 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 _canUseSandbox=1
fi 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 fi # COMMON_VARS_SH_SOURCED

View file

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

View file

@ -15,5 +15,5 @@ suites += {
'dep-built-drv.sh', 'dep-built-drv.sh',
'old-daemon-error-hack.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. # A simple content-addressed derivation.
# The derivation can be arbitrarily modified by passing a different `seed`, # 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 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. # A simple content-addressed derivation.
# The derivation can be arbitrarily modified by passing a different `seed`, # 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 ]] [[ $(nix eval --impure --expr "import $TEST_ROOT/foo/bar") = 123 ]]
# Test --arg-from-file. # 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. # Check that special(-ish) files are drained.
if [[ -e /proc/version ]]; then 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 { rec {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,10 @@
source common.sh 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" cd "$TEST_HOME"

View file

@ -34,7 +34,10 @@ writeSimpleFlake() {
} }
EOF 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() { createSimpleGitFlake() {

View file

@ -2,7 +2,8 @@
source common.sh 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 cd $TEST_HOME
@ -26,7 +27,17 @@ cat <<EOF > flake.nix
EOF EOF
# Without --accept-flake-config, the post hook should not run. # 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
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 ]]) (! [[ -f post-hook-ran ]])
TODO_NixOS TODO_NixOS
clearStore clearStore

View file

@ -5,11 +5,11 @@ source ../common.sh
TODO_NixOS TODO_NixOS
clearStore 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. # Create flake under test.
cp ../shell-hello.nix ../config.nix $TEST_HOME/ cp ../shell-hello.nix "$config_nix" "$TEST_HOME/"
cat <<EOF >$TEST_HOME/flake.nix cat <<EOF >"$TEST_HOME/flake.nix"
{ {
inputs.nixpkgs.url = "$TEST_HOME/nixpkgs"; inputs.nixpkgs.url = "$TEST_HOME/nixpkgs";
outputs = {self, nixpkgs}: { outputs = {self, nixpkgs}: {
@ -24,9 +24,13 @@ cat <<EOF >$TEST_HOME/flake.nix
EOF EOF
# Create fake nixpkgs flake. # Create fake nixpkgs flake.
mkdir -p $TEST_HOME/nixpkgs mkdir -p "$TEST_HOME/nixpkgs"
cp ../config.nix ../shell.nix $TEST_HOME/nixpkgs cp "${config_nix}" ../shell.nix "$TEST_HOME/nixpkgs"
cat <<EOF >$TEST_HOME/nixpkgs/flake.nix
# `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}: { outputs = {self}: {
legacyPackages.$system.bashInteractive = (import ./shell.nix {}).bashInteractive; legacyPackages.$system.bashInteractive = (import ./shell.nix {}).bashInteractive;
@ -34,7 +38,7 @@ cat <<EOF >$TEST_HOME/nixpkgs/flake.nix
} }
EOF EOF
cd $TEST_HOME cd "$TEST_HOME"
# Test whether `nix develop` passes through environment variables. # Test whether `nix develop` passes through environment variables.
[[ "$( [[ "$(
@ -43,13 +47,86 @@ echo "\$ENVVAR"
EOF EOF
)" = "a" ]] )" = "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 "$( [[ -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" echo "\$ENVVAR"
EOF 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. # Determine the bashInteractive executable.
nix build --no-write-lock-file './nixpkgs#bashInteractive' --out-link ./bash-interactive nix build --no-write-lock-file './nixpkgs#bashInteractive' --out-link ./bash-interactive
BASH_INTERACTIVE_EXECUTABLE="$PWD/bash-interactive/bin/bash" 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. # 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" echo "\$SHELL"
EOF EOF
)" -ef "$BASH_INTERACTIVE_EXECUTABLE" ]] )" -ef "$BASH_INTERACTIVE_EXECUTABLE" ]]

View file

@ -7,7 +7,7 @@ requireGit
flake1Dir="$TEST_ROOT/eval-cache-flake" flake1Dir="$TEST_ROOT/eval-cache-flake"
createGitRepo "$flake1Dir" "" 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" add simple.nix simple.builder.sh config.nix
git -C "$flake1Dir" commit -m "config.nix" git -C "$flake1Dir" commit -m "config.nix"

View file

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

View file

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

View file

@ -6,7 +6,10 @@ TODO_NixOS
clearStore clearStore
rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local 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 cd $TEST_HOME
cat <<EOF > flake.nix cat <<EOF > flake.nix

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