Merge remote-tracking branch 'nixos/master'

This commit is contained in:
Max Headroom 2024-04-22 23:29:11 +02:00
commit 5ecd820c18
59 changed files with 998 additions and 226 deletions

2
.gitignore vendored
View file

@ -154,6 +154,8 @@ result-*
.vscode/
.idea/
.pre-commit-config.yaml
# clangd and possibly more
.cache/

View file

@ -27,6 +27,7 @@ makefiles = \
ifdef HOST_UNIX
makefiles += \
scripts/local.mk \
maintainers/local.mk \
misc/bash/local.mk \
misc/fish/local.mk \
misc/zsh/local.mk \

View file

@ -317,6 +317,17 @@ case "$host_os" in
[CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS"])
have_seccomp=1
AC_DEFINE([HAVE_SECCOMP], [1], [Whether seccomp is available and should be used for sandboxing.])
AC_COMPILE_IFELSE([
AC_LANG_SOURCE([[
#include <seccomp.h>
#ifndef __SNR_fchmodat2
# error "Missing support for fchmodat2"
#endif
]])
], [], [
echo "libseccomp is missing __SNR_fchmodat2. Please provide libseccomp 2.5.5 or later"
exit 1
])
else
have_seccomp=
fi

View file

@ -273,6 +273,29 @@ Configure your editor to use the `clangd` from the `.#native-clangStdenvPackages
> Some other editors (e.g. Emacs, Vim) need a plugin to support LSP servers in general (e.g. [lsp-mode](https://github.com/emacs-lsp/lsp-mode) for Emacs and [vim-lsp](https://github.com/prabirshrestha/vim-lsp) for vim).
> Editor-specific setup is typically opinionated, so we will not cover it here in more detail.
## Formatting and pre-commit hooks
You may run the formatters as a one-off using:
```console
make format
```
If you'd like to run the formatters before every commit, install the hooks:
```
pre-commit-hooks-install
```
This installs [pre-commit](https://pre-commit.com) using [cachix/git-hooks.nix](https://github.com/cachix/git-hooks.nix).
When making a commit, pay attention to the console output.
If it fails, run `git add --patch` to approve the suggestions _and commit again_.
To refresh pre-commit hook's config file, do the following:
1. Exit the development shell and start it again by running `nix develop`.
2. If you also use the pre-commit hook, also run `pre-commit-hooks-install` again.
## Add a release note
`doc/manual/rl-next` contains release notes entries for all unreleased changes.

View file

@ -295,6 +295,25 @@
[path]: ./language/values.md#type-path
[attribute name]: ./language/values.md#attribute-set
- [base directory]{#gloss-base-directory}
The location from which relative paths are resolved.
- For expressions in a file, the base directory is the directory containing that file.
This is analogous to the directory of a [base URL](https://datatracker.ietf.org/doc/html/rfc1808#section-3.3).
<!-- which is sufficient for resolving non-empty URLs -->
<!--
The wording here may look awkward, but it's for these reasons:
* "with --expr": it's a flag, and not an option with an accompanying value
* "written in": the expression itself must be written as an argument,
whereas the more natural "passed as an argument" allows an interpretation
where the expression could be passed by file name.
-->
- For expressions written in command line arguments with [`--expr`](@docroot@/command-ref/opt-common.html#opt-expr), the base directory is the current working directory.
[base directory]: #gloss-base-directory
- [experimental feature]{#gloss-experimental-feature}
Not yet stabilized functionality guarded by named experimental feature flags.

View file

@ -50,7 +50,7 @@ Supported systems:
To explicitly instruct the installer to perform a multi-user installation on your system:
```console
$ curl -L https://nixos.org/nix/install | sh -s -- --daemon
$ bash <(curl -L https://nixos.org/nix/install) --daemon
```
You can run this under your usual user account or `root`.
@ -61,7 +61,7 @@ The script will invoke `sudo` as needed.
To explicitly select a single-user installation on your system:
```console
$ curl -L https://nixos.org/nix/install | sh -s -- --no-daemon
$ bash <(curl -L https://nixos.org/nix/install) --no-daemon
```
In a single-user installation, `/nix` is owned by the invoking user.

View file

@ -5,8 +5,9 @@
If you have a [single-user installation](./installing-binary.md#single-user-installation) of Nix, uninstall it by running:
```console
$ rm -rf /nix
$ rm -rf /nix ~/.nix-channels ~/.nix-defexpr ~/.nix-profile
```
You might also want to manually remove references to Nix from your `~/.profile`.
## Multi User

View file

@ -97,8 +97,8 @@
is not a path: it's parsed as an expression that selects the
attribute `sh` from the variable `builder`. If the file name is
relative, i.e., if it does not begin with a slash, it is made
absolute at parse time relative to the directory of the Nix
expression that contained it. For instance, if a Nix expression in
absolute at parse time relative to the [base directory](@docroot@/glossary.md#gloss-base-directory).
For instance, if a Nix expression in
`/foo/bar/bla.nix` refers to `../xyzzy/fnord.nix`, the absolute path
is `/foo/xyzzy/fnord.nix`.
@ -107,7 +107,7 @@
e.g. `~/foo` would be equivalent to `/home/edolstra/foo` for a user
whose home directory is `/home/edolstra`.
For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` in the current directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.
For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` in the base directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.
Note that the Nix language assumes that all input files will remain _unchanged_ while evaluating a Nix expression.
For example, assume you used a file path in an interpolated string during a `nix repl` session.

View file

@ -16,6 +16,41 @@
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1712014858,
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"libgit2": {
"flake": false,
"locked": {
@ -64,12 +99,40 @@
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": [],
"flake-utils": "flake-utils",
"gitignore": [],
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1712897695,
"narHash": "sha256-nMirxrGteNAl9sWiOhoN5tIHyjBbVi5e2tgZUgZlK3Y=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "40e6053ecb65fcbf12863338a6dcefb3f55f1bf8",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"libgit2": "libgit2",
"nixpkgs": "nixpkgs",
"nixpkgs-regression": "nixpkgs-regression"
"nixpkgs-regression": "nixpkgs-regression",
"pre-commit-hooks": "pre-commit-hooks"
}
}
},

View file

@ -13,7 +13,19 @@
inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
inputs.libgit2 = { url = "github:libgit2/libgit2"; flake = false; };
outputs = { self, nixpkgs, nixpkgs-regression, libgit2, ... }:
# dev tooling
inputs.flake-parts.url = "github:hercules-ci/flake-parts";
inputs.pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix";
# work around https://github.com/NixOS/nix/issues/7730
inputs.flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs";
inputs.pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs";
inputs.pre-commit-hooks.inputs.nixpkgs-stable.follows = "nixpkgs";
# work around 7730 and https://github.com/NixOS/nix/issues/7807
inputs.pre-commit-hooks.inputs.flake-compat.follows = "";
inputs.pre-commit-hooks.inputs.gitignore.follows = "";
outputs = inputs@{ self, nixpkgs, nixpkgs-regression, libgit2, ... }:
let
inherit (nixpkgs) lib;
@ -62,6 +74,17 @@
})
stdenvs);
# We don't apply flake-parts to the whole flake so that non-development attributes
# load without fetching any development inputs.
devFlake = inputs.flake-parts.lib.mkFlake { inherit inputs; } {
imports = [ ./maintainers/flake-module.nix ];
systems = lib.subtractLists crossSystems systems;
perSystem = { system, ... }: {
_module.args.pkgs = nixpkgsFor.${system}.native;
};
};
# Memoize nixpkgs for different platforms for efficiency.
nixpkgsFor = forAllSystems
(system: let
@ -191,6 +214,13 @@
inherit fileset stdenv;
};
# See https://github.com/NixOS/nixpkgs/pull/214409
# Remove when fixed in this flake's nixpkgs
pre-commit =
if prev.stdenv.hostPlatform.system == "i686-linux"
then (prev.pre-commit.override (o: { dotnet-sdk = ""; })).overridePythonAttrs (o: { doCheck = false; })
else prev.pre-commit;
};
in {
@ -366,7 +396,8 @@
# Since the support is only best-effort there, disable the perl
# bindings
perlBindings = self.hydraJobs.perlBindings.${system};
});
} // devFlake.checks.${system} or {}
);
packages = forAllSystems (system: rec {
inherit (nixpkgsFor.${system}.native) nix changelog-d-nix;
@ -401,7 +432,11 @@
stdenvs)));
devShells = let
makeShell = pkgs: stdenv: (pkgs.nix.override { inherit stdenv; forDevShell = true; }).overrideAttrs (attrs: {
makeShell = pkgs: stdenv: (pkgs.nix.override { inherit stdenv; forDevShell = true; }).overrideAttrs (attrs:
let
modular = devFlake.getSystem stdenv.buildPlatform.system;
in {
pname = "shell-for-" + attrs.pname;
installFlags = "sysconfdir=$(out)/etc";
shellHook = ''
PATH=$prefix/bin:$PATH
@ -412,7 +447,21 @@
XDG_DATA_DIRS+=:$out/share
'';
# We use this shell with the local checkout, not unpackPhase.
src = null;
env = {
# 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}";
};
nativeBuildInputs = attrs.nativeBuildInputs or []
++ [
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

View file

@ -0,0 +1,436 @@
{ lib, getSystem, inputs, ... }:
{
imports = [
inputs.pre-commit-hooks.flakeModule
];
perSystem = { config, pkgs, ... }: {
# https://flake.parts/options/pre-commit-hooks-nix.html#options
pre-commit.settings = {
hooks = {
clang-format.enable = true;
# TODO: nixfmt, https://github.com/NixOS/nixfmt/issues/153
};
excludes = [
# We don't want to format test data
# ''tests/(?!nixos/).*\.nix''
''^tests/.*''
# Don't format vendored code
''^src/toml11/.*''
''^doc/manual/redirects\.js$''
''^doc/manual/theme/highlight\.js$''
# We haven't applied formatting to these files yet
''^doc/manual/redirects\.js$''
''^doc/manual/theme/highlight\.js$''
''^precompiled-headers\.h$''
''^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$''
''^src/libcmd/installable-attr-path\.cc$''
''^src/libcmd/installable-attr-path\.hh$''
''^src/libcmd/installable-derived-path\.cc$''
''^src/libcmd/installable-derived-path\.hh$''
''^src/libcmd/installable-flake\.cc$''
''^src/libcmd/installable-flake\.hh$''
''^src/libcmd/installable-value\.cc$''
''^src/libcmd/installable-value\.hh$''
''^src/libcmd/installables\.cc$''
''^src/libcmd/installables\.hh$''
''^src/libcmd/legacy\.hh$''
''^src/libcmd/markdown\.cc$''
''^src/libcmd/misc-store-flags\.cc$''
''^src/libcmd/repl-interacter\.cc$''
''^src/libcmd/repl-interacter\.hh$''
''^src/libcmd/repl\.cc$''
''^src/libcmd/repl\.hh$''
''^src/libexpr-c/nix_api_expr\.cc$''
''^src/libexpr-c/nix_api_external\.cc$''
''^src/libexpr/attr-path\.cc$''
''^src/libexpr/attr-path\.hh$''
''^src/libexpr/attr-set\.cc$''
''^src/libexpr/attr-set\.hh$''
''^src/libexpr/eval-cache\.cc$''
''^src/libexpr/eval-cache\.hh$''
''^src/libexpr/eval-error\.cc$''
''^src/libexpr/eval-inline\.hh$''
''^src/libexpr/eval-settings\.cc$''
''^src/libexpr/eval-settings\.hh$''
''^src/libexpr/eval\.cc$''
''^src/libexpr/eval\.hh$''
''^src/libexpr/flake/config\.cc$''
''^src/libexpr/flake/flake\.cc$''
''^src/libexpr/flake/flake\.hh$''
''^src/libexpr/flake/flakeref\.cc$''
''^src/libexpr/flake/flakeref\.hh$''
''^src/libexpr/flake/lockfile\.cc$''
''^src/libexpr/flake/lockfile\.hh$''
''^src/libexpr/flake/url-name\.cc$''
''^src/libexpr/function-trace\.cc$''
''^src/libexpr/gc-small-vector\.hh$''
''^src/libexpr/get-drvs\.cc$''
''^src/libexpr/get-drvs\.hh$''
''^src/libexpr/json-to-value\.cc$''
''^src/libexpr/nixexpr\.cc$''
''^src/libexpr/nixexpr\.hh$''
''^src/libexpr/parser-state\.hh$''
''^src/libexpr/pos-table\.hh$''
''^src/libexpr/primops\.cc$''
''^src/libexpr/primops\.hh$''
''^src/libexpr/primops/context\.cc$''
''^src/libexpr/primops/fetchClosure\.cc$''
''^src/libexpr/primops/fetchMercurial\.cc$''
''^src/libexpr/primops/fetchTree\.cc$''
''^src/libexpr/primops/fromTOML\.cc$''
''^src/libexpr/print-ambiguous\.cc$''
''^src/libexpr/print-ambiguous\.hh$''
''^src/libexpr/print-options\.hh$''
''^src/libexpr/print\.cc$''
''^src/libexpr/print\.hh$''
''^src/libexpr/search-path\.cc$''
''^src/libexpr/symbol-table\.hh$''
''^src/libexpr/value-to-json\.cc$''
''^src/libexpr/value-to-json\.hh$''
''^src/libexpr/value-to-xml\.cc$''
''^src/libexpr/value-to-xml\.hh$''
''^src/libexpr/value\.hh$''
''^src/libexpr/value/context\.cc$''
''^src/libexpr/value/context\.hh$''
''^src/libfetchers/attrs\.cc$''
''^src/libfetchers/cache\.cc$''
''^src/libfetchers/cache\.hh$''
''^src/libfetchers/fetch-settings\.cc$''
''^src/libfetchers/fetch-settings\.hh$''
''^src/libfetchers/fetch-to-store\.cc$''
''^src/libfetchers/fetchers\.cc$''
''^src/libfetchers/fetchers\.hh$''
''^src/libfetchers/filtering-input-accessor\.cc$''
''^src/libfetchers/filtering-input-accessor\.hh$''
''^src/libfetchers/fs-input-accessor\.cc$''
''^src/libfetchers/fs-input-accessor\.hh$''
''^src/libfetchers/git-utils\.cc$''
''^src/libfetchers/git-utils\.hh$''
''^src/libfetchers/github\.cc$''
''^src/libfetchers/indirect\.cc$''
''^src/libfetchers/memory-input-accessor\.cc$''
''^src/libfetchers/path\.cc$''
''^src/libfetchers/registry\.cc$''
''^src/libfetchers/registry\.hh$''
''^src/libfetchers/tarball\.cc$''
''^src/libfetchers/tarball\.hh$''
''^src/libfetchers/unix/git\.cc$''
''^src/libfetchers/unix/mercurial\.cc$''
''^src/libmain/common-args\.cc$''
''^src/libmain/common-args\.hh$''
''^src/libmain/loggers\.cc$''
''^src/libmain/loggers\.hh$''
''^src/libmain/progress-bar\.cc$''
''^src/libmain/shared\.cc$''
''^src/libmain/shared\.hh$''
''^src/libmain/unix/stack\.cc$''
''^src/libstore/binary-cache-store\.cc$''
''^src/libstore/binary-cache-store\.hh$''
''^src/libstore/build-result\.hh$''
''^src/libstore/builtins\.hh$''
''^src/libstore/builtins/buildenv\.cc$''
''^src/libstore/builtins/buildenv\.hh$''
''^src/libstore/common-protocol-impl\.hh$''
''^src/libstore/common-protocol\.cc$''
''^src/libstore/common-protocol\.hh$''
''^src/libstore/content-address\.cc$''
''^src/libstore/content-address\.hh$''
''^src/libstore/daemon\.cc$''
''^src/libstore/daemon\.hh$''
''^src/libstore/derivations\.cc$''
''^src/libstore/derivations\.hh$''
''^src/libstore/derived-path-map\.cc$''
''^src/libstore/derived-path-map\.hh$''
''^src/libstore/derived-path\.cc$''
''^src/libstore/derived-path\.hh$''
''^src/libstore/downstream-placeholder\.cc$''
''^src/libstore/downstream-placeholder\.hh$''
''^src/libstore/dummy-store\.cc$''
''^src/libstore/export-import\.cc$''
''^src/libstore/filetransfer\.cc$''
''^src/libstore/filetransfer\.hh$''
''^src/libstore/gc-store\.hh$''
''^src/libstore/globals\.cc$''
''^src/libstore/globals\.hh$''
''^src/libstore/http-binary-cache-store\.cc$''
''^src/libstore/legacy-ssh-store\.cc$''
''^src/libstore/legacy-ssh-store\.hh$''
''^src/libstore/length-prefixed-protocol-helper\.hh$''
''^src/libstore/linux/personality\.cc$''
''^src/libstore/linux/personality\.hh$''
''^src/libstore/local-binary-cache-store\.cc$''
''^src/libstore/local-fs-store\.cc$''
''^src/libstore/local-fs-store\.hh$''
''^src/libstore/log-store\.cc$''
''^src/libstore/log-store\.hh$''
''^src/libstore/machines\.cc$''
''^src/libstore/machines\.hh$''
''^src/libstore/make-content-addressed\.cc$''
''^src/libstore/make-content-addressed\.hh$''
''^src/libstore/misc\.cc$''
''^src/libstore/names\.cc$''
''^src/libstore/names\.hh$''
''^src/libstore/nar-accessor\.cc$''
''^src/libstore/nar-accessor\.hh$''
''^src/libstore/nar-info-disk-cache\.cc$''
''^src/libstore/nar-info-disk-cache\.hh$''
''^src/libstore/nar-info\.cc$''
''^src/libstore/nar-info\.hh$''
''^src/libstore/outputs-spec\.cc$''
''^src/libstore/outputs-spec\.hh$''
''^src/libstore/parsed-derivations\.cc$''
''^src/libstore/path-info\.cc$''
''^src/libstore/path-info\.hh$''
''^src/libstore/path-references\.cc$''
''^src/libstore/path-regex\.hh$''
''^src/libstore/path-with-outputs\.cc$''
''^src/libstore/path\.cc$''
''^src/libstore/path\.hh$''
''^src/libstore/pathlocks\.cc$''
''^src/libstore/pathlocks\.hh$''
''^src/libstore/profiles\.cc$''
''^src/libstore/profiles\.hh$''
''^src/libstore/realisation\.cc$''
''^src/libstore/realisation\.hh$''
''^src/libstore/remote-fs-accessor\.cc$''
''^src/libstore/remote-fs-accessor\.hh$''
''^src/libstore/remote-store-connection\.hh$''
''^src/libstore/remote-store\.cc$''
''^src/libstore/remote-store\.hh$''
''^src/libstore/s3-binary-cache-store\.cc$''
''^src/libstore/s3\.hh$''
''^src/libstore/serve-protocol-impl\.cc$''
''^src/libstore/serve-protocol-impl\.hh$''
''^src/libstore/serve-protocol\.cc$''
''^src/libstore/serve-protocol\.hh$''
''^src/libstore/sqlite\.cc$''
''^src/libstore/sqlite\.hh$''
''^src/libstore/ssh-store-config\.hh$''
''^src/libstore/ssh-store\.cc$''
''^src/libstore/ssh\.cc$''
''^src/libstore/ssh\.hh$''
''^src/libstore/store-api\.cc$''
''^src/libstore/store-api\.hh$''
''^src/libstore/store-dir-config\.hh$''
''^src/libstore/unix/build/derivation-goal\.cc$''
''^src/libstore/unix/build/derivation-goal\.hh$''
''^src/libstore/unix/build/drv-output-substitution-goal\.cc$''
''^src/libstore/unix/build/drv-output-substitution-goal\.hh$''
''^src/libstore/unix/build/entry-points\.cc$''
''^src/libstore/unix/build/goal\.cc$''
''^src/libstore/unix/build/goal\.hh$''
''^src/libstore/unix/build/hook-instance\.cc$''
''^src/libstore/unix/build/local-derivation-goal\.cc$''
''^src/libstore/unix/build/local-derivation-goal\.hh$''
''^src/libstore/unix/build/substitution-goal\.cc$''
''^src/libstore/unix/build/substitution-goal\.hh$''
''^src/libstore/unix/build/worker\.cc$''
''^src/libstore/unix/build/worker\.hh$''
''^src/libstore/unix/builtins/fetchurl\.cc$''
''^src/libstore/unix/builtins/unpack-channel\.cc$''
''^src/libstore/unix/gc\.cc$''
''^src/libstore/unix/local-overlay-store\.cc$''
''^src/libstore/unix/local-overlay-store\.hh$''
''^src/libstore/unix/local-store\.cc$''
''^src/libstore/unix/local-store\.hh$''
''^src/libstore/unix/lock\.cc$''
''^src/libstore/unix/lock\.hh$''
''^src/libstore/unix/optimise-store\.cc$''
''^src/libstore/unix/pathlocks\.cc$''
''^src/libstore/unix/posix-fs-canonicalise\.cc$''
''^src/libstore/unix/posix-fs-canonicalise\.hh$''
''^src/libstore/unix/uds-remote-store\.cc$''
''^src/libstore/unix/uds-remote-store\.hh$''
''^src/libstore/windows/build\.cc$''
''^src/libstore/worker-protocol-impl\.hh$''
''^src/libstore/worker-protocol\.cc$''
''^src/libstore/worker-protocol\.hh$''
''^src/libutil-c/nix_api_util_internal\.h$''
''^src/libutil/archive\.cc$''
''^src/libutil/archive\.hh$''
''^src/libutil/args\.cc$''
''^src/libutil/args\.hh$''
''^src/libutil/args/root\.hh$''
''^src/libutil/callback\.hh$''
''^src/libutil/canon-path\.cc$''
''^src/libutil/canon-path\.hh$''
''^src/libutil/chunked-vector\.hh$''
''^src/libutil/closure\.hh$''
''^src/libutil/comparator\.hh$''
''^src/libutil/compute-levels\.cc$''
''^src/libutil/config-impl\.hh$''
''^src/libutil/config\.cc$''
''^src/libutil/config\.hh$''
''^src/libutil/current-process\.cc$''
''^src/libutil/current-process\.hh$''
''^src/libutil/english\.cc$''
''^src/libutil/english\.hh$''
''^src/libutil/environment-variables\.cc$''
''^src/libutil/error\.cc$''
''^src/libutil/error\.hh$''
''^src/libutil/exit\.hh$''
''^src/libutil/experimental-features\.cc$''
''^src/libutil/experimental-features\.hh$''
''^src/libutil/file-content-address\.cc$''
''^src/libutil/file-content-address\.hh$''
''^src/libutil/file-descriptor\.cc$''
''^src/libutil/file-descriptor\.hh$''
''^src/libutil/file-path-impl\.hh$''
''^src/libutil/file-path\.hh$''
''^src/libutil/file-system\.cc$''
''^src/libutil/file-system\.hh$''
''^src/libutil/finally\.hh$''
''^src/libutil/fmt\.hh$''
''^src/libutil/fs-sink\.cc$''
''^src/libutil/fs-sink\.hh$''
''^src/libutil/git\.cc$''
''^src/libutil/git\.hh$''
''^src/libutil/hash\.cc$''
''^src/libutil/hash\.hh$''
''^src/libutil/hilite\.cc$''
''^src/libutil/hilite\.hh$''
''^src/libutil/input-accessor\.hh$''
''^src/libutil/json-impls\.hh$''
''^src/libutil/json-utils\.cc$''
''^src/libutil/json-utils\.hh$''
''^src/libutil/linux/cgroup\.cc$''
''^src/libutil/linux/namespaces\.cc$''
''^src/libutil/logging\.cc$''
''^src/libutil/logging\.hh$''
''^src/libutil/lru-cache\.hh$''
''^src/libutil/memory-source-accessor\.cc$''
''^src/libutil/memory-source-accessor\.hh$''
''^src/libutil/pool\.hh$''
''^src/libutil/position\.cc$''
''^src/libutil/position\.hh$''
''^src/libutil/posix-source-accessor\.cc$''
''^src/libutil/posix-source-accessor\.hh$''
''^src/libutil/processes\.hh$''
''^src/libutil/ref\.hh$''
''^src/libutil/references\.cc$''
''^src/libutil/references\.hh$''
''^src/libutil/regex-combinators\.hh$''
''^src/libutil/serialise\.cc$''
''^src/libutil/serialise\.hh$''
''^src/libutil/signals\.hh$''
''^src/libutil/signature/local-keys\.cc$''
''^src/libutil/signature/local-keys\.hh$''
''^src/libutil/signature/signer\.cc$''
''^src/libutil/signature/signer\.hh$''
''^src/libutil/source-accessor\.cc$''
''^src/libutil/source-accessor\.hh$''
''^src/libutil/source-path\.cc$''
''^src/libutil/source-path\.hh$''
''^src/libutil/split\.hh$''
''^src/libutil/suggestions\.cc$''
''^src/libutil/suggestions\.hh$''
''^src/libutil/sync\.hh$''
''^src/libutil/terminal\.cc$''
''^src/libutil/terminal\.hh$''
''^src/libutil/thread-pool\.cc$''
''^src/libutil/thread-pool\.hh$''
''^src/libutil/topo-sort\.hh$''
''^src/libutil/types\.hh$''
''^src/libutil/unix/file-descriptor\.cc$''
''^src/libutil/unix/file-path\.cc$''
''^src/libutil/unix/monitor-fd\.hh$''
''^src/libutil/unix/processes\.cc$''
''^src/libutil/unix/signals-impl\.hh$''
''^src/libutil/unix/signals\.cc$''
''^src/libutil/unix/unix-domain-socket\.cc$''
''^src/libutil/unix/users\.cc$''
''^src/libutil/url-parts\.hh$''
''^src/libutil/url\.cc$''
''^src/libutil/url\.hh$''
''^src/libutil/users\.cc$''
''^src/libutil/users\.hh$''
''^src/libutil/util\.cc$''
''^src/libutil/util\.hh$''
''^src/libutil/variant-wrapper\.hh$''
''^src/libutil/windows/environment-variables\.cc$''
''^src/libutil/windows/file-descriptor\.cc$''
''^src/libutil/windows/file-path\.cc$''
''^src/libutil/windows/processes\.cc$''
''^src/libutil/windows/users\.cc$''
''^src/libutil/windows/windows-error\.cc$''
''^src/libutil/windows/windows-error\.hh$''
''^src/libutil/xml-writer\.cc$''
''^src/libutil/xml-writer\.hh$''
''^src/nix-build/nix-build\.cc$''
''^src/nix-channel/nix-channel\.cc$''
''^src/nix-collect-garbage/nix-collect-garbage\.cc$''
''^src/nix-env/buildenv.nix$''
''^src/nix-env/nix-env\.cc$''
''^src/nix-env/user-env\.cc$''
''^src/nix-env/user-env\.hh$''
''^src/nix-instantiate/nix-instantiate\.cc$''
''^src/nix-store/dotgraph\.cc$''
''^src/nix-store/graphml\.cc$''
''^src/nix-store/nix-store\.cc$''
''^src/nix/add-to-store\.cc$''
''^src/nix/app\.cc$''
''^src/nix/build\.cc$''
''^src/nix/bundle\.cc$''
''^src/nix/cat\.cc$''
''^src/nix/config-check\.cc$''
''^src/nix/config\.cc$''
''^src/nix/copy\.cc$''
''^src/nix/derivation-add\.cc$''
''^src/nix/derivation-show\.cc$''
''^src/nix/derivation\.cc$''
''^src/nix/develop\.cc$''
''^src/nix/diff-closures\.cc$''
''^src/nix/dump-path\.cc$''
''^src/nix/edit\.cc$''
''^src/nix/eval\.cc$''
''^src/nix/flake\.cc$''
''^src/nix/fmt\.cc$''
''^src/nix/hash\.cc$''
''^src/nix/log\.cc$''
''^src/nix/ls\.cc$''
''^src/nix/main\.cc$''
''^src/nix/make-content-addressed\.cc$''
''^src/nix/nar\.cc$''
''^src/nix/optimise-store\.cc$''
''^src/nix/path-from-hash-part\.cc$''
''^src/nix/path-info\.cc$''
''^src/nix/prefetch\.cc$''
''^src/nix/profile\.cc$''
''^src/nix/realisation\.cc$''
''^src/nix/registry\.cc$''
''^src/nix/repl\.cc$''
''^src/nix/run\.cc$''
''^src/nix/run\.hh$''
''^src/nix/search\.cc$''
''^src/nix/sigs\.cc$''
''^src/nix/store-copy-log\.cc$''
''^src/nix/store-delete\.cc$''
''^src/nix/store-gc\.cc$''
''^src/nix/store-info\.cc$''
''^src/nix/store-repair\.cc$''
''^src/nix/store\.cc$''
''^src/nix/unix/daemon\.cc$''
''^src/nix/upgrade-nix\.cc$''
''^src/nix/verify\.cc$''
''^src/nix/why-depends\.cc$''
];
};
};
# We'll be pulling from this in the main flake
flake.getSystem = getSystem;
}

15
maintainers/local.mk Normal file
View file

@ -0,0 +1,15 @@
.PHONY: format
print-top-help += echo ' format: Format source code'
# This uses the cached .pre-commit-hooks.yaml file
format:
@if ! type -p pre-commit &>/dev/null; then \
echo "make format: pre-commit not found. Please use \`nix develop\`."; \
exit 1; \
fi; \
if test -z "$$_NIX_PRE_COMMIT_HOOKS_CONFIG"; then \
echo "make format: _NIX_PRE_COMMIT_HOOKS_CONFIG not set. Please use \`nix develop\`."; \
exit 1; \
fi; \
pre-commit run --config $$_NIX_PRE_COMMIT_HOOKS_CONFIG --all-files

View file

@ -1,4 +1,5 @@
{ lib
, fetchurl
, stdenv
, releaseTools
, autoconf-archive
@ -167,6 +168,8 @@ in {
./m4
# TODO: do we really need README.md? It doesn't seem used in the build.
./README.md
# This could be put behind a conditional
./maintainers/local.mk
# For make, regardless of what we are building
./local.mk
./Makefile
@ -246,7 +249,13 @@ in {
] ++ lib.optionals buildUnitTests [
gtest
rapidcheck
] ++ lib.optional stdenv.isLinux libseccomp
] ++ lib.optional stdenv.isLinux (libseccomp.overrideAttrs (_: rec {
version = "2.5.5";
src = fetchurl {
url = "https://github.com/seccomp/libseccomp/releases/download/v${version}/libseccomp-${version}.tar.gz";
hash = "sha256-JIosik2bmFiqa69ScSw0r+/PnJ6Ut23OAsHJqiX7M3U=";
};
}))
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid
# There have been issues building these dependencies
++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin))

View file

@ -22,7 +22,6 @@
#include "experimental-features.hh"
using namespace nix;
using namespace nix::unix;
using std::cin;
static void handleAlarm(int sig) {

View file

@ -128,10 +128,10 @@ ref<EvalState> EvalCommand::getEvalState()
evalState =
#if HAVE_BOEHMGC
std::allocate_shared<EvalState>(traceable_allocator<EvalState>(),
searchPath, getEvalStore(), getStore())
lookupPath, getEvalStore(), getStore())
#else
std::make_shared<EvalState>(
searchPath, getEvalStore(), getStore())
lookupPath, getEvalStore(), getStore())
#endif
;

View file

@ -125,7 +125,7 @@ MixEvalArgs::MixEvalArgs()
.category = category,
.labels = {"path"},
.handler = {[&](std::string s) {
searchPath.elements.emplace_back(SearchPath::Elem::parse(s));
lookupPath.elements.emplace_back(LookupPath::Elem::parse(s));
}}
});

View file

@ -23,7 +23,7 @@ struct MixEvalArgs : virtual Args, virtual MixRepair
Bindings * getAutoArgs(EvalState & state);
SearchPath searchPath;
LookupPath lookupPath;
std::optional<std::string> evalStoreUrl;
@ -38,6 +38,9 @@ private:
std::map<std::string, AutoArg> autoArgs;
};
/**
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
*/
SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * baseDir = nullptr);
}

View file

@ -77,7 +77,7 @@ struct NixRepl
std::unique_ptr<ReplInteracter> interacter;
NixRepl(const SearchPath & searchPath, nix::ref<Store> store,ref<EvalState> state,
NixRepl(const LookupPath & lookupPath, nix::ref<Store> store,ref<EvalState> state,
std::function<AnnotatedValues()> getValues);
virtual ~NixRepl() = default;
@ -122,7 +122,7 @@ std::string removeWhitespace(std::string s)
}
NixRepl::NixRepl(const SearchPath & searchPath, nix::ref<Store> store, ref<EvalState> state,
NixRepl::NixRepl(const LookupPath & lookupPath, nix::ref<Store> store, ref<EvalState> state,
std::function<NixRepl::AnnotatedValues()> getValues)
: AbstractNixRepl(state)
, debugTraceIndex(0)
@ -508,7 +508,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
// runProgram redirects stdout to a StringSink,
// using runProgram2 to allow editors to display their UI
runProgram2(RunOptions { .program = editor, .searchPath = true, .args = args });
runProgram2(RunOptions { .program = editor, .lookupPath = true, .args = args });
// Reload right after exiting the editor
state->resetFileCache();
@ -784,11 +784,11 @@ void NixRepl::evalString(std::string s, Value & v)
std::unique_ptr<AbstractNixRepl> AbstractNixRepl::create(
const SearchPath & searchPath, nix::ref<Store> store, ref<EvalState> state,
const LookupPath & lookupPath, nix::ref<Store> store, ref<EvalState> state,
std::function<AnnotatedValues()> getValues)
{
return std::make_unique<NixRepl>(
searchPath,
lookupPath,
openStore(),
state,
getValues
@ -804,9 +804,9 @@ ReplExitStatus AbstractNixRepl::runSimple(
NixRepl::AnnotatedValues values;
return values;
};
SearchPath searchPath = {};
LookupPath lookupPath = {};
auto repl = std::make_unique<NixRepl>(
searchPath,
lookupPath,
openStore(),
evalState,
getValues

View file

@ -20,7 +20,7 @@ struct AbstractNixRepl
typedef std::vector<std::pair<Value*,std::string>> AnnotatedValues;
static std::unique_ptr<AbstractNixRepl> create(
const SearchPath & searchPath, nix::ref<Store> store, ref<EvalState> state,
const LookupPath & lookupPath, nix::ref<Store> store, ref<EvalState> state,
std::function<AnnotatedValues()> getValues);
static ReplExitStatus runSimple(

View file

@ -85,17 +85,17 @@ nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, Value *
NIXC_CATCH_ERRS
}
EvalState * nix_state_create(nix_c_context * context, const char ** searchPath_c, Store * store)
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c, Store * store)
{
if (context)
context->last_err_code = NIX_OK;
try {
nix::Strings searchPath;
if (searchPath_c != nullptr)
for (size_t i = 0; searchPath_c[i] != nullptr; i++)
searchPath.push_back(searchPath_c[i]);
nix::Strings lookupPath;
if (lookupPath_c != nullptr)
for (size_t i = 0; lookupPath_c[i] != nullptr; i++)
lookupPath.push_back(lookupPath_c[i]);
return new EvalState{nix::EvalState(nix::SearchPath::parse(searchPath), store->ptr)};
return new EvalState{nix::EvalState(nix::LookupPath::parse(lookupPath), store->ptr)};
}
NIXC_CATCH_ERRS_NULL
}

View file

@ -140,11 +140,11 @@ nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, Value *
* @brief Create a new Nix language evaluator state.
*
* @param[out] context Optional, stores error information
* @param[in] searchPath Array of strings corresponding to entries in NIX_PATH.
* @param[in] lookupPath Array of strings corresponding to entries in NIX_PATH.
* @param[in] store The Nix store to use.
* @return A new Nix state or NULL on failure.
*/
EvalState * nix_state_create(nix_c_context * context, const char ** searchPath, Store * store);
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath, Store * store);
/**
* @brief Frees a Nix state.

View file

@ -343,7 +343,7 @@ void initGC()
}
EvalState::EvalState(
const SearchPath & _searchPath,
const LookupPath & _lookupPath,
ref<Store> store,
std::shared_ptr<Store> buildStore)
: sWith(symbols.create("<with>"))
@ -448,16 +448,16 @@ EvalState::EvalState(
/* Initialise the Nix expression search path. */
if (!evalSettings.pureEval) {
for (auto & i : _searchPath.elements)
searchPath.elements.emplace_back(SearchPath::Elem {i});
for (auto & i : _lookupPath.elements)
lookupPath.elements.emplace_back(LookupPath::Elem {i});
for (auto & i : evalSettings.nixPath.get())
searchPath.elements.emplace_back(SearchPath::Elem::parse(i));
lookupPath.elements.emplace_back(LookupPath::Elem::parse(i));
}
/* Allow access to all paths in the search path. */
if (rootFS.dynamic_pointer_cast<AllowListInputAccessor>())
for (auto & i : searchPath.elements)
resolveSearchPathPath(i.path, true);
for (auto & i : lookupPath.elements)
resolveLookupPathPath(i.path, true);
corepkgsFS->addFile(
CanonPath("fetchurl.nix"),
@ -2820,19 +2820,19 @@ Expr * EvalState::parseStdin()
SourcePath EvalState::findFile(const std::string_view path)
{
return findFile(searchPath, path);
return findFile(lookupPath, path);
}
SourcePath EvalState::findFile(const SearchPath & searchPath, const std::string_view path, const PosIdx pos)
SourcePath EvalState::findFile(const LookupPath & lookupPath, const std::string_view path, const PosIdx pos)
{
for (auto & i : searchPath.elements) {
for (auto & i : lookupPath.elements) {
auto suffixOpt = i.prefix.suffixIfPotentialMatch(path);
if (!suffixOpt) continue;
auto suffix = *suffixOpt;
auto rOpt = resolveSearchPathPath(i.path);
auto rOpt = resolveLookupPathPath(i.path);
if (!rOpt) continue;
auto r = *rOpt;
@ -2852,11 +2852,11 @@ SourcePath EvalState::findFile(const SearchPath & searchPath, const std::string_
}
std::optional<std::string> EvalState::resolveSearchPathPath(const SearchPath::Path & value0, bool initAccessControl)
std::optional<std::string> EvalState::resolveLookupPathPath(const LookupPath::Path & value0, bool initAccessControl)
{
auto & value = value0.s;
auto i = searchPathResolved.find(value);
if (i != searchPathResolved.end()) return i->second;
auto i = lookupPathResolved.find(value);
if (i != lookupPathResolved.end()) return i->second;
std::optional<std::string> res;
@ -2912,7 +2912,7 @@ std::optional<std::string> EvalState::resolveSearchPathPath(const SearchPath::Pa
else
debug("failed to resolve search path element '%s'", value);
searchPathResolved.emplace(value, res);
lookupPathResolved.emplace(value, res);
return res;
}

View file

@ -161,9 +161,6 @@ struct DebugTrace {
bool isError;
};
// Don't want Windows function
#undef SearchPath
class EvalState : public std::enable_shared_from_this<EvalState>
{
public:
@ -311,9 +308,9 @@ private:
#endif
FileEvalCache fileEvalCache;
SearchPath searchPath;
LookupPath lookupPath;
std::map<std::string, std::optional<std::string>> searchPathResolved;
std::map<std::string, std::optional<std::string>> lookupPathResolved;
/**
* Cache used by prim_match().
@ -335,12 +332,12 @@ private:
public:
EvalState(
const SearchPath & _searchPath,
const LookupPath & _lookupPath,
ref<Store> store,
std::shared_ptr<Store> buildStore = nullptr);
~EvalState();
SearchPath getSearchPath() { return searchPath; }
LookupPath getLookupPath() { return lookupPath; }
/**
* Return a `SourcePath` that refers to `path` in the root
@ -409,7 +406,7 @@ public:
* Look up a file in the search path.
*/
SourcePath findFile(const std::string_view path);
SourcePath findFile(const SearchPath & searchPath, const std::string_view path, const PosIdx pos = noPos);
SourcePath findFile(const LookupPath & lookupPath, const std::string_view path, const PosIdx pos = noPos);
/**
* Try to resolve a search path value (not the optional key part).
@ -418,8 +415,8 @@ public:
*
* If it is not found, return `std::nullopt`
*/
std::optional<std::string> resolveSearchPathPath(
const SearchPath::Path & elem,
std::optional<std::string> resolveLookupPathPath(
const LookupPath::Path & elem,
bool initAccessControl = false);
/**

View file

@ -68,24 +68,39 @@ struct FlakeRef
std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef);
/**
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
*/
FlakeRef parseFlakeRef(
const std::string & url,
const std::optional<Path> & baseDir = {},
bool allowMissing = false,
bool isFlake = true);
/**
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
*/
std::optional<FlakeRef> maybeParseFlake(
const std::string & url, const std::optional<Path> & baseDir = {});
/**
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
*/
std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
const std::string & url,
const std::optional<Path> & baseDir = {},
bool allowMissing = false,
bool isFlake = true);
/**
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
*/
std::optional<std::pair<FlakeRef, std::string>> maybeParseFlakeRefWithFragment(
const std::string & url, const std::optional<Path> & baseDir = {});
/**
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
*/
std::tuple<FlakeRef, std::string, ExtendedOutputsSpec> parseFlakeRefWithFragmentAndExtendedOutputsSpec(
const std::string & url,
const std::optional<Path> & baseDir = {},

View file

@ -1716,7 +1716,7 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, V
{
state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.findFile");
SearchPath searchPath;
LookupPath lookupPath;
for (auto v2 : args[0]->listItems()) {
state.forceAttrs(*v2, pos, "while evaluating an element of the list passed to builtins.findFile");
@ -1744,15 +1744,15 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, V
).atPos(pos).debugThrow();
}
searchPath.elements.emplace_back(SearchPath::Elem {
.prefix = SearchPath::Prefix { .s = prefix },
.path = SearchPath::Path { .s = path },
lookupPath.elements.emplace_back(LookupPath::Elem {
.prefix = LookupPath::Prefix { .s = prefix },
.path = LookupPath::Path { .s = path },
});
}
auto path = state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.findFile");
v.mkPath(state.findFile(searchPath, path, pos));
v.mkPath(state.findFile(lookupPath, path, pos));
}
static RegisterPrimOp primop_findFile(PrimOp {
@ -4637,8 +4637,8 @@ void EvalState::createBaseEnv()
});
/* Add a value containing the current Nix expression search path. */
auto list = buildList(searchPath.elements.size());
for (const auto & [n, i] : enumerate(searchPath.elements)) {
auto list = buildList(lookupPath.elements.size());
for (const auto & [n, i] : enumerate(lookupPath.elements)) {
auto attrs = buildBindings(2);
attrs.alloc("path").mkString(i.path.s);
attrs.alloc("prefix").mkString(i.prefix.s);

View file

@ -2,7 +2,7 @@
namespace nix {
std::optional<std::string_view> SearchPath::Prefix::suffixIfPotentialMatch(
std::optional<std::string_view> LookupPath::Prefix::suffixIfPotentialMatch(
std::string_view path) const
{
auto n = s.size();
@ -27,11 +27,11 @@ std::optional<std::string_view> SearchPath::Prefix::suffixIfPotentialMatch(
}
SearchPath::Elem SearchPath::Elem::parse(std::string_view rawElem)
LookupPath::Elem LookupPath::Elem::parse(std::string_view rawElem)
{
size_t pos = rawElem.find('=');
return SearchPath::Elem {
return LookupPath::Elem {
.prefix = Prefix {
.s = pos == std::string::npos
? std::string { "" }
@ -44,11 +44,11 @@ SearchPath::Elem SearchPath::Elem::parse(std::string_view rawElem)
}
SearchPath SearchPath::parse(const Strings & rawElems)
LookupPath LookupPath::parse(const Strings & rawElems)
{
SearchPath res;
LookupPath res;
for (auto & rawElem : rawElems)
res.elements.emplace_back(SearchPath::Elem::parse(rawElem));
res.elements.emplace_back(LookupPath::Elem::parse(rawElem));
return res;
}

View file

@ -8,17 +8,14 @@
namespace nix {
// Do not want the windows macro (alias to `SearchPathA`)
#undef SearchPath
/**
* A "search path" is a list of ways look for something, used with
* `builtins.findFile` and `< >` lookup expressions.
*/
struct SearchPath
struct LookupPath
{
/**
* A single element of a `SearchPath`.
* A single element of a `LookupPath`.
*
* Each element is tried in succession when looking up a path. The first
* element to completely match wins.
@ -26,16 +23,16 @@ struct SearchPath
struct Elem;
/**
* The first part of a `SearchPath::Elem` pair.
* The first part of a `LookupPath::Elem` pair.
*
* Called a "prefix" because it takes the form of a prefix of a file
* path (first `n` path components). When looking up a path, to use
* a `SearchPath::Elem`, its `Prefix` must match the path.
* a `LookupPath::Elem`, its `Prefix` must match the path.
*/
struct Prefix;
/**
* The second part of a `SearchPath::Elem` pair.
* The second part of a `LookupPath::Elem` pair.
*
* It is either a path or a URL (with certain restrictions / extra
* structure).
@ -43,7 +40,7 @@ struct SearchPath
* If the prefix of the path we are looking up matches, we then
* check if the rest of the path points to something that exists
* within the directory denoted by this. If so, the
* `SearchPath::Elem` as a whole matches, and that *something* being
* `LookupPath::Elem` as a whole matches, and that *something* being
* pointed to by the rest of the path we are looking up is the
* result.
*/
@ -54,24 +51,24 @@ struct SearchPath
* when looking up. (The actual lookup entry point is in `EvalState`
* not in this class.)
*/
std::list<SearchPath::Elem> elements;
std::list<LookupPath::Elem> elements;
/**
* Parse a string into a `SearchPath`
* Parse a string into a `LookupPath`
*/
static SearchPath parse(const Strings & rawElems);
static LookupPath parse(const Strings & rawElems);
};
struct SearchPath::Prefix
struct LookupPath::Prefix
{
/**
* Underlying string
*
* @todo Should we normalize this when constructing a `SearchPath::Prefix`?
* @todo Should we normalize this when constructing a `LookupPath::Prefix`?
*/
std::string s;
GENERATE_CMP(SearchPath::Prefix, me->s);
GENERATE_CMP(LookupPath::Prefix, me->s);
/**
* If the path possibly matches this search path element, return the
@ -82,7 +79,7 @@ struct SearchPath::Prefix
std::optional<std::string_view> suffixIfPotentialMatch(std::string_view path) const;
};
struct SearchPath::Path
struct LookupPath::Path
{
/**
* The location of a search path item, as a path or URL.
@ -91,21 +88,21 @@ struct SearchPath::Path
*/
std::string s;
GENERATE_CMP(SearchPath::Path, me->s);
GENERATE_CMP(LookupPath::Path, me->s);
};
struct SearchPath::Elem
struct LookupPath::Elem
{
Prefix prefix;
Path path;
GENERATE_CMP(SearchPath::Elem, me->prefix, me->path);
GENERATE_CMP(LookupPath::Elem, me->prefix, me->path);
/**
* Parse a string into a `SearchPath::Elem`
* Parse a string into a `LookupPath::Elem`
*/
static SearchPath::Elem parse(std::string_view rawElem);
static LookupPath::Elem parse(std::string_view rawElem);
};
}

View file

@ -385,7 +385,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
runProgram(RunOptions {
.program = "git",
.searchPath = true,
.lookupPath = true,
// FIXME: git stderr messes up our progress indicator, so
// we're using --quiet for now. Should process its stderr.
.args = gitArgs,

View file

@ -24,7 +24,7 @@ static RunOptions hgOptions(const Strings & args)
return {
.program = "hg",
.searchPath = true,
.lookupPath = true,
.args = args,
.environment = env
};

View file

@ -113,7 +113,7 @@ static void sigHandler(int signo) { }
#endif
void initNix()
void initNix(bool loadConfig)
{
/* Turn on buffering for cerr. */
#if HAVE_PUBSETBUF
@ -121,7 +121,7 @@ void initNix()
std::cerr.rdbuf()->pubsetbuf(buf, sizeof(buf));
#endif
initLibStore();
initLibStore(loadConfig);
#ifndef _WIN32
unix::startSignalHandlerThread();

View file

@ -21,8 +21,9 @@ int handleExceptions(const std::string & programName, std::function<void()> fun)
/**
* Don't forget to call initPlugins() after settings are initialized!
* @param loadConfig Whether to load configuration from `nix.conf`, `NIX_CONFIG`, etc. May be disabled for unit tests.
*/
void initNix();
void initNix(bool loadConfig = true);
void parseCmdLine(int argc, char * * argv,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg);

View file

@ -19,6 +19,16 @@ nix_err nix_libstore_init(nix_c_context * context)
NIXC_CATCH_ERRS
}
nix_err nix_libstore_init_no_load_config(nix_c_context * context)
{
if (context)
context->last_err_code = NIX_OK;
try {
nix::initLibStore(false);
}
NIXC_CATCH_ERRS
}
nix_err nix_init_plugins(nix_c_context * context)
{
if (context)

View file

@ -35,6 +35,13 @@ typedef struct StorePath StorePath;
*/
nix_err nix_libstore_init(nix_c_context * context);
/**
* @brief Like nix_libstore_init, but does not load the Nix configuration.
*
* This is useful when external configuration is not desired, such as when running unit tests.
*/
nix_err nix_libstore_init_no_load_config(nix_c_context * context);
/**
* @brief Loads the plugins specified in Nix's plugin-files setting.
*

View file

@ -427,12 +427,13 @@ void assertLibStoreInitialized() {
};
}
void initLibStore() {
void initLibStore(bool loadConfig) {
if (initLibStoreDone) return;
initLibUtil();
loadConfFile();
if (loadConfig)
loadConfFile();
preloadNSS();

View file

@ -1279,9 +1279,10 @@ std::vector<Path> getUserConfigFiles();
extern const std::string nixVersion;
/**
* NB: This is not sufficient. You need to call initNix()
* @param loadConfig Whether to load configuration from `nix.conf`, `NIX_CONFIG`, etc. May be disabled for unit tests.
* @note When using libexpr, and/or libmain, This is not sufficient. See initNix().
*/
void initLibStore();
void initLibStore(bool loadConfig = true);
/**
* It's important to initialize before doing _anything_, which is why we

View file

@ -5,10 +5,26 @@
namespace nix {
/**
* Open (possibly create) a lock file and return the file descriptor.
* -1 is returned if create is false and the lock could not be opened
* because it doesn't exist. Any other error throws an exception.
*/
AutoCloseFD openLockFile(const Path & path, bool create);
/**
* Delete an open lock file.
*/
void deleteLockFile(const Path & path, Descriptor desc);
enum LockType { ltRead, ltWrite, ltNone };
bool lockFile(Descriptor desc, LockType lockType, bool wait);
class PathLocks
{
private:
typedef std::pair<int, Path> FDPair;
typedef std::pair<Descriptor, Path> FDPair;
std::list<FDPair> fds;
bool deletePaths;
@ -24,6 +40,18 @@ public:
void setDeletion(bool deletePaths);
};
}
struct FdLock
{
Descriptor desc;
bool acquired = false;
#include "pathlocks-impl.hh"
FdLock(Descriptor desc, LockType lockType, bool wait, std::string_view waitMsg);
~FdLock()
{
if (acquired)
lockFile(desc, ltNone, false);
}
};
}

View file

@ -77,7 +77,7 @@ void handleDiffHook(
try {
auto diffRes = runProgram(RunOptions {
.program = diffHook,
.searchPath = true,
.lookupPath = true,
.args = {tryA, tryB, drvPath, tmpDir},
.uid = uid,
.gid = gid,

View file

@ -9,8 +9,6 @@
namespace nix {
using namespace nix::unix;
#if __linux__
static std::vector<gid_t> get_group_list(const char *username, gid_t group_id)

View file

@ -1,38 +0,0 @@
#pragma once
///@file
#include "file-descriptor.hh"
namespace nix::unix {
/**
* Open (possibly create) a lock file and return the file descriptor.
* -1 is returned if create is false and the lock could not be opened
* because it doesn't exist. Any other error throws an exception.
*/
AutoCloseFD openLockFile(const Path & path, bool create);
/**
* Delete an open lock file.
*/
void deleteLockFile(const Path & path, int fd);
enum LockType { ltRead, ltWrite, ltNone };
bool lockFile(int fd, LockType lockType, bool wait);
struct FdLock
{
int fd;
bool acquired = false;
FdLock(int fd, LockType lockType, bool wait, std::string_view waitMsg);
~FdLock()
{
if (acquired)
lockFile(fd, ltNone, false);
}
};
}

View file

@ -14,9 +14,7 @@
namespace nix {
using namespace nix::unix;
AutoCloseFD unix::openLockFile(const Path & path, bool create)
AutoCloseFD openLockFile(const Path & path, bool create)
{
AutoCloseFD fd;
@ -28,20 +26,20 @@ AutoCloseFD unix::openLockFile(const Path & path, bool create)
}
void unix::deleteLockFile(const Path & path, int fd)
void deleteLockFile(const Path & path, Descriptor desc)
{
/* Get rid of the lock file. Have to be careful not to introduce
races. Write a (meaningless) token to the file to indicate to
other processes waiting on this lock that the lock is stale
(deleted). */
unlink(path.c_str());
writeFull(fd, "d");
writeFull(desc, "d");
/* Note that the result of unlink() is ignored; removing the lock
file is an optimisation, not a necessity. */
}
bool unix::lockFile(int fd, LockType lockType, bool wait)
bool lockFile(Descriptor desc, LockType lockType, bool wait)
{
int type;
if (lockType == ltRead) type = LOCK_SH;
@ -50,7 +48,7 @@ bool unix::lockFile(int fd, LockType lockType, bool wait)
else abort();
if (wait) {
while (flock(fd, type) != 0) {
while (flock(desc, type) != 0) {
checkInterrupt();
if (errno != EINTR)
throw SysError("acquiring/releasing lock");
@ -58,7 +56,7 @@ bool unix::lockFile(int fd, LockType lockType, bool wait)
return false;
}
} else {
while (flock(fd, type | LOCK_NB) != 0) {
while (flock(desc, type | LOCK_NB) != 0) {
checkInterrupt();
if (errno == EWOULDBLOCK) return false;
if (errno != EINTR)
@ -149,16 +147,16 @@ void PathLocks::unlock()
}
FdLock::FdLock(int fd, LockType lockType, bool wait, std::string_view waitMsg)
: fd(fd)
FdLock::FdLock(Descriptor desc, LockType lockType, bool wait, std::string_view waitMsg)
: desc(desc)
{
if (wait) {
if (!lockFile(fd, lockType, false)) {
if (!lockFile(desc, lockType, false)) {
printInfo("%s", waitMsg);
acquired = lockFile(fd, lockType, true);
acquired = lockFile(desc, lockType, true);
}
} else
acquired = lockFile(fd, lockType, false);
acquired = lockFile(desc, lockType, false);
}

View file

@ -1,2 +0,0 @@
#pragma once
///@file Needed because Unix-specific counterpart

View file

@ -1,16 +1,149 @@
#include "logging.hh"
#include "pathlocks.hh"
#include "signals.hh"
#include "util.hh"
#include <errhandlingapi.h>
#include <fileapi.h>
#include <windows.h>
#include "windows-error.hh"
namespace nix {
bool PathLocks::lockPaths(const PathSet & _paths, const std::string & waitMsg, bool wait)
void deleteLockFile(const Path & path, Descriptor desc)
{
return true;
int exit = DeleteFileA(path.c_str());
if (exit == 0)
warn("%s: &s", path, std::to_string(GetLastError()));
}
void PathLocks::unlock()
{
warn("PathLocks::unlock: not yet implemented");
for (auto & i : fds) {
if (deletePaths)
deleteLockFile(i.second, i.first);
if (CloseHandle(i.first) == -1)
printError("error (ignored): cannot close lock file on '%1%'", i.second);
debug("lock released on '%1%'", i.second);
}
fds.clear();
}
AutoCloseFD openLockFile(const Path & path, bool create)
{
AutoCloseFD desc = CreateFileA(
path.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
create ? OPEN_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_POSIX_SEMANTICS, NULL);
if (desc.get() == INVALID_HANDLE_VALUE)
warn("%s: %s", path, std::to_string(GetLastError()));
return desc;
}
bool lockFile(Descriptor desc, LockType lockType, bool wait)
{
switch (lockType) {
case ltNone: {
OVERLAPPED ov = {0};
if (!UnlockFileEx(desc, 0, 2, 0, &ov)) {
WinError winError("Failed to unlock file desc %s", desc);
throw winError;
}
return true;
}
case ltRead: {
OVERLAPPED ov = {0};
if (!LockFileEx(desc, wait ? 0 : LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &ov)) {
WinError winError("Failed to lock file desc %s", desc);
if (winError.lastError == ERROR_LOCK_VIOLATION)
return false;
throw winError;
}
ov.Offset = 1;
if (!UnlockFileEx(desc, 0, 1, 0, &ov)) {
WinError winError("Failed to unlock file desc %s", desc);
if (winError.lastError != ERROR_NOT_LOCKED)
throw winError;
}
return true;
}
case ltWrite: {
OVERLAPPED ov = {0};
ov.Offset = 1;
if (!LockFileEx(desc, LOCKFILE_EXCLUSIVE_LOCK | (wait ? 0 : LOCKFILE_FAIL_IMMEDIATELY), 0, 1, 0, &ov)) {
WinError winError("Failed to lock file desc %s", desc);
if (winError.lastError == ERROR_LOCK_VIOLATION)
return false;
throw winError;
}
ov.Offset = 0;
if (!UnlockFileEx(desc, 0, 1, 0, &ov)) {
WinError winError("Failed to unlock file desc %s", desc);
if (winError.lastError != ERROR_NOT_LOCKED)
throw winError;
}
return true;
}
default:
assert(false);
}
}
bool PathLocks::lockPaths(const PathSet & paths, const std::string & waitMsg, bool wait)
{
assert(fds.empty());
for (auto & path : paths) {
checkInterrupt();
Path lockPath = path + ".lock";
debug("locking path '%1%'", path);
AutoCloseFD fd;
while (1) {
fd = openLockFile(lockPath, true);
if (!lockFile(fd.get(), ltWrite, false)) {
if (wait) {
if (waitMsg != "")
printError(waitMsg);
lockFile(fd.get(), ltWrite, true);
} else {
unlock();
return false;
}
}
debug("lock aquired on '%1%'", lockPath);
struct _stat st;
if (_fstat(fromDescriptorReadOnly(fd.get()), &st) == -1)
throw SysError("statting lock file '%1%'", lockPath);
if (st.st_size != 0)
debug("open lock file '%1%' has become stale", lockPath);
else
break;
}
fds.push_back(FDPair(fd.release(), lockPath));
}
return true;
}
FdLock::FdLock(Descriptor desc, LockType lockType, bool wait, std::string_view waitMsg)
: desc(desc)
{
if (wait) {
if (!lockFile(desc, lockType, false)) {
printInfo("%s", waitMsg);
acquired = lockFile(desc, lockType, true);
}
} else
acquired = lockFile(desc, lockType, false);
}
}

View file

@ -41,7 +41,7 @@ public:
virtual std::string doc() { return ""; }
/**
* @brief Get the base directory for the command.
* @brief Get the [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) for the command.
*
* @return Generally the working directory, but in case of a shebang
* interpreter, returns the directory of the script.

View file

@ -80,14 +80,14 @@ pid_t startProcess(std::function<void()> fun, const ProcessOptions & options = P
* Run a program and return its stdout in a string (i.e., like the
* shell backtick operator).
*/
std::string runProgram(Path program, bool searchPath = false,
std::string runProgram(Path program, bool lookupPath = false,
const Strings & args = Strings(),
const std::optional<std::string> & input = {}, bool isInteractive = false);
struct RunOptions
{
Path program;
bool searchPath = true;
bool lookupPath = true;
Strings args;
#ifndef _WIN32
std::optional<uid_t> uid;

View file

@ -245,10 +245,10 @@ pid_t startProcess(std::function<void()> fun, const ProcessOptions & options)
}
std::string runProgram(Path program, bool searchPath, const Strings & args,
std::string runProgram(Path program, bool lookupPath, const Strings & args,
const std::optional<std::string> & input, bool isInteractive)
{
auto res = runProgram(RunOptions {.program = program, .searchPath = searchPath, .args = args, .input = input, .isInteractive = isInteractive});
auto res = runProgram(RunOptions {.program = program, .lookupPath = lookupPath, .args = args, .input = input, .isInteractive = isInteractive});
if (!statusOk(res.first))
throw ExecError(res.first, "program '%1%' %2%", program, statusToString(res.first));
@ -335,7 +335,7 @@ void runProgram2(const RunOptions & options)
restoreProcessContext();
if (options.searchPath)
if (options.lookupPath)
execvp(options.program.c_str(), stringsToCharPtrs(args_).data());
// This allows you to refer to a program with a pathname relative
// to the PATH variable.

View file

@ -28,7 +28,7 @@
namespace nix {
std::string runProgram(Path program, bool searchPath, const Strings & args,
std::string runProgram(Path program, bool lookupPath, const Strings & args,
const std::optional<std::string> & input, bool isInteractive)
{
throw UnimplementedError("Cannot shell out to git on Windows yet");

View file

@ -258,7 +258,7 @@ static void main_nix_build(int argc, char * * argv)
auto store = openStore();
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
auto state = std::make_unique<EvalState>(myArgs.searchPath, evalStore, store);
auto state = std::make_unique<EvalState>(myArgs.lookupPath, evalStore, store);
state->repair = myArgs.repair;
if (myArgs.repair) buildMode = bmRepair;

View file

@ -1525,7 +1525,7 @@ static int main_nix_env(int argc, char * * argv)
auto store = openStore();
globals.state = std::shared_ptr<EvalState>(new EvalState(myArgs.searchPath, store));
globals.state = std::shared_ptr<EvalState>(new EvalState(myArgs.lookupPath, store));
globals.state->repair = myArgs.repair;
globals.instSource.nixExprPath = std::make_shared<SourcePath>(

View file

@ -157,7 +157,7 @@ static int main_nix_instantiate(int argc, char * * argv)
auto store = openStore();
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
auto state = std::make_unique<EvalState>(myArgs.searchPath, evalStore, store);
auto state = std::make_unique<EvalState>(myArgs.lookupPath, evalStore, store);
state->repair = myArgs.repair;
Bindings & autoArgs = *myArgs.getAutoArgs(*state);

View file

@ -687,7 +687,7 @@ struct CmdDevelop : Common, MixEnvironment
}
}
runProgramInStore(store, UseSearchPath::Use, shell, args, buildEnvironment.getSystem());
runProgramInStore(store, UseLookupPath::Use, shell, args, buildEnvironment.getSystem());
#endif
}
};

View file

@ -454,11 +454,6 @@ struct CmdFlakeCheck : FlakeCommand
if (v.payload.lambda.fun->hasFormals()
|| !argHasName(v.payload.lambda.fun->arg, "final"))
throw Error("overlay does not take an argument named 'final'");
auto body = dynamic_cast<ExprLambda *>(v.payload.lambda.fun->body);
if (!body
|| body->hasFormals()
|| !argHasName(body->arg, "prev"))
throw Error("overlay does not take an argument named 'prev'");
// FIXME: if we have a 'nixpkgs' input, use it to
// evaluate the overlay.
} catch (Error & e) {

View file

@ -49,7 +49,7 @@ struct CmdFmt : SourceExprCommand {
}
}
runProgramInStore(store, UseSearchPath::DontUse, app.program, programArgs);
runProgramInStore(store, UseLookupPath::DontUse, app.program, programArgs);
};
};

View file

@ -193,7 +193,7 @@ static int main_nix_prefetch_url(int argc, char * * argv)
startProgressBar();
auto store = openStore();
auto state = std::make_unique<EvalState>(myArgs.searchPath, store);
auto state = std::make_unique<EvalState>(myArgs.lookupPath, store);
Bindings & autoArgs = *myArgs.getAutoArgs(*state);

View file

@ -78,7 +78,7 @@ struct CmdRepl : RawInstallablesCommand
return values;
};
auto repl = AbstractNixRepl::create(
searchPath,
lookupPath,
openStore(),
state,
getValues

View file

@ -26,7 +26,7 @@ std::string chrootHelperName = "__run_in_chroot";
namespace nix {
void runProgramInStore(ref<Store> store,
UseSearchPath useSearchPath,
UseLookupPath useLookupPath,
const std::string & program,
const Strings & args,
std::optional<std::string_view> system)
@ -62,7 +62,7 @@ void runProgramInStore(ref<Store> store,
linux::setPersonality(*system);
#endif
if (useSearchPath == UseSearchPath::Use)
if (useLookupPath == UseLookupPath::Use)
execvp(program.c_str(), stringsToCharPtrs(args).data());
else
execv(program.c_str(), stringsToCharPtrs(args).data());
@ -183,7 +183,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment
Strings args;
for (auto & arg : command) args.push_back(arg);
runProgramInStore(store, UseSearchPath::Use, *command.begin(), args);
runProgramInStore(store, UseLookupPath::Use, *command.begin(), args);
}
};
@ -246,7 +246,7 @@ struct CmdRun : InstallableValueCommand
Strings allArgs{app.program};
for (auto & i : args) allArgs.push_back(i);
runProgramInStore(store, UseSearchPath::DontUse, app.program, allArgs);
runProgramInStore(store, UseLookupPath::DontUse, app.program, allArgs);
}
};

View file

@ -5,13 +5,13 @@
namespace nix {
enum struct UseSearchPath {
enum struct UseLookupPath {
Use,
DontUse
};
void runProgramInStore(ref<Store> store,
UseSearchPath useSearchPath,
UseLookupPath useLookupPath,
const std::string & program,
const Strings & args,
std::optional<std::string_view> system = std::nullopt);

View file

@ -147,7 +147,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
auto req = FileTransferRequest((std::string&) settings.upgradeNixStorePathUrl);
auto res = getFileTransfer()->download(req);
auto state = std::make_unique<EvalState>(SearchPath{}, store);
auto state = std::make_unique<EvalState>(LookupPath{}, store);
auto v = state->allocValue();
state->eval(state->parseExprFromString(res.data, state->rootPath(CanonPath("/no-such-path"))), *v);
Bindings & bindings(*state->allocBindings(0));

View file

@ -5,85 +5,85 @@
namespace nix {
TEST(SearchPathElem, parse_justPath) {
TEST(LookupPathElem, parse_justPath) {
ASSERT_EQ(
SearchPath::Elem::parse("foo"),
(SearchPath::Elem {
.prefix = SearchPath::Prefix { .s = "" },
.path = SearchPath::Path { .s = "foo" },
LookupPath::Elem::parse("foo"),
(LookupPath::Elem {
.prefix = LookupPath::Prefix { .s = "" },
.path = LookupPath::Path { .s = "foo" },
}));
}
TEST(SearchPathElem, parse_emptyPrefix) {
TEST(LookupPathElem, parse_emptyPrefix) {
ASSERT_EQ(
SearchPath::Elem::parse("=foo"),
(SearchPath::Elem {
.prefix = SearchPath::Prefix { .s = "" },
.path = SearchPath::Path { .s = "foo" },
LookupPath::Elem::parse("=foo"),
(LookupPath::Elem {
.prefix = LookupPath::Prefix { .s = "" },
.path = LookupPath::Path { .s = "foo" },
}));
}
TEST(SearchPathElem, parse_oneEq) {
TEST(LookupPathElem, parse_oneEq) {
ASSERT_EQ(
SearchPath::Elem::parse("foo=bar"),
(SearchPath::Elem {
.prefix = SearchPath::Prefix { .s = "foo" },
.path = SearchPath::Path { .s = "bar" },
LookupPath::Elem::parse("foo=bar"),
(LookupPath::Elem {
.prefix = LookupPath::Prefix { .s = "foo" },
.path = LookupPath::Path { .s = "bar" },
}));
}
TEST(SearchPathElem, parse_twoEqs) {
TEST(LookupPathElem, parse_twoEqs) {
ASSERT_EQ(
SearchPath::Elem::parse("foo=bar=baz"),
(SearchPath::Elem {
.prefix = SearchPath::Prefix { .s = "foo" },
.path = SearchPath::Path { .s = "bar=baz" },
LookupPath::Elem::parse("foo=bar=baz"),
(LookupPath::Elem {
.prefix = LookupPath::Prefix { .s = "foo" },
.path = LookupPath::Path { .s = "bar=baz" },
}));
}
TEST(SearchPathElem, suffixIfPotentialMatch_justPath) {
SearchPath::Prefix prefix { .s = "" };
TEST(LookupPathElem, suffixIfPotentialMatch_justPath) {
LookupPath::Prefix prefix { .s = "" };
ASSERT_EQ(prefix.suffixIfPotentialMatch("any/thing"), std::optional { "any/thing" });
}
TEST(SearchPathElem, suffixIfPotentialMatch_misleadingPrefix1) {
SearchPath::Prefix prefix { .s = "foo" };
TEST(LookupPathElem, suffixIfPotentialMatch_misleadingPrefix1) {
LookupPath::Prefix prefix { .s = "foo" };
ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX"), std::nullopt);
}
TEST(SearchPathElem, suffixIfPotentialMatch_misleadingPrefix2) {
SearchPath::Prefix prefix { .s = "foo" };
TEST(LookupPathElem, suffixIfPotentialMatch_misleadingPrefix2) {
LookupPath::Prefix prefix { .s = "foo" };
ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX/bar"), std::nullopt);
}
TEST(SearchPathElem, suffixIfPotentialMatch_partialPrefix) {
SearchPath::Prefix prefix { .s = "fooX" };
TEST(LookupPathElem, suffixIfPotentialMatch_partialPrefix) {
LookupPath::Prefix prefix { .s = "fooX" };
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::nullopt);
}
TEST(SearchPathElem, suffixIfPotentialMatch_exactPrefix) {
SearchPath::Prefix prefix { .s = "foo" };
TEST(LookupPathElem, suffixIfPotentialMatch_exactPrefix) {
LookupPath::Prefix prefix { .s = "foo" };
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::optional { "" });
}
TEST(SearchPathElem, suffixIfPotentialMatch_multiKey) {
SearchPath::Prefix prefix { .s = "foo/bar" };
TEST(LookupPathElem, suffixIfPotentialMatch_multiKey) {
LookupPath::Prefix prefix { .s = "foo/bar" };
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "baz" });
}
TEST(SearchPathElem, suffixIfPotentialMatch_trailingSlash) {
SearchPath::Prefix prefix { .s = "foo" };
TEST(LookupPathElem, suffixIfPotentialMatch_trailingSlash) {
LookupPath::Prefix prefix { .s = "foo" };
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/"), std::optional { "" });
}
TEST(SearchPathElem, suffixIfPotentialMatch_trailingDoubleSlash) {
SearchPath::Prefix prefix { .s = "foo" };
TEST(LookupPathElem, suffixIfPotentialMatch_trailingDoubleSlash) {
LookupPath::Prefix prefix { .s = "foo" };
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo//"), std::optional { "/" });
}
TEST(SearchPathElem, suffixIfPotentialMatch_trailingPath) {
SearchPath::Prefix prefix { .s = "foo" };
TEST(LookupPathElem, suffixIfPotentialMatch_trailingPath) {
LookupPath::Prefix prefix { .s = "foo" };
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "bar/baz" });
}

View file

@ -11,7 +11,7 @@ namespace nix {
class LibStoreTest : public virtual ::testing::Test {
public:
static void SetUpTestSuite() {
initLibStore();
initLibStore(false);
}
protected: