Compare commits
138 Commits
dead-code-
...
2.29.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a885a36130 | ||
|
|
2851af6784 | ||
|
|
42ddc10d92 | ||
|
|
a5ab03cb16 | ||
|
|
b4871a4a94 | ||
|
|
027bf13e18 | ||
|
|
3e3d2b7d01 | ||
|
|
1a55d733ce | ||
|
|
9328af84d3 | ||
|
|
2aba7ac90d | ||
|
|
adc17bace9 | ||
|
|
d6aebd8847 | ||
|
|
c53ac76f7b | ||
|
|
2454267de0 | ||
|
|
9572fdeb3b | ||
|
|
69d2e6eeef | ||
|
|
2870c177d6 | ||
|
|
b0169fdc5f | ||
|
|
7b08e8d20e | ||
|
|
aabe327111 | ||
|
|
ab4951588b | ||
|
|
b41101c815 | ||
|
|
cb73841205 | ||
|
|
931ca7d11a | ||
|
|
b5efc9ac56 | ||
|
|
012f429104 | ||
|
|
830dfc3b60 | ||
|
|
2968e18d37 | ||
|
|
66a379a6de | ||
|
|
1dcd12b819 | ||
|
|
2298df294b | ||
|
|
b4cd61900b | ||
|
|
2c258dd275 | ||
|
|
75bece800d | ||
|
|
582caa9d8f | ||
|
|
8a3d3b2dce | ||
|
|
56069a968b | ||
|
|
87ee4423ea | ||
|
|
c9ecc99ce5 | ||
|
|
ceb4d561fa | ||
|
|
5d58ab8042 | ||
|
|
27a8b457b8 | ||
|
|
229e97195a | ||
|
|
e3f4cef054 | ||
|
|
223d3222b3 | ||
|
|
a98f742d67 | ||
|
|
e0ceebe2ee | ||
|
|
bb0e9b20aa | ||
|
|
d7ed70841a | ||
|
|
7d1704218f | ||
|
|
44a1e7e88c | ||
|
|
ed7ebdfad3 | ||
|
|
82fa307ca6 | ||
|
|
4d9d307477 | ||
|
|
ee39380c12 | ||
|
|
47ce401222 | ||
|
|
78ac959e4c | ||
|
|
709349b118 | ||
|
|
9106a0b73a | ||
|
|
1b97d7409a | ||
|
|
ab95054e64 | ||
|
|
a5deed32f7 | ||
|
|
94723d5b72 | ||
|
|
ef8dc34bd0 | ||
|
|
bb8b50e4f3 | ||
|
|
0877680b08 | ||
|
|
e37fce3899 | ||
|
|
c1f54da018 | ||
|
|
a1efe99f5b | ||
|
|
359227ad14 | ||
|
|
e0d2cf5a89 | ||
|
|
da770a89e6 | ||
|
|
58c71ed812 | ||
|
|
c972f66475 | ||
|
|
bfc5678471 | ||
|
|
a5684b2c83 | ||
|
|
c17e66af6f | ||
|
|
661caad5bb | ||
|
|
281e3b0247 | ||
|
|
af342d8b2b | ||
|
|
7c2b240ded | ||
|
|
0e35cd6f3e | ||
|
|
a5cfab671b | ||
|
|
bd1ff9f254 | ||
|
|
036cd2a408 | ||
|
|
82bf098fbe | ||
|
|
4b3bbf8511 | ||
|
|
8736cb537d | ||
|
|
d4d0853fee | ||
|
|
aaffbc2209 | ||
|
|
8f6c5d088a | ||
|
|
d0290d342d | ||
|
|
7b050cec80 | ||
|
|
82dcbe0510 | ||
|
|
31e19b0a28 | ||
|
|
7bb2001997 | ||
|
|
5d78f74fe4 | ||
|
|
b3b137ec4a | ||
|
|
833406121c | ||
|
|
01619fbe2d | ||
|
|
075df0b446 | ||
|
|
2f6c758d3d | ||
|
|
4c7e5ce7a8 | ||
|
|
86fbaf3b14 | ||
|
|
5c3aed3e88 | ||
|
|
fcdffffa37 | ||
|
|
aeb627bebf | ||
|
|
a2567f6d7a | ||
|
|
c1e272b47d | ||
|
|
cfba4b3bf4 | ||
|
|
d761dad79c | ||
|
|
d068b82c2f | ||
|
|
8ca4d2ef08 | ||
|
|
acc3cd460d | ||
|
|
c4813b8cbc | ||
|
|
0cd1fce3c3 | ||
|
|
90eb2f759c | ||
|
|
d1e4be6fb4 | ||
|
|
29d98da636 | ||
|
|
91dc6e7fa0 | ||
|
|
b33fd1e4fb | ||
|
|
1c618a9d87 | ||
|
|
ab2abebfc3 | ||
|
|
0f132fc129 | ||
|
|
6fc6db3496 | ||
|
|
ca0bde3578 | ||
|
|
f51b537239 | ||
|
|
2b7e3e9b81 | ||
|
|
fee8454dd0 | ||
|
|
dc238ba102 | ||
|
|
fa7a5ab07a | ||
|
|
27932ae6da | ||
|
|
631d23788e | ||
|
|
4f03bfebd9 | ||
|
|
7f488dc7d3 | ||
|
|
1b2e88effd | ||
|
|
4dcf21a2f6 | ||
|
|
ff24751bdd |
@@ -8,7 +8,7 @@ BraceWrapping:
|
||||
AfterUnion: true
|
||||
SplitEmptyRecord: false
|
||||
PointerAlignment: Middle
|
||||
FixNamespaceComments: false
|
||||
FixNamespaceComments: true
|
||||
SortIncludes: Never
|
||||
#IndentPPDirectives: BeforeHash
|
||||
SpaceAfterCStyleCast: true
|
||||
@@ -32,3 +32,4 @@ IndentPPDirectives: AfterHash
|
||||
PPIndentWidth: 2
|
||||
BinPackArguments: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
SeparateDefinitionBlocks: Always
|
||||
|
||||
4
.git-blame-ignore-revs
Normal file
4
.git-blame-ignore-revs
Normal file
@@ -0,0 +1,4 @@
|
||||
# bulk initial re-formatting with clang-format
|
||||
0e35cd6f3e27760976ead16fb45008ece0185aad # !autorebase ./maintainers/format.sh --until-stable
|
||||
# nixfmt 1.0.0
|
||||
d6aebd884790ae82c21ef2b58a010026ce757eaf # !autorebase ./maintainers/format.sh --until-stable
|
||||
50
.github/actions/install-nix-action/action.yaml
vendored
Normal file
50
.github/actions/install-nix-action/action.yaml
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
name: "Install Nix"
|
||||
description: "Helper action for installing Nix with support for dogfooding from master"
|
||||
inputs:
|
||||
dogfood:
|
||||
description: "Whether to use Nix installed from the latest artifact from master branch"
|
||||
required: true # Be explicit about the fact that we are using unreleased artifacts
|
||||
extra_nix_config:
|
||||
description: "Gets appended to `/etc/nix/nix.conf` if passed."
|
||||
install_url:
|
||||
description: "URL of the Nix installer"
|
||||
required: false
|
||||
default: "https://releases.nixos.org/nix/nix-2.29.1/install"
|
||||
github_token:
|
||||
description: "Github token"
|
||||
required: true
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: "Download nix install artifact from master"
|
||||
shell: bash
|
||||
id: download-nix-installer
|
||||
if: inputs.dogfood == 'true'
|
||||
run: |
|
||||
RUN_ID=$(gh run list --repo "$DOGFOOD_REPO" --workflow ci.yml --branch master --status success --json databaseId --jq ".[0].databaseId")
|
||||
|
||||
if [ "$RUNNER_OS" == "Linux" ]; then
|
||||
INSTALLER_ARTIFACT="installer-linux"
|
||||
elif [ "$RUNNER_OS" == "macOS" ]; then
|
||||
INSTALLER_ARTIFACT="installer-darwin"
|
||||
else
|
||||
echo "::error ::Unsupported RUNNER_OS: $RUNNER_OS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
INSTALLER_DOWNLOAD_DIR="$GITHUB_WORKSPACE/$INSTALLER_ARTIFACT"
|
||||
mkdir -p "$INSTALLER_DOWNLOAD_DIR"
|
||||
|
||||
gh run download "$RUN_ID" --repo "$DOGFOOD_REPO" -n "$INSTALLER_ARTIFACT" -D "$INSTALLER_DOWNLOAD_DIR"
|
||||
echo "installer-path=file://$INSTALLER_DOWNLOAD_DIR" >> "$GITHUB_OUTPUT"
|
||||
|
||||
echo "::notice ::Dogfooding Nix installer from master (https://github.com/$DOGFOOD_REPO/actions/runs/$RUN_ID)"
|
||||
env:
|
||||
GH_TOKEN: ${{ inputs.github_token }}
|
||||
DOGFOOD_REPO: "NixOS/nix"
|
||||
- uses: cachix/install-nix-action@c134e4c9e34bac6cab09cf239815f9339aaaf84e # v31.5.1
|
||||
with:
|
||||
# Ternary operator in GHA: https://www.github.com/actions/runner/issues/409#issuecomment-752775072
|
||||
install_url: ${{ inputs.dogfood == 'true' && format('{0}/install', steps.download-nix-installer.outputs.installer-path) || inputs.install_url }}
|
||||
install_options: ${{ inputs.dogfood == 'true' && format('--tarball-url-prefix {0}', steps.download-nix-installer.outputs.installer-path) || '' }}
|
||||
extra_nix_config: ${{ inputs.extra_nix_config }}
|
||||
27
.github/workflows/ci.yml
vendored
27
.github/workflows/ci.yml
vendored
@@ -13,8 +13,13 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: cachix/install-nix-action@v31
|
||||
- run: nix --experimental-features 'nix-command flakes' flake show --all-systems --json
|
||||
- uses: ./.github/actions/install-nix-action
|
||||
with:
|
||||
dogfood: false
|
||||
extra_nix_config:
|
||||
experimental-features = nix-command flakes
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- run: nix flake show --all-systems --json
|
||||
|
||||
tests:
|
||||
strategy:
|
||||
@@ -34,8 +39,10 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: cachix/install-nix-action@v31
|
||||
- uses: ./.github/actions/install-nix-action
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
dogfood: false
|
||||
# The sandbox would otherwise be disabled by default on Darwin
|
||||
extra_nix_config: |
|
||||
sandbox = true
|
||||
@@ -175,7 +182,12 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
- uses: ./.github/actions/install-nix-action
|
||||
with:
|
||||
dogfood: false
|
||||
extra_nix_config:
|
||||
experimental-features = nix-command flakes
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
- run: |
|
||||
nix build -L \
|
||||
@@ -201,6 +213,11 @@ jobs:
|
||||
with:
|
||||
repository: NixOS/flake-regressions-data
|
||||
path: flake-regressions/tests
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
- uses: ./.github/actions/install-nix-action
|
||||
with:
|
||||
dogfood: false
|
||||
extra_nix_config:
|
||||
experimental-features = nix-command flakes
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
- run: nix build -L --out-link ./new-nix && PATH=$(pwd)/new-nix/bin:$PATH MAX_FLAKES=25 flake-regressions/eval-all.sh
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -47,3 +47,6 @@ result-*
|
||||
.DS_Store
|
||||
|
||||
flake-regressions
|
||||
|
||||
# direnv
|
||||
.direnv/
|
||||
|
||||
@@ -46,24 +46,23 @@ mkMesonDerivation (finalAttrs: {
|
||||
];
|
||||
|
||||
# Hack for sake of the dev shell
|
||||
passthru.externalNativeBuildInputs =
|
||||
[
|
||||
meson
|
||||
ninja
|
||||
(lib.getBin lowdown-unsandboxed)
|
||||
mdbook
|
||||
mdbook-linkcheck
|
||||
jq
|
||||
python3
|
||||
rsync
|
||||
changelog-d
|
||||
]
|
||||
++ lib.optionals (!officialRelease) [
|
||||
# When not an official release, we likely have changelog entries that have
|
||||
# yet to be rendered.
|
||||
# When released, these are rendered into a committed file to save a dependency.
|
||||
changelog-d
|
||||
];
|
||||
passthru.externalNativeBuildInputs = [
|
||||
meson
|
||||
ninja
|
||||
(lib.getBin lowdown-unsandboxed)
|
||||
mdbook
|
||||
mdbook-linkcheck
|
||||
jq
|
||||
python3
|
||||
rsync
|
||||
changelog-d
|
||||
]
|
||||
++ lib.optionals (!officialRelease) [
|
||||
# When not an official release, we likely have changelog entries that have
|
||||
# yet to be rendered.
|
||||
# When released, these are rendered into a committed file to save a dependency.
|
||||
changelog-d
|
||||
];
|
||||
|
||||
nativeBuildInputs = finalAttrs.passthru.externalNativeBuildInputs ++ [
|
||||
nix-cli
|
||||
|
||||
17
doc/manual/rl-next/outpath-and-sourceinfo-fixes.md
Normal file
17
doc/manual/rl-next/outpath-and-sourceinfo-fixes.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
synopsis: Non-flake inputs now contain a `sourceInfo` attribute
|
||||
issues: 13164
|
||||
prs: 13170
|
||||
---
|
||||
|
||||
Flakes have always a `sourceInfo` attribute which describes the source of the flake.
|
||||
The `sourceInfo.outPath` is often identical to the flake's `outPath`, however it can differ when the flake is located in a subdirectory of its source.
|
||||
|
||||
Non-flake inputs (i.e. inputs with `flake = false`) can also be located at some path _within_ a wider source.
|
||||
This usually happens when defining a relative path input within the same source as the parent flake, e.g. `inputs.foo.url = ./some-file.nix`.
|
||||
Such relative inputs will now inherit their parent's `sourceInfo`.
|
||||
|
||||
This also means it is now possible to use `?dir=subdir` on non-flake inputs.
|
||||
|
||||
This iterates on the work done in 2.26 to improve relative path support ([#10089](https://github.com/NixOS/nix/pull/10089)),
|
||||
and resolves a regression introduced in 2.28 relating to nested relative path inputs ([#13164](https://github.com/NixOS/nix/issues/13164)).
|
||||
@@ -53,6 +53,11 @@ This command has the following operations:
|
||||
Download the Nix expressions of subscribed channels and create a new generation.
|
||||
Update all channels if none is specified, and only those included in *names* otherwise.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Downloaded channel contents are cached.
|
||||
> Use `--tarball-ttl` or the [`tarball-ttl` configuration option](@docroot@/command-ref/conf-file.md#conf-tarball-ttl) to change the validity period of cached downloads.
|
||||
|
||||
- `--list-generations`
|
||||
|
||||
Prints a list of all the current existing generations for the
|
||||
|
||||
@@ -215,14 +215,18 @@ nix build .#nix-everything-x86_64-w64-mingw32
|
||||
|
||||
For historic reasons and backward-compatibility, some CPU and OS identifiers are translated as follows:
|
||||
|
||||
| `config.guess` | Nix |
|
||||
|----------------------------|---------------------|
|
||||
| `amd64` | `x86_64` |
|
||||
| `i*86` | `i686` |
|
||||
| `arm6` | `arm6l` |
|
||||
| `arm7` | `arm7l` |
|
||||
| `linux-gnu*` | `linux` |
|
||||
| `linux-musl*` | `linux` |
|
||||
| `host_machine.cpu_family()` | `host_machine.endian()` | Nix |
|
||||
|-----------------------------|-------------------------|---------------------|
|
||||
| `x86` | | `i686` |
|
||||
| `arm` | | `host_machine.cpu()`|
|
||||
| `ppc` | `little` | `powerpcle` |
|
||||
| `ppc64` | `little` | `powerpc64le` |
|
||||
| `ppc` | `big` | `powerpc` |
|
||||
| `ppc64` | `big` | `powerpc64` |
|
||||
| `mips` | `little` | `mipsel` |
|
||||
| `mips64` | `little` | `mips64el` |
|
||||
| `mips` | `big` | `mips` |
|
||||
| `mips64` | `big` | `mips64` |
|
||||
|
||||
## Compilation environments
|
||||
|
||||
|
||||
@@ -20,8 +20,9 @@ prs: 1238
|
||||
Here's one or more paragraphs that describe the change.
|
||||
|
||||
- It's markdown
|
||||
- Add references to the manual using @docroot@
|
||||
- Add references to the manual using [links like this](@_at_docroot@/example.md)
|
||||
```
|
||||
<!-- for the raw markdown readers: that means using @docroot@ -->
|
||||
|
||||
Significant changes should add the following header, which moves them to the top.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ This performs the default type of installation for your platform:
|
||||
|
||||
We recommend the multi-user installation if it supports your platform and you can authenticate with `sudo`.
|
||||
|
||||
The installer can configured with various command line arguments and environment variables.
|
||||
The installer can be configured with various command line arguments and environment variables.
|
||||
To show available command line flags:
|
||||
|
||||
```console
|
||||
|
||||
@@ -73,7 +73,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> If set to `true`, other advanced attributes such as [`allowedReferences`](#adv-attr-allowedReferences), [`allowedReferences`](#adv-attr-allowedReferences), [`allowedRequisites`](#adv-attr-allowedRequisites),
|
||||
> If set to `true`, other advanced attributes such as [`allowedReferences`](#adv-attr-allowedReferences), [`allowedRequisites`](#adv-attr-allowedRequisites),
|
||||
[`disallowedReferences`](#adv-attr-disallowedReferences) and [`disallowedRequisites`](#adv-attr-disallowedRequisites), maxSize, and maxClosureSize.
|
||||
will have no effect.
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ All comparison operators are implemented in terms of `<`, and the following equi
|
||||
|
||||
## Logical implication
|
||||
|
||||
Equivalent to `!`*b1* `||` *b2*.
|
||||
Equivalent to `!`*b1* `||` *b2* (or `if` *b1* `then` *b2* `else true`)
|
||||
|
||||
[Logical implication]: #logical-implication
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ There are two types of placeholder, corresponding to the two cases where this pr
|
||||
|
||||
> **Explanation**
|
||||
>
|
||||
> In general, we need to realise [realise] a [store object] in order to be sure to have a store object for it.
|
||||
> In general, we need to [realise] a [store object] in order to be sure to have a store object for it.
|
||||
> But for these two cases this is either impossible or impractical:
|
||||
>
|
||||
> - In the output case this is impossible:
|
||||
@@ -189,7 +189,7 @@ This ensures that there is a canonical [store path] used to refer to the derivat
|
||||
> **Note**
|
||||
>
|
||||
> Currently, the canonical encoding for every derivation is the "ATerm" format,
|
||||
> but this is subject to change for types derivations which are not yet stable.
|
||||
> but this is subject to change for the types of derivations which are not yet stable.
|
||||
|
||||
Regardless of the format used, when serializing a derivation to a store object, that store object will be content-addressed.
|
||||
|
||||
@@ -282,7 +282,7 @@ type DerivingPath = ConstantPath | OutputPath;
|
||||
|
||||
Under this extended model, `DerivingPath`s are thus inductively built up from a root `ConstantPath`, wrapped with zero or more outer `OutputPath`s.
|
||||
|
||||
### Encoding {#deriving-path-encoding}
|
||||
### Encoding {#deriving-path-encoding-higher-order}
|
||||
|
||||
The encoding is adjusted in the natural way, encoding the `drv` field recursively using the same deriving path encoding.
|
||||
The result of this is that it is possible to have a chain of `^<output-name>` at the end of the final string, as opposed to just a single one.
|
||||
|
||||
@@ -23,7 +23,7 @@ The output spec for an output with a fixed content addresses additionally contai
|
||||
> **Design note**
|
||||
>
|
||||
> In principle, the output spec could also specify the references the store object should have, since the references and file system objects are equally parts of a content-addressed store object proper that contribute to its content-addressed.
|
||||
> However, at this time, the references are not not done because all fixed content-addressed outputs are required to have no references (including no self-reference).
|
||||
> However, at this time, the references are not done because all fixed content-addressed outputs are required to have no references (including no self-reference).
|
||||
>
|
||||
> Also in principle, rather than specifying the references and file system object data with separate hashes, a single hash that constraints both could be used.
|
||||
> This could be done with the final store path's digest, or better yet, the hash that will become the store path's digest before it is truncated.
|
||||
@@ -116,7 +116,7 @@ Because the derivation output is not fixed (just like with [input addressing]),
|
||||
> (The "environment", in this case, consists of attributes such as the Operating System Nix runs atop, along with the operating-system-specific privileges that Nix has been granted.
|
||||
> Because of how conventional operating systems like macos, Linux, etc. work, granting builders *fewer* privileges may ironically require that Nix be run with *more* privileges.)
|
||||
|
||||
That said, derivations producing floating content-addressed outputs may declare their builders as impure (like the builders of derivations producing producing fixed outputs).
|
||||
That said, derivations producing floating content-addressed outputs may declare their builders as impure (like the builders of derivations producing fixed outputs).
|
||||
This is provisionally supported as part of the [`impure-derivations`][xp-feature-impure-derivations] experimental feature.
|
||||
|
||||
### Compatibility negotiation
|
||||
@@ -144,7 +144,7 @@ A *deterministic* content-addressing derivation should produce outputs with the
|
||||
The choice of provisional store path can be thought of as an impurity, since it is an arbitrary choice.
|
||||
|
||||
If provisional outputs paths are deterministically chosen, we are in the first branch of part (1).
|
||||
The builder the data it produces based on it in arbitrary ways, but this gets us closer to to [input addressing].
|
||||
The builder the data it produces based on it in arbitrary ways, but this gets us closer to [input addressing].
|
||||
Deterministically choosing the provisional path may be considered "complete sandboxing" by removing an impurity, but this is unsatisfactory
|
||||
|
||||
<!--
|
||||
|
||||
@@ -83,7 +83,7 @@ The rules for this are fairly concise:
|
||||
|
||||
- A content-addressing derivation may be pure or impure
|
||||
|
||||
- If it is impure, it may be be fixed (typical), or it may be floating if the additional [`impure-derivations`][xp-feature-impure-derivations] experimental feature is enabled.
|
||||
- If it is impure, it may be fixed (typical), or it may be floating if the additional [`impure-derivations`][xp-feature-impure-derivations] experimental feature is enabled.
|
||||
|
||||
- If it is pure, it must be floating.
|
||||
|
||||
|
||||
@@ -18,14 +18,14 @@ In particular, the edge corresponding to a reference is from the store object th
|
||||
References other than a self-reference must not form a cycle.
|
||||
The graph of references excluding self-references thus forms a [directed acyclic graph].
|
||||
|
||||
[directed acyclic graph]: @docroot@/glossary.md#gloss-directed acyclic graph
|
||||
[directed acyclic graph]: @docroot@/glossary.md#gloss-directed-acyclic-graph
|
||||
|
||||
We can take the [transitive closure] of the references graph, which any pair of store objects have an edge not if there is a single reference from the first to the second, but a path of one or more references from the first to the second.
|
||||
The *requisites* of a store object are all store objects reachable by paths of references which start with given store object's references.
|
||||
|
||||
[transitive closure]: https://en.wikipedia.org/wiki/Transitive_closure
|
||||
|
||||
We can also take the [transpose graph] ofthe references graph, where we reverse the orientation of all edges.
|
||||
We can also take the [transpose graph] of the references graph, where we reverse the orientation of all edges.
|
||||
The *referrers* of a store object are the store objects that reference it.
|
||||
|
||||
[transpose graph]: https://en.wikipedia.org/wiki/Transpose_graph
|
||||
|
||||
@@ -57,6 +57,9 @@ def recursive_replace(data: dict[str, t.Any], book_root: Path, search_path: Path
|
||||
).replace(
|
||||
'@docroot@',
|
||||
("../" * len(path_to_chapter.parent.parts) or "./")[:-1]
|
||||
).replace(
|
||||
'@_at_',
|
||||
'@'
|
||||
),
|
||||
sub_items = [
|
||||
recursive_replace(sub_item, book_root, search_path)
|
||||
|
||||
112
docker.nix
112
docker.nix
@@ -38,60 +38,58 @@ let
|
||||
]
|
||||
++ extraPkgs;
|
||||
|
||||
users =
|
||||
{
|
||||
users = {
|
||||
|
||||
root = {
|
||||
uid = 0;
|
||||
shell = "${pkgs.bashInteractive}/bin/bash";
|
||||
home = "/root";
|
||||
gid = 0;
|
||||
groups = [ "root" ];
|
||||
description = "System administrator";
|
||||
};
|
||||
|
||||
nobody = {
|
||||
uid = 65534;
|
||||
shell = "${pkgs.shadow}/bin/nologin";
|
||||
home = "/var/empty";
|
||||
gid = 65534;
|
||||
groups = [ "nobody" ];
|
||||
description = "Unprivileged account (don't use!)";
|
||||
};
|
||||
|
||||
}
|
||||
// lib.optionalAttrs (uid != 0) {
|
||||
"${uname}" = {
|
||||
uid = uid;
|
||||
shell = "${pkgs.bashInteractive}/bin/bash";
|
||||
home = "/home/${uname}";
|
||||
gid = gid;
|
||||
groups = [ "${gname}" ];
|
||||
description = "Nix user";
|
||||
};
|
||||
}
|
||||
// lib.listToAttrs (
|
||||
map (n: {
|
||||
name = "nixbld${toString n}";
|
||||
value = {
|
||||
uid = 30000 + n;
|
||||
gid = 30000;
|
||||
groups = [ "nixbld" ];
|
||||
description = "Nix build user ${toString n}";
|
||||
};
|
||||
}) (lib.lists.range 1 32)
|
||||
);
|
||||
|
||||
groups =
|
||||
{
|
||||
root.gid = 0;
|
||||
nixbld.gid = 30000;
|
||||
nobody.gid = 65534;
|
||||
}
|
||||
// lib.optionalAttrs (gid != 0) {
|
||||
"${gname}".gid = gid;
|
||||
root = {
|
||||
uid = 0;
|
||||
shell = "${pkgs.bashInteractive}/bin/bash";
|
||||
home = "/root";
|
||||
gid = 0;
|
||||
groups = [ "root" ];
|
||||
description = "System administrator";
|
||||
};
|
||||
|
||||
nobody = {
|
||||
uid = 65534;
|
||||
shell = "${pkgs.shadow}/bin/nologin";
|
||||
home = "/var/empty";
|
||||
gid = 65534;
|
||||
groups = [ "nobody" ];
|
||||
description = "Unprivileged account (don't use!)";
|
||||
};
|
||||
|
||||
}
|
||||
// lib.optionalAttrs (uid != 0) {
|
||||
"${uname}" = {
|
||||
uid = uid;
|
||||
shell = "${pkgs.bashInteractive}/bin/bash";
|
||||
home = "/home/${uname}";
|
||||
gid = gid;
|
||||
groups = [ "${gname}" ];
|
||||
description = "Nix user";
|
||||
};
|
||||
}
|
||||
// lib.listToAttrs (
|
||||
map (n: {
|
||||
name = "nixbld${toString n}";
|
||||
value = {
|
||||
uid = 30000 + n;
|
||||
gid = 30000;
|
||||
groups = [ "nixbld" ];
|
||||
description = "Nix build user ${toString n}";
|
||||
};
|
||||
}) (lib.lists.range 1 32)
|
||||
);
|
||||
|
||||
groups = {
|
||||
root.gid = 0;
|
||||
nixbld.gid = 30000;
|
||||
nobody.gid = 65534;
|
||||
}
|
||||
// lib.optionalAttrs (gid != 0) {
|
||||
"${gname}".gid = gid;
|
||||
};
|
||||
|
||||
userToPasswd = (
|
||||
k:
|
||||
{
|
||||
@@ -155,7 +153,7 @@ let
|
||||
|
||||
nixConfContents =
|
||||
(lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsFlatten (
|
||||
lib.mapAttrsToList (
|
||||
n: v:
|
||||
let
|
||||
vStr = if builtins.isList v then lib.concatStringsSep " " v else v;
|
||||
@@ -173,7 +171,12 @@ let
|
||||
channel = pkgs.runCommand "channel-nixos" { inherit bundleNixpkgs; } ''
|
||||
mkdir $out
|
||||
if [ "$bundleNixpkgs" ]; then
|
||||
ln -s ${nixpkgs} $out/nixpkgs
|
||||
ln -s ${
|
||||
builtins.path {
|
||||
path = nixpkgs;
|
||||
name = "source";
|
||||
}
|
||||
} $out/nixpkgs
|
||||
echo "[]" > $out/manifest.nix
|
||||
fi
|
||||
'';
|
||||
@@ -275,7 +278,6 @@ let
|
||||
|
||||
ln -s ${profile} $out/nix/var/nix/profiles/default-1-link
|
||||
ln -s /nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default
|
||||
ln -s /nix/var/nix/profiles/default $out${userHome}/.nix-profile
|
||||
|
||||
ln -s ${channel} $out/nix/var/nix/profiles/per-user/${uname}/channels-1-link
|
||||
ln -s /nix/var/nix/profiles/per-user/${uname}/channels-1-link $out/nix/var/nix/profiles/per-user/${uname}/channels
|
||||
@@ -327,7 +329,7 @@ pkgs.dockerTools.buildLayeredImageWithNixDb {
|
||||
'';
|
||||
|
||||
config = {
|
||||
Cmd = [ "${userHome}/.nix-profile/bin/bash" ];
|
||||
Cmd = [ (lib.getExe pkgs.bashInteractive) ];
|
||||
User = "${toString uid}:${toString gid}";
|
||||
Env = [
|
||||
"USER=${uname}"
|
||||
|
||||
8
flake.lock
generated
8
flake.lock
generated
@@ -63,16 +63,16 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1746141548,
|
||||
"narHash": "sha256-IgBWhX7A2oJmZFIrpRuMnw5RAufVnfvOgHWgIdds+hc=",
|
||||
"lastModified": 1756178832,
|
||||
"narHash": "sha256-O2CIn7HjZwEGqBrwu9EU76zlmA5dbmna7jL1XUmAId8=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f02fddb8acef29a8b32f10a335d44828d7825b78",
|
||||
"rev": "d98ce345cdab58477ca61855540999c86577d19d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"ref": "nixos-25.05-small",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
description = "The purely functional package manager";
|
||||
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05-small";
|
||||
|
||||
inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
|
||||
inputs.nixpkgs-23-11.url = "github:NixOS/nixpkgs/a62e6edd6d5e1fa0329b8653c801147986f8d446";
|
||||
@@ -32,7 +32,7 @@
|
||||
let
|
||||
inherit (nixpkgs) lib;
|
||||
|
||||
officialRelease = false;
|
||||
officialRelease = true;
|
||||
|
||||
linux32BitSystems = [ "i686-linux" ];
|
||||
linux64BitSystems = [
|
||||
|
||||
@@ -77,467 +77,6 @@
|
||||
# Don't format vendored code
|
||||
''^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/include/nix/cmd/built-path\.hh$''
|
||||
''^src/libcmd/common-eval-args\.cc$''
|
||||
''^src/libcmd/include/nix/cmd/common-eval-args\.hh$''
|
||||
''^src/libcmd/editor-for\.cc$''
|
||||
''^src/libcmd/installable-attr-path\.cc$''
|
||||
''^src/libcmd/include/nix/cmd/installable-attr-path\.hh$''
|
||||
''^src/libcmd/installable-derived-path\.cc$''
|
||||
''^src/libcmd/include/nix/cmd/installable-derived-path\.hh$''
|
||||
''^src/libcmd/installable-flake\.cc$''
|
||||
''^src/libcmd/include/nix/cmd/installable-flake\.hh$''
|
||||
''^src/libcmd/installable-value\.cc$''
|
||||
''^src/libcmd/include/nix/cmd/installable-value\.hh$''
|
||||
''^src/libcmd/installables\.cc$''
|
||||
''^src/libcmd/include/nix/cmd/installables\.hh$''
|
||||
''^src/libcmd/include/nix/cmd/legacy\.hh$''
|
||||
''^src/libcmd/markdown\.cc$''
|
||||
''^src/libcmd/misc-store-flags\.cc$''
|
||||
''^src/libcmd/repl-interacter\.cc$''
|
||||
''^src/libcmd/include/nix/cmd/repl-interacter\.hh$''
|
||||
''^src/libcmd/repl\.cc$''
|
||||
''^src/libcmd/include/nix/cmd/repl\.hh$''
|
||||
''^src/libexpr-c/nix_api_expr\.cc$''
|
||||
''^src/libexpr-c/nix_api_external\.cc$''
|
||||
''^src/libexpr/attr-path\.cc$''
|
||||
''^src/libexpr/include/nix/expr/attr-path\.hh$''
|
||||
''^src/libexpr/attr-set\.cc$''
|
||||
''^src/libexpr/include/nix/expr/attr-set\.hh$''
|
||||
''^src/libexpr/eval-cache\.cc$''
|
||||
''^src/libexpr/include/nix/expr/eval-cache\.hh$''
|
||||
''^src/libexpr/eval-error\.cc$''
|
||||
''^src/libexpr/include/nix/expr/eval-inline\.hh$''
|
||||
''^src/libexpr/eval-settings\.cc$''
|
||||
''^src/libexpr/include/nix/expr/eval-settings\.hh$''
|
||||
''^src/libexpr/eval\.cc$''
|
||||
''^src/libexpr/include/nix/expr/eval\.hh$''
|
||||
''^src/libexpr/function-trace\.cc$''
|
||||
''^src/libexpr/include/nix/expr/gc-small-vector\.hh$''
|
||||
''^src/libexpr/get-drvs\.cc$''
|
||||
''^src/libexpr/include/nix/expr/get-drvs\.hh$''
|
||||
''^src/libexpr/json-to-value\.cc$''
|
||||
''^src/libexpr/nixexpr\.cc$''
|
||||
''^src/libexpr/include/nix/expr/nixexpr\.hh$''
|
||||
''^src/libexpr/include/nix/expr/parser-state\.hh$''
|
||||
''^src/libexpr/primops\.cc$''
|
||||
''^src/libexpr/include/nix/expr/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/include/nix/expr/print-ambiguous\.hh$''
|
||||
''^src/libexpr/include/nix/expr/print-options\.hh$''
|
||||
''^src/libexpr/print\.cc$''
|
||||
''^src/libexpr/include/nix/expr/print\.hh$''
|
||||
''^src/libexpr/search-path\.cc$''
|
||||
''^src/libexpr/include/nix/expr/symbol-table\.hh$''
|
||||
''^src/libexpr/value-to-json\.cc$''
|
||||
''^src/libexpr/include/nix/expr/value-to-json\.hh$''
|
||||
''^src/libexpr/value-to-xml\.cc$''
|
||||
''^src/libexpr/include/nix/expr/value-to-xml\.hh$''
|
||||
''^src/libexpr/include/nix/expr/value\.hh$''
|
||||
''^src/libexpr/value/context\.cc$''
|
||||
''^src/libexpr/include/nix/expr/value/context\.hh$''
|
||||
''^src/libfetchers/attrs\.cc$''
|
||||
''^src/libfetchers/cache\.cc$''
|
||||
''^src/libfetchers/include/nix/fetchers/cache\.hh$''
|
||||
''^src/libfetchers/fetch-settings\.cc$''
|
||||
''^src/libfetchers/include/nix/fetchers/fetch-settings\.hh$''
|
||||
''^src/libfetchers/fetch-to-store\.cc$''
|
||||
''^src/libfetchers/fetchers\.cc$''
|
||||
''^src/libfetchers/include/nix/fetchers/fetchers\.hh$''
|
||||
''^src/libfetchers/filtering-source-accessor\.cc$''
|
||||
''^src/libfetchers/include/nix/fetchers/filtering-source-accessor\.hh$''
|
||||
''^src/libfetchers/fs-source-accessor\.cc$''
|
||||
''^src/libfetchers/include/nix/fs-source-accessor\.hh$''
|
||||
''^src/libfetchers/git-utils\.cc$''
|
||||
''^src/libfetchers/include/nix/fetchers/git-utils\.hh$''
|
||||
''^src/libfetchers/github\.cc$''
|
||||
''^src/libfetchers/indirect\.cc$''
|
||||
''^src/libfetchers/memory-source-accessor\.cc$''
|
||||
''^src/libfetchers/path\.cc$''
|
||||
''^src/libfetchers/registry\.cc$''
|
||||
''^src/libfetchers/include/nix/fetchers/registry\.hh$''
|
||||
''^src/libfetchers/tarball\.cc$''
|
||||
''^src/libfetchers/include/nix/fetchers/tarball\.hh$''
|
||||
''^src/libfetchers/git\.cc$''
|
||||
''^src/libfetchers/mercurial\.cc$''
|
||||
''^src/libflake/config\.cc$''
|
||||
''^src/libflake/flake\.cc$''
|
||||
''^src/libflake/include/nix/flake/flake\.hh$''
|
||||
''^src/libflake/flakeref\.cc$''
|
||||
''^src/libflake/include/nix/flake/flakeref\.hh$''
|
||||
''^src/libflake/lockfile\.cc$''
|
||||
''^src/libflake/include/nix/flake/lockfile\.hh$''
|
||||
''^src/libflake/url-name\.cc$''
|
||||
''^src/libmain/common-args\.cc$''
|
||||
''^src/libmain/include/nix/main/common-args\.hh$''
|
||||
''^src/libmain/loggers\.cc$''
|
||||
''^src/libmain/include/nix/main/loggers\.hh$''
|
||||
''^src/libmain/progress-bar\.cc$''
|
||||
''^src/libmain/shared\.cc$''
|
||||
''^src/libmain/include/nix/main/shared\.hh$''
|
||||
''^src/libmain/unix/stack\.cc$''
|
||||
''^src/libstore/binary-cache-store\.cc$''
|
||||
''^src/libstore/include/nix/store/binary-cache-store\.hh$''
|
||||
''^src/libstore/include/nix/store/build-result\.hh$''
|
||||
''^src/libstore/include/nix/store/builtins\.hh$''
|
||||
''^src/libstore/builtins/buildenv\.cc$''
|
||||
''^src/libstore/include/nix/store/builtins/buildenv\.hh$''
|
||||
''^src/libstore/include/nix/store/common-protocol-impl\.hh$''
|
||||
''^src/libstore/common-protocol\.cc$''
|
||||
''^src/libstore/include/nix/store/common-protocol\.hh$''
|
||||
''^src/libstore/include/nix/store/common-ssh-store-config\.hh$''
|
||||
''^src/libstore/content-address\.cc$''
|
||||
''^src/libstore/include/nix/store/content-address\.hh$''
|
||||
''^src/libstore/daemon\.cc$''
|
||||
''^src/libstore/include/nix/store/daemon\.hh$''
|
||||
''^src/libstore/derivations\.cc$''
|
||||
''^src/libstore/include/nix/store/derivations\.hh$''
|
||||
''^src/libstore/derived-path-map\.cc$''
|
||||
''^src/libstore/include/nix/store/derived-path-map\.hh$''
|
||||
''^src/libstore/derived-path\.cc$''
|
||||
''^src/libstore/include/nix/store/derived-path\.hh$''
|
||||
''^src/libstore/downstream-placeholder\.cc$''
|
||||
''^src/libstore/include/nix/store/downstream-placeholder\.hh$''
|
||||
''^src/libstore/dummy-store\.cc$''
|
||||
''^src/libstore/export-import\.cc$''
|
||||
''^src/libstore/filetransfer\.cc$''
|
||||
''^src/libstore/include/nix/store/filetransfer\.hh$''
|
||||
''^src/libstore/include/nix/store/gc-store\.hh$''
|
||||
''^src/libstore/globals\.cc$''
|
||||
''^src/libstore/include/nix/store/globals\.hh$''
|
||||
''^src/libstore/http-binary-cache-store\.cc$''
|
||||
''^src/libstore/legacy-ssh-store\.cc$''
|
||||
''^src/libstore/include/nix/store/legacy-ssh-store\.hh$''
|
||||
''^src/libstore/include/nix/store/length-prefixed-protocol-helper\.hh$''
|
||||
''^src/libstore/linux/personality\.cc$''
|
||||
''^src/libstore/linux/include/nix/store/personality\.hh$''
|
||||
''^src/libstore/local-binary-cache-store\.cc$''
|
||||
''^src/libstore/local-fs-store\.cc$''
|
||||
''^src/libstore/include/nix/store/local-fs-store\.hh$''
|
||||
''^src/libstore/log-store\.cc$''
|
||||
''^src/libstore/include/nix/store/log-store\.hh$''
|
||||
''^src/libstore/machines\.cc$''
|
||||
''^src/libstore/include/nix/store/machines\.hh$''
|
||||
''^src/libstore/make-content-addressed\.cc$''
|
||||
''^src/libstore/include/nix/store/make-content-addressed\.hh$''
|
||||
''^src/libstore/misc\.cc$''
|
||||
''^src/libstore/names\.cc$''
|
||||
''^src/libstore/include/nix/store/names\.hh$''
|
||||
''^src/libstore/nar-accessor\.cc$''
|
||||
''^src/libstore/include/nix/store/nar-accessor\.hh$''
|
||||
''^src/libstore/nar-info-disk-cache\.cc$''
|
||||
''^src/libstore/include/nix/store/nar-info-disk-cache\.hh$''
|
||||
''^src/libstore/nar-info\.cc$''
|
||||
''^src/libstore/include/nix/store/nar-info\.hh$''
|
||||
''^src/libstore/outputs-spec\.cc$''
|
||||
''^src/libstore/include/nix/store/outputs-spec\.hh$''
|
||||
''^src/libstore/parsed-derivations\.cc$''
|
||||
''^src/libstore/path-info\.cc$''
|
||||
''^src/libstore/include/nix/store/path-info\.hh$''
|
||||
''^src/libstore/path-references\.cc$''
|
||||
''^src/libstore/include/nix/store/path-regex\.hh$''
|
||||
''^src/libstore/path-with-outputs\.cc$''
|
||||
''^src/libstore/path\.cc$''
|
||||
''^src/libstore/include/nix/store/path\.hh$''
|
||||
''^src/libstore/pathlocks\.cc$''
|
||||
''^src/libstore/include/nix/store/pathlocks\.hh$''
|
||||
''^src/libstore/profiles\.cc$''
|
||||
''^src/libstore/include/nix/store/profiles\.hh$''
|
||||
''^src/libstore/realisation\.cc$''
|
||||
''^src/libstore/include/nix/store/realisation\.hh$''
|
||||
''^src/libstore/remote-fs-accessor\.cc$''
|
||||
''^src/libstore/include/nix/store/remote-fs-accessor\.hh$''
|
||||
''^src/libstore/include/nix/store/remote-store-connection\.hh$''
|
||||
''^src/libstore/remote-store\.cc$''
|
||||
''^src/libstore/include/nix/store/remote-store\.hh$''
|
||||
''^src/libstore/s3-binary-cache-store\.cc$''
|
||||
''^src/libstore/include/nix/store/s3\.hh$''
|
||||
''^src/libstore/serve-protocol-impl\.cc$''
|
||||
''^src/libstore/include/nix/store/serve-protocol-impl\.hh$''
|
||||
''^src/libstore/serve-protocol\.cc$''
|
||||
''^src/libstore/include/nix/store/serve-protocol\.hh$''
|
||||
''^src/libstore/sqlite\.cc$''
|
||||
''^src/libstore/include/nix/store/sqlite\.hh$''
|
||||
''^src/libstore/ssh-store\.cc$''
|
||||
''^src/libstore/ssh\.cc$''
|
||||
''^src/libstore/include/nix/store/ssh\.hh$''
|
||||
''^src/libstore/store-api\.cc$''
|
||||
''^src/libstore/include/nix/store/store-api\.hh$''
|
||||
''^src/libstore/include/nix/store/store-dir-config\.hh$''
|
||||
''^src/libstore/build/derivation-goal\.cc$''
|
||||
''^src/libstore/include/nix/store/build/derivation-goal\.hh$''
|
||||
''^src/libstore/build/drv-output-substitution-goal\.cc$''
|
||||
''^src/libstore/include/nix/store/build/drv-output-substitution-goal\.hh$''
|
||||
''^src/libstore/build/entry-points\.cc$''
|
||||
''^src/libstore/build/goal\.cc$''
|
||||
''^src/libstore/include/nix/store/build/goal\.hh$''
|
||||
''^src/libstore/unix/build/hook-instance\.cc$''
|
||||
''^src/libstore/unix/build/derivation-builder\.cc$''
|
||||
''^src/libstore/unix/include/nix/store/build/derivation-builder\.hh$''
|
||||
''^src/libstore/build/substitution-goal\.cc$''
|
||||
''^src/libstore/include/nix/store/build/substitution-goal\.hh$''
|
||||
''^src/libstore/build/worker\.cc$''
|
||||
''^src/libstore/include/nix/store/build/worker\.hh$''
|
||||
''^src/libstore/builtins/fetchurl\.cc$''
|
||||
''^src/libstore/builtins/unpack-channel\.cc$''
|
||||
''^src/libstore/gc\.cc$''
|
||||
''^src/libstore/local-overlay-store\.cc$''
|
||||
''^src/libstore/include/nix/store/local-overlay-store\.hh$''
|
||||
''^src/libstore/local-store\.cc$''
|
||||
''^src/libstore/include/nix/store/local-store\.hh$''
|
||||
''^src/libstore/unix/user-lock\.cc$''
|
||||
''^src/libstore/unix/include/nix/store/user-lock\.hh$''
|
||||
''^src/libstore/optimise-store\.cc$''
|
||||
''^src/libstore/unix/pathlocks\.cc$''
|
||||
''^src/libstore/posix-fs-canonicalise\.cc$''
|
||||
''^src/libstore/include/nix/store/posix-fs-canonicalise\.hh$''
|
||||
''^src/libstore/uds-remote-store\.cc$''
|
||||
''^src/libstore/include/nix/store/uds-remote-store\.hh$''
|
||||
''^src/libstore/windows/build\.cc$''
|
||||
''^src/libstore/include/nix/store/worker-protocol-impl\.hh$''
|
||||
''^src/libstore/worker-protocol\.cc$''
|
||||
''^src/libstore/include/nix/store/worker-protocol\.hh$''
|
||||
''^src/libutil-c/nix_api_util_internal\.h$''
|
||||
''^src/libutil/archive\.cc$''
|
||||
''^src/libutil/include/nix/util/archive\.hh$''
|
||||
''^src/libutil/args\.cc$''
|
||||
''^src/libutil/include/nix/util/args\.hh$''
|
||||
''^src/libutil/include/nix/util/args/root\.hh$''
|
||||
''^src/libutil/include/nix/util/callback\.hh$''
|
||||
''^src/libutil/canon-path\.cc$''
|
||||
''^src/libutil/include/nix/util/canon-path\.hh$''
|
||||
''^src/libutil/include/nix/util/chunked-vector\.hh$''
|
||||
''^src/libutil/include/nix/util/closure\.hh$''
|
||||
''^src/libutil/include/nix/util/comparator\.hh$''
|
||||
''^src/libutil/compute-levels\.cc$''
|
||||
''^src/libutil/include/nix/util/config-impl\.hh$''
|
||||
''^src/libutil/configuration\.cc$''
|
||||
''^src/libutil/include/nix/util/configuration\.hh$''
|
||||
''^src/libutil/current-process\.cc$''
|
||||
''^src/libutil/include/nix/util/current-process\.hh$''
|
||||
''^src/libutil/english\.cc$''
|
||||
''^src/libutil/include/nix/util/english\.hh$''
|
||||
''^src/libutil/error\.cc$''
|
||||
''^src/libutil/include/nix/util/error\.hh$''
|
||||
''^src/libutil/include/nix/util/exit\.hh$''
|
||||
''^src/libutil/experimental-features\.cc$''
|
||||
''^src/libutil/include/nix/util/experimental-features\.hh$''
|
||||
''^src/libutil/file-content-address\.cc$''
|
||||
''^src/libutil/include/nix/util/file-content-address\.hh$''
|
||||
''^src/libutil/file-descriptor\.cc$''
|
||||
''^src/libutil/include/nix/util/file-descriptor\.hh$''
|
||||
''^src/libutil/include/nix/util/file-path-impl\.hh$''
|
||||
''^src/libutil/include/nix/util/file-path\.hh$''
|
||||
''^src/libutil/file-system\.cc$''
|
||||
''^src/libutil/include/nix/util/file-system\.hh$''
|
||||
''^src/libutil/include/nix/util/finally\.hh$''
|
||||
''^src/libutil/include/nix/util/fmt\.hh$''
|
||||
''^src/libutil/fs-sink\.cc$''
|
||||
''^src/libutil/include/nix/util/fs-sink\.hh$''
|
||||
''^src/libutil/git\.cc$''
|
||||
''^src/libutil/include/nix/util/git\.hh$''
|
||||
''^src/libutil/hash\.cc$''
|
||||
''^src/libutil/include/nix/util/hash\.hh$''
|
||||
''^src/libutil/hilite\.cc$''
|
||||
''^src/libutil/include/nix/util/hilite\.hh$''
|
||||
''^src/libutil/source-accessor\.hh$''
|
||||
''^src/libutil/include/nix/util/json-impls\.hh$''
|
||||
''^src/libutil/json-utils\.cc$''
|
||||
''^src/libutil/include/nix/util/json-utils\.hh$''
|
||||
''^src/libutil/linux/cgroup\.cc$''
|
||||
''^src/libutil/linux/namespaces\.cc$''
|
||||
''^src/libutil/logging\.cc$''
|
||||
''^src/libutil/include/nix/util/logging\.hh$''
|
||||
''^src/libutil/memory-source-accessor\.cc$''
|
||||
''^src/libutil/include/nix/util/memory-source-accessor\.hh$''
|
||||
''^src/libutil/include/nix/util/pool\.hh$''
|
||||
''^src/libutil/position\.cc$''
|
||||
''^src/libutil/include/nix/util/position\.hh$''
|
||||
''^src/libutil/posix-source-accessor\.cc$''
|
||||
''^src/libutil/include/nix/util/posix-source-accessor\.hh$''
|
||||
''^src/libutil/include/nix/util/processes\.hh$''
|
||||
''^src/libutil/include/nix/util/ref\.hh$''
|
||||
''^src/libutil/references\.cc$''
|
||||
''^src/libutil/include/nix/util/references\.hh$''
|
||||
''^src/libutil/regex-combinators\.hh$''
|
||||
''^src/libutil/serialise\.cc$''
|
||||
''^src/libutil/include/nix/util/serialise\.hh$''
|
||||
''^src/libutil/include/nix/util/signals\.hh$''
|
||||
''^src/libutil/signature/local-keys\.cc$''
|
||||
''^src/libutil/include/nix/util/signature/local-keys\.hh$''
|
||||
''^src/libutil/signature/signer\.cc$''
|
||||
''^src/libutil/include/nix/util/signature/signer\.hh$''
|
||||
''^src/libutil/source-accessor\.cc$''
|
||||
''^src/libutil/include/nix/util/source-accessor\.hh$''
|
||||
''^src/libutil/source-path\.cc$''
|
||||
''^src/libutil/include/nix/util/source-path\.hh$''
|
||||
''^src/libutil/include/nix/util/split\.hh$''
|
||||
''^src/libutil/suggestions\.cc$''
|
||||
''^src/libutil/include/nix/util/suggestions\.hh$''
|
||||
''^src/libutil/include/nix/util/sync\.hh$''
|
||||
''^src/libutil/terminal\.cc$''
|
||||
''^src/libutil/include/nix/util/terminal\.hh$''
|
||||
''^src/libutil/thread-pool\.cc$''
|
||||
''^src/libutil/include/nix/util/thread-pool\.hh$''
|
||||
''^src/libutil/include/nix/util/topo-sort\.hh$''
|
||||
''^src/libutil/include/nix/util/types\.hh$''
|
||||
''^src/libutil/unix/file-descriptor\.cc$''
|
||||
''^src/libutil/unix/file-path\.cc$''
|
||||
''^src/libutil/unix/processes\.cc$''
|
||||
''^src/libutil/unix/include/nix/util/signals-impl\.hh$''
|
||||
''^src/libutil/unix/signals\.cc$''
|
||||
''^src/libutil/unix-domain-socket\.cc$''
|
||||
''^src/libutil/unix/users\.cc$''
|
||||
''^src/libutil/include/nix/util/url-parts\.hh$''
|
||||
''^src/libutil/url\.cc$''
|
||||
''^src/libutil/include/nix/util/url\.hh$''
|
||||
''^src/libutil/users\.cc$''
|
||||
''^src/libutil/include/nix/util/users\.hh$''
|
||||
''^src/libutil/util\.cc$''
|
||||
''^src/libutil/include/nix/util/util\.hh$''
|
||||
''^src/libutil/include/nix/util/variant-wrapper\.hh$''
|
||||
''^src/libutil/widecharwidth/widechar_width\.h$'' # vendored source
|
||||
''^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/include/nix/util/windows-error\.hh$''
|
||||
''^src/libutil/xml-writer\.cc$''
|
||||
''^src/libutil/include/nix/util/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$''
|
||||
|
||||
''^tests/functional/plugins/plugintest\.cc''
|
||||
''^tests/functional/test-libstoreconsumer/main\.cc''
|
||||
''^tests/nixos/ca-fd-leak/sender\.c''
|
||||
''^tests/nixos/ca-fd-leak/smuggler\.c''
|
||||
''^tests/nixos/user-sandboxing/attacker\.c''
|
||||
''^src/libexpr-test-support/include/nix/expr/tests/libexpr\.hh''
|
||||
''^src/libexpr-test-support/tests/value/context\.cc''
|
||||
''^src/libexpr-test-support/include/nix/expr/tests/value/context\.hh''
|
||||
''^src/libexpr-tests/derived-path\.cc''
|
||||
''^src/libexpr-tests/error_traces\.cc''
|
||||
''^src/libexpr-tests/eval\.cc''
|
||||
''^src/libexpr-tests/json\.cc''
|
||||
''^src/libexpr-tests/main\.cc''
|
||||
''^src/libexpr-tests/primops\.cc''
|
||||
''^src/libexpr-tests/search-path\.cc''
|
||||
''^src/libexpr-tests/trivial\.cc''
|
||||
''^src/libexpr-tests/value/context\.cc''
|
||||
''^src/libexpr-tests/value/print\.cc''
|
||||
''^src/libfetchers-tests/public-key\.cc''
|
||||
''^src/libflake-tests/flakeref\.cc''
|
||||
''^src/libflake-tests/url-name\.cc''
|
||||
''^src/libstore-test-support/tests/derived-path\.cc''
|
||||
''^src/libstore-test-support/include/nix/store/tests/derived-path\.hh''
|
||||
''^src/libstore-test-support/include/nix/store/tests/nix_api_store\.hh''
|
||||
''^src/libstore-test-support/tests/outputs-spec\.cc''
|
||||
''^src/libstore-test-support/include/nix/store/tests/outputs-spec\.hh''
|
||||
''^src/libstore-test-support/path\.cc''
|
||||
''^src/libstore-test-support/include/nix/store/tests/path\.hh''
|
||||
''^src/libstore-test-support/include/nix/store/tests/protocol\.hh''
|
||||
''^src/libstore-tests/common-protocol\.cc''
|
||||
''^src/libstore-tests/content-address\.cc''
|
||||
''^src/libstore-tests/derivation\.cc''
|
||||
''^src/libstore-tests/derived-path\.cc''
|
||||
''^src/libstore-tests/downstream-placeholder\.cc''
|
||||
''^src/libstore-tests/machines\.cc''
|
||||
''^src/libstore-tests/nar-info-disk-cache\.cc''
|
||||
''^src/libstore-tests/nar-info\.cc''
|
||||
''^src/libstore-tests/outputs-spec\.cc''
|
||||
''^src/libstore-tests/path-info\.cc''
|
||||
''^src/libstore-tests/path\.cc''
|
||||
''^src/libstore-tests/serve-protocol\.cc''
|
||||
''^src/libstore-tests/worker-protocol\.cc''
|
||||
''^src/libutil-test-support/include/nix/util/tests/characterization\.hh''
|
||||
''^src/libutil-test-support/hash\.cc''
|
||||
''^src/libutil-test-support/include/nix/util/tests/hash\.hh''
|
||||
''^src/libutil-tests/args\.cc''
|
||||
''^src/libutil-tests/canon-path\.cc''
|
||||
''^src/libutil-tests/chunked-vector\.cc''
|
||||
''^src/libutil-tests/closure\.cc''
|
||||
''^src/libutil-tests/compression\.cc''
|
||||
''^src/libutil-tests/config\.cc''
|
||||
''^src/libutil-tests/file-content-address\.cc''
|
||||
''^src/libutil-tests/git\.cc''
|
||||
''^src/libutil-tests/hash\.cc''
|
||||
''^src/libutil-tests/hilite\.cc''
|
||||
''^src/libutil-tests/json-utils\.cc''
|
||||
''^src/libutil-tests/logging\.cc''
|
||||
''^src/libutil-tests/lru-cache\.cc''
|
||||
''^src/libutil-tests/pool\.cc''
|
||||
''^src/libutil-tests/references\.cc''
|
||||
''^src/libutil-tests/suggestions\.cc''
|
||||
''^src/libutil-tests/url\.cc''
|
||||
''^src/libutil-tests/xml-writer\.cc''
|
||||
];
|
||||
};
|
||||
shellcheck = {
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if ! type -p pre-commit &>/dev/null; then
|
||||
echo "format.sh: pre-commit not found. Please use \`nix develop\`.";
|
||||
echo "format.sh: pre-commit not found. Please use \`nix develop -c ./maintainers/format.sh\`.";
|
||||
exit 1;
|
||||
fi;
|
||||
if test -z "$_NIX_PRE_COMMIT_HOOKS_CONFIG"; then
|
||||
echo "format.sh: _NIX_PRE_COMMIT_HOOKS_CONFIG not set. Please use \`nix develop\`.";
|
||||
echo "format.sh: _NIX_PRE_COMMIT_HOOKS_CONFIG not set. Please use \`nix develop -c ./maintainers/format.sh\`.";
|
||||
exit 1;
|
||||
fi;
|
||||
pre-commit run --config "$_NIX_PRE_COMMIT_HOOKS_CONFIG" --all-files
|
||||
|
||||
while ! pre-commit run --config "$_NIX_PRE_COMMIT_HOOKS_CONFIG" --all-files; do
|
||||
if [ "${1:-}" != "--until-stable" ]; then
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
19
nix-meson-build-support/default-system-cpu/meson.build
Normal file
19
nix-meson-build-support/default-system-cpu/meson.build
Normal file
@@ -0,0 +1,19 @@
|
||||
# This attempts to translate meson cpu_family and cpu_name specified via
|
||||
# --cross-file [1] into a nix *system double*. Nixpkgs mostly respects ([2]) the
|
||||
# conventions outlined in [1].
|
||||
#
|
||||
# [1]: https://mesonbuild.com/Reference-tables.html#cpu-families
|
||||
# [2]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/lib/meson.nix
|
||||
|
||||
nix_system_cpu = {'ppc64' : 'powerpc64', 'ppc' : 'powerpc', 'x86' : 'i686'}.get(
|
||||
host_machine.cpu_family(),
|
||||
host_machine.cpu_family(),
|
||||
)
|
||||
|
||||
if (host_machine.cpu_family() in [ 'ppc64', 'ppc' ]) and host_machine.endian() == 'little'
|
||||
nix_system_cpu += 'le'
|
||||
elif host_machine.cpu_family() in [ 'mips64', 'mips' ] and host_machine.endian() == 'little'
|
||||
nix_system_cpu += 'el'
|
||||
elif host_machine.cpu_family() == 'arm'
|
||||
nix_system_cpu = host_machine.cpu()
|
||||
endif
|
||||
@@ -11,12 +11,18 @@ endforeach
|
||||
requires_public += deps_public
|
||||
|
||||
extra_pkg_config_variables = get_variable('extra_pkg_config_variables', {})
|
||||
|
||||
extra_cflags = []
|
||||
if not meson.project_name().endswith('-c')
|
||||
extra_cflags += ['-std=c++2a']
|
||||
endif
|
||||
|
||||
import('pkgconfig').generate(
|
||||
this_library,
|
||||
filebase : meson.project_name(),
|
||||
name : 'Nix',
|
||||
description : 'Nix Package Manager',
|
||||
extra_cflags : ['-std=c++2a'],
|
||||
extra_cflags : extra_cflags,
|
||||
requires : requires_public,
|
||||
requires_private : requires_private,
|
||||
libraries_private : libraries_private,
|
||||
|
||||
@@ -54,12 +54,12 @@ let
|
||||
preConfigure =
|
||||
prevAttrs.preConfigure or ""
|
||||
+
|
||||
# Update the repo-global .version file.
|
||||
# Symlink ./.version points there, but by default only workDir is writable.
|
||||
''
|
||||
chmod u+w ./.version
|
||||
echo ${finalAttrs.version} > ./.version
|
||||
'';
|
||||
# Update the repo-global .version file.
|
||||
# Symlink ./.version points there, but by default only workDir is writable.
|
||||
''
|
||||
chmod u+w ./.version
|
||||
echo ${finalAttrs.version} > ./.version
|
||||
'';
|
||||
};
|
||||
|
||||
localSourceLayer =
|
||||
@@ -148,7 +148,8 @@ let
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
ninja
|
||||
] ++ prevAttrs.nativeBuildInputs or [ ];
|
||||
]
|
||||
++ prevAttrs.nativeBuildInputs or [ ];
|
||||
mesonCheckFlags = prevAttrs.mesonCheckFlags or [ ] ++ [
|
||||
"--print-errorlogs"
|
||||
];
|
||||
@@ -166,6 +167,17 @@ let
|
||||
outputs = prevAttrs.outputs or [ "out" ] ++ [ "dev" ];
|
||||
};
|
||||
|
||||
fixupStaticLayer = finalAttrs: prevAttrs: {
|
||||
postFixup =
|
||||
prevAttrs.postFixup or ""
|
||||
+ lib.optionalString (stdenv.hostPlatform.isStatic) ''
|
||||
# HACK: Otherwise the result will have the entire buildInputs closure
|
||||
# injected by the pkgsStatic stdenv
|
||||
# <https://github.com/NixOS/nixpkgs/issues/83667>
|
||||
rm -f $out/nix-support/propagated-build-inputs
|
||||
'';
|
||||
};
|
||||
|
||||
# Work around weird `--as-needed` linker behavior with BSD, see
|
||||
# https://github.com/mesonbuild/meson/issues/3593
|
||||
bsdNoLinkAsNeeded =
|
||||
@@ -301,6 +313,7 @@ in
|
||||
scope.sourceLayer
|
||||
setVersionLayer
|
||||
mesonLayer
|
||||
fixupStaticLayer
|
||||
scope.mesonComponentOverrides
|
||||
];
|
||||
mkMesonExecutable = mkPackageBuilder [
|
||||
@@ -310,6 +323,7 @@ in
|
||||
setVersionLayer
|
||||
mesonLayer
|
||||
mesonBuildLayer
|
||||
fixupStaticLayer
|
||||
scope.mesonComponentOverrides
|
||||
];
|
||||
mkMesonLibrary = mkPackageBuilder [
|
||||
@@ -320,6 +334,7 @@ in
|
||||
setVersionLayer
|
||||
mesonBuildLayer
|
||||
mesonLibraryLayer
|
||||
fixupStaticLayer
|
||||
scope.mesonComponentOverrides
|
||||
];
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ scope: {
|
||||
"--with-coroutine"
|
||||
"--with-iostreams"
|
||||
];
|
||||
enableIcu = false;
|
||||
}).overrideAttrs
|
||||
(old: {
|
||||
# Need to remove `--with-*` to use `--with-libraries=...`
|
||||
|
||||
@@ -71,17 +71,16 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
|
||||
# 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
|
||||
}";
|
||||
}
|
||||
// lib.optionalAttrs stdenv.hostPlatform.isLinux {
|
||||
CC_LD = "mold";
|
||||
CXX_LD = "mold";
|
||||
};
|
||||
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
|
||||
}";
|
||||
}
|
||||
// lib.optionalAttrs stdenv.hostPlatform.isLinux {
|
||||
CC_LD = "mold";
|
||||
CXX_LD = "mold";
|
||||
};
|
||||
|
||||
mesonFlags =
|
||||
map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents2.nix-util.mesonFlags)
|
||||
@@ -113,15 +112,13 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
|
||||
) pkgs.buildPackages.mesonEmulatorHook
|
||||
++ [
|
||||
pkgs.buildPackages.cmake
|
||||
pkgs.buildPackages.gnused
|
||||
pkgs.buildPackages.shellcheck
|
||||
pkgs.buildPackages.changelog-d
|
||||
modular.pre-commit.settings.package
|
||||
(pkgs.writeScriptBin "pre-commit-hooks-install" modular.pre-commit.settings.installationScript)
|
||||
pkgs.buildPackages.nixfmt-rfc-style
|
||||
]
|
||||
# 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
|
||||
)
|
||||
|
||||
@@ -47,25 +47,25 @@
|
||||
}:
|
||||
|
||||
let
|
||||
libs =
|
||||
{
|
||||
inherit
|
||||
nix-util
|
||||
nix-util-c
|
||||
nix-store
|
||||
nix-store-c
|
||||
nix-fetchers
|
||||
nix-fetchers-c
|
||||
nix-expr
|
||||
nix-expr-c
|
||||
nix-flake
|
||||
nix-flake-c
|
||||
nix-main
|
||||
nix-main-c
|
||||
nix-cmd
|
||||
;
|
||||
}
|
||||
// lib.optionalAttrs
|
||||
libs = {
|
||||
inherit
|
||||
nix-util
|
||||
nix-util-c
|
||||
nix-store
|
||||
nix-store-c
|
||||
nix-fetchers
|
||||
nix-fetchers-c
|
||||
nix-expr
|
||||
nix-expr-c
|
||||
nix-flake
|
||||
nix-flake-c
|
||||
nix-main
|
||||
nix-main-c
|
||||
nix-cmd
|
||||
;
|
||||
}
|
||||
//
|
||||
lib.optionalAttrs
|
||||
(!stdenv.hostPlatform.isStatic && stdenv.buildPlatform.canExecute stdenv.hostPlatform)
|
||||
{
|
||||
# Currently fails in static build
|
||||
@@ -127,20 +127,19 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
*/
|
||||
dontFixup = true;
|
||||
|
||||
checkInputs =
|
||||
[
|
||||
# Make sure the unit tests have passed
|
||||
nix-util-tests.tests.run
|
||||
nix-store-tests.tests.run
|
||||
nix-expr-tests.tests.run
|
||||
nix-fetchers-tests.tests.run
|
||||
nix-flake-tests.tests.run
|
||||
checkInputs = [
|
||||
# Make sure the unit tests have passed
|
||||
nix-util-tests.tests.run
|
||||
nix-store-tests.tests.run
|
||||
nix-expr-tests.tests.run
|
||||
nix-fetchers-tests.tests.run
|
||||
nix-flake-tests.tests.run
|
||||
|
||||
# Make sure the functional tests have passed
|
||||
nix-functional-tests
|
||||
]
|
||||
++ lib.optionals
|
||||
(!stdenv.hostPlatform.isStatic && stdenv.buildPlatform.canExecute stdenv.hostPlatform)
|
||||
# Make sure the functional tests have passed
|
||||
nix-functional-tests
|
||||
]
|
||||
++
|
||||
lib.optionals (!stdenv.hostPlatform.isStatic && stdenv.buildPlatform.canExecute stdenv.hostPlatform)
|
||||
[
|
||||
# Perl currently fails in static build
|
||||
# TODO: Split out tests into a separate derivation?
|
||||
|
||||
@@ -49,15 +49,15 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <grp.h>
|
||||
# include <netdb.h>
|
||||
# include <pwd.h>
|
||||
# include <sys/resource.h>
|
||||
# include <sys/select.h>
|
||||
# include <sys/socket.h>
|
||||
# include <sys/utsname.h>
|
||||
# include <sys/wait.h>
|
||||
# include <termios.h>
|
||||
# include <grp.h>
|
||||
# include <netdb.h>
|
||||
# include <pwd.h>
|
||||
# include <sys/resource.h>
|
||||
# include <sys/select.h>
|
||||
# include <sys/socket.h>
|
||||
# include <sys/utsname.h>
|
||||
# include <sys/wait.h>
|
||||
# include <termios.h>
|
||||
#endif
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
# Only execute this file once per shell.
|
||||
if test -z "$HOME" || \
|
||||
test -n "$__ETC_PROFILE_NIX_SOURCED"
|
||||
if test -z "$HOME" || test -n "$__ETC_PROFILE_NIX_SOURCED"
|
||||
exit
|
||||
end
|
||||
|
||||
set --global __ETC_PROFILE_NIX_SOURCED 1
|
||||
set --global --export __ETC_PROFILE_NIX_SOURCED 1
|
||||
|
||||
# Local helpers
|
||||
|
||||
function add_path --argument-names new_path
|
||||
if type -q fish_add_path
|
||||
# fish 3.2.0 or newer
|
||||
fish_add_path --prepend --global $new_path
|
||||
fish_add_path --prepend --global $new_path
|
||||
else
|
||||
# older versions of fish
|
||||
if not contains $new_path $fish_user_paths
|
||||
@@ -24,7 +23,33 @@ end
|
||||
|
||||
# Set up the per-user profile.
|
||||
|
||||
set --local NIX_LINK $HOME/.nix-profile
|
||||
set --local NIX_LINK "$HOME/.nix-profile"
|
||||
set --local NIX_LINK_NEW
|
||||
if test -n "$XDG_STATE_HOME"
|
||||
set NIX_LINK_NEW "$XDG_STATE_HOME/nix/profile"
|
||||
else
|
||||
set NIX_LINK_NEW "$HOME/.local/state/nix/profile"
|
||||
end
|
||||
if test -e "$NIX_LINK_NEW"
|
||||
if test -t 2; and test -e "$NIX_LINK"
|
||||
set --local warning "\033[1;35mwarning:\033[0m "
|
||||
printf "$warning Both %s and legacy %s exist; using the former.\n" "$NIX_LINK_NEW" "$NIX_LINK" 1>&2
|
||||
|
||||
if test (realpath "$NIX_LINK") = (realpath "$NIX_LINK_NEW")
|
||||
printf " Since the profiles match, you can safely delete either of them.\n" 1>&2
|
||||
else
|
||||
# This should be an exceptionally rare occasion: the only way to get it would be to
|
||||
# 1. Update to newer Nix;
|
||||
# 2. Remove .nix-profile;
|
||||
# 3. Set the $NIX_LINK_NEW to something other than the default user profile;
|
||||
# 4. Roll back to older Nix.
|
||||
# If someone did all that, they can probably figure out how to migrate the profile.
|
||||
printf "$warning Profiles do not match. You should manually migrate from %s to %s.\n" "$NIX_LINK" "$NIX_LINK_NEW" 1>&2
|
||||
end
|
||||
end
|
||||
|
||||
set NIX_LINK "$NIX_LINK_NEW"
|
||||
end
|
||||
|
||||
# Set up environment.
|
||||
# This part should be kept in sync with nixpkgs:nixos/modules/programs/environment.nix
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
# Only execute this file once per shell.
|
||||
if test -z "$HOME" || \
|
||||
test -n "$__ETC_PROFILE_NIX_SOURCED"
|
||||
if test -z "$HOME" || test -n "$__ETC_PROFILE_NIX_SOURCED"
|
||||
exit
|
||||
end
|
||||
|
||||
set --global __ETC_PROFILE_NIX_SOURCED 1
|
||||
set --global --export __ETC_PROFILE_NIX_SOURCED 1
|
||||
|
||||
# Local helpers
|
||||
|
||||
function add_path --argument-names new_path
|
||||
if type -q fish_add_path
|
||||
# fish 3.2.0 or newer
|
||||
fish_add_path --prepend --global $new_path
|
||||
fish_add_path --prepend --global $new_path
|
||||
else
|
||||
# older versions of fish
|
||||
if not contains $new_path $fish_user_paths
|
||||
@@ -24,7 +23,38 @@ end
|
||||
|
||||
# Set up the per-user profile.
|
||||
|
||||
set --local NIX_LINK $HOME/.nix-profile
|
||||
set --local NIX_LINK
|
||||
if test -n "$NIX_STATE_HOME"
|
||||
set NIX_LINK "$NIX_STATE_HOME/.nix-profile"
|
||||
else
|
||||
set NIX_LINK "$HOME/.nix-profile"
|
||||
set --local NIX_LINK_NEW
|
||||
if test -n "$XDG_STATE_HOME"
|
||||
set NIX_LINK_NEW "$XDG_STATE_HOME/nix/profile"
|
||||
else
|
||||
set NIX_LINK_NEW "$HOME/.local/state/nix/profile"
|
||||
end
|
||||
if test -e "$NIX_LINK_NEW"
|
||||
if test -t 2; and test -e "$NIX_LINK"
|
||||
set --local warning "\033[1;35mwarning:\033[0m "
|
||||
printf "$warning Both %s and legacy %s exist; using the former.\n" "$NIX_LINK_NEW" "$NIX_LINK" 1>&2
|
||||
|
||||
if test (realpath "$NIX_LINK") = (realpath "$NIX_LINK_NEW")
|
||||
printf " Since the profiles match, you can safely delete either of them.\n" 1>&2
|
||||
else
|
||||
# This should be an exceptionally rare occasion: the only way to get it would be to
|
||||
# 1. Update to newer Nix;
|
||||
# 2. Remove .nix-profile;
|
||||
# 3. Set the $NIX_LINK_NEW to something other than the default user profile;
|
||||
# 4. Roll back to older Nix.
|
||||
# If someone did all that, they can probably figure out how to migrate the profile.
|
||||
printf "$warning Profiles do not match. You should manually migrate from %s to %s.\n" "$NIX_LINK" "$NIX_LINK_NEW" 1>&2
|
||||
end
|
||||
end
|
||||
|
||||
set NIX_LINK "$NIX_LINK_NEW"
|
||||
end
|
||||
end
|
||||
|
||||
# Set up environment.
|
||||
# This part should be kept in sync with nixpkgs:nixos/modules/programs/environment.nix
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <tuple>
|
||||
#include <iomanip>
|
||||
#ifdef __APPLE__
|
||||
#include <sys/time.h>
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "nix/store/machines.hh"
|
||||
@@ -26,8 +26,7 @@
|
||||
using namespace nix;
|
||||
using std::cin;
|
||||
|
||||
static void handleAlarm(int sig) {
|
||||
}
|
||||
static void handleAlarm(int sig) {}
|
||||
|
||||
std::string escapeUri(std::string uri)
|
||||
{
|
||||
@@ -42,13 +41,15 @@ static AutoCloseFD openSlotLock(const Machine & m, uint64_t slot)
|
||||
return openLockFile(fmt("%s/%s-%d", currentLoad, escapeUri(m.storeUri.render()), slot), true);
|
||||
}
|
||||
|
||||
static bool allSupportedLocally(Store & store, const StringSet& requiredFeatures) {
|
||||
static bool allSupportedLocally(Store & store, const StringSet & requiredFeatures)
|
||||
{
|
||||
for (auto & feature : requiredFeatures)
|
||||
if (!store.config.systemFeatures.get().count(feature)) return false;
|
||||
if (!store.config.systemFeatures.get().count(feature))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int main_build_remote(int argc, char * * argv)
|
||||
static int main_build_remote(int argc, char ** argv)
|
||||
{
|
||||
{
|
||||
logger = makeJSONLogger(getStandardError());
|
||||
@@ -85,7 +86,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
that gets cleared on reboot, but it wouldn't work on macOS. */
|
||||
auto currentLoadName = "/current-load";
|
||||
if (auto localStore = store.dynamic_pointer_cast<LocalFSStore>())
|
||||
currentLoad = std::string { localStore->config.stateDir } + currentLoadName;
|
||||
currentLoad = std::string{localStore->config.stateDir} + currentLoadName;
|
||||
else
|
||||
currentLoad = settings.nixStateDir + currentLoadName;
|
||||
|
||||
@@ -107,8 +108,11 @@ static int main_build_remote(int argc, char * * argv)
|
||||
|
||||
try {
|
||||
auto s = readString(source);
|
||||
if (s != "try") return 0;
|
||||
} catch (EndOfFile &) { return 0; }
|
||||
if (s != "try")
|
||||
return 0;
|
||||
} catch (EndOfFile &) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto amWilling = readInt(source);
|
||||
auto neededSystem = readString(source);
|
||||
@@ -117,10 +121,10 @@ static int main_build_remote(int argc, char * * argv)
|
||||
|
||||
/* It would be possible to build locally after some builds clear out,
|
||||
so don't show the warning now: */
|
||||
bool couldBuildLocally = maxBuildJobs > 0
|
||||
&& ( neededSystem == settings.thisSystem
|
||||
|| settings.extraPlatforms.get().count(neededSystem) > 0)
|
||||
&& allSupportedLocally(*store, requiredFeatures);
|
||||
bool couldBuildLocally =
|
||||
maxBuildJobs > 0
|
||||
&& (neededSystem == settings.thisSystem || settings.extraPlatforms.get().count(neededSystem) > 0)
|
||||
&& allSupportedLocally(*store, requiredFeatures);
|
||||
/* It's possible to build this locally right now: */
|
||||
bool canBuildLocally = amWilling && couldBuildLocally;
|
||||
|
||||
@@ -139,11 +143,8 @@ static int main_build_remote(int argc, char * * argv)
|
||||
for (auto & m : machines) {
|
||||
debug("considering building on remote machine '%s'", m.storeUri.render());
|
||||
|
||||
if (m.enabled &&
|
||||
m.systemSupported(neededSystem) &&
|
||||
m.allSupported(requiredFeatures) &&
|
||||
m.mandatoryMet(requiredFeatures))
|
||||
{
|
||||
if (m.enabled && m.systemSupported(neededSystem) && m.allSupported(requiredFeatures)
|
||||
&& m.mandatoryMet(requiredFeatures)) {
|
||||
rightType = true;
|
||||
AutoCloseFD free;
|
||||
uint64_t load = 0;
|
||||
@@ -185,8 +186,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
if (!bestSlotLock) {
|
||||
if (rightType && !canBuildLocally)
|
||||
std::cerr << "# postpone\n";
|
||||
else
|
||||
{
|
||||
else {
|
||||
// build the hint template.
|
||||
std::string errorText =
|
||||
"Failed to find a machine for remote build!\n"
|
||||
@@ -205,16 +205,11 @@ static int main_build_remote(int argc, char * * argv)
|
||||
drvstr = "<unknown>";
|
||||
|
||||
auto error = HintFmt::fromFormatString(errorText);
|
||||
error
|
||||
% drvstr
|
||||
% neededSystem
|
||||
% concatStringsSep<StringSet>(", ", requiredFeatures)
|
||||
error % drvstr % neededSystem % concatStringsSep<StringSet>(", ", requiredFeatures)
|
||||
% machines.size();
|
||||
|
||||
for (auto & m : machines)
|
||||
error
|
||||
% concatStringsSep<StringSet>(", ", m.systemTypes)
|
||||
% m.maxJobs
|
||||
error % concatStringsSep<StringSet>(", ", m.systemTypes) % m.maxJobs
|
||||
% concatStringsSep<StringSet>(", ", m.supportedFeatures)
|
||||
% concatStringsSep<StringSet>(", ", m.mandatoryFeatures);
|
||||
|
||||
@@ -242,9 +237,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
sshStore->connect();
|
||||
} catch (std::exception & e) {
|
||||
auto msg = chomp(drainFD(5, false));
|
||||
printError("cannot build on '%s': %s%s",
|
||||
storeUri, e.what(),
|
||||
msg.empty() ? "" : ": " + msg);
|
||||
printError("cannot build on '%s': %s%s", storeUri, e.what(), msg.empty() ? "" : ": " + msg);
|
||||
bestMachine->enabled = false;
|
||||
continue;
|
||||
}
|
||||
@@ -253,7 +246,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
}
|
||||
}
|
||||
|
||||
connected:
|
||||
connected:
|
||||
close(5);
|
||||
|
||||
assert(sshStore);
|
||||
@@ -265,13 +258,14 @@ connected:
|
||||
|
||||
AutoCloseFD uploadLock;
|
||||
{
|
||||
auto setUpdateLock = [&](auto && fileName){
|
||||
auto setUpdateLock = [&](auto && fileName) {
|
||||
uploadLock = openLockFile(currentLoad + "/" + escapeUri(fileName) + ".upload-lock", true);
|
||||
};
|
||||
try {
|
||||
setUpdateLock(storeUri);
|
||||
} catch (SysError & e) {
|
||||
if (e.errNo != ENAMETOOLONG) throw;
|
||||
if (e.errNo != ENAMETOOLONG)
|
||||
throw;
|
||||
// Try again hashing the store URL so we have a shorter path
|
||||
auto h = hashString(HashAlgorithm::MD5, storeUri);
|
||||
setUpdateLock(h.to_string(HashFormat::Base64, false));
|
||||
@@ -315,7 +309,7 @@ connected:
|
||||
//
|
||||
// This condition mirrors that: that code enforces the "rules" outlined there;
|
||||
// we do the best we can given those "rules".
|
||||
if (trustedOrLegacy || drv.type().isCA()) {
|
||||
if (trustedOrLegacy || drv.type().isCA()) {
|
||||
// Hijack the inputs paths of the derivation to include all
|
||||
// the paths that come from the `inputDrvs` set. We don’t do
|
||||
// that for the derivations whose `inputDrvs` is empty
|
||||
@@ -330,28 +324,26 @@ connected:
|
||||
optResult = sshStore->buildDerivation(*drvPath, (const BasicDerivation &) drv);
|
||||
auto & result = *optResult;
|
||||
if (!result.success())
|
||||
throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg);
|
||||
throw Error(
|
||||
"build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg);
|
||||
} else {
|
||||
copyClosure(*store, *sshStore, StorePathSet {*drvPath}, NoRepair, NoCheckSigs, substitute);
|
||||
auto res = sshStore->buildPathsWithResults({
|
||||
DerivedPath::Built {
|
||||
.drvPath = makeConstantStorePathRef(*drvPath),
|
||||
.outputs = OutputsSpec::All {},
|
||||
}
|
||||
});
|
||||
copyClosure(*store, *sshStore, StorePathSet{*drvPath}, NoRepair, NoCheckSigs, substitute);
|
||||
auto res = sshStore->buildPathsWithResults({DerivedPath::Built{
|
||||
.drvPath = makeConstantStorePathRef(*drvPath),
|
||||
.outputs = OutputsSpec::All{},
|
||||
}});
|
||||
// One path to build should produce exactly one build result
|
||||
assert(res.size() == 1);
|
||||
optResult = std::move(res[0]);
|
||||
}
|
||||
|
||||
|
||||
auto outputHashes = staticOutputHashes(*store, drv);
|
||||
std::set<Realisation> missingRealisations;
|
||||
StorePathSet missingPaths;
|
||||
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations) && !drv.type().hasKnownOutputPaths()) {
|
||||
for (auto & outputName : wantedOutputs) {
|
||||
auto thisOutputHash = outputHashes.at(outputName);
|
||||
auto thisOutputId = DrvOutput{ thisOutputHash, outputName };
|
||||
auto thisOutputId = DrvOutput{thisOutputHash, outputName};
|
||||
if (!store->queryRealisation(thisOutputId)) {
|
||||
debug("missing output %s", outputName);
|
||||
assert(optResult);
|
||||
|
||||
@@ -10,23 +10,13 @@
|
||||
namespace nix {
|
||||
|
||||
// Custom implementation to avoid `ref` ptr equality
|
||||
GENERATE_CMP_EXT(
|
||||
,
|
||||
std::strong_ordering,
|
||||
SingleBuiltPathBuilt,
|
||||
*me->drvPath,
|
||||
me->output);
|
||||
GENERATE_CMP_EXT(, std::strong_ordering, SingleBuiltPathBuilt, *me->drvPath, me->output);
|
||||
|
||||
// Custom implementation to avoid `ref` ptr equality
|
||||
|
||||
// TODO no `GENERATE_CMP_EXT` because no `std::set::operator<=>` on
|
||||
// Darwin, per header.
|
||||
GENERATE_EQUAL(
|
||||
,
|
||||
BuiltPathBuilt ::,
|
||||
BuiltPathBuilt,
|
||||
*me->drvPath,
|
||||
me->outputs);
|
||||
GENERATE_EQUAL(, BuiltPathBuilt ::, BuiltPathBuilt, *me->drvPath, me->outputs);
|
||||
|
||||
StorePath SingleBuiltPath::outPath() const
|
||||
{
|
||||
@@ -34,8 +24,8 @@ StorePath SingleBuiltPath::outPath() const
|
||||
overloaded{
|
||||
[](const SingleBuiltPath::Opaque & p) { return p.path; },
|
||||
[](const SingleBuiltPath::Built & b) { return b.output.second; },
|
||||
}, raw()
|
||||
);
|
||||
},
|
||||
raw());
|
||||
}
|
||||
|
||||
StorePathSet BuiltPath::outPaths() const
|
||||
@@ -49,13 +39,13 @@ StorePathSet BuiltPath::outPaths() const
|
||||
res.insert(path);
|
||||
return res;
|
||||
},
|
||||
}, raw()
|
||||
);
|
||||
},
|
||||
raw());
|
||||
}
|
||||
|
||||
SingleDerivedPath::Built SingleBuiltPath::Built::discardOutputPath() const
|
||||
{
|
||||
return SingleDerivedPath::Built {
|
||||
return SingleDerivedPath::Built{
|
||||
.drvPath = make_ref<SingleDerivedPath>(drvPath->discardOutputPath()),
|
||||
.output = output.first,
|
||||
};
|
||||
@@ -65,14 +55,10 @@ SingleDerivedPath SingleBuiltPath::discardOutputPath() const
|
||||
{
|
||||
return std::visit(
|
||||
overloaded{
|
||||
[](const SingleBuiltPath::Opaque & p) -> SingleDerivedPath {
|
||||
return p;
|
||||
},
|
||||
[](const SingleBuiltPath::Built & b) -> SingleDerivedPath {
|
||||
return b.discardOutputPath();
|
||||
},
|
||||
}, raw()
|
||||
);
|
||||
[](const SingleBuiltPath::Opaque & p) -> SingleDerivedPath { return p; },
|
||||
[](const SingleBuiltPath::Built & b) -> SingleDerivedPath { return b.discardOutputPath(); },
|
||||
},
|
||||
raw());
|
||||
}
|
||||
|
||||
nlohmann::json BuiltPath::Built::toJSON(const StoreDirConfig & store) const
|
||||
@@ -97,16 +83,12 @@ nlohmann::json SingleBuiltPath::Built::toJSON(const StoreDirConfig & store) cons
|
||||
|
||||
nlohmann::json SingleBuiltPath::toJSON(const StoreDirConfig & store) const
|
||||
{
|
||||
return std::visit([&](const auto & buildable) {
|
||||
return buildable.toJSON(store);
|
||||
}, raw());
|
||||
return std::visit([&](const auto & buildable) { return buildable.toJSON(store); }, raw());
|
||||
}
|
||||
|
||||
nlohmann::json BuiltPath::toJSON(const StoreDirConfig & store) const
|
||||
{
|
||||
return std::visit([&](const auto & buildable) {
|
||||
return buildable.toJSON(store);
|
||||
}, raw());
|
||||
return std::visit([&](const auto & buildable) { return buildable.toJSON(store); }, raw());
|
||||
}
|
||||
|
||||
RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const
|
||||
@@ -116,20 +98,18 @@ RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const
|
||||
overloaded{
|
||||
[&](const BuiltPath::Opaque & p) { res.insert(p.path); },
|
||||
[&](const BuiltPath::Built & p) {
|
||||
auto drvHashes =
|
||||
staticOutputHashes(store, store.readDerivation(p.drvPath->outPath()));
|
||||
for (auto& [outputName, outputPath] : p.outputs) {
|
||||
if (experimentalFeatureSettings.isEnabled(
|
||||
Xp::CaDerivations)) {
|
||||
auto drvHashes = staticOutputHashes(store, store.readDerivation(p.drvPath->outPath()));
|
||||
for (auto & [outputName, outputPath] : p.outputs) {
|
||||
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) {
|
||||
auto drvOutput = get(drvHashes, outputName);
|
||||
if (!drvOutput)
|
||||
throw Error(
|
||||
"the derivation '%s' has unrealised output '%s' (derived-path.cc/toRealisedPaths)",
|
||||
store.printStorePath(p.drvPath->outPath()), outputName);
|
||||
auto thisRealisation = store.queryRealisation(
|
||||
DrvOutput{*drvOutput, outputName});
|
||||
assert(thisRealisation); // We’ve built it, so we must
|
||||
// have the realisation
|
||||
store.printStorePath(p.drvPath->outPath()),
|
||||
outputName);
|
||||
auto thisRealisation = store.queryRealisation(DrvOutput{*drvOutput, outputName});
|
||||
assert(thisRealisation); // We’ve built it, so we must
|
||||
// have the realisation
|
||||
res.insert(*thisRealisation);
|
||||
} else {
|
||||
res.insert(outputPath);
|
||||
@@ -141,4 +121,4 @@ RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -8,4 +8,4 @@ void InstallableValueCommand::run(ref<Store> store, ref<Installable> installable
|
||||
run(store, installableValue);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -402,4 +402,4 @@ void MixOutLinkBase::createOutLinksMaybe(const std::vector<BuiltPathWithResult>
|
||||
createOutLinks(outLink, toBuiltPaths(buildables), *store2);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -18,12 +18,11 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
fetchers::Settings fetchSettings;
|
||||
|
||||
static GlobalConfig::Register rFetchSettings(&fetchSettings);
|
||||
|
||||
EvalSettings evalSettings {
|
||||
EvalSettings evalSettings{
|
||||
settings.readOnlyMode,
|
||||
{
|
||||
{
|
||||
@@ -31,10 +30,11 @@ EvalSettings evalSettings {
|
||||
[](EvalState & state, std::string_view rest) {
|
||||
experimentalFeatureSettings.require(Xp::Flakes);
|
||||
// FIXME `parseFlakeRef` should take a `std::string_view`.
|
||||
auto flakeRef = parseFlakeRef(fetchSettings, std::string { rest }, {}, true, false);
|
||||
auto flakeRef = parseFlakeRef(fetchSettings, std::string{rest}, {}, true, false);
|
||||
debug("fetching flake search path element '%s''", rest);
|
||||
auto [accessor, lockedRef] = flakeRef.resolve(state.store).lazyFetch(state.store);
|
||||
auto storePath = nix::fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName());
|
||||
auto storePath =
|
||||
nix::fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName());
|
||||
state.allowPath(storePath);
|
||||
return state.storePath(storePath);
|
||||
},
|
||||
@@ -44,17 +44,14 @@ EvalSettings evalSettings {
|
||||
|
||||
static GlobalConfig::Register rEvalSettings(&evalSettings);
|
||||
|
||||
|
||||
flake::Settings flakeSettings;
|
||||
|
||||
static GlobalConfig::Register rFlakeSettings(&flakeSettings);
|
||||
|
||||
|
||||
CompatibilitySettings compatibilitySettings {};
|
||||
CompatibilitySettings compatibilitySettings{};
|
||||
|
||||
static GlobalConfig::Register rCompatibilitySettings(&compatibilitySettings);
|
||||
|
||||
|
||||
MixEvalArgs::MixEvalArgs()
|
||||
{
|
||||
addFlag({
|
||||
@@ -62,7 +59,9 @@ MixEvalArgs::MixEvalArgs()
|
||||
.description = "Pass the value *expr* as the argument *name* to Nix functions.",
|
||||
.category = category,
|
||||
.labels = {"name", "expr"},
|
||||
.handler = {[&](std::string name, std::string expr) { autoArgs.insert_or_assign(name, AutoArg{AutoArgExpr{expr}}); }},
|
||||
.handler = {[&](std::string name, std::string expr) {
|
||||
autoArgs.insert_or_assign(name, AutoArg{AutoArgExpr{expr}});
|
||||
}},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
@@ -70,7 +69,9 @@ MixEvalArgs::MixEvalArgs()
|
||||
.description = "Pass the string *string* as the argument *name* to Nix functions.",
|
||||
.category = category,
|
||||
.labels = {"name", "string"},
|
||||
.handler = {[&](std::string name, std::string s) { autoArgs.insert_or_assign(name, AutoArg{AutoArgString{s}}); }},
|
||||
.handler = {[&](std::string name, std::string s) {
|
||||
autoArgs.insert_or_assign(name, AutoArg{AutoArgString{s}});
|
||||
}},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
@@ -78,7 +79,9 @@ MixEvalArgs::MixEvalArgs()
|
||||
.description = "Pass the contents of file *path* as the argument *name* to Nix functions.",
|
||||
.category = category,
|
||||
.labels = {"name", "path"},
|
||||
.handler = {[&](std::string name, std::string path) { autoArgs.insert_or_assign(name, AutoArg{AutoArgFile{path}}); }},
|
||||
.handler = {[&](std::string name, std::string path) {
|
||||
autoArgs.insert_or_assign(name, AutoArg{AutoArgFile{path}});
|
||||
}},
|
||||
.completer = completePath,
|
||||
});
|
||||
|
||||
@@ -102,18 +105,14 @@ MixEvalArgs::MixEvalArgs()
|
||||
)",
|
||||
.category = category,
|
||||
.labels = {"path"},
|
||||
.handler = {[&](std::string s) {
|
||||
lookupPath.elements.emplace_back(LookupPath::Elem::parse(s));
|
||||
}},
|
||||
.handler = {[&](std::string s) { lookupPath.elements.emplace_back(LookupPath::Elem::parse(s)); }},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "impure",
|
||||
.description = "Allow access to mutable paths and repositories.",
|
||||
.category = category,
|
||||
.handler = {[&]() {
|
||||
evalSettings.pureEval = false;
|
||||
}},
|
||||
.handler = {[&]() { evalSettings.pureEval = false; }},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
@@ -125,7 +124,8 @@ MixEvalArgs::MixEvalArgs()
|
||||
auto from = parseFlakeRef(fetchSettings, _from, std::filesystem::current_path().string());
|
||||
auto to = parseFlakeRef(fetchSettings, _to, std::filesystem::current_path().string());
|
||||
fetchers::Attrs extraAttrs;
|
||||
if (to.subdir != "") extraAttrs["dir"] = to.subdir;
|
||||
if (to.subdir != "")
|
||||
extraAttrs["dir"] = to.subdir;
|
||||
fetchers::overrideRegistry(from.input, to.input, extraAttrs);
|
||||
}},
|
||||
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
||||
@@ -136,7 +136,7 @@ MixEvalArgs::MixEvalArgs()
|
||||
addFlag({
|
||||
.longName = "eval-store",
|
||||
.description =
|
||||
R"(
|
||||
R"(
|
||||
The [URL of the Nix store](@docroot@/store/types/index.md#store-url-format)
|
||||
to use for evaluation, i.e. to store derivations (`.drv` files) and inputs referenced by them.
|
||||
)",
|
||||
@@ -151,20 +151,21 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
|
||||
auto res = state.buildBindings(autoArgs.size());
|
||||
for (auto & [name, arg] : autoArgs) {
|
||||
auto v = state.allocValue();
|
||||
std::visit(overloaded {
|
||||
[&](const AutoArgExpr & arg) {
|
||||
state.mkThunk_(*v, state.parseExprFromString(arg.expr, compatibilitySettings.nixShellShebangArgumentsRelativeToScript ? state.rootPath(absPath(getCommandBaseDir())) : state.rootPath(".")));
|
||||
},
|
||||
[&](const AutoArgString & arg) {
|
||||
v->mkString(arg.s);
|
||||
},
|
||||
[&](const AutoArgFile & arg) {
|
||||
v->mkString(readFile(arg.path.string()));
|
||||
},
|
||||
[&](const AutoArgStdin & arg) {
|
||||
v->mkString(readFile(STDIN_FILENO));
|
||||
}
|
||||
}, arg);
|
||||
std::visit(
|
||||
overloaded{
|
||||
[&](const AutoArgExpr & arg) {
|
||||
state.mkThunk_(
|
||||
*v,
|
||||
state.parseExprFromString(
|
||||
arg.expr,
|
||||
compatibilitySettings.nixShellShebangArgumentsRelativeToScript
|
||||
? state.rootPath(absPath(getCommandBaseDir()))
|
||||
: state.rootPath(".")));
|
||||
},
|
||||
[&](const AutoArgString & arg) { v->mkString(arg.s); },
|
||||
[&](const AutoArgFile & arg) { v->mkString(readFile(arg.path.string())); },
|
||||
[&](const AutoArgStdin & arg) { v->mkString(readFile(STDIN_FILENO)); }},
|
||||
arg);
|
||||
res.insert(state.symbols.create(name), v);
|
||||
}
|
||||
return res.finish();
|
||||
@@ -173,10 +174,7 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
|
||||
SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * baseDir)
|
||||
{
|
||||
if (EvalSettings::isPseudoUrl(s)) {
|
||||
auto accessor = fetchers::downloadTarball(
|
||||
state.store,
|
||||
state.fetchSettings,
|
||||
EvalSettings::resolvePseudoUrl(s));
|
||||
auto accessor = fetchers::downloadTarball(state.store, state.fetchSettings, EvalSettings::resolvePseudoUrl(s));
|
||||
auto storePath = fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy);
|
||||
return state.storePath(storePath);
|
||||
}
|
||||
@@ -185,7 +183,8 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * bas
|
||||
experimentalFeatureSettings.require(Xp::Flakes);
|
||||
auto flakeRef = parseFlakeRef(fetchSettings, std::string(s.substr(6)), {}, true, false);
|
||||
auto [accessor, lockedRef] = flakeRef.resolve(state.store).lazyFetch(state.store);
|
||||
auto storePath = nix::fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName());
|
||||
auto storePath =
|
||||
nix::fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName());
|
||||
state.allowPath(storePath);
|
||||
return state.storePath(storePath);
|
||||
}
|
||||
@@ -199,4 +198,4 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * bas
|
||||
return state.rootPath(baseDir ? absPath(s, *baseDir) : absPath(s));
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -11,14 +11,12 @@ Strings editorFor(const SourcePath & file, uint32_t line)
|
||||
throw Error("cannot open '%s' in an editor because it has no physical path", file);
|
||||
auto editor = getEnv("EDITOR").value_or("cat");
|
||||
auto args = tokenizeString<Strings>(editor);
|
||||
if (line > 0 && (
|
||||
editor.find("emacs") != std::string::npos ||
|
||||
editor.find("nano") != std::string::npos ||
|
||||
editor.find("vim") != std::string::npos ||
|
||||
editor.find("kak") != std::string::npos))
|
||||
if (line > 0
|
||||
&& (editor.find("emacs") != std::string::npos || editor.find("nano") != std::string::npos
|
||||
|| editor.find("vim") != std::string::npos || editor.find("kak") != std::string::npos))
|
||||
args.push_back(fmt("+%d", line));
|
||||
args.push_back(path->string());
|
||||
return args;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -8,7 +8,8 @@ namespace nix {
|
||||
|
||||
struct SingleBuiltPath;
|
||||
|
||||
struct SingleBuiltPathBuilt {
|
||||
struct SingleBuiltPathBuilt
|
||||
{
|
||||
ref<SingleBuiltPath> drvPath;
|
||||
std::pair<std::string, StorePath> output;
|
||||
|
||||
@@ -18,26 +19,25 @@ struct SingleBuiltPathBuilt {
|
||||
static SingleBuiltPathBuilt parse(const StoreDirConfig & store, std::string_view, std::string_view);
|
||||
nlohmann::json toJSON(const StoreDirConfig & store) const;
|
||||
|
||||
bool operator ==(const SingleBuiltPathBuilt &) const noexcept;
|
||||
std::strong_ordering operator <=>(const SingleBuiltPathBuilt &) const noexcept;
|
||||
bool operator==(const SingleBuiltPathBuilt &) const noexcept;
|
||||
std::strong_ordering operator<=>(const SingleBuiltPathBuilt &) const noexcept;
|
||||
};
|
||||
|
||||
using _SingleBuiltPathRaw = std::variant<
|
||||
DerivedPathOpaque,
|
||||
SingleBuiltPathBuilt
|
||||
>;
|
||||
using _SingleBuiltPathRaw = std::variant<DerivedPathOpaque, SingleBuiltPathBuilt>;
|
||||
|
||||
struct SingleBuiltPath : _SingleBuiltPathRaw {
|
||||
struct SingleBuiltPath : _SingleBuiltPathRaw
|
||||
{
|
||||
using Raw = _SingleBuiltPathRaw;
|
||||
using Raw::Raw;
|
||||
|
||||
using Opaque = DerivedPathOpaque;
|
||||
using Built = SingleBuiltPathBuilt;
|
||||
|
||||
bool operator == (const SingleBuiltPath &) const = default;
|
||||
auto operator <=> (const SingleBuiltPath &) const = default;
|
||||
bool operator==(const SingleBuiltPath &) const = default;
|
||||
auto operator<=>(const SingleBuiltPath &) const = default;
|
||||
|
||||
inline const Raw & raw() const {
|
||||
inline const Raw & raw() const
|
||||
{
|
||||
return static_cast<const Raw &>(*this);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ struct SingleBuiltPath : _SingleBuiltPathRaw {
|
||||
|
||||
static inline ref<SingleBuiltPath> staticDrv(StorePath drvPath)
|
||||
{
|
||||
return make_ref<SingleBuiltPath>(SingleBuiltPath::Opaque { drvPath });
|
||||
return make_ref<SingleBuiltPath>(SingleBuiltPath::Opaque{drvPath});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,40 +59,41 @@ static inline ref<SingleBuiltPath> staticDrv(StorePath drvPath)
|
||||
*
|
||||
* See 'BuiltPath' for more an explanation.
|
||||
*/
|
||||
struct BuiltPathBuilt {
|
||||
struct BuiltPathBuilt
|
||||
{
|
||||
ref<SingleBuiltPath> drvPath;
|
||||
std::map<std::string, StorePath> outputs;
|
||||
|
||||
bool operator == (const BuiltPathBuilt &) const noexcept;
|
||||
bool operator==(const BuiltPathBuilt &) const noexcept;
|
||||
// TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet.
|
||||
//std::strong_ordering operator <=> (const BuiltPathBuilt &) const noexcept;
|
||||
// std::strong_ordering operator <=> (const BuiltPathBuilt &) const noexcept;
|
||||
|
||||
std::string to_string(const StoreDirConfig & store) const;
|
||||
static BuiltPathBuilt parse(const StoreDirConfig & store, std::string_view, std::string_view);
|
||||
nlohmann::json toJSON(const StoreDirConfig & store) const;
|
||||
};
|
||||
|
||||
using _BuiltPathRaw = std::variant<
|
||||
DerivedPath::Opaque,
|
||||
BuiltPathBuilt
|
||||
>;
|
||||
using _BuiltPathRaw = std::variant<DerivedPath::Opaque, BuiltPathBuilt>;
|
||||
|
||||
/**
|
||||
* A built path. Similar to a DerivedPath, but enriched with the corresponding
|
||||
* output path(s).
|
||||
*/
|
||||
struct BuiltPath : _BuiltPathRaw {
|
||||
struct BuiltPath : _BuiltPathRaw
|
||||
{
|
||||
using Raw = _BuiltPathRaw;
|
||||
using Raw::Raw;
|
||||
|
||||
using Opaque = DerivedPathOpaque;
|
||||
using Built = BuiltPathBuilt;
|
||||
|
||||
bool operator == (const BuiltPath &) const = default;
|
||||
// TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet.
|
||||
//auto operator <=> (const BuiltPath &) const = default;
|
||||
bool operator==(const BuiltPath &) const = default;
|
||||
|
||||
inline const Raw & raw() const {
|
||||
// TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet.
|
||||
// auto operator <=> (const BuiltPath &) const = default;
|
||||
|
||||
inline const Raw & raw() const
|
||||
{
|
||||
return static_cast<const Raw &>(*this);
|
||||
}
|
||||
|
||||
@@ -104,4 +105,4 @@ struct BuiltPath : _BuiltPathRaw {
|
||||
|
||||
typedef std::vector<BuiltPath> BuiltPaths;
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -20,4 +20,4 @@ struct InstallableValueCommand : InstallableCommand
|
||||
void run(ref<Store> store, ref<Installable> installable) override;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -12,7 +12,9 @@ namespace nix {
|
||||
|
||||
class Store;
|
||||
|
||||
namespace fetchers { struct Settings; }
|
||||
namespace fetchers {
|
||||
struct Settings;
|
||||
}
|
||||
|
||||
class EvalState;
|
||||
struct EvalSettings;
|
||||
@@ -20,7 +22,9 @@ struct CompatibilitySettings;
|
||||
class Bindings;
|
||||
struct SourcePath;
|
||||
|
||||
namespace flake { struct Settings; }
|
||||
namespace flake {
|
||||
struct Settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Get rid of global setttings variables
|
||||
@@ -55,10 +59,23 @@ struct MixEvalArgs : virtual Args, virtual MixRepair
|
||||
std::optional<std::string> evalStoreUrl;
|
||||
|
||||
private:
|
||||
struct AutoArgExpr { std::string expr; };
|
||||
struct AutoArgString { std::string s; };
|
||||
struct AutoArgFile { std::filesystem::path path; };
|
||||
struct AutoArgStdin { };
|
||||
struct AutoArgExpr
|
||||
{
|
||||
std::string expr;
|
||||
};
|
||||
|
||||
struct AutoArgString
|
||||
{
|
||||
std::string s;
|
||||
};
|
||||
|
||||
struct AutoArgFile
|
||||
{
|
||||
std::filesystem::path path;
|
||||
};
|
||||
|
||||
struct AutoArgStdin
|
||||
{};
|
||||
|
||||
using AutoArg = std::variant<AutoArgExpr, AutoArgString, AutoArgFile, AutoArgStdin>;
|
||||
|
||||
@@ -70,4 +87,4 @@ private:
|
||||
*/
|
||||
SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * baseDir = nullptr);
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -33,4 +33,4 @@ struct CompatibilitySettings : public Config
|
||||
)"};
|
||||
};
|
||||
|
||||
};
|
||||
}; // namespace nix
|
||||
|
||||
@@ -12,4 +12,4 @@ namespace nix {
|
||||
*/
|
||||
Strings editorFor(const SourcePath & file, uint32_t line);
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -39,7 +39,10 @@ class InstallableAttrPath : public InstallableValue
|
||||
const std::string & attrPath,
|
||||
ExtendedOutputsSpec extendedOutputsSpec);
|
||||
|
||||
std::string what() const override { return attrPath; };
|
||||
std::string what() const override
|
||||
{
|
||||
return attrPath;
|
||||
};
|
||||
|
||||
std::pair<Value *, PosIdx> toValue(EvalState & state) override;
|
||||
|
||||
@@ -55,4 +58,4 @@ public:
|
||||
ExtendedOutputsSpec extendedOutputsSpec);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -11,8 +11,10 @@ struct InstallableDerivedPath : Installable
|
||||
DerivedPath derivedPath;
|
||||
|
||||
InstallableDerivedPath(ref<Store> store, DerivedPath && derivedPath)
|
||||
: store(store), derivedPath(std::move(derivedPath))
|
||||
{ }
|
||||
: store(store)
|
||||
, derivedPath(std::move(derivedPath))
|
||||
{
|
||||
}
|
||||
|
||||
std::string what() const override;
|
||||
|
||||
@@ -20,10 +22,8 @@ struct InstallableDerivedPath : Installable
|
||||
|
||||
std::optional<StorePath> getStorePath() override;
|
||||
|
||||
static InstallableDerivedPath parse(
|
||||
ref<Store> store,
|
||||
std::string_view prefix,
|
||||
ExtendedOutputsSpec extendedOutputsSpec);
|
||||
static InstallableDerivedPath
|
||||
parse(ref<Store> store, std::string_view prefix, ExtendedOutputsSpec extendedOutputsSpec);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -18,7 +18,8 @@ struct ExtraPathInfoFlake : ExtraPathInfoValue
|
||||
/**
|
||||
* Extra struct to get around C++ designated initializer limitations
|
||||
*/
|
||||
struct Flake {
|
||||
struct Flake
|
||||
{
|
||||
FlakeRef originalRef;
|
||||
FlakeRef lockedRef;
|
||||
};
|
||||
@@ -26,8 +27,10 @@ struct ExtraPathInfoFlake : ExtraPathInfoValue
|
||||
Flake flake;
|
||||
|
||||
ExtraPathInfoFlake(Value && v, Flake && f)
|
||||
: ExtraPathInfoValue(std::move(v)), flake(std::move(f))
|
||||
{ }
|
||||
: ExtraPathInfoValue(std::move(v))
|
||||
, flake(std::move(f))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct InstallableFlake : InstallableValue
|
||||
@@ -49,7 +52,10 @@ struct InstallableFlake : InstallableValue
|
||||
Strings prefixes,
|
||||
const flake::LockFlags & lockFlags);
|
||||
|
||||
std::string what() const override { return flakeRef.to_string() + "#" + *attrPaths.begin(); }
|
||||
std::string what() const override
|
||||
{
|
||||
return flakeRef.to_string() + "#" + *attrPaths.begin();
|
||||
}
|
||||
|
||||
std::vector<std::string> getActualAttrPaths();
|
||||
|
||||
@@ -61,8 +67,7 @@ struct InstallableFlake : InstallableValue
|
||||
* Get a cursor to every attrpath in getActualAttrPaths() that
|
||||
* exists. However if none exists, throw an exception.
|
||||
*/
|
||||
std::vector<ref<eval_cache::AttrCursor>>
|
||||
getCursors(EvalState & state) override;
|
||||
std::vector<ref<eval_cache::AttrCursor>> getCursors(EvalState & state) override;
|
||||
|
||||
std::shared_ptr<flake::LockedFlake> getLockedFlake() const;
|
||||
|
||||
@@ -79,11 +84,9 @@ struct InstallableFlake : InstallableValue
|
||||
*/
|
||||
static inline FlakeRef defaultNixpkgsFlakeRef()
|
||||
{
|
||||
return FlakeRef::fromAttrs(fetchSettings, {{"type","indirect"}, {"id", "nixpkgs"}});
|
||||
return FlakeRef::fromAttrs(fetchSettings, {{"type", "indirect"}, {"id", "nixpkgs"}});
|
||||
}
|
||||
|
||||
ref<eval_cache::EvalCache> openEvalCache(
|
||||
EvalState & state,
|
||||
std::shared_ptr<flake::LockedFlake> lockedFlake);
|
||||
ref<eval_cache::EvalCache> openEvalCache(EvalState & state, std::shared_ptr<flake::LockedFlake> lockedFlake);
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -9,7 +9,10 @@ namespace nix {
|
||||
struct PackageInfo;
|
||||
struct SourceExprCommand;
|
||||
|
||||
namespace eval_cache { class EvalCache; class AttrCursor; }
|
||||
namespace eval_cache {
|
||||
class EvalCache;
|
||||
class AttrCursor;
|
||||
} // namespace eval_cache
|
||||
|
||||
struct App
|
||||
{
|
||||
@@ -37,7 +40,8 @@ struct ExtraPathInfoValue : ExtraPathInfo
|
||||
/**
|
||||
* Extra struct to get around C++ designated initializer limitations
|
||||
*/
|
||||
struct Value {
|
||||
struct Value
|
||||
{
|
||||
/**
|
||||
* An optional priority for use with "build envs". See Package
|
||||
*/
|
||||
@@ -61,7 +65,8 @@ struct ExtraPathInfoValue : ExtraPathInfo
|
||||
|
||||
ExtraPathInfoValue(Value && v)
|
||||
: value(std::move(v))
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ExtraPathInfoValue() = default;
|
||||
};
|
||||
@@ -74,9 +79,12 @@ struct InstallableValue : Installable
|
||||
{
|
||||
ref<EvalState> state;
|
||||
|
||||
InstallableValue(ref<EvalState> state) : state(state) {}
|
||||
InstallableValue(ref<EvalState> state)
|
||||
: state(state)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~InstallableValue() { }
|
||||
virtual ~InstallableValue() {}
|
||||
|
||||
virtual std::pair<Value *, PosIdx> toValue(EvalState & state) = 0;
|
||||
|
||||
@@ -85,15 +93,13 @@ struct InstallableValue : Installable
|
||||
* However if none exists, throw exception instead of returning
|
||||
* empty vector.
|
||||
*/
|
||||
virtual std::vector<ref<eval_cache::AttrCursor>>
|
||||
getCursors(EvalState & state);
|
||||
virtual std::vector<ref<eval_cache::AttrCursor>> getCursors(EvalState & state);
|
||||
|
||||
/**
|
||||
* Get the first and most preferred cursor this Installable could
|
||||
* refer to, or throw an exception if none exists.
|
||||
*/
|
||||
virtual ref<eval_cache::AttrCursor>
|
||||
getCursor(EvalState & state);
|
||||
virtual ref<eval_cache::AttrCursor> getCursor(EvalState & state);
|
||||
|
||||
UnresolvedApp toApp(EvalState & state);
|
||||
|
||||
@@ -116,7 +122,8 @@ protected:
|
||||
* @result A derived path (with empty info, for now) if the value
|
||||
* matched the above criteria.
|
||||
*/
|
||||
std::optional<DerivedPathWithInfo> trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx);
|
||||
std::optional<DerivedPathWithInfo>
|
||||
trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -112,7 +112,7 @@ typedef std::vector<ref<Installable>> Installables;
|
||||
*/
|
||||
struct Installable
|
||||
{
|
||||
virtual ~Installable() { }
|
||||
virtual ~Installable() {}
|
||||
|
||||
/**
|
||||
* What Installable is this?
|
||||
@@ -168,37 +168,19 @@ struct Installable
|
||||
BuildMode bMode = bmNormal);
|
||||
|
||||
static std::set<StorePath> toStorePathSet(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
const Installables & installables);
|
||||
ref<Store> evalStore, ref<Store> store, Realise mode, OperateOn operateOn, const Installables & installables);
|
||||
|
||||
static std::vector<StorePath> toStorePaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
const Installables & installables);
|
||||
ref<Store> evalStore, ref<Store> store, Realise mode, OperateOn operateOn, const Installables & installables);
|
||||
|
||||
static StorePath toStorePath(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
ref<Installable> installable);
|
||||
ref<Store> evalStore, ref<Store> store, Realise mode, OperateOn operateOn, ref<Installable> installable);
|
||||
|
||||
static std::set<StorePath> toDerivations(
|
||||
ref<Store> store,
|
||||
const Installables & installables,
|
||||
bool useDeriver = false);
|
||||
static std::set<StorePath>
|
||||
toDerivations(ref<Store> store, const Installables & installables, bool useDeriver = false);
|
||||
|
||||
static BuiltPaths toBuiltPaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
const Installables & installables);
|
||||
ref<Store> evalStore, ref<Store> store, Realise mode, OperateOn operateOn, const Installables & installables);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
typedef std::function<void(int, char * *)> MainFunction;
|
||||
typedef std::function<void(int, char **)> MainFunction;
|
||||
|
||||
struct RegisterLegacyCommand
|
||||
{
|
||||
typedef std::map<std::string, MainFunction> Commands;
|
||||
|
||||
static Commands & commands() {
|
||||
static Commands & commands()
|
||||
{
|
||||
static Commands commands;
|
||||
return commands;
|
||||
}
|
||||
@@ -24,4 +25,4 @@ struct RegisterLegacyCommand
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -14,4 +14,4 @@ namespace nix {
|
||||
*/
|
||||
std::string renderMarkdownToTerminal(std::string_view markdown);
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -4,18 +4,22 @@
|
||||
namespace nix::flag {
|
||||
|
||||
Args::Flag hashAlgo(std::string && longName, HashAlgorithm * ha);
|
||||
|
||||
static inline Args::Flag hashAlgo(HashAlgorithm * ha)
|
||||
{
|
||||
return hashAlgo("hash-algo", ha);
|
||||
}
|
||||
|
||||
Args::Flag hashAlgoOpt(std::string && longName, std::optional<HashAlgorithm> * oha);
|
||||
Args::Flag hashFormatWithDefault(std::string && longName, HashFormat * hf);
|
||||
Args::Flag hashFormatOpt(std::string && longName, std::optional<HashFormat> * ohf);
|
||||
|
||||
static inline Args::Flag hashAlgoOpt(std::optional<HashAlgorithm> * oha)
|
||||
{
|
||||
return hashAlgoOpt("hash-algo", oha);
|
||||
}
|
||||
|
||||
Args::Flag fileIngestionMethod(FileIngestionMethod * method);
|
||||
Args::Flag contentAddressMethod(ContentAddressMethod * method);
|
||||
|
||||
}
|
||||
} // namespace nix::flag
|
||||
|
||||
@@ -19,4 +19,4 @@ extern const StringSet networkProxyVariables;
|
||||
*/
|
||||
bool haveNetworkProxyConnection();
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -11,10 +11,11 @@ namespace nix {
|
||||
namespace detail {
|
||||
/** Provides the completion hooks for the repl, without exposing its complete
|
||||
* internals. */
|
||||
struct ReplCompleterMixin {
|
||||
struct ReplCompleterMixin
|
||||
{
|
||||
virtual StringSet completePrefix(const std::string & prefix) = 0;
|
||||
};
|
||||
};
|
||||
}; // namespace detail
|
||||
|
||||
enum class ReplPromptType {
|
||||
ReplPrompt,
|
||||
@@ -29,7 +30,7 @@ public:
|
||||
virtual Guard init(detail::ReplCompleterMixin * repl) = 0;
|
||||
/** Returns a boolean of whether the interacter got EOF */
|
||||
virtual bool getLine(std::string & input, ReplPromptType promptType) = 0;
|
||||
virtual ~ReplInteracter(){};
|
||||
virtual ~ReplInteracter() {};
|
||||
};
|
||||
|
||||
class ReadlineLikeInteracter : public virtual ReplInteracter
|
||||
@@ -40,9 +41,10 @@ public:
|
||||
: historyFile(historyFile)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Guard init(detail::ReplCompleterMixin * repl) override;
|
||||
virtual bool getLine(std::string & input, ReplPromptType promptType) override;
|
||||
virtual ~ReadlineLikeInteracter() override;
|
||||
};
|
||||
|
||||
};
|
||||
}; // namespace nix
|
||||
|
||||
@@ -12,12 +12,12 @@ struct AbstractNixRepl
|
||||
|
||||
AbstractNixRepl(ref<EvalState> state)
|
||||
: state(state)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~AbstractNixRepl()
|
||||
{ }
|
||||
virtual ~AbstractNixRepl() {}
|
||||
|
||||
typedef std::vector<std::pair<Value*,std::string>> AnnotatedValues;
|
||||
typedef std::vector<std::pair<Value *, std::string>> AnnotatedValues;
|
||||
|
||||
using RunNix = void(Path program, const Strings & args, const std::optional<std::string> & input);
|
||||
|
||||
@@ -33,13 +33,11 @@ struct AbstractNixRepl
|
||||
std::function<AnnotatedValues()> getValues,
|
||||
RunNix * runNix = nullptr);
|
||||
|
||||
static ReplExitStatus runSimple(
|
||||
ref<EvalState> evalState,
|
||||
const ValMap & extraEnv);
|
||||
static ReplExitStatus runSimple(ref<EvalState> evalState, const ValMap & extraEnv);
|
||||
|
||||
virtual void initEnv() = 0;
|
||||
|
||||
virtual ReplExitStatus mainLoop() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -35,7 +35,8 @@ InstallableAttrPath::InstallableAttrPath(
|
||||
, v(allocRootValue(v))
|
||||
, attrPath(attrPath)
|
||||
, extendedOutputsSpec(std::move(extendedOutputsSpec))
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
std::pair<Value *, PosIdx> InstallableAttrPath::toValue(EvalState & state)
|
||||
{
|
||||
@@ -48,12 +49,9 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths()
|
||||
{
|
||||
auto [v, pos] = toValue(*state);
|
||||
|
||||
if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths(
|
||||
*v,
|
||||
pos,
|
||||
fmt("while evaluating the attribute '%s'", attrPath)))
|
||||
{
|
||||
return { *derivedPathWithInfo };
|
||||
if (std::optional derivedPathWithInfo =
|
||||
trySinglePathToDerivedPaths(*v, pos, fmt("while evaluating the attribute '%s'", attrPath))) {
|
||||
return {*derivedPathWithInfo};
|
||||
}
|
||||
|
||||
Bindings & autoArgs = *cmd.getAutoArgs(*state);
|
||||
@@ -70,19 +68,19 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths()
|
||||
if (!drvPath)
|
||||
throw Error("'%s' is not a derivation", what());
|
||||
|
||||
auto newOutputs = std::visit(overloaded {
|
||||
[&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec {
|
||||
StringSet outputsToInstall;
|
||||
for (auto & output : packageInfo.queryOutputs(false, true))
|
||||
outputsToInstall.insert(output.first);
|
||||
if (outputsToInstall.empty())
|
||||
outputsToInstall.insert("out");
|
||||
return OutputsSpec::Names { std::move(outputsToInstall) };
|
||||
auto newOutputs = std::visit(
|
||||
overloaded{
|
||||
[&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec {
|
||||
StringSet outputsToInstall;
|
||||
for (auto & output : packageInfo.queryOutputs(false, true))
|
||||
outputsToInstall.insert(output.first);
|
||||
if (outputsToInstall.empty())
|
||||
outputsToInstall.insert("out");
|
||||
return OutputsSpec::Names{std::move(outputsToInstall)};
|
||||
},
|
||||
[&](const ExtendedOutputsSpec::Explicit & e) -> OutputsSpec { return e; },
|
||||
},
|
||||
[&](const ExtendedOutputsSpec::Explicit & e) -> OutputsSpec {
|
||||
return e;
|
||||
},
|
||||
}, extendedOutputsSpec.raw);
|
||||
extendedOutputsSpec.raw);
|
||||
|
||||
auto [iter, didInsert] = byDrvPath.emplace(*drvPath, newOutputs);
|
||||
|
||||
@@ -93,11 +91,12 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths()
|
||||
DerivedPathsWithInfo res;
|
||||
for (auto & [drvPath, outputs] : byDrvPath)
|
||||
res.push_back({
|
||||
.path = DerivedPath::Built {
|
||||
.drvPath = makeConstantStorePathRef(drvPath),
|
||||
.outputs = outputs,
|
||||
},
|
||||
.info = make_ref<ExtraPathInfoValue>(ExtraPathInfoValue::Value {
|
||||
.path =
|
||||
DerivedPath::Built{
|
||||
.drvPath = makeConstantStorePathRef(drvPath),
|
||||
.outputs = outputs,
|
||||
},
|
||||
.info = make_ref<ExtraPathInfoValue>(ExtraPathInfoValue::Value{
|
||||
.extendedOutputsSpec = outputs,
|
||||
/* FIXME: reconsider backwards compatibility above
|
||||
so we can fill in this info. */
|
||||
@@ -115,10 +114,12 @@ InstallableAttrPath InstallableAttrPath::parse(
|
||||
ExtendedOutputsSpec extendedOutputsSpec)
|
||||
{
|
||||
return {
|
||||
state, cmd, v,
|
||||
prefix == "." ? "" : std::string { prefix },
|
||||
state,
|
||||
cmd,
|
||||
v,
|
||||
prefix == "." ? "" : std::string{prefix},
|
||||
std::move(extendedOutputsSpec),
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -21,35 +21,35 @@ std::optional<StorePath> InstallableDerivedPath::getStorePath()
|
||||
return derivedPath.getBaseStorePath();
|
||||
}
|
||||
|
||||
InstallableDerivedPath InstallableDerivedPath::parse(
|
||||
ref<Store> store,
|
||||
std::string_view prefix,
|
||||
ExtendedOutputsSpec extendedOutputsSpec)
|
||||
InstallableDerivedPath
|
||||
InstallableDerivedPath::parse(ref<Store> store, std::string_view prefix, ExtendedOutputsSpec extendedOutputsSpec)
|
||||
{
|
||||
auto derivedPath = std::visit(overloaded {
|
||||
// If the user did not use ^, we treat the output more
|
||||
// liberally: we accept a symlink chain or an actual
|
||||
// store path.
|
||||
[&](const ExtendedOutputsSpec::Default &) -> DerivedPath {
|
||||
auto storePath = store->followLinksToStorePath(prefix);
|
||||
return DerivedPath::Opaque {
|
||||
.path = std::move(storePath),
|
||||
};
|
||||
auto derivedPath = std::visit(
|
||||
overloaded{
|
||||
// If the user did not use ^, we treat the output more
|
||||
// liberally: we accept a symlink chain or an actual
|
||||
// store path.
|
||||
[&](const ExtendedOutputsSpec::Default &) -> DerivedPath {
|
||||
auto storePath = store->followLinksToStorePath(prefix);
|
||||
return DerivedPath::Opaque{
|
||||
.path = std::move(storePath),
|
||||
};
|
||||
},
|
||||
// If the user did use ^, we just do exactly what is written.
|
||||
[&](const ExtendedOutputsSpec::Explicit & outputSpec) -> DerivedPath {
|
||||
auto drv = make_ref<SingleDerivedPath>(SingleDerivedPath::parse(*store, prefix));
|
||||
drvRequireExperiment(*drv);
|
||||
return DerivedPath::Built{
|
||||
.drvPath = std::move(drv),
|
||||
.outputs = outputSpec,
|
||||
};
|
||||
},
|
||||
},
|
||||
// If the user did use ^, we just do exactly what is written.
|
||||
[&](const ExtendedOutputsSpec::Explicit & outputSpec) -> DerivedPath {
|
||||
auto drv = make_ref<SingleDerivedPath>(SingleDerivedPath::parse(*store, prefix));
|
||||
drvRequireExperiment(*drv);
|
||||
return DerivedPath::Built {
|
||||
.drvPath = std::move(drv),
|
||||
.outputs = outputSpec,
|
||||
};
|
||||
},
|
||||
}, extendedOutputsSpec.raw);
|
||||
return InstallableDerivedPath {
|
||||
extendedOutputsSpec.raw);
|
||||
return InstallableDerivedPath{
|
||||
store,
|
||||
std::move(derivedPath),
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -28,8 +28,8 @@ namespace nix {
|
||||
std::vector<std::string> InstallableFlake::getActualAttrPaths()
|
||||
{
|
||||
std::vector<std::string> res;
|
||||
if (attrPaths.size() == 1 && attrPaths.front().starts_with(".")){
|
||||
attrPaths.front().erase(0,1);
|
||||
if (attrPaths.size() == 1 && attrPaths.front().starts_with(".")) {
|
||||
attrPaths.front().erase(0, 1);
|
||||
res.push_back(attrPaths.front());
|
||||
return res;
|
||||
}
|
||||
@@ -47,8 +47,11 @@ static std::string showAttrPaths(const std::vector<std::string> & paths)
|
||||
{
|
||||
std::string s;
|
||||
for (const auto & [n, i] : enumerate(paths)) {
|
||||
if (n > 0) s += n + 1 == paths.size() ? " or " : ", ";
|
||||
s += '\''; s += i; s += '\'';
|
||||
if (n > 0)
|
||||
s += n + 1 == paths.size() ? " or " : ", ";
|
||||
s += '\'';
|
||||
s += i;
|
||||
s += '\'';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -62,12 +65,12 @@ InstallableFlake::InstallableFlake(
|
||||
Strings attrPaths,
|
||||
Strings prefixes,
|
||||
const flake::LockFlags & lockFlags)
|
||||
: InstallableValue(state),
|
||||
flakeRef(flakeRef),
|
||||
attrPaths(fragment == "" ? attrPaths : Strings{(std::string) fragment}),
|
||||
prefixes(fragment == "" ? Strings{} : prefixes),
|
||||
extendedOutputsSpec(std::move(extendedOutputsSpec)),
|
||||
lockFlags(lockFlags)
|
||||
: InstallableValue(state)
|
||||
, flakeRef(flakeRef)
|
||||
, attrPaths(fragment == "" ? attrPaths : Strings{(std::string) fragment})
|
||||
, prefixes(fragment == "" ? Strings{} : prefixes)
|
||||
, extendedOutputsSpec(std::move(extendedOutputsSpec))
|
||||
, lockFlags(lockFlags)
|
||||
{
|
||||
if (cmd && cmd->getAutoArgs(*state)->size())
|
||||
throw UsageError("'--arg' and '--argstr' are incompatible with flakes");
|
||||
@@ -87,18 +90,14 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths()
|
||||
auto v = attr->forceValue();
|
||||
|
||||
if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths(
|
||||
v,
|
||||
noPos,
|
||||
fmt("while evaluating the flake output attribute '%s'", attrPath)))
|
||||
{
|
||||
return { *derivedPathWithInfo };
|
||||
v, noPos, fmt("while evaluating the flake output attribute '%s'", attrPath))) {
|
||||
return {*derivedPathWithInfo};
|
||||
} else {
|
||||
throw Error(
|
||||
"expected flake output attribute '%s' to be a derivation or path but found %s: %s",
|
||||
attrPath,
|
||||
showType(v),
|
||||
ValuePrinter(*this->state, v, errorPrintOptions)
|
||||
);
|
||||
ValuePrinter(*this->state, v, errorPrintOptions));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,39 +112,40 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths()
|
||||
}
|
||||
|
||||
return {{
|
||||
.path = DerivedPath::Built {
|
||||
.drvPath = makeConstantStorePathRef(std::move(drvPath)),
|
||||
.outputs = std::visit(overloaded {
|
||||
[&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec {
|
||||
StringSet outputsToInstall;
|
||||
if (auto aOutputSpecified = attr->maybeGetAttr(state->sOutputSpecified)) {
|
||||
if (aOutputSpecified->getBool()) {
|
||||
if (auto aOutputName = attr->maybeGetAttr("outputName"))
|
||||
outputsToInstall = { aOutputName->getString() };
|
||||
}
|
||||
} else if (auto aMeta = attr->maybeGetAttr(state->sMeta)) {
|
||||
if (auto aOutputsToInstall = aMeta->maybeGetAttr("outputsToInstall"))
|
||||
for (auto & s : aOutputsToInstall->getListOfStrings())
|
||||
outputsToInstall.insert(s);
|
||||
}
|
||||
.path =
|
||||
DerivedPath::Built{
|
||||
.drvPath = makeConstantStorePathRef(std::move(drvPath)),
|
||||
.outputs = std::visit(
|
||||
overloaded{
|
||||
[&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec {
|
||||
StringSet outputsToInstall;
|
||||
if (auto aOutputSpecified = attr->maybeGetAttr(state->sOutputSpecified)) {
|
||||
if (aOutputSpecified->getBool()) {
|
||||
if (auto aOutputName = attr->maybeGetAttr("outputName"))
|
||||
outputsToInstall = {aOutputName->getString()};
|
||||
}
|
||||
} else if (auto aMeta = attr->maybeGetAttr(state->sMeta)) {
|
||||
if (auto aOutputsToInstall = aMeta->maybeGetAttr("outputsToInstall"))
|
||||
for (auto & s : aOutputsToInstall->getListOfStrings())
|
||||
outputsToInstall.insert(s);
|
||||
}
|
||||
|
||||
if (outputsToInstall.empty())
|
||||
outputsToInstall.insert("out");
|
||||
if (outputsToInstall.empty())
|
||||
outputsToInstall.insert("out");
|
||||
|
||||
return OutputsSpec::Names { std::move(outputsToInstall) };
|
||||
},
|
||||
[&](const ExtendedOutputsSpec::Explicit & e) -> OutputsSpec {
|
||||
return e;
|
||||
},
|
||||
}, extendedOutputsSpec.raw),
|
||||
},
|
||||
return OutputsSpec::Names{std::move(outputsToInstall)};
|
||||
},
|
||||
[&](const ExtendedOutputsSpec::Explicit & e) -> OutputsSpec { return e; },
|
||||
},
|
||||
extendedOutputsSpec.raw),
|
||||
},
|
||||
.info = make_ref<ExtraPathInfoFlake>(
|
||||
ExtraPathInfoValue::Value {
|
||||
ExtraPathInfoValue::Value{
|
||||
.priority = priority,
|
||||
.attrPath = attrPath,
|
||||
.extendedOutputsSpec = extendedOutputsSpec,
|
||||
},
|
||||
ExtraPathInfoFlake::Flake {
|
||||
ExtraPathInfoFlake::Flake{
|
||||
.originalRef = flakeRef,
|
||||
.lockedRef = getLockedFlake()->flake.lockedRef,
|
||||
}),
|
||||
@@ -157,8 +157,7 @@ std::pair<Value *, PosIdx> InstallableFlake::toValue(EvalState & state)
|
||||
return {&getCursor(state)->forceValue(), noPos};
|
||||
}
|
||||
|
||||
std::vector<ref<eval_cache::AttrCursor>>
|
||||
InstallableFlake::getCursors(EvalState & state)
|
||||
std::vector<ref<eval_cache::AttrCursor>> InstallableFlake::getCursors(EvalState & state)
|
||||
{
|
||||
auto evalCache = openEvalCache(state, getLockedFlake());
|
||||
|
||||
@@ -181,11 +180,7 @@ InstallableFlake::getCursors(EvalState & state)
|
||||
}
|
||||
|
||||
if (res.size() == 0)
|
||||
throw Error(
|
||||
suggestions,
|
||||
"flake '%s' does not provide attribute %s",
|
||||
flakeRef,
|
||||
showAttrPaths(attrPaths));
|
||||
throw Error(suggestions, "flake '%s' does not provide attribute %s", flakeRef, showAttrPaths(attrPaths));
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -196,8 +191,8 @@ std::shared_ptr<flake::LockedFlake> InstallableFlake::getLockedFlake() const
|
||||
flake::LockFlags lockFlagsApplyConfig = lockFlags;
|
||||
// FIXME why this side effect?
|
||||
lockFlagsApplyConfig.applyNixConfig = true;
|
||||
_lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(
|
||||
flakeSettings, *state, flakeRef, lockFlagsApplyConfig));
|
||||
_lockedFlake =
|
||||
std::make_shared<flake::LockedFlake>(lockFlake(flakeSettings, *state, flakeRef, lockFlagsApplyConfig));
|
||||
}
|
||||
return _lockedFlake;
|
||||
}
|
||||
@@ -216,4 +211,4 @@ FlakeRef InstallableFlake::nixpkgsFlakeRef() const
|
||||
return defaultNixpkgsFlakeRef();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -4,17 +4,14 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
std::vector<ref<eval_cache::AttrCursor>>
|
||||
InstallableValue::getCursors(EvalState & state)
|
||||
std::vector<ref<eval_cache::AttrCursor>> InstallableValue::getCursors(EvalState & state)
|
||||
{
|
||||
auto evalCache =
|
||||
std::make_shared<nix::eval_cache::EvalCache>(std::nullopt, state,
|
||||
[&]() { return toValue(state).first; });
|
||||
std::make_shared<nix::eval_cache::EvalCache>(std::nullopt, state, [&]() { return toValue(state).first; });
|
||||
return {evalCache->getRoot()};
|
||||
}
|
||||
|
||||
ref<eval_cache::AttrCursor>
|
||||
InstallableValue::getCursor(EvalState & state)
|
||||
ref<eval_cache::AttrCursor> InstallableValue::getCursor(EvalState & state)
|
||||
{
|
||||
/* Although getCursors should return at least one element, in case it doesn't,
|
||||
bound check to avoid an undefined behavior for vector[0] */
|
||||
@@ -39,30 +36,32 @@ ref<InstallableValue> InstallableValue::require(ref<Installable> installable)
|
||||
auto castedInstallable = installable.dynamic_pointer_cast<InstallableValue>();
|
||||
if (!castedInstallable)
|
||||
throw nonValueInstallable(*installable);
|
||||
return ref { castedInstallable };
|
||||
return ref{castedInstallable};
|
||||
}
|
||||
|
||||
std::optional<DerivedPathWithInfo> InstallableValue::trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx)
|
||||
std::optional<DerivedPathWithInfo>
|
||||
InstallableValue::trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx)
|
||||
{
|
||||
if (v.type() == nPath) {
|
||||
auto storePath = fetchToStore(*state->store, v.path(), FetchMode::Copy);
|
||||
return {{
|
||||
.path = DerivedPath::Opaque {
|
||||
.path = std::move(storePath),
|
||||
},
|
||||
.path =
|
||||
DerivedPath::Opaque{
|
||||
.path = std::move(storePath),
|
||||
},
|
||||
.info = make_ref<ExtraPathInfo>(),
|
||||
}};
|
||||
}
|
||||
|
||||
else if (v.type() == nString) {
|
||||
return {{
|
||||
.path = DerivedPath::fromSingle(
|
||||
state->coerceToSingleDerivedPath(pos, v, errorCtx)),
|
||||
.path = DerivedPath::fromSingle(state->coerceToSingleDerivedPath(pos, v, errorCtx)),
|
||||
.info = make_ref<ExtraPathInfo>(),
|
||||
}};
|
||||
}
|
||||
|
||||
else return std::nullopt;
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -61,7 +61,8 @@ MixFlakeOptions::MixFlakeOptions()
|
||||
.category = category,
|
||||
.handler = {[&]() {
|
||||
lockFlags.recreateLockFile = true;
|
||||
warn("'--recreate-lock-file' is deprecated and will be removed in a future version; use 'nix flake update' instead.");
|
||||
warn(
|
||||
"'--recreate-lock-file' is deprecated and will be removed in a future version; use 'nix flake update' instead.");
|
||||
}},
|
||||
});
|
||||
|
||||
@@ -158,9 +159,7 @@ MixFlakeOptions::MixFlakeOptions()
|
||||
.description = "Write the given lock file instead of `flake.lock` within the top-level flake.",
|
||||
.category = category,
|
||||
.labels = {"flake-lock-path"},
|
||||
.handler = {[&](std::string lockFilePath) {
|
||||
lockFlags.outputLockFilePath = lockFilePath;
|
||||
}},
|
||||
.handler = {[&](std::string lockFilePath) { lockFlags.outputLockFilePath = lockFilePath; }},
|
||||
.completer = completePath,
|
||||
});
|
||||
|
||||
@@ -175,12 +174,12 @@ MixFlakeOptions::MixFlakeOptions()
|
||||
flakeSettings,
|
||||
*evalState,
|
||||
parseFlakeRef(fetchSettings, flakeRef, absPath(getCommandBaseDir())),
|
||||
{ .writeLockFile = false });
|
||||
{.writeLockFile = false});
|
||||
for (auto & [inputName, input] : flake.lockFile.root->inputs) {
|
||||
auto input2 = flake.lockFile.findInput({inputName}); // resolve 'follows' nodes
|
||||
if (auto input3 = std::dynamic_pointer_cast<const flake::LockedNode>(input2)) {
|
||||
overrideRegistry(
|
||||
fetchers::Input::fromAttrs(fetchSettings, {{"type","indirect"}, {"id", inputName}}),
|
||||
fetchers::Input::fromAttrs(fetchSettings, {{"type", "indirect"}, {"id", inputName}}),
|
||||
input3->lockedRef.input,
|
||||
{});
|
||||
}
|
||||
@@ -209,7 +208,8 @@ SourceExprCommand::SourceExprCommand()
|
||||
|
||||
addFlag({
|
||||
.longName = "expr",
|
||||
.description = "Interpret [*installables*](@docroot@/command-ref/new-cli/nix.md#installables) as attribute paths relative to the Nix expression *expr*.",
|
||||
.description =
|
||||
"Interpret [*installables*](@docroot@/command-ref/new-cli/nix.md#installables) as attribute paths relative to the Nix expression *expr*.",
|
||||
.category = installablesCategory,
|
||||
.labels = {"expr"},
|
||||
.handler = {&expr},
|
||||
@@ -220,32 +220,26 @@ MixReadOnlyOption::MixReadOnlyOption()
|
||||
{
|
||||
addFlag({
|
||||
.longName = "read-only",
|
||||
.description =
|
||||
"Do not instantiate each evaluated derivation. "
|
||||
"This improves performance, but can cause errors when accessing "
|
||||
"store paths of derivations during evaluation.",
|
||||
.description = "Do not instantiate each evaluated derivation. "
|
||||
"This improves performance, but can cause errors when accessing "
|
||||
"store paths of derivations during evaluation.",
|
||||
.handler = {&settings.readOnlyMode, true},
|
||||
});
|
||||
}
|
||||
|
||||
Strings SourceExprCommand::getDefaultFlakeAttrPaths()
|
||||
{
|
||||
return {
|
||||
"packages." + settings.thisSystem.get() + ".default",
|
||||
"defaultPackage." + settings.thisSystem.get()
|
||||
};
|
||||
return {"packages." + settings.thisSystem.get() + ".default", "defaultPackage." + settings.thisSystem.get()};
|
||||
}
|
||||
|
||||
Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
|
||||
{
|
||||
return {
|
||||
// As a convenience, look for the attribute in
|
||||
// 'outputs.packages'.
|
||||
"packages." + settings.thisSystem.get() + ".",
|
||||
// As a temporary hack until Nixpkgs is properly converted
|
||||
// to provide a clean 'packages' set, look in 'legacyPackages'.
|
||||
"legacyPackages." + settings.thisSystem.get() + "."
|
||||
};
|
||||
return {// As a convenience, look for the attribute in
|
||||
// 'outputs.packages'.
|
||||
"packages." + settings.thisSystem.get() + ".",
|
||||
// As a temporary hack until Nixpkgs is properly converted
|
||||
// to provide a clean 'packages' set, look in 'legacyPackages'.
|
||||
"legacyPackages." + settings.thisSystem.get() + "."};
|
||||
}
|
||||
|
||||
Args::CompleterClosure SourceExprCommand::getCompleteInstallable()
|
||||
@@ -263,10 +257,7 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s
|
||||
|
||||
evalSettings.pureEval = false;
|
||||
auto state = getEvalState();
|
||||
auto e =
|
||||
state->parseExprFromFile(
|
||||
resolveExprPath(
|
||||
lookupFileArg(*state, *file)));
|
||||
auto e = state->parseExprFromFile(resolveExprPath(lookupFileArg(*state, *file)));
|
||||
|
||||
Value root;
|
||||
state->eval(e, root);
|
||||
@@ -285,7 +276,7 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s
|
||||
}
|
||||
|
||||
auto [v, pos] = findAlongAttrPath(*state, prefix_, *autoArgs, root);
|
||||
Value &v1(*v);
|
||||
Value & v1(*v);
|
||||
state->forceValue(v1, pos);
|
||||
Value v2;
|
||||
state->autoCallFunction(*autoArgs, v1, v2);
|
||||
@@ -310,7 +301,7 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s
|
||||
getDefaultFlakeAttrPaths(),
|
||||
prefix);
|
||||
}
|
||||
} catch (EvalError&) {
|
||||
} catch (EvalError &) {
|
||||
// Don't want eval errors to mess-up with the completion engine, so let's just swallow them
|
||||
}
|
||||
}
|
||||
@@ -334,22 +325,23 @@ void completeFlakeRefWithFragment(
|
||||
|
||||
auto fragment = prefix.substr(hash + 1);
|
||||
std::string prefixRoot = "";
|
||||
if (fragment.starts_with(".")){
|
||||
if (fragment.starts_with(".")) {
|
||||
fragment = fragment.substr(1);
|
||||
prefixRoot = ".";
|
||||
}
|
||||
auto flakeRefS = std::string(prefix.substr(0, hash));
|
||||
|
||||
// TODO: ideally this would use the command base directory instead of assuming ".".
|
||||
auto flakeRef = parseFlakeRef(fetchSettings, expandTilde(flakeRefS), std::filesystem::current_path().string());
|
||||
auto flakeRef =
|
||||
parseFlakeRef(fetchSettings, expandTilde(flakeRefS), std::filesystem::current_path().string());
|
||||
|
||||
auto evalCache = openEvalCache(*evalState,
|
||||
std::make_shared<flake::LockedFlake>(lockFlake(
|
||||
flakeSettings, *evalState, flakeRef, lockFlags)));
|
||||
auto evalCache = openEvalCache(
|
||||
*evalState,
|
||||
std::make_shared<flake::LockedFlake>(lockFlake(flakeSettings, *evalState, flakeRef, lockFlags)));
|
||||
|
||||
auto root = evalCache->getRoot();
|
||||
|
||||
if (prefixRoot == "."){
|
||||
if (prefixRoot == ".") {
|
||||
attrPathPrefixes.clear();
|
||||
}
|
||||
/* Complete 'fragment' relative to all the
|
||||
@@ -369,7 +361,8 @@ void completeFlakeRefWithFragment(
|
||||
}
|
||||
|
||||
auto attr = root->findAlongAttrPath(attrPath);
|
||||
if (!attr) continue;
|
||||
if (!attr)
|
||||
continue;
|
||||
|
||||
for (auto & attr2 : (*attr)->getAttrs()) {
|
||||
if (hasPrefix(evalState->symbols[attr2], lastAttr)) {
|
||||
@@ -377,7 +370,9 @@ void completeFlakeRefWithFragment(
|
||||
/* Strip the attrpath prefix. */
|
||||
attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size());
|
||||
// FIXME: handle names with dots
|
||||
completions.add(flakeRefS + "#" + prefixRoot + concatStringsSep(".", evalState->symbols.resolve(attrPath2)));
|
||||
completions.add(
|
||||
flakeRefS + "#" + prefixRoot
|
||||
+ concatStringsSep(".", evalState->symbols.resolve(attrPath2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -387,7 +382,8 @@ void completeFlakeRefWithFragment(
|
||||
if (fragment.empty()) {
|
||||
for (auto & attrPath : defaultFlakeAttrPaths) {
|
||||
auto attr = root->findAlongAttrPath(parseAttrPath(*evalState, attrPath));
|
||||
if (!attr) continue;
|
||||
if (!attr)
|
||||
continue;
|
||||
completions.add(flakeRefS + "#" + prefixRoot);
|
||||
}
|
||||
}
|
||||
@@ -427,14 +423,12 @@ DerivedPathWithInfo Installable::toDerivedPath()
|
||||
{
|
||||
auto buildables = toDerivedPaths();
|
||||
if (buildables.size() != 1)
|
||||
throw Error("installable '%s' evaluates to %d derivations, where only one is expected", what(), buildables.size());
|
||||
throw Error(
|
||||
"installable '%s' evaluates to %d derivations, where only one is expected", what(), buildables.size());
|
||||
return std::move(buildables[0]);
|
||||
}
|
||||
|
||||
static StorePath getDeriver(
|
||||
ref<Store> store,
|
||||
const Installable & i,
|
||||
const StorePath & drvPath)
|
||||
static StorePath getDeriver(ref<Store> store, const Installable & i, const StorePath & drvPath)
|
||||
{
|
||||
auto derivers = store->queryValidDerivers(drvPath);
|
||||
if (derivers.empty())
|
||||
@@ -443,35 +437,35 @@ static StorePath getDeriver(
|
||||
return *derivers.begin();
|
||||
}
|
||||
|
||||
ref<eval_cache::EvalCache> openEvalCache(
|
||||
EvalState & state,
|
||||
std::shared_ptr<flake::LockedFlake> lockedFlake)
|
||||
ref<eval_cache::EvalCache> openEvalCache(EvalState & state, std::shared_ptr<flake::LockedFlake> lockedFlake)
|
||||
{
|
||||
auto fingerprint = evalSettings.useEvalCache && evalSettings.pureEval
|
||||
? lockedFlake->getFingerprint(state.store, state.fetchSettings)
|
||||
: std::nullopt;
|
||||
auto rootLoader = [&state, lockedFlake]()
|
||||
{
|
||||
/* For testing whether the evaluation cache is
|
||||
complete. */
|
||||
if (getEnv("NIX_ALLOW_EVAL").value_or("1") == "0")
|
||||
throw Error("not everything is cached, but evaluation is not allowed");
|
||||
? lockedFlake->getFingerprint(state.store, state.fetchSettings)
|
||||
: std::nullopt;
|
||||
auto rootLoader = [&state, lockedFlake]() {
|
||||
/* For testing whether the evaluation cache is
|
||||
complete. */
|
||||
if (getEnv("NIX_ALLOW_EVAL").value_or("1") == "0")
|
||||
throw Error("not everything is cached, but evaluation is not allowed");
|
||||
|
||||
auto vFlake = state.allocValue();
|
||||
flake::callFlake(state, *lockedFlake, *vFlake);
|
||||
auto vFlake = state.allocValue();
|
||||
flake::callFlake(state, *lockedFlake, *vFlake);
|
||||
|
||||
state.forceAttrs(*vFlake, noPos, "while parsing cached flake data");
|
||||
state.forceAttrs(*vFlake, noPos, "while parsing cached flake data");
|
||||
|
||||
auto aOutputs = vFlake->attrs()->get(state.symbols.create("outputs"));
|
||||
assert(aOutputs);
|
||||
auto aOutputs = vFlake->attrs()->get(state.symbols.create("outputs"));
|
||||
assert(aOutputs);
|
||||
|
||||
return aOutputs->value;
|
||||
};
|
||||
return aOutputs->value;
|
||||
};
|
||||
|
||||
if (fingerprint) {
|
||||
auto search = state.evalCaches.find(fingerprint.value());
|
||||
if (search == state.evalCaches.end()) {
|
||||
search = state.evalCaches.emplace(fingerprint.value(), make_ref<nix::eval_cache::EvalCache>(fingerprint, state, rootLoader)).first;
|
||||
search =
|
||||
state.evalCaches
|
||||
.emplace(fingerprint.value(), make_ref<nix::eval_cache::EvalCache>(fingerprint, state, rootLoader))
|
||||
.first;
|
||||
}
|
||||
return search->second;
|
||||
} else {
|
||||
@@ -479,8 +473,7 @@ ref<eval_cache::EvalCache> openEvalCache(
|
||||
}
|
||||
}
|
||||
|
||||
Installables SourceExprCommand::parseInstallables(
|
||||
ref<Store> store, std::vector<std::string> ss)
|
||||
Installables SourceExprCommand::parseInstallables(ref<Store> store, std::vector<std::string> ss)
|
||||
{
|
||||
Installables result;
|
||||
|
||||
@@ -501,12 +494,10 @@ Installables SourceExprCommand::parseInstallables(
|
||||
if (file == "-") {
|
||||
auto e = state->parseStdin();
|
||||
state->eval(e, *vFile);
|
||||
}
|
||||
else if (file) {
|
||||
} else if (file) {
|
||||
auto dir = absPath(getCommandBaseDir());
|
||||
state->evalFile(lookupFileArg(*state, *file, &dir), *vFile);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Path dir = absPath(getCommandBaseDir());
|
||||
auto e = state->parseExprFromString(*expr, state->rootPath(dir));
|
||||
state->eval(e, *vFile);
|
||||
@@ -515,9 +506,8 @@ Installables SourceExprCommand::parseInstallables(
|
||||
for (auto & s : ss) {
|
||||
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(s);
|
||||
result.push_back(
|
||||
make_ref<InstallableAttrPath>(
|
||||
InstallableAttrPath::parse(
|
||||
state, *this, vFile, std::move(prefix), std::move(extendedOutputsSpec))));
|
||||
make_ref<InstallableAttrPath>(InstallableAttrPath::parse(
|
||||
state, *this, vFile, std::move(prefix), std::move(extendedOutputsSpec))));
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -532,8 +522,9 @@ Installables SourceExprCommand::parseInstallables(
|
||||
|
||||
if (prefix.find('/') != std::string::npos) {
|
||||
try {
|
||||
result.push_back(make_ref<InstallableDerivedPath>(
|
||||
InstallableDerivedPath::parse(store, prefix, extendedOutputsSpec.raw)));
|
||||
result.push_back(
|
||||
make_ref<InstallableDerivedPath>(
|
||||
InstallableDerivedPath::parse(store, prefix, extendedOutputsSpec.raw)));
|
||||
continue;
|
||||
} catch (BadStorePath &) {
|
||||
} catch (...) {
|
||||
@@ -543,9 +534,10 @@ Installables SourceExprCommand::parseInstallables(
|
||||
}
|
||||
|
||||
try {
|
||||
auto [flakeRef, fragment] = parseFlakeRefWithFragment(
|
||||
fetchSettings, std::string { prefix }, absPath(getCommandBaseDir()));
|
||||
result.push_back(make_ref<InstallableFlake>(
|
||||
auto [flakeRef, fragment] =
|
||||
parseFlakeRefWithFragment(fetchSettings, std::string{prefix}, absPath(getCommandBaseDir()));
|
||||
result.push_back(
|
||||
make_ref<InstallableFlake>(
|
||||
this,
|
||||
getEvalState(),
|
||||
std::move(flakeRef),
|
||||
@@ -566,8 +558,7 @@ Installables SourceExprCommand::parseInstallables(
|
||||
return result;
|
||||
}
|
||||
|
||||
ref<Installable> SourceExprCommand::parseInstallable(
|
||||
ref<Store> store, const std::string & installable)
|
||||
ref<Installable> SourceExprCommand::parseInstallable(ref<Store> store, const std::string & installable)
|
||||
{
|
||||
auto installables = parseInstallables(store, {installable});
|
||||
assert(installables.size() == 1);
|
||||
@@ -578,20 +569,18 @@ static SingleBuiltPath getBuiltPath(ref<Store> evalStore, ref<Store> store, cons
|
||||
{
|
||||
return std::visit(
|
||||
overloaded{
|
||||
[&](const SingleDerivedPath::Opaque & bo) -> SingleBuiltPath {
|
||||
return SingleBuiltPath::Opaque { bo.path };
|
||||
},
|
||||
[&](const SingleDerivedPath::Opaque & bo) -> SingleBuiltPath { return SingleBuiltPath::Opaque{bo.path}; },
|
||||
[&](const SingleDerivedPath::Built & bfd) -> SingleBuiltPath {
|
||||
auto drvPath = getBuiltPath(evalStore, store, *bfd.drvPath);
|
||||
// Resolving this instead of `bfd` will yield the same result, but avoid duplicative work.
|
||||
SingleDerivedPath::Built truncatedBfd {
|
||||
SingleDerivedPath::Built truncatedBfd{
|
||||
.drvPath = makeConstantStorePathRef(drvPath.outPath()),
|
||||
.output = bfd.output,
|
||||
};
|
||||
auto outputPath = resolveDerivedPath(*store, truncatedBfd, &*evalStore);
|
||||
return SingleBuiltPath::Built {
|
||||
return SingleBuiltPath::Built{
|
||||
.drvPath = make_ref<SingleBuiltPath>(std::move(drvPath)),
|
||||
.output = { bfd.output, outputPath },
|
||||
.output = {bfd.output, outputPath},
|
||||
};
|
||||
},
|
||||
},
|
||||
@@ -599,11 +588,7 @@ static SingleBuiltPath getBuiltPath(ref<Store> evalStore, ref<Store> store, cons
|
||||
}
|
||||
|
||||
std::vector<BuiltPathWithResult> Installable::build(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
const Installables & installables,
|
||||
BuildMode bMode)
|
||||
ref<Store> evalStore, ref<Store> store, Realise mode, const Installables & installables, BuildMode bMode)
|
||||
{
|
||||
std::vector<BuiltPathWithResult> res;
|
||||
for (auto & [_, builtPathWithResult] : build2(evalStore, store, mode, installables, bMode))
|
||||
@@ -611,9 +596,7 @@ std::vector<BuiltPathWithResult> Installable::build(
|
||||
return res;
|
||||
}
|
||||
|
||||
static void throwBuildErrors(
|
||||
std::vector<KeyedBuildResult> & buildResults,
|
||||
const Store & store)
|
||||
static void throwBuildErrors(std::vector<KeyedBuildResult> & buildResults, const Store & store)
|
||||
{
|
||||
std::vector<KeyedBuildResult> failed;
|
||||
for (auto & buildResult : buildResults) {
|
||||
@@ -630,10 +613,11 @@ static void throwBuildErrors(
|
||||
StringSet failedPaths;
|
||||
for (; failedResult != failed.end(); failedResult++) {
|
||||
if (!failedResult->errorMsg.empty()) {
|
||||
logError(ErrorInfo{
|
||||
.level = lvlError,
|
||||
.msg = failedResult->errorMsg,
|
||||
});
|
||||
logError(
|
||||
ErrorInfo{
|
||||
.level = lvlError,
|
||||
.msg = failedResult->errorMsg,
|
||||
});
|
||||
}
|
||||
failedPaths.insert(failedResult->path.to_string(store));
|
||||
}
|
||||
@@ -643,11 +627,7 @@ static void throwBuildErrors(
|
||||
}
|
||||
|
||||
std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build2(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
const Installables & installables,
|
||||
BuildMode bMode)
|
||||
ref<Store> evalStore, ref<Store> store, Realise mode, const Installables & installables, BuildMode bMode)
|
||||
{
|
||||
if (mode == Realise::Nothing)
|
||||
settings.readOnlyMode = true;
|
||||
@@ -678,22 +658,25 @@ std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build
|
||||
|
||||
for (auto & path : pathsToBuild) {
|
||||
for (auto & aux : backmap[path]) {
|
||||
std::visit(overloaded {
|
||||
[&](const DerivedPath::Built & bfd) {
|
||||
auto outputs = resolveDerivedPath(*store, bfd, &*evalStore);
|
||||
res.push_back({aux.installable, {
|
||||
.path = BuiltPath::Built {
|
||||
.drvPath = make_ref<SingleBuiltPath>(getBuiltPath(evalStore, store, *bfd.drvPath)),
|
||||
.outputs = outputs,
|
||||
},
|
||||
.info = aux.info}});
|
||||
std::visit(
|
||||
overloaded{
|
||||
[&](const DerivedPath::Built & bfd) {
|
||||
auto outputs = resolveDerivedPath(*store, bfd, &*evalStore);
|
||||
res.push_back(
|
||||
{aux.installable,
|
||||
{.path =
|
||||
BuiltPath::Built{
|
||||
.drvPath =
|
||||
make_ref<SingleBuiltPath>(getBuiltPath(evalStore, store, *bfd.drvPath)),
|
||||
.outputs = outputs,
|
||||
},
|
||||
.info = aux.info}});
|
||||
},
|
||||
[&](const DerivedPath::Opaque & bo) {
|
||||
res.push_back({aux.installable, {.path = BuiltPath::Opaque{bo.path}, .info = aux.info}});
|
||||
},
|
||||
},
|
||||
[&](const DerivedPath::Opaque & bo) {
|
||||
res.push_back({aux.installable, {
|
||||
.path = BuiltPath::Opaque { bo.path },
|
||||
.info = aux.info}});
|
||||
},
|
||||
}, path.raw());
|
||||
path.raw());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,26 +690,30 @@ std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build
|
||||
throwBuildErrors(buildResults, *store);
|
||||
for (auto & buildResult : buildResults) {
|
||||
for (auto & aux : backmap[buildResult.path]) {
|
||||
std::visit(overloaded {
|
||||
[&](const DerivedPath::Built & bfd) {
|
||||
std::map<std::string, StorePath> outputs;
|
||||
for (auto & [outputName, realisation] : buildResult.builtOutputs)
|
||||
outputs.emplace(outputName, realisation.outPath);
|
||||
res.push_back({aux.installable, {
|
||||
.path = BuiltPath::Built {
|
||||
.drvPath = make_ref<SingleBuiltPath>(getBuiltPath(evalStore, store, *bfd.drvPath)),
|
||||
.outputs = outputs,
|
||||
},
|
||||
.info = aux.info,
|
||||
.result = buildResult}});
|
||||
std::visit(
|
||||
overloaded{
|
||||
[&](const DerivedPath::Built & bfd) {
|
||||
std::map<std::string, StorePath> outputs;
|
||||
for (auto & [outputName, realisation] : buildResult.builtOutputs)
|
||||
outputs.emplace(outputName, realisation.outPath);
|
||||
res.push_back(
|
||||
{aux.installable,
|
||||
{.path =
|
||||
BuiltPath::Built{
|
||||
.drvPath =
|
||||
make_ref<SingleBuiltPath>(getBuiltPath(evalStore, store, *bfd.drvPath)),
|
||||
.outputs = outputs,
|
||||
},
|
||||
.info = aux.info,
|
||||
.result = buildResult}});
|
||||
},
|
||||
[&](const DerivedPath::Opaque & bo) {
|
||||
res.push_back(
|
||||
{aux.installable,
|
||||
{.path = BuiltPath::Opaque{bo.path}, .info = aux.info, .result = buildResult}});
|
||||
},
|
||||
},
|
||||
[&](const DerivedPath::Opaque & bo) {
|
||||
res.push_back({aux.installable, {
|
||||
.path = BuiltPath::Opaque { bo.path },
|
||||
.info = aux.info,
|
||||
.result = buildResult}});
|
||||
},
|
||||
}, buildResult.path.raw());
|
||||
buildResult.path.raw());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,11 +728,7 @@ std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build
|
||||
}
|
||||
|
||||
BuiltPaths Installable::toBuiltPaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
const Installables & installables)
|
||||
ref<Store> evalStore, ref<Store> store, Realise mode, OperateOn operateOn, const Installables & installables)
|
||||
{
|
||||
if (operateOn == OperateOn::Output) {
|
||||
BuiltPaths res;
|
||||
@@ -764,10 +747,7 @@ BuiltPaths Installable::toBuiltPaths(
|
||||
}
|
||||
|
||||
StorePathSet Installable::toStorePathSet(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
const Installables & installables)
|
||||
ref<Store> evalStore, ref<Store> store, Realise mode, OperateOn operateOn, const Installables & installables)
|
||||
{
|
||||
StorePathSet outPaths;
|
||||
for (auto & path : toBuiltPaths(evalStore, store, mode, operateOn, installables)) {
|
||||
@@ -778,10 +758,7 @@ StorePathSet Installable::toStorePathSet(
|
||||
}
|
||||
|
||||
StorePaths Installable::toStorePaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
const Installables & installables)
|
||||
ref<Store> evalStore, ref<Store> store, Realise mode, OperateOn operateOn, const Installables & installables)
|
||||
{
|
||||
StorePaths outPaths;
|
||||
for (auto & path : toBuiltPaths(evalStore, store, mode, operateOn, installables)) {
|
||||
@@ -792,10 +769,7 @@ StorePaths Installable::toStorePaths(
|
||||
}
|
||||
|
||||
StorePath Installable::toStorePath(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
ref<Installable> installable)
|
||||
ref<Store> evalStore, ref<Store> store, Realise mode, OperateOn operateOn, ref<Installable> installable)
|
||||
{
|
||||
auto paths = toStorePathSet(evalStore, store, mode, operateOn, {installable});
|
||||
|
||||
@@ -805,28 +779,23 @@ StorePath Installable::toStorePath(
|
||||
return *paths.begin();
|
||||
}
|
||||
|
||||
StorePathSet Installable::toDerivations(
|
||||
ref<Store> store,
|
||||
const Installables & installables,
|
||||
bool useDeriver)
|
||||
StorePathSet Installable::toDerivations(ref<Store> store, const Installables & installables, bool useDeriver)
|
||||
{
|
||||
StorePathSet drvPaths;
|
||||
|
||||
for (const auto & i : installables)
|
||||
for (const auto & b : i->toDerivedPaths())
|
||||
std::visit(overloaded {
|
||||
[&](const DerivedPath::Opaque & bo) {
|
||||
drvPaths.insert(
|
||||
bo.path.isDerivation()
|
||||
? bo.path
|
||||
: useDeriver
|
||||
? getDeriver(store, *i, bo.path)
|
||||
: throw Error("argument '%s' did not evaluate to a derivation", i->what()));
|
||||
std::visit(
|
||||
overloaded{
|
||||
[&](const DerivedPath::Opaque & bo) {
|
||||
drvPaths.insert(
|
||||
bo.path.isDerivation() ? bo.path
|
||||
: useDeriver ? getDeriver(store, *i, bo.path)
|
||||
: throw Error("argument '%s' did not evaluate to a derivation", i->what()));
|
||||
},
|
||||
[&](const DerivedPath::Built & bfd) { drvPaths.insert(resolveDerivedPath(*store, *bfd.drvPath)); },
|
||||
},
|
||||
[&](const DerivedPath::Built & bfd) {
|
||||
drvPaths.insert(resolveDerivedPath(*store, *bfd.drvPath));
|
||||
},
|
||||
}, b.path.raw());
|
||||
b.path.raw());
|
||||
|
||||
return drvPaths;
|
||||
}
|
||||
@@ -861,10 +830,7 @@ std::vector<FlakeRef> RawInstallablesCommand::getFlakeRefsForCompletion()
|
||||
std::vector<FlakeRef> res;
|
||||
res.reserve(rawInstallables.size());
|
||||
for (const auto & i : rawInstallables)
|
||||
res.push_back(parseFlakeRefWithFragment(
|
||||
fetchSettings,
|
||||
expandTilde(i),
|
||||
absPath(getCommandBaseDir())).first);
|
||||
res.push_back(parseFlakeRefWithFragment(fetchSettings, expandTilde(i), absPath(getCommandBaseDir())).first);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -883,12 +849,7 @@ void RawInstallablesCommand::run(ref<Store> store)
|
||||
|
||||
std::vector<FlakeRef> InstallableCommand::getFlakeRefsForCompletion()
|
||||
{
|
||||
return {
|
||||
parseFlakeRefWithFragment(
|
||||
fetchSettings,
|
||||
expandTilde(_installable),
|
||||
absPath(getCommandBaseDir())).first
|
||||
};
|
||||
return {parseFlakeRefWithFragment(fetchSettings, expandTilde(_installable), absPath(getCommandBaseDir())).first};
|
||||
}
|
||||
|
||||
void InstallablesCommand::run(ref<Store> store, std::vector<std::string> && rawInstallables)
|
||||
@@ -928,4 +889,4 @@ BuiltPaths toBuiltPaths(const std::vector<BuiltPathWithResult> & builtPathsWithR
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -18,25 +18,24 @@ static std::string doRenderMarkdownToTerminal(std::string_view markdown)
|
||||
{
|
||||
int windowWidth = getWindowSize().second;
|
||||
|
||||
#if HAVE_LOWDOWN_1_4
|
||||
struct lowdown_opts_term opts_term {
|
||||
# if HAVE_LOWDOWN_1_4
|
||||
struct lowdown_opts_term opts_term{
|
||||
.cols = (size_t) std::max(windowWidth - 5, 60),
|
||||
.hmargin = 0,
|
||||
.vmargin = 0,
|
||||
};
|
||||
#endif
|
||||
struct lowdown_opts opts
|
||||
{
|
||||
# endif
|
||||
struct lowdown_opts opts{
|
||||
.type = LOWDOWN_TERM,
|
||||
#if HAVE_LOWDOWN_1_4
|
||||
# if HAVE_LOWDOWN_1_4
|
||||
.term = opts_term,
|
||||
#endif
|
||||
# endif
|
||||
.maxdepth = 20,
|
||||
#if !HAVE_LOWDOWN_1_4
|
||||
# if !HAVE_LOWDOWN_1_4
|
||||
.cols = (size_t) std::max(windowWidth - 5, 60),
|
||||
.hmargin = 0,
|
||||
.vmargin = 0,
|
||||
#endif
|
||||
# endif
|
||||
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
|
||||
.oflags = LOWDOWN_TERM_NOLINK,
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "nix/cmd/misc-store-flags.hh"
|
||||
|
||||
namespace nix::flag
|
||||
{
|
||||
namespace nix::flag {
|
||||
|
||||
static void hashFormatCompleter(AddCompletions & completions, size_t index, std::string_view prefix)
|
||||
{
|
||||
@@ -15,27 +14,23 @@ static void hashFormatCompleter(AddCompletions & completions, size_t index, std:
|
||||
Args::Flag hashFormatWithDefault(std::string && longName, HashFormat * hf)
|
||||
{
|
||||
assert(*hf == nix::HashFormat::SRI);
|
||||
return Args::Flag {
|
||||
.longName = std::move(longName),
|
||||
.description = "Hash format (`base16`, `nix32`, `base64`, `sri`). Default: `sri`.",
|
||||
.labels = {"hash-format"},
|
||||
.handler = {[hf](std::string s) {
|
||||
*hf = parseHashFormat(s);
|
||||
}},
|
||||
.completer = hashFormatCompleter,
|
||||
return Args::Flag{
|
||||
.longName = std::move(longName),
|
||||
.description = "Hash format (`base16`, `nix32`, `base64`, `sri`). Default: `sri`.",
|
||||
.labels = {"hash-format"},
|
||||
.handler = {[hf](std::string s) { *hf = parseHashFormat(s); }},
|
||||
.completer = hashFormatCompleter,
|
||||
};
|
||||
}
|
||||
|
||||
Args::Flag hashFormatOpt(std::string && longName, std::optional<HashFormat> * ohf)
|
||||
{
|
||||
return Args::Flag {
|
||||
.longName = std::move(longName),
|
||||
.description = "Hash format (`base16`, `nix32`, `base64`, `sri`).",
|
||||
.labels = {"hash-format"},
|
||||
.handler = {[ohf](std::string s) {
|
||||
*ohf = std::optional<HashFormat>{parseHashFormat(s)};
|
||||
}},
|
||||
.completer = hashFormatCompleter,
|
||||
return Args::Flag{
|
||||
.longName = std::move(longName),
|
||||
.description = "Hash format (`base16`, `nix32`, `base64`, `sri`).",
|
||||
.labels = {"hash-format"},
|
||||
.handler = {[ohf](std::string s) { *ohf = std::optional<HashFormat>{parseHashFormat(s)}; }},
|
||||
.completer = hashFormatCompleter,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -48,34 +43,31 @@ static void hashAlgoCompleter(AddCompletions & completions, size_t index, std::s
|
||||
|
||||
Args::Flag hashAlgo(std::string && longName, HashAlgorithm * ha)
|
||||
{
|
||||
return Args::Flag {
|
||||
.longName = std::move(longName),
|
||||
.description = "Hash algorithm (`blake3`, `md5`, `sha1`, `sha256`, or `sha512`).",
|
||||
.labels = {"hash-algo"},
|
||||
.handler = {[ha](std::string s) {
|
||||
*ha = parseHashAlgo(s);
|
||||
}},
|
||||
.completer = hashAlgoCompleter,
|
||||
return Args::Flag{
|
||||
.longName = std::move(longName),
|
||||
.description = "Hash algorithm (`blake3`, `md5`, `sha1`, `sha256`, or `sha512`).",
|
||||
.labels = {"hash-algo"},
|
||||
.handler = {[ha](std::string s) { *ha = parseHashAlgo(s); }},
|
||||
.completer = hashAlgoCompleter,
|
||||
};
|
||||
}
|
||||
|
||||
Args::Flag hashAlgoOpt(std::string && longName, std::optional<HashAlgorithm> * oha)
|
||||
{
|
||||
return Args::Flag {
|
||||
.longName = std::move(longName),
|
||||
.description = "Hash algorithm (`blake3`, `md5`, `sha1`, `sha256`, or `sha512`). Can be omitted for SRI hashes.",
|
||||
.labels = {"hash-algo"},
|
||||
.handler = {[oha](std::string s) {
|
||||
*oha = std::optional<HashAlgorithm>{parseHashAlgo(s)};
|
||||
}},
|
||||
.completer = hashAlgoCompleter,
|
||||
return Args::Flag{
|
||||
.longName = std::move(longName),
|
||||
.description =
|
||||
"Hash algorithm (`blake3`, `md5`, `sha1`, `sha256`, or `sha512`). Can be omitted for SRI hashes.",
|
||||
.labels = {"hash-algo"},
|
||||
.handler = {[oha](std::string s) { *oha = std::optional<HashAlgorithm>{parseHashAlgo(s)}; }},
|
||||
.completer = hashAlgoCompleter,
|
||||
};
|
||||
}
|
||||
|
||||
Args::Flag fileIngestionMethod(FileIngestionMethod * method)
|
||||
{
|
||||
return Args::Flag {
|
||||
.longName = "mode",
|
||||
return Args::Flag{
|
||||
.longName = "mode",
|
||||
// FIXME indentation carefully made for context, this is messed up.
|
||||
.description = R"(
|
||||
How to compute the hash of the input.
|
||||
@@ -92,16 +84,14 @@ Args::Flag fileIngestionMethod(FileIngestionMethod * method)
|
||||
it to the hash function.
|
||||
)",
|
||||
.labels = {"file-ingestion-method"},
|
||||
.handler = {[method](std::string s) {
|
||||
*method = parseFileIngestionMethod(s);
|
||||
}},
|
||||
.handler = {[method](std::string s) { *method = parseFileIngestionMethod(s); }},
|
||||
};
|
||||
}
|
||||
|
||||
Args::Flag contentAddressMethod(ContentAddressMethod * method)
|
||||
{
|
||||
return Args::Flag {
|
||||
.longName = "mode",
|
||||
return Args::Flag{
|
||||
.longName = "mode",
|
||||
// FIXME indentation carefully made for context, this is messed up.
|
||||
.description = R"(
|
||||
How to compute the content-address of the store object.
|
||||
@@ -126,10 +116,8 @@ Args::Flag contentAddressMethod(ContentAddressMethod * method)
|
||||
for regular usage prefer `nar` and `flat`.
|
||||
)",
|
||||
.labels = {"content-address-method"},
|
||||
.handler = {[method](std::string s) {
|
||||
*method = ContentAddressMethod::parse(s);
|
||||
}},
|
||||
.handler = {[method](std::string s) { *method = ContentAddressMethod::parse(s); }},
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix::flag
|
||||
|
||||
@@ -47,4 +47,4 @@ bool haveNetworkProxyConnection()
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -53,7 +53,8 @@ mkMesonLibrary (finalAttrs: {
|
||||
|
||||
buildInputs = [
|
||||
({ inherit editline readline; }.${readlineFlavor})
|
||||
] ++ lib.optional enableMarkdown lowdown;
|
||||
]
|
||||
++ lib.optional enableMarkdown lowdown;
|
||||
|
||||
propagatedBuildInputs = [
|
||||
nix-util
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include <cstdio>
|
||||
|
||||
#if USE_READLINE
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
# include <readline/history.h>
|
||||
# include <readline/readline.h>
|
||||
#else
|
||||
// editline < 1.15.2 don't wrap their API for C++ usage
|
||||
// (added in https://github.com/troglobit/editline/commit/91398ceb3427b730995357e9d120539fb9bb7461).
|
||||
@@ -12,7 +12,7 @@
|
||||
// For compatibility with these versions, we wrap the API here
|
||||
// (wrapping multiple times on newer versions is no problem).
|
||||
extern "C" {
|
||||
#include <editline.h>
|
||||
# include <editline.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,7 @@ void sigintHandler(int signo)
|
||||
{
|
||||
g_signal_received = signo;
|
||||
}
|
||||
};
|
||||
}; // namespace
|
||||
|
||||
static detail::ReplCompleterMixin * curRepl; // ugly
|
||||
|
||||
@@ -183,8 +183,7 @@ bool ReadlineLikeInteracter::getLine(std::string & input, ReplPromptType promptT
|
||||
// editline doesn't echo the input to the output when non-interactive, unlike readline
|
||||
// this results in a different behavior when running tests. The echoing is
|
||||
// quite useful for reading the test output, so we add it here.
|
||||
if (auto e = getEnv("_NIX_TEST_REPL_ECHO"); s && e && *e == "1")
|
||||
{
|
||||
if (auto e = getEnv("_NIX_TEST_REPL_ECHO"); s && e && *e == "1") {
|
||||
#if !USE_READLINE
|
||||
// This is probably not right for multi-line input, but we don't use that
|
||||
// in the characterisation tests, so it's fine.
|
||||
@@ -205,4 +204,4 @@ ReadlineLikeInteracter::~ReadlineLikeInteracter()
|
||||
write_history(historyFile.c_str());
|
||||
}
|
||||
|
||||
};
|
||||
}; // namespace nix
|
||||
|
||||
@@ -54,10 +54,7 @@ enum class ProcessLineResult {
|
||||
PromptAgain,
|
||||
};
|
||||
|
||||
struct NixRepl
|
||||
: AbstractNixRepl
|
||||
, detail::ReplCompleterMixin
|
||||
, gc
|
||||
struct NixRepl : AbstractNixRepl, detail::ReplCompleterMixin, gc
|
||||
{
|
||||
size_t debugTraceIndex;
|
||||
|
||||
@@ -79,8 +76,12 @@ struct NixRepl
|
||||
|
||||
std::unique_ptr<ReplInteracter> interacter;
|
||||
|
||||
NixRepl(const LookupPath & lookupPath, nix::ref<Store> store,ref<EvalState> state,
|
||||
std::function<AnnotatedValues()> getValues, RunNix * runNix);
|
||||
NixRepl(
|
||||
const LookupPath & lookupPath,
|
||||
nix::ref<Store> store,
|
||||
ref<EvalState> state,
|
||||
std::function<AnnotatedValues()> getValues,
|
||||
RunNix * runNix);
|
||||
virtual ~NixRepl() = default;
|
||||
|
||||
ReplExitStatus mainLoop() override;
|
||||
@@ -101,20 +102,22 @@ struct NixRepl
|
||||
void evalString(std::string s, Value & v);
|
||||
void loadDebugTraceEnv(DebugTrace & dt);
|
||||
|
||||
void printValue(std::ostream & str,
|
||||
Value & v,
|
||||
unsigned int maxDepth = std::numeric_limits<unsigned int>::max())
|
||||
void printValue(std::ostream & str, Value & v, unsigned int maxDepth = std::numeric_limits<unsigned int>::max())
|
||||
{
|
||||
// Hide the progress bar during printing because it might interfere
|
||||
auto suspension = logger->suspend();
|
||||
::nix::printValue(*state, str, v, PrintOptions {
|
||||
.ansiColors = true,
|
||||
.force = true,
|
||||
.derivationPaths = true,
|
||||
.maxDepth = maxDepth,
|
||||
.prettyIndent = 2,
|
||||
.errors = ErrorPrintBehavior::ThrowTopLevel,
|
||||
});
|
||||
::nix::printValue(
|
||||
*state,
|
||||
str,
|
||||
v,
|
||||
PrintOptions{
|
||||
.ansiColors = true,
|
||||
.force = true,
|
||||
.derivationPaths = true,
|
||||
.maxDepth = maxDepth,
|
||||
.prettyIndent = 2,
|
||||
.errors = ErrorPrintBehavior::ThrowTopLevel,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -122,13 +125,17 @@ std::string removeWhitespace(std::string s)
|
||||
{
|
||||
s = chomp(s);
|
||||
size_t n = s.find_first_not_of(" \n\r\t");
|
||||
if (n != std::string::npos) s = std::string(s, n);
|
||||
if (n != std::string::npos)
|
||||
s = std::string(s, n);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
NixRepl::NixRepl(const LookupPath & lookupPath, nix::ref<Store> store, ref<EvalState> state,
|
||||
std::function<NixRepl::AnnotatedValues()> getValues, RunNix * runNix)
|
||||
NixRepl::NixRepl(
|
||||
const LookupPath & lookupPath,
|
||||
nix::ref<Store> store,
|
||||
ref<EvalState> state,
|
||||
std::function<NixRepl::AnnotatedValues()> getValues,
|
||||
RunNix * runNix)
|
||||
: AbstractNixRepl(state)
|
||||
, debugTraceIndex(0)
|
||||
, getValues(getValues)
|
||||
@@ -184,7 +191,8 @@ ReplExitStatus NixRepl::mainLoop()
|
||||
auto suspension = logger->suspend();
|
||||
// When continuing input from previous lines, don't print a prompt, just align to the same
|
||||
// number of chars as the prompt.
|
||||
if (!interacter->getLine(input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) {
|
||||
if (!interacter->getLine(
|
||||
input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) {
|
||||
// Ctrl-D should exit the debugger.
|
||||
state->debugStop = false;
|
||||
logger->cout("");
|
||||
@@ -196,14 +204,14 @@ ReplExitStatus NixRepl::mainLoop()
|
||||
}
|
||||
try {
|
||||
switch (processLine(input)) {
|
||||
case ProcessLineResult::Quit:
|
||||
return ReplExitStatus::QuitAll;
|
||||
case ProcessLineResult::Continue:
|
||||
return ReplExitStatus::Continue;
|
||||
case ProcessLineResult::PromptAgain:
|
||||
break;
|
||||
default:
|
||||
unreachable();
|
||||
case ProcessLineResult::Quit:
|
||||
return ReplExitStatus::QuitAll;
|
||||
case ProcessLineResult::Continue:
|
||||
return ReplExitStatus::Continue;
|
||||
case ProcessLineResult::PromptAgain:
|
||||
break;
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
} catch (ParseError & e) {
|
||||
if (e.msg().find("unexpected end of file") != std::string::npos) {
|
||||
@@ -211,7 +219,7 @@ ReplExitStatus NixRepl::mainLoop()
|
||||
// input without clearing the input so far.
|
||||
continue;
|
||||
} else {
|
||||
printMsg(lvlError, e.msg());
|
||||
printMsg(lvlError, e.msg());
|
||||
}
|
||||
} catch (EvalError & e) {
|
||||
printMsg(lvlError, e.msg());
|
||||
@@ -260,7 +268,8 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
|
||||
/* This is a variable name; look it up in the current scope. */
|
||||
StringSet::iterator i = varNames.lower_bound(cur);
|
||||
while (i != varNames.end()) {
|
||||
if (i->substr(0, cur.size()) != cur) break;
|
||||
if (i->substr(0, cur.size()) != cur)
|
||||
break;
|
||||
completions.insert(prev + *i);
|
||||
i++;
|
||||
}
|
||||
@@ -279,11 +288,15 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
|
||||
Expr * e = parseString(expr);
|
||||
Value v;
|
||||
e->eval(*state, *env, v);
|
||||
state->forceAttrs(v, noPos, "while evaluating an attrset for the purpose of completion (this error should not be displayed; file an issue?)");
|
||||
state->forceAttrs(
|
||||
v,
|
||||
noPos,
|
||||
"while evaluating an attrset for the purpose of completion (this error should not be displayed; file an issue?)");
|
||||
|
||||
for (auto & i : *v.attrs()) {
|
||||
std::string_view name = state->symbols[i.name];
|
||||
if (name.substr(0, cur2.size()) != cur2) continue;
|
||||
if (name.substr(0, cur2.size()) != cur2)
|
||||
continue;
|
||||
completions.insert(concatStrings(prev, expr, ".", name));
|
||||
}
|
||||
|
||||
@@ -301,24 +314,23 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
|
||||
return completions;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: DRY and match or use the parser
|
||||
static bool isVarName(std::string_view s)
|
||||
{
|
||||
if (s.size() == 0) return false;
|
||||
if (s.size() == 0)
|
||||
return false;
|
||||
char c = s[0];
|
||||
if ((c >= '0' && c <= '9') || c == '-' || c == '\'') return false;
|
||||
if ((c >= '0' && c <= '9') || c == '-' || c == '\'')
|
||||
return false;
|
||||
for (auto & i : s)
|
||||
if (!((i >= 'a' && i <= 'z') ||
|
||||
(i >= 'A' && i <= 'Z') ||
|
||||
(i >= '0' && i <= '9') ||
|
||||
i == '_' || i == '-' || i == '\''))
|
||||
if (!((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || (i >= '0' && i <= '9') || i == '_' || i == '-'
|
||||
|| i == '\''))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
StorePath NixRepl::getDerivationPath(Value & v) {
|
||||
StorePath NixRepl::getDerivationPath(Value & v)
|
||||
{
|
||||
auto packageInfo = getDerivation(*state, v, false);
|
||||
if (!packageInfo)
|
||||
throw Error("expression does not evaluate to a derivation, so I can't build it");
|
||||
@@ -357,52 +369,49 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
if (line[0] == ':') {
|
||||
size_t p = line.find_first_of(" \n\r\t");
|
||||
command = line.substr(0, p);
|
||||
if (p != std::string::npos) arg = removeWhitespace(line.substr(p));
|
||||
if (p != std::string::npos)
|
||||
arg = removeWhitespace(line.substr(p));
|
||||
} else {
|
||||
arg = line;
|
||||
}
|
||||
|
||||
if (command == ":?" || command == ":help") {
|
||||
// FIXME: convert to Markdown, include in the 'nix repl' manpage.
|
||||
std::cout
|
||||
<< "The following commands are available:\n"
|
||||
<< "\n"
|
||||
<< " <expr> Evaluate and print expression\n"
|
||||
<< " <x> = <expr> Bind expression to variable\n"
|
||||
<< " :a, :add <expr> Add attributes from resulting set to scope\n"
|
||||
<< " :b <expr> Build a derivation\n"
|
||||
<< " :bl <expr> Build a derivation, creating GC roots in the\n"
|
||||
<< " working directory\n"
|
||||
<< " :e, :edit <expr> Open package or function in $EDITOR\n"
|
||||
<< " :i <expr> Build derivation, then install result into\n"
|
||||
<< " current profile\n"
|
||||
<< " :l, :load <path> Load Nix expression and add it to scope\n"
|
||||
<< " :lf, :load-flake <ref> Load Nix flake and add it to scope\n"
|
||||
<< " :p, :print <expr> Evaluate and print expression recursively\n"
|
||||
<< " Strings are printed directly, without escaping.\n"
|
||||
<< " :q, :quit Exit nix-repl\n"
|
||||
<< " :r, :reload Reload all files\n"
|
||||
<< " :sh <expr> Build dependencies of derivation, then start\n"
|
||||
<< " nix-shell\n"
|
||||
<< " :t <expr> Describe result of evaluation\n"
|
||||
<< " :u <expr> Build derivation, then start nix-shell\n"
|
||||
<< " :doc <expr> Show documentation of a builtin function\n"
|
||||
<< " :log <expr> Show logs for a derivation\n"
|
||||
<< " :te, :trace-enable [bool] Enable, disable or toggle showing traces for\n"
|
||||
<< " errors\n"
|
||||
<< " :?, :help Brings up this help menu\n"
|
||||
;
|
||||
std::cout << "The following commands are available:\n"
|
||||
<< "\n"
|
||||
<< " <expr> Evaluate and print expression\n"
|
||||
<< " <x> = <expr> Bind expression to variable\n"
|
||||
<< " :a, :add <expr> Add attributes from resulting set to scope\n"
|
||||
<< " :b <expr> Build a derivation\n"
|
||||
<< " :bl <expr> Build a derivation, creating GC roots in the\n"
|
||||
<< " working directory\n"
|
||||
<< " :e, :edit <expr> Open package or function in $EDITOR\n"
|
||||
<< " :i <expr> Build derivation, then install result into\n"
|
||||
<< " current profile\n"
|
||||
<< " :l, :load <path> Load Nix expression and add it to scope\n"
|
||||
<< " :lf, :load-flake <ref> Load Nix flake and add it to scope\n"
|
||||
<< " :p, :print <expr> Evaluate and print expression recursively\n"
|
||||
<< " Strings are printed directly, without escaping.\n"
|
||||
<< " :q, :quit Exit nix-repl\n"
|
||||
<< " :r, :reload Reload all files\n"
|
||||
<< " :sh <expr> Build dependencies of derivation, then start\n"
|
||||
<< " nix-shell\n"
|
||||
<< " :t <expr> Describe result of evaluation\n"
|
||||
<< " :u <expr> Build derivation, then start nix-shell\n"
|
||||
<< " :doc <expr> Show documentation of a builtin function\n"
|
||||
<< " :log <expr> Show logs for a derivation\n"
|
||||
<< " :te, :trace-enable [bool] Enable, disable or toggle showing traces for\n"
|
||||
<< " errors\n"
|
||||
<< " :?, :help Brings up this help menu\n";
|
||||
if (state->debugRepl) {
|
||||
std::cout
|
||||
<< "\n"
|
||||
<< " Debug mode commands\n"
|
||||
<< " :env Show env stack\n"
|
||||
<< " :bt, :backtrace Show trace stack\n"
|
||||
<< " :st Show current trace\n"
|
||||
<< " :st <idx> Change to another trace in the stack\n"
|
||||
<< " :c, :continue Go until end of program, exception, or builtins.break\n"
|
||||
<< " :s, :step Go one step\n"
|
||||
;
|
||||
std::cout << "\n"
|
||||
<< " Debug mode commands\n"
|
||||
<< " :env Show env stack\n"
|
||||
<< " :bt, :backtrace Show trace stack\n"
|
||||
<< " :st Show current trace\n"
|
||||
<< " :st <idx> Change to another trace in the stack\n"
|
||||
<< " :c, :continue Go until end of program, exception, or builtins.break\n"
|
||||
<< " :s, :step Go one step\n";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -427,17 +436,18 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
try {
|
||||
// change the DebugTrace index.
|
||||
debugTraceIndex = stoi(arg);
|
||||
} catch (...) { }
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
for (const auto & [idx, i] : enumerate(state->debugTraces)) {
|
||||
if (idx == debugTraceIndex) {
|
||||
std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": ";
|
||||
showDebugTrace(std::cout, state->positions, i);
|
||||
std::cout << std::endl;
|
||||
printEnvBindings(*state, i.expr, i.env);
|
||||
loadDebugTraceEnv(i);
|
||||
break;
|
||||
}
|
||||
if (idx == debugTraceIndex) {
|
||||
std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": ";
|
||||
showDebugTrace(std::cout, state->positions, i);
|
||||
std::cout << std::endl;
|
||||
printEnvBindings(*state, i.expr, i.env);
|
||||
loadDebugTraceEnv(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,7 +487,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
Value v;
|
||||
evalString(arg, v);
|
||||
|
||||
const auto [path, line] = [&] () -> std::pair<SourcePath, uint32_t> {
|
||||
const auto [path, line] = [&]() -> std::pair<SourcePath, uint32_t> {
|
||||
if (v.type() == nPath || v.type() == nString) {
|
||||
NixStringContext context;
|
||||
auto path = state->coerceToPath(noPos, v, context, "while evaluating the filename to edit");
|
||||
@@ -501,7 +511,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, .lookupPath = true, .args = args , .isInteractive = true });
|
||||
runProgram2(RunOptions{.program = editor, .lookupPath = true, .args = args, .isInteractive = true});
|
||||
|
||||
// Reload right after exiting the editor
|
||||
state->resetFileCache();
|
||||
@@ -532,9 +542,9 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
|
||||
if (command == ":b" || command == ":bl") {
|
||||
state->store->buildPaths({
|
||||
DerivedPath::Built {
|
||||
DerivedPath::Built{
|
||||
.drvPath = makeConstantStorePathRef(drvPath),
|
||||
.outputs = OutputsSpec::All { },
|
||||
.outputs = OutputsSpec::All{},
|
||||
},
|
||||
});
|
||||
auto drv = state->store->readDerivation(drvPath);
|
||||
@@ -553,9 +563,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
runNix("nix-env", {"-i", drvPathRaw});
|
||||
} else if (command == ":log") {
|
||||
settings.readOnlyMode = true;
|
||||
Finally roModeReset([&]() {
|
||||
settings.readOnlyMode = false;
|
||||
});
|
||||
Finally roModeReset([&]() { settings.readOnlyMode = false; });
|
||||
auto subs = getDefaultSubstituters();
|
||||
|
||||
subs.push_front(state->store);
|
||||
@@ -578,7 +586,8 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundLog) throw Error("build log of '%s' is not available", drvPathRaw);
|
||||
if (!foundLog)
|
||||
throw Error("build log of '%s' is not available", drvPathRaw);
|
||||
} else {
|
||||
runNix("nix-shell", {drvPathRaw});
|
||||
}
|
||||
@@ -641,9 +650,8 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
for (auto & arg : args)
|
||||
arg = "*" + arg + "*";
|
||||
|
||||
markdown +=
|
||||
"**Synopsis:** `builtins." + (std::string) (*doc->name) + "` "
|
||||
+ concatStringsSep(" ", args) + "\n\n";
|
||||
markdown += "**Synopsis:** `builtins." + (std::string) (*doc->name) + "` " + concatStringsSep(" ", args)
|
||||
+ "\n\n";
|
||||
}
|
||||
|
||||
markdown += stripIndentation(doc->doc);
|
||||
@@ -684,11 +692,8 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
else {
|
||||
size_t p = line.find('=');
|
||||
std::string name;
|
||||
if (p != std::string::npos &&
|
||||
p < line.size() &&
|
||||
line[p + 1] != '=' &&
|
||||
isVarName(name = removeWhitespace(line.substr(0, p))))
|
||||
{
|
||||
if (p != std::string::npos && p < line.size() && line[p + 1] != '='
|
||||
&& isVarName(name = removeWhitespace(line.substr(0, p)))) {
|
||||
Expr * e = parseString(line.substr(p + 1));
|
||||
Value & v(*state->allocValue());
|
||||
v.mkThunk(env, e);
|
||||
@@ -736,9 +741,13 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
|
||||
|
||||
Value v;
|
||||
|
||||
flake::callFlake(*state,
|
||||
flake::lockFlake(flakeSettings, *state, flakeRef,
|
||||
flake::LockFlags {
|
||||
flake::callFlake(
|
||||
*state,
|
||||
flake::lockFlake(
|
||||
flakeSettings,
|
||||
*state,
|
||||
flakeRef,
|
||||
flake::LockFlags{
|
||||
.updateLockFile = false,
|
||||
.useRegistries = !evalSettings.pureEval,
|
||||
.allowUnlocked = !evalSettings.pureEval,
|
||||
@@ -747,7 +756,6 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
|
||||
addAttrsToScope(v);
|
||||
}
|
||||
|
||||
|
||||
void NixRepl::initEnv()
|
||||
{
|
||||
env = &state->allocEnv(envSize);
|
||||
@@ -760,7 +768,6 @@ void NixRepl::initEnv()
|
||||
varNames.emplace(state->symbols[i.first]);
|
||||
}
|
||||
|
||||
|
||||
void NixRepl::reloadFilesAndFlakes()
|
||||
{
|
||||
initEnv();
|
||||
@@ -769,7 +776,6 @@ void NixRepl::reloadFilesAndFlakes()
|
||||
loadFlakes();
|
||||
}
|
||||
|
||||
|
||||
void NixRepl::loadFiles()
|
||||
{
|
||||
Strings old = loadedFiles;
|
||||
@@ -786,7 +792,6 @@ void NixRepl::loadFiles()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NixRepl::loadFlakes()
|
||||
{
|
||||
Strings old = loadedFlakes;
|
||||
@@ -798,10 +803,12 @@ void NixRepl::loadFlakes()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NixRepl::addAttrsToScope(Value & attrs)
|
||||
{
|
||||
state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); }, "while evaluating an attribute set to be merged in the global scope");
|
||||
state->forceAttrs(
|
||||
attrs,
|
||||
[&]() { return attrs.determinePos(noPos); },
|
||||
"while evaluating an attribute set to be merged in the global scope");
|
||||
if (displ + attrs.attrs()->size() >= envSize)
|
||||
throw Error("environment full; cannot add more variables");
|
||||
|
||||
@@ -815,7 +822,6 @@ void NixRepl::addAttrsToScope(Value & attrs)
|
||||
notice("Added %1% variables.", attrs.attrs()->size());
|
||||
}
|
||||
|
||||
|
||||
void NixRepl::addVarToScope(const Symbol name, Value & v)
|
||||
{
|
||||
if (displ >= envSize)
|
||||
@@ -828,13 +834,11 @@ void NixRepl::addVarToScope(const Symbol name, Value & v)
|
||||
varNames.emplace(state->symbols[name]);
|
||||
}
|
||||
|
||||
|
||||
Expr * NixRepl::parseString(std::string s)
|
||||
{
|
||||
return state->parseExprFromString(std::move(s), state->rootPath("."), staticEnv);
|
||||
}
|
||||
|
||||
|
||||
void NixRepl::evalString(std::string s, Value & v)
|
||||
{
|
||||
Expr * e = parseString(s);
|
||||
@@ -842,46 +846,39 @@ void NixRepl::evalString(std::string s, Value & v)
|
||||
state->forceValue(v, v.determinePos(noPos));
|
||||
}
|
||||
|
||||
|
||||
void NixRepl::runNix(Path program, const Strings & args, const std::optional<std::string> & input)
|
||||
{
|
||||
if (runNixPtr)
|
||||
(*runNixPtr)(program, args, input);
|
||||
else
|
||||
throw Error("Cannot run '%s' because no method of calling the Nix CLI was provided. This is a configuration problem pertaining to how this program was built. See Nix 2.25 release notes", program);
|
||||
throw Error(
|
||||
"Cannot run '%s' because no method of calling the Nix CLI was provided. This is a configuration problem pertaining to how this program was built. See Nix 2.25 release notes",
|
||||
program);
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<AbstractNixRepl> AbstractNixRepl::create(
|
||||
const LookupPath & lookupPath, nix::ref<Store> store, ref<EvalState> state,
|
||||
std::function<AnnotatedValues()> getValues, RunNix * runNix)
|
||||
const LookupPath & lookupPath,
|
||||
nix::ref<Store> store,
|
||||
ref<EvalState> state,
|
||||
std::function<AnnotatedValues()> getValues,
|
||||
RunNix * runNix)
|
||||
{
|
||||
return std::make_unique<NixRepl>(
|
||||
lookupPath,
|
||||
std::move(store),
|
||||
state,
|
||||
getValues,
|
||||
runNix
|
||||
);
|
||||
return std::make_unique<NixRepl>(lookupPath, std::move(store), state, getValues, runNix);
|
||||
}
|
||||
|
||||
|
||||
ReplExitStatus AbstractNixRepl::runSimple(
|
||||
ref<EvalState> evalState,
|
||||
const ValMap & extraEnv)
|
||||
ReplExitStatus AbstractNixRepl::runSimple(ref<EvalState> evalState, const ValMap & extraEnv)
|
||||
{
|
||||
auto getValues = [&]()->NixRepl::AnnotatedValues{
|
||||
auto getValues = [&]() -> NixRepl::AnnotatedValues {
|
||||
NixRepl::AnnotatedValues values;
|
||||
return values;
|
||||
};
|
||||
LookupPath lookupPath = {};
|
||||
auto repl = std::make_unique<NixRepl>(
|
||||
lookupPath,
|
||||
openStore(),
|
||||
evalState,
|
||||
getValues,
|
||||
/*runNix=*/nullptr
|
||||
);
|
||||
lookupPath,
|
||||
openStore(),
|
||||
evalState,
|
||||
getValues,
|
||||
/*runNix=*/nullptr);
|
||||
|
||||
repl->initEnv();
|
||||
|
||||
@@ -892,4 +889,4 @@ ReplExitStatus AbstractNixRepl::runSimple(
|
||||
return repl->mainLoop();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -31,13 +31,11 @@
|
||||
* @param init Function that takes a T* and returns the initializer for T
|
||||
* @return Pointer to allocated and initialized object
|
||||
*/
|
||||
template <typename T, typename F>
|
||||
template<typename T, typename F>
|
||||
static T * unsafe_new_with_self(F && init)
|
||||
{
|
||||
// Allocate
|
||||
void * p = ::operator new(
|
||||
sizeof(T),
|
||||
static_cast<std::align_val_t>(alignof(T)));
|
||||
void * p = ::operator new(sizeof(T), static_cast<std::align_val_t>(alignof(T)));
|
||||
// Initialize with placement new
|
||||
return new (p) T(init(static_cast<T *>(p)));
|
||||
}
|
||||
@@ -86,12 +84,13 @@ nix_err nix_value_call(nix_c_context * context, EvalState * state, Value * fn, n
|
||||
NIXC_CATCH_ERRS
|
||||
}
|
||||
|
||||
nix_err nix_value_call_multi(nix_c_context * context, EvalState * state, nix_value * fn, size_t nargs, nix_value ** args, nix_value * value)
|
||||
nix_err nix_value_call_multi(
|
||||
nix_c_context * context, EvalState * state, nix_value * fn, size_t nargs, nix_value ** args, nix_value * value)
|
||||
{
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
state->state.callFunction(fn->value, {(nix::Value * *) args, nargs}, value->value, nix::noPos);
|
||||
state->state.callFunction(fn->value, {(nix::Value **) args, nargs}, value->value, nix::noPos);
|
||||
state->state.forceValue(value->value, nix::noPos);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
@@ -152,7 +151,8 @@ nix_err nix_eval_state_builder_load(nix_c_context * context, nix_eval_state_buil
|
||||
NIXC_CATCH_ERRS
|
||||
}
|
||||
|
||||
nix_err nix_eval_state_builder_set_lookup_path(nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath_c)
|
||||
nix_err nix_eval_state_builder_set_lookup_path(
|
||||
nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath_c)
|
||||
{
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
@@ -175,11 +175,7 @@ EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder
|
||||
return EvalState{
|
||||
.fetchSettings = std::move(builder->fetchSettings),
|
||||
.settings = std::move(builder->settings),
|
||||
.state = nix::EvalState(
|
||||
builder->lookupPath,
|
||||
builder->store,
|
||||
self->fetchSettings,
|
||||
self->settings),
|
||||
.state = nix::EvalState(builder->lookupPath, builder->store, self->fetchSettings, self->settings),
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -195,11 +191,10 @@ EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c
|
||||
if (nix_eval_state_builder_load(context, builder) != NIX_OK)
|
||||
return nullptr;
|
||||
|
||||
if (nix_eval_state_builder_set_lookup_path(context, builder, lookupPath_c)
|
||||
!= NIX_OK)
|
||||
if (nix_eval_state_builder_set_lookup_path(context, builder, lookupPath_c) != NIX_OK)
|
||||
return nullptr;
|
||||
|
||||
auto *state = nix_eval_state_build(context, builder);
|
||||
auto * state = nix_eval_state_build(context, builder);
|
||||
nix_eval_state_builder_free(builder);
|
||||
return state;
|
||||
}
|
||||
@@ -265,20 +260,23 @@ nix_err nix_gc_incref(nix_c_context * context, const void *)
|
||||
context->last_err_code = NIX_OK;
|
||||
return NIX_OK;
|
||||
}
|
||||
|
||||
nix_err nix_gc_decref(nix_c_context * context, const void *)
|
||||
{
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
return NIX_OK;
|
||||
}
|
||||
|
||||
void nix_gc_now() {}
|
||||
#endif
|
||||
|
||||
nix_err nix_value_incref(nix_c_context * context, nix_value *x)
|
||||
nix_err nix_value_incref(nix_c_context * context, nix_value * x)
|
||||
{
|
||||
return nix_gc_incref(context, (const void *) x);
|
||||
}
|
||||
nix_err nix_value_decref(nix_c_context * context, nix_value *x)
|
||||
|
||||
nix_err nix_value_decref(nix_c_context * context, nix_value * x)
|
||||
{
|
||||
return nix_gc_decref(context, (const void *) x);
|
||||
}
|
||||
|
||||
@@ -48,11 +48,13 @@ class NixCExternalValue : public nix::ExternalValueBase
|
||||
public:
|
||||
NixCExternalValue(NixCExternalValueDesc & desc, void * v)
|
||||
: desc(desc)
|
||||
, v(v){};
|
||||
, v(v) {};
|
||||
|
||||
void * get_ptr()
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print out the value
|
||||
*/
|
||||
@@ -155,11 +157,17 @@ public:
|
||||
}
|
||||
nix_string_context ctx{context};
|
||||
desc.printValueAsXML(
|
||||
v, (EvalState *) &state, strict, location, &doc, &ctx, &drvsSeen,
|
||||
v,
|
||||
(EvalState *) &state,
|
||||
strict,
|
||||
location,
|
||||
&doc,
|
||||
&ctx,
|
||||
&drvsSeen,
|
||||
*reinterpret_cast<const uint32_t *>(&pos));
|
||||
}
|
||||
|
||||
virtual ~NixCExternalValue() override{};
|
||||
virtual ~NixCExternalValue() override {};
|
||||
};
|
||||
|
||||
ExternalValue * nix_create_external_value(nix_c_context * context, NixCExternalValueDesc * desc, void * v)
|
||||
|
||||
@@ -16,141 +16,159 @@
|
||||
#include "nix/store/tests/libstore.hh"
|
||||
|
||||
namespace nix {
|
||||
class LibExprTest : public LibStoreTest {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
LibStoreTest::SetUpTestSuite();
|
||||
initGC();
|
||||
}
|
||||
|
||||
protected:
|
||||
LibExprTest()
|
||||
: LibStoreTest()
|
||||
, state({}, store, fetchSettings, evalSettings, nullptr)
|
||||
{
|
||||
evalSettings.nixPath = {};
|
||||
}
|
||||
Value eval(std::string input, bool forceValue = true) {
|
||||
Value v;
|
||||
Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root));
|
||||
assert(e);
|
||||
state.eval(e, v);
|
||||
if (forceValue)
|
||||
state.forceValue(v, noPos);
|
||||
return v;
|
||||
}
|
||||
|
||||
Value * maybeThunk(std::string input, bool forceValue = true) {
|
||||
Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root));
|
||||
assert(e);
|
||||
return e->maybeThunk(state, state.baseEnv);
|
||||
}
|
||||
|
||||
Symbol createSymbol(const char * value) {
|
||||
return state.symbols.create(value);
|
||||
}
|
||||
|
||||
bool readOnlyMode = true;
|
||||
fetchers::Settings fetchSettings{};
|
||||
EvalSettings evalSettings{readOnlyMode};
|
||||
EvalState state;
|
||||
};
|
||||
|
||||
MATCHER(IsListType, "") {
|
||||
return arg != nList;
|
||||
class LibExprTest : public LibStoreTest
|
||||
{
|
||||
public:
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
LibStoreTest::SetUpTestSuite();
|
||||
initGC();
|
||||
}
|
||||
|
||||
MATCHER(IsList, "") {
|
||||
return arg.type() == nList;
|
||||
protected:
|
||||
LibExprTest()
|
||||
: LibStoreTest()
|
||||
, state({}, store, fetchSettings, evalSettings, nullptr)
|
||||
{
|
||||
evalSettings.nixPath = {};
|
||||
}
|
||||
|
||||
MATCHER(IsString, "") {
|
||||
return arg.type() == nString;
|
||||
Value eval(std::string input, bool forceValue = true)
|
||||
{
|
||||
Value v;
|
||||
Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root));
|
||||
assert(e);
|
||||
state.eval(e, v);
|
||||
if (forceValue)
|
||||
state.forceValue(v, noPos);
|
||||
return v;
|
||||
}
|
||||
|
||||
MATCHER(IsNull, "") {
|
||||
return arg.type() == nNull;
|
||||
Value * maybeThunk(std::string input, bool forceValue = true)
|
||||
{
|
||||
Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root));
|
||||
assert(e);
|
||||
return e->maybeThunk(state, state.baseEnv);
|
||||
}
|
||||
|
||||
MATCHER(IsThunk, "") {
|
||||
return arg.type() == nThunk;
|
||||
Symbol createSymbol(const char * value)
|
||||
{
|
||||
return state.symbols.create(value);
|
||||
}
|
||||
|
||||
MATCHER(IsAttrs, "") {
|
||||
return arg.type() == nAttrs;
|
||||
}
|
||||
bool readOnlyMode = true;
|
||||
fetchers::Settings fetchSettings{};
|
||||
EvalSettings evalSettings{readOnlyMode};
|
||||
EvalState state;
|
||||
};
|
||||
|
||||
MATCHER_P(IsStringEq, s, fmt("The string is equal to \"%1%\"", s)) {
|
||||
if (arg.type() != nString) {
|
||||
MATCHER(IsListType, "")
|
||||
{
|
||||
return arg != nList;
|
||||
}
|
||||
|
||||
MATCHER(IsList, "")
|
||||
{
|
||||
return arg.type() == nList;
|
||||
}
|
||||
|
||||
MATCHER(IsString, "")
|
||||
{
|
||||
return arg.type() == nString;
|
||||
}
|
||||
|
||||
MATCHER(IsNull, "")
|
||||
{
|
||||
return arg.type() == nNull;
|
||||
}
|
||||
|
||||
MATCHER(IsThunk, "")
|
||||
{
|
||||
return arg.type() == nThunk;
|
||||
}
|
||||
|
||||
MATCHER(IsAttrs, "")
|
||||
{
|
||||
return arg.type() == nAttrs;
|
||||
}
|
||||
|
||||
MATCHER_P(IsStringEq, s, fmt("The string is equal to \"%1%\"", s))
|
||||
{
|
||||
if (arg.type() != nString) {
|
||||
return false;
|
||||
}
|
||||
return std::string_view(arg.c_str()) == s;
|
||||
}
|
||||
|
||||
MATCHER_P(IsIntEq, v, fmt("The string is equal to \"%1%\"", v))
|
||||
{
|
||||
if (arg.type() != nInt) {
|
||||
return false;
|
||||
}
|
||||
return arg.integer().value == v;
|
||||
}
|
||||
|
||||
MATCHER_P(IsFloatEq, v, fmt("The float is equal to \"%1%\"", v))
|
||||
{
|
||||
if (arg.type() != nFloat) {
|
||||
return false;
|
||||
}
|
||||
return arg.fpoint() == v;
|
||||
}
|
||||
|
||||
MATCHER(IsTrue, "")
|
||||
{
|
||||
if (arg.type() != nBool) {
|
||||
return false;
|
||||
}
|
||||
return arg.boolean() == true;
|
||||
}
|
||||
|
||||
MATCHER(IsFalse, "")
|
||||
{
|
||||
if (arg.type() != nBool) {
|
||||
return false;
|
||||
}
|
||||
return arg.boolean() == false;
|
||||
}
|
||||
|
||||
MATCHER_P(IsPathEq, p, fmt("Is a path equal to \"%1%\"", p))
|
||||
{
|
||||
if (arg.type() != nPath) {
|
||||
*result_listener << "Expected a path got " << arg.type();
|
||||
return false;
|
||||
} else {
|
||||
auto path = arg.path();
|
||||
if (path.path != CanonPath(p)) {
|
||||
*result_listener << "Expected a path that equals \"" << p << "\" but got: " << path.path;
|
||||
return false;
|
||||
}
|
||||
return std::string_view(arg.c_str()) == s;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MATCHER_P(IsIntEq, v, fmt("The string is equal to \"%1%\"", v)) {
|
||||
if (arg.type() != nInt) {
|
||||
return false;
|
||||
}
|
||||
return arg.integer().value == v;
|
||||
MATCHER_P(IsListOfSize, n, fmt("Is a list of size [%1%]", n))
|
||||
{
|
||||
if (arg.type() != nList) {
|
||||
*result_listener << "Expected list got " << arg.type();
|
||||
return false;
|
||||
} else if (arg.listSize() != (size_t) n) {
|
||||
*result_listener << "Expected as list of size " << n << " got " << arg.listSize();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MATCHER_P(IsFloatEq, v, fmt("The float is equal to \"%1%\"", v)) {
|
||||
if (arg.type() != nFloat) {
|
||||
return false;
|
||||
}
|
||||
return arg.fpoint() == v;
|
||||
MATCHER_P(IsAttrsOfSize, n, fmt("Is a set of size [%1%]", n))
|
||||
{
|
||||
if (arg.type() != nAttrs) {
|
||||
*result_listener << "Expected set got " << arg.type();
|
||||
return false;
|
||||
} else if (arg.attrs()->size() != (size_t) n) {
|
||||
*result_listener << "Expected a set with " << n << " attributes but got " << arg.attrs()->size();
|
||||
return false;
|
||||
}
|
||||
|
||||
MATCHER(IsTrue, "") {
|
||||
if (arg.type() != nBool) {
|
||||
return false;
|
||||
}
|
||||
return arg.boolean() == true;
|
||||
}
|
||||
|
||||
MATCHER(IsFalse, "") {
|
||||
if (arg.type() != nBool) {
|
||||
return false;
|
||||
}
|
||||
return arg.boolean() == false;
|
||||
}
|
||||
|
||||
MATCHER_P(IsPathEq, p, fmt("Is a path equal to \"%1%\"", p)) {
|
||||
if (arg.type() != nPath) {
|
||||
*result_listener << "Expected a path got " << arg.type();
|
||||
return false;
|
||||
} else {
|
||||
auto path = arg.path();
|
||||
if (path.path != CanonPath(p)) {
|
||||
*result_listener << "Expected a path that equals \"" << p << "\" but got: " << path.path;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
MATCHER_P(IsListOfSize, n, fmt("Is a list of size [%1%]", n)) {
|
||||
if (arg.type() != nList) {
|
||||
*result_listener << "Expected list got " << arg.type();
|
||||
return false;
|
||||
} else if (arg.listSize() != (size_t)n) {
|
||||
*result_listener << "Expected as list of size " << n << " got " << arg.listSize();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MATCHER_P(IsAttrsOfSize, n, fmt("Is a set of size [%1%]", n)) {
|
||||
if (arg.type() != nAttrs) {
|
||||
*result_listener << "Expected set got " << arg.type();
|
||||
return false;
|
||||
} else if (arg.attrs()->size() != (size_t) n) {
|
||||
*result_listener << "Expected a set with " << n << " attributes but got " << arg.attrs()->size();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* namespace nix */
|
||||
|
||||
@@ -18,6 +18,7 @@ protected:
|
||||
state = nix_state_create(nullptr, nullptr, store);
|
||||
value = nix_alloc_value(nullptr, state);
|
||||
}
|
||||
|
||||
~nix_api_expr_test()
|
||||
{
|
||||
nix_gc_decref(nullptr, value);
|
||||
@@ -28,4 +29,4 @@ protected:
|
||||
nix_value * value;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nixC
|
||||
|
||||
@@ -9,23 +9,27 @@ namespace rc {
|
||||
using namespace nix;
|
||||
|
||||
template<>
|
||||
struct Arbitrary<NixStringContextElem::Opaque> {
|
||||
struct Arbitrary<NixStringContextElem::Opaque>
|
||||
{
|
||||
static Gen<NixStringContextElem::Opaque> arbitrary();
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Arbitrary<NixStringContextElem::Built> {
|
||||
struct Arbitrary<NixStringContextElem::Built>
|
||||
{
|
||||
static Gen<NixStringContextElem::Built> arbitrary();
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Arbitrary<NixStringContextElem::DrvDeep> {
|
||||
struct Arbitrary<NixStringContextElem::DrvDeep>
|
||||
{
|
||||
static Gen<NixStringContextElem::DrvDeep> arbitrary();
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Arbitrary<NixStringContextElem> {
|
||||
struct Arbitrary<NixStringContextElem>
|
||||
{
|
||||
static Gen<NixStringContextElem> arbitrary();
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace rc
|
||||
|
||||
@@ -36,4 +36,4 @@ Gen<NixStringContextElem> Arbitrary<NixStringContextElem>::arbitrary()
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace rc
|
||||
|
||||
@@ -8,36 +8,30 @@
|
||||
namespace nix {
|
||||
|
||||
// Testing of trivial expressions
|
||||
class DerivedPathExpressionTest : public LibExprTest {};
|
||||
class DerivedPathExpressionTest : public LibExprTest
|
||||
{};
|
||||
|
||||
// FIXME: `RC_GTEST_FIXTURE_PROP` isn't calling `SetUpTestSuite` because it is
|
||||
// no a real fixture.
|
||||
//
|
||||
// See https://github.com/emil-e/rapidcheck/blob/master/doc/gtest.md#rc_gtest_fixture_propfixture-name-args
|
||||
TEST_F(DerivedPathExpressionTest, force_init)
|
||||
{
|
||||
}
|
||||
TEST_F(DerivedPathExpressionTest, force_init) {}
|
||||
|
||||
#ifndef COVERAGE
|
||||
|
||||
RC_GTEST_FIXTURE_PROP(
|
||||
DerivedPathExpressionTest,
|
||||
prop_opaque_path_round_trip,
|
||||
(const SingleDerivedPath::Opaque & o))
|
||||
RC_GTEST_FIXTURE_PROP(DerivedPathExpressionTest, prop_opaque_path_round_trip, (const SingleDerivedPath::Opaque & o))
|
||||
{
|
||||
auto * v = state.allocValue();
|
||||
state.mkStorePathString(o.path, *v);
|
||||
auto d = state.coerceToSingleDerivedPath(noPos, *v, "");
|
||||
RC_ASSERT(SingleDerivedPath { o } == d);
|
||||
RC_ASSERT(SingleDerivedPath{o} == d);
|
||||
}
|
||||
|
||||
// TODO use DerivedPath::Built for parameter once it supports a single output
|
||||
// path only.
|
||||
|
||||
RC_GTEST_FIXTURE_PROP(
|
||||
DerivedPathExpressionTest,
|
||||
prop_derived_path_built_placeholder_round_trip,
|
||||
(const SingleDerivedPath::Built & b))
|
||||
DerivedPathExpressionTest, prop_derived_path_built_placeholder_round_trip, (const SingleDerivedPath::Built & b))
|
||||
{
|
||||
/**
|
||||
* We set these in tests rather than the regular globals so we don't have
|
||||
@@ -49,7 +43,7 @@ RC_GTEST_FIXTURE_PROP(
|
||||
auto * v = state.allocValue();
|
||||
state.mkOutputString(*v, b, std::nullopt, mockXpSettings);
|
||||
auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, "", mockXpSettings);
|
||||
RC_ASSERT(SingleDerivedPath { b } == d);
|
||||
RC_ASSERT(SingleDerivedPath{b} == d);
|
||||
}
|
||||
|
||||
RC_GTEST_FIXTURE_PROP(
|
||||
@@ -63,7 +57,7 @@ RC_GTEST_FIXTURE_PROP(
|
||||
auto * v = state.allocValue();
|
||||
state.mkOutputString(*v, b, outPath, mockXpSettings);
|
||||
auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, "", mockXpSettings);
|
||||
RC_ASSERT(SingleDerivedPath { b } == d);
|
||||
RC_ASSERT(SingleDerivedPath{b} == d);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,8 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
TEST(nix_isAllowedURI, http_example_com) {
|
||||
TEST(nix_isAllowedURI, http_example_com)
|
||||
{
|
||||
Strings allowed;
|
||||
allowed.push_back("http://example.com");
|
||||
|
||||
@@ -20,7 +21,8 @@ TEST(nix_isAllowedURI, http_example_com) {
|
||||
ASSERT_FALSE(isAllowedURI("http://example.org/foo", allowed));
|
||||
}
|
||||
|
||||
TEST(nix_isAllowedURI, http_example_com_foo) {
|
||||
TEST(nix_isAllowedURI, http_example_com_foo)
|
||||
{
|
||||
Strings allowed;
|
||||
allowed.push_back("http://example.com/foo");
|
||||
|
||||
@@ -34,7 +36,8 @@ TEST(nix_isAllowedURI, http_example_com_foo) {
|
||||
// ASSERT_TRUE(isAllowedURI("http://example.com/foo?ok=1", allowed));
|
||||
}
|
||||
|
||||
TEST(nix_isAllowedURI, http) {
|
||||
TEST(nix_isAllowedURI, http)
|
||||
{
|
||||
Strings allowed;
|
||||
allowed.push_back("http://");
|
||||
|
||||
@@ -48,7 +51,8 @@ TEST(nix_isAllowedURI, http) {
|
||||
ASSERT_FALSE(isAllowedURI("http:foo", allowed));
|
||||
}
|
||||
|
||||
TEST(nix_isAllowedURI, https) {
|
||||
TEST(nix_isAllowedURI, https)
|
||||
{
|
||||
Strings allowed;
|
||||
allowed.push_back("https://");
|
||||
|
||||
@@ -58,7 +62,8 @@ TEST(nix_isAllowedURI, https) {
|
||||
ASSERT_FALSE(isAllowedURI("http://example.com/https:", allowed));
|
||||
}
|
||||
|
||||
TEST(nix_isAllowedURI, absolute_path) {
|
||||
TEST(nix_isAllowedURI, absolute_path)
|
||||
{
|
||||
Strings allowed;
|
||||
allowed.push_back("/var/evil"); // bad idea
|
||||
|
||||
@@ -76,7 +81,8 @@ TEST(nix_isAllowedURI, absolute_path) {
|
||||
ASSERT_FALSE(isAllowedURI("http://example.com//var/evil/foo", allowed));
|
||||
}
|
||||
|
||||
TEST(nix_isAllowedURI, file_url) {
|
||||
TEST(nix_isAllowedURI, file_url)
|
||||
{
|
||||
Strings allowed;
|
||||
allowed.push_back("file:///var/evil"); // bad idea
|
||||
|
||||
@@ -103,7 +109,8 @@ TEST(nix_isAllowedURI, file_url) {
|
||||
ASSERT_FALSE(isAllowedURI("file://", allowed));
|
||||
}
|
||||
|
||||
TEST(nix_isAllowedURI, github_all) {
|
||||
TEST(nix_isAllowedURI, github_all)
|
||||
{
|
||||
Strings allowed;
|
||||
allowed.push_back("github:");
|
||||
ASSERT_TRUE(isAllowedURI("github:", allowed));
|
||||
@@ -117,7 +124,8 @@ TEST(nix_isAllowedURI, github_all) {
|
||||
ASSERT_FALSE(isAllowedURI("github", allowed));
|
||||
}
|
||||
|
||||
TEST(nix_isAllowedURI, github_org) {
|
||||
TEST(nix_isAllowedURI, github_org)
|
||||
{
|
||||
Strings allowed;
|
||||
allowed.push_back("github:foo");
|
||||
ASSERT_FALSE(isAllowedURI("github:", allowed));
|
||||
@@ -130,7 +138,8 @@ TEST(nix_isAllowedURI, github_org) {
|
||||
ASSERT_FALSE(isAllowedURI("file:///github:foo/bar/archive/master.tar.gz", allowed));
|
||||
}
|
||||
|
||||
TEST(nix_isAllowedURI, non_scheme_colon) {
|
||||
TEST(nix_isAllowedURI, non_scheme_colon)
|
||||
{
|
||||
Strings allowed;
|
||||
allowed.push_back("https://foo/bar:");
|
||||
ASSERT_TRUE(isAllowedURI("https://foo/bar:", allowed));
|
||||
@@ -138,16 +147,19 @@ TEST(nix_isAllowedURI, non_scheme_colon) {
|
||||
ASSERT_FALSE(isAllowedURI("https://foo/bar:baz", allowed));
|
||||
}
|
||||
|
||||
class EvalStateTest : public LibExprTest {};
|
||||
class EvalStateTest : public LibExprTest
|
||||
{};
|
||||
|
||||
TEST_F(EvalStateTest, getBuiltins_ok) {
|
||||
TEST_F(EvalStateTest, getBuiltins_ok)
|
||||
{
|
||||
auto evaled = maybeThunk("builtins");
|
||||
auto & builtins = state.getBuiltins();
|
||||
ASSERT_TRUE(builtins.type() == nAttrs);
|
||||
ASSERT_EQ(evaled, &builtins);
|
||||
}
|
||||
|
||||
TEST_F(EvalStateTest, getBuiltin_ok) {
|
||||
TEST_F(EvalStateTest, getBuiltin_ok)
|
||||
{
|
||||
auto & builtin = state.getBuiltin("toString");
|
||||
ASSERT_TRUE(builtin.type() == nFunction);
|
||||
// FIXME
|
||||
@@ -157,7 +169,8 @@ TEST_F(EvalStateTest, getBuiltin_ok) {
|
||||
ASSERT_EQ(state.forceBool(builtin2, noPos, "in unit test"), true);
|
||||
}
|
||||
|
||||
TEST_F(EvalStateTest, getBuiltin_fail) {
|
||||
TEST_F(EvalStateTest, getBuiltin_fail)
|
||||
{
|
||||
ASSERT_THROW(state.getBuiltin("nonexistent"), EvalError);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,65 +4,75 @@
|
||||
namespace nix {
|
||||
// Testing the conversion to JSON
|
||||
|
||||
class JSONValueTest : public LibExprTest {
|
||||
protected:
|
||||
std::string getJSONValue(Value& value) {
|
||||
std::stringstream ss;
|
||||
NixStringContext ps;
|
||||
printValueAsJSON(state, true, value, noPos, ss, ps);
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(JSONValueTest, null) {
|
||||
Value v;
|
||||
v.mkNull();
|
||||
ASSERT_EQ(getJSONValue(v), "null");
|
||||
class JSONValueTest : public LibExprTest
|
||||
{
|
||||
protected:
|
||||
std::string getJSONValue(Value & value)
|
||||
{
|
||||
std::stringstream ss;
|
||||
NixStringContext ps;
|
||||
printValueAsJSON(state, true, value, noPos, ss, ps);
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(JSONValueTest, BoolFalse) {
|
||||
Value v;
|
||||
v.mkBool(false);
|
||||
ASSERT_EQ(getJSONValue(v),"false");
|
||||
}
|
||||
TEST_F(JSONValueTest, null)
|
||||
{
|
||||
Value v;
|
||||
v.mkNull();
|
||||
ASSERT_EQ(getJSONValue(v), "null");
|
||||
}
|
||||
|
||||
TEST_F(JSONValueTest, BoolTrue) {
|
||||
Value v;
|
||||
v.mkBool(true);
|
||||
ASSERT_EQ(getJSONValue(v), "true");
|
||||
}
|
||||
TEST_F(JSONValueTest, BoolFalse)
|
||||
{
|
||||
Value v;
|
||||
v.mkBool(false);
|
||||
ASSERT_EQ(getJSONValue(v), "false");
|
||||
}
|
||||
|
||||
TEST_F(JSONValueTest, IntPositive) {
|
||||
Value v;
|
||||
v.mkInt(100);
|
||||
ASSERT_EQ(getJSONValue(v), "100");
|
||||
}
|
||||
TEST_F(JSONValueTest, BoolTrue)
|
||||
{
|
||||
Value v;
|
||||
v.mkBool(true);
|
||||
ASSERT_EQ(getJSONValue(v), "true");
|
||||
}
|
||||
|
||||
TEST_F(JSONValueTest, IntNegative) {
|
||||
Value v;
|
||||
v.mkInt(-100);
|
||||
ASSERT_EQ(getJSONValue(v), "-100");
|
||||
}
|
||||
TEST_F(JSONValueTest, IntPositive)
|
||||
{
|
||||
Value v;
|
||||
v.mkInt(100);
|
||||
ASSERT_EQ(getJSONValue(v), "100");
|
||||
}
|
||||
|
||||
TEST_F(JSONValueTest, String) {
|
||||
Value v;
|
||||
v.mkString("test");
|
||||
ASSERT_EQ(getJSONValue(v), "\"test\"");
|
||||
}
|
||||
TEST_F(JSONValueTest, IntNegative)
|
||||
{
|
||||
Value v;
|
||||
v.mkInt(-100);
|
||||
ASSERT_EQ(getJSONValue(v), "-100");
|
||||
}
|
||||
|
||||
TEST_F(JSONValueTest, StringQuotes) {
|
||||
Value v;
|
||||
TEST_F(JSONValueTest, String)
|
||||
{
|
||||
Value v;
|
||||
v.mkString("test");
|
||||
ASSERT_EQ(getJSONValue(v), "\"test\"");
|
||||
}
|
||||
|
||||
v.mkString("test\"");
|
||||
ASSERT_EQ(getJSONValue(v), "\"test\\\"\"");
|
||||
}
|
||||
TEST_F(JSONValueTest, StringQuotes)
|
||||
{
|
||||
Value v;
|
||||
|
||||
// The dummy store doesn't support writing files. Fails with this exception message:
|
||||
// C++ exception with description "error: operation 'addToStoreFromDump' is
|
||||
// not supported by store 'dummy'" thrown in the test body.
|
||||
TEST_F(JSONValueTest, DISABLED_Path) {
|
||||
Value v;
|
||||
v.mkPath(state.rootPath(CanonPath("/test")));
|
||||
ASSERT_EQ(getJSONValue(v), "\"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x\"");
|
||||
}
|
||||
v.mkString("test\"");
|
||||
ASSERT_EQ(getJSONValue(v), "\"test\\\"\"");
|
||||
}
|
||||
|
||||
// The dummy store doesn't support writing files. Fails with this exception message:
|
||||
// C++ exception with description "error: operation 'addToStoreFromDump' is
|
||||
// not supported by store 'dummy'" thrown in the test body.
|
||||
TEST_F(JSONValueTest, DISABLED_Path)
|
||||
{
|
||||
Value v;
|
||||
v.mkPath(state.rootPath(CanonPath("/test")));
|
||||
ASSERT_EQ(getJSONValue(v), "\"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x\"");
|
||||
}
|
||||
} /* namespace nix */
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
using namespace nix;
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
if (argc > 1 && std::string_view(argv[1]) == "__build-remote") {
|
||||
printError("test-build-remote: not supported in libexpr unit tests");
|
||||
return 1;
|
||||
@@ -14,25 +15,26 @@ int main (int argc, char **argv) {
|
||||
// Disable build hook. We won't be testing remote builds in these unit tests. If we do, fix the above build hook.
|
||||
settings.buildHook = {};
|
||||
|
||||
#ifdef __linux__ // should match the conditional around sandboxBuildDir declaration.
|
||||
#ifdef __linux__ // should match the conditional around sandboxBuildDir declaration.
|
||||
|
||||
// When building and testing nix within the host's Nix sandbox, our store dir will be located in the host's sandboxBuildDir, e.g.:
|
||||
// Host
|
||||
// When building and testing nix within the host's Nix sandbox, our store dir will be located in the host's
|
||||
// sandboxBuildDir, e.g.: Host
|
||||
// storeDir = /nix/store
|
||||
// sandboxBuildDir = /build
|
||||
// This process
|
||||
// storeDir = /build/foo/bar/store
|
||||
// sandboxBuildDir = /build
|
||||
// However, we have a rule that the store dir must not be inside the storeDir, so we need to pick a different sandboxBuildDir.
|
||||
// However, we have a rule that the store dir must not be inside the storeDir, so we need to pick a different
|
||||
// sandboxBuildDir.
|
||||
settings.sandboxBuildDir = "/test-build-dir-instead-of-usual-build-dir";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifdef __APPLE__
|
||||
// Avoid this error, when already running in a sandbox:
|
||||
// sandbox-exec: sandbox_apply: Operation not permitted
|
||||
settings.sandboxMode = smDisabled;
|
||||
setEnv("_NIX_TEST_NO_SANDBOX", "1");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// For pipe operator tests in trivial.cc
|
||||
experimentalFeatureSettings.set("experimental-features", "pipe-operators");
|
||||
|
||||
@@ -32,8 +32,8 @@ deps_private += rapidcheck
|
||||
gtest = dependency('gtest')
|
||||
deps_private += gtest
|
||||
|
||||
gtest = dependency('gmock')
|
||||
deps_private += gtest
|
||||
gmock = dependency('gmock')
|
||||
deps_private += gmock
|
||||
|
||||
configdata = configuration_data()
|
||||
configdata.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||
|
||||
@@ -394,6 +394,7 @@ static void primop_bad_return_thunk(
|
||||
{
|
||||
nix_init_apply(context, ret, args[0], args[1]);
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_expr_primop_bad_return_thunk)
|
||||
{
|
||||
PrimOp * primop =
|
||||
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
|
||||
private:
|
||||
int _x;
|
||||
|
||||
static void print_function(void * self, nix_printer * printer) {}
|
||||
|
||||
static void show_type_function(void * self, nix_string_return * res) {}
|
||||
@@ -68,4 +69,4 @@ TEST_F(nix_api_expr_test, nix_expr_eval_external)
|
||||
nix_state_free(stateFn);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nixC
|
||||
|
||||
@@ -120,6 +120,7 @@ TEST_F(nix_api_expr_test, nix_value_set_get_path_invalid)
|
||||
ASSERT_EQ(nullptr, nix_get_path_string(ctx, value));
|
||||
assert_ctx_err();
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_path)
|
||||
{
|
||||
const char * p = "/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname";
|
||||
@@ -399,4 +400,4 @@ TEST_F(nix_api_expr_test, nix_copy_value)
|
||||
nix_gc_decref(ctx, source);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nixC
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,86 +5,98 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
TEST(LookupPathElem, parse_justPath) {
|
||||
TEST(LookupPathElem, parse_justPath)
|
||||
{
|
||||
ASSERT_EQ(
|
||||
LookupPath::Elem::parse("foo"),
|
||||
(LookupPath::Elem {
|
||||
.prefix = LookupPath::Prefix { .s = "" },
|
||||
.path = LookupPath::Path { .s = "foo" },
|
||||
(LookupPath::Elem{
|
||||
.prefix = LookupPath::Prefix{.s = ""},
|
||||
.path = LookupPath::Path{.s = "foo"},
|
||||
}));
|
||||
}
|
||||
|
||||
TEST(LookupPathElem, parse_emptyPrefix) {
|
||||
TEST(LookupPathElem, parse_emptyPrefix)
|
||||
{
|
||||
ASSERT_EQ(
|
||||
LookupPath::Elem::parse("=foo"),
|
||||
(LookupPath::Elem {
|
||||
.prefix = LookupPath::Prefix { .s = "" },
|
||||
.path = LookupPath::Path { .s = "foo" },
|
||||
(LookupPath::Elem{
|
||||
.prefix = LookupPath::Prefix{.s = ""},
|
||||
.path = LookupPath::Path{.s = "foo"},
|
||||
}));
|
||||
}
|
||||
|
||||
TEST(LookupPathElem, parse_oneEq) {
|
||||
TEST(LookupPathElem, parse_oneEq)
|
||||
{
|
||||
ASSERT_EQ(
|
||||
LookupPath::Elem::parse("foo=bar"),
|
||||
(LookupPath::Elem {
|
||||
.prefix = LookupPath::Prefix { .s = "foo" },
|
||||
.path = LookupPath::Path { .s = "bar" },
|
||||
(LookupPath::Elem{
|
||||
.prefix = LookupPath::Prefix{.s = "foo"},
|
||||
.path = LookupPath::Path{.s = "bar"},
|
||||
}));
|
||||
}
|
||||
|
||||
TEST(LookupPathElem, parse_twoEqs) {
|
||||
TEST(LookupPathElem, parse_twoEqs)
|
||||
{
|
||||
ASSERT_EQ(
|
||||
LookupPath::Elem::parse("foo=bar=baz"),
|
||||
(LookupPath::Elem {
|
||||
.prefix = LookupPath::Prefix { .s = "foo" },
|
||||
.path = LookupPath::Path { .s = "bar=baz" },
|
||||
(LookupPath::Elem{
|
||||
.prefix = LookupPath::Prefix{.s = "foo"},
|
||||
.path = LookupPath::Path{.s = "bar=baz"},
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_justPath) {
|
||||
LookupPath::Prefix prefix { .s = "" };
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("any/thing"), std::optional { "any/thing" });
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_justPath)
|
||||
{
|
||||
LookupPath::Prefix prefix{.s = ""};
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("any/thing"), std::optional{"any/thing"});
|
||||
}
|
||||
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_misleadingPrefix1) {
|
||||
LookupPath::Prefix prefix { .s = "foo" };
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_misleadingPrefix1)
|
||||
{
|
||||
LookupPath::Prefix prefix{.s = "foo"};
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX"), std::nullopt);
|
||||
}
|
||||
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_misleadingPrefix2) {
|
||||
LookupPath::Prefix prefix { .s = "foo" };
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_misleadingPrefix2)
|
||||
{
|
||||
LookupPath::Prefix prefix{.s = "foo"};
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX/bar"), std::nullopt);
|
||||
}
|
||||
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_partialPrefix) {
|
||||
LookupPath::Prefix prefix { .s = "fooX" };
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_partialPrefix)
|
||||
{
|
||||
LookupPath::Prefix prefix{.s = "fooX"};
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::nullopt);
|
||||
}
|
||||
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_exactPrefix) {
|
||||
LookupPath::Prefix prefix { .s = "foo" };
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::optional { "" });
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_exactPrefix)
|
||||
{
|
||||
LookupPath::Prefix prefix{.s = "foo"};
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::optional{""});
|
||||
}
|
||||
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_multiKey) {
|
||||
LookupPath::Prefix prefix { .s = "foo/bar" };
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "baz" });
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_multiKey)
|
||||
{
|
||||
LookupPath::Prefix prefix{.s = "foo/bar"};
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional{"baz"});
|
||||
}
|
||||
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_trailingSlash) {
|
||||
LookupPath::Prefix prefix { .s = "foo" };
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/"), std::optional { "" });
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_trailingSlash)
|
||||
{
|
||||
LookupPath::Prefix prefix{.s = "foo"};
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/"), std::optional{""});
|
||||
}
|
||||
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_trailingDoubleSlash) {
|
||||
LookupPath::Prefix prefix { .s = "foo" };
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo//"), std::optional { "/" });
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_trailingDoubleSlash)
|
||||
{
|
||||
LookupPath::Prefix prefix{.s = "foo"};
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo//"), std::optional{"/"});
|
||||
}
|
||||
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_trailingPath) {
|
||||
LookupPath::Prefix prefix { .s = "foo" };
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "bar/baz" });
|
||||
TEST(LookupPathElem, suffixIfPotentialMatch_trailingPath)
|
||||
{
|
||||
LookupPath::Prefix prefix{.s = "foo"};
|
||||
ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional{"bar/baz"});
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -1,181 +1,202 @@
|
||||
#include "nix/expr/tests/libexpr.hh"
|
||||
|
||||
namespace nix {
|
||||
// Testing of trivial expressions
|
||||
class TrivialExpressionTest : public LibExprTest {};
|
||||
// Testing of trivial expressions
|
||||
class TrivialExpressionTest : public LibExprTest
|
||||
{};
|
||||
|
||||
TEST_F(TrivialExpressionTest, true) {
|
||||
auto v = eval("true");
|
||||
ASSERT_THAT(v, IsTrue());
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, true)
|
||||
{
|
||||
auto v = eval("true");
|
||||
ASSERT_THAT(v, IsTrue());
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, false) {
|
||||
auto v = eval("false");
|
||||
ASSERT_THAT(v, IsFalse());
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, false)
|
||||
{
|
||||
auto v = eval("false");
|
||||
ASSERT_THAT(v, IsFalse());
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, null) {
|
||||
auto v = eval("null");
|
||||
ASSERT_THAT(v, IsNull());
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, null)
|
||||
{
|
||||
auto v = eval("null");
|
||||
ASSERT_THAT(v, IsNull());
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, 1) {
|
||||
auto v = eval("1");
|
||||
ASSERT_THAT(v, IsIntEq(1));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, 1)
|
||||
{
|
||||
auto v = eval("1");
|
||||
ASSERT_THAT(v, IsIntEq(1));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, 1plus1) {
|
||||
auto v = eval("1+1");
|
||||
ASSERT_THAT(v, IsIntEq(2));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, 1plus1)
|
||||
{
|
||||
auto v = eval("1+1");
|
||||
ASSERT_THAT(v, IsIntEq(2));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, minus1) {
|
||||
auto v = eval("-1");
|
||||
ASSERT_THAT(v, IsIntEq(-1));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, minus1)
|
||||
{
|
||||
auto v = eval("-1");
|
||||
ASSERT_THAT(v, IsIntEq(-1));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, 1minus1) {
|
||||
auto v = eval("1-1");
|
||||
ASSERT_THAT(v, IsIntEq(0));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, 1minus1)
|
||||
{
|
||||
auto v = eval("1-1");
|
||||
ASSERT_THAT(v, IsIntEq(0));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, lambdaAdd) {
|
||||
auto v = eval("let add = a: b: a + b; in add 1 2");
|
||||
ASSERT_THAT(v, IsIntEq(3));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, lambdaAdd)
|
||||
{
|
||||
auto v = eval("let add = a: b: a + b; in add 1 2");
|
||||
ASSERT_THAT(v, IsIntEq(3));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, list) {
|
||||
auto v = eval("[]");
|
||||
ASSERT_THAT(v, IsListOfSize(0));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, list)
|
||||
{
|
||||
auto v = eval("[]");
|
||||
ASSERT_THAT(v, IsListOfSize(0));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, attrs) {
|
||||
auto v = eval("{}");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(0));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, attrs)
|
||||
{
|
||||
auto v = eval("{}");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(0));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, float) {
|
||||
auto v = eval("1.234");
|
||||
ASSERT_THAT(v, IsFloatEq(1.234));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, float)
|
||||
{
|
||||
auto v = eval("1.234");
|
||||
ASSERT_THAT(v, IsFloatEq(1.234));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, updateAttrs) {
|
||||
auto v = eval("{ a = 1; } // { b = 2; a = 3; }");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(2));
|
||||
auto a = v.attrs()->find(createSymbol("a"));
|
||||
ASSERT_NE(a, nullptr);
|
||||
ASSERT_THAT(*a->value, IsIntEq(3));
|
||||
TEST_F(TrivialExpressionTest, updateAttrs)
|
||||
{
|
||||
auto v = eval("{ a = 1; } // { b = 2; a = 3; }");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(2));
|
||||
auto a = v.attrs()->find(createSymbol("a"));
|
||||
ASSERT_NE(a, nullptr);
|
||||
ASSERT_THAT(*a->value, IsIntEq(3));
|
||||
|
||||
auto b = v.attrs()->find(createSymbol("b"));
|
||||
ASSERT_NE(b, nullptr);
|
||||
ASSERT_THAT(*b->value, IsIntEq(2));
|
||||
}
|
||||
auto b = v.attrs()->find(createSymbol("b"));
|
||||
ASSERT_NE(b, nullptr);
|
||||
ASSERT_THAT(*b->value, IsIntEq(2));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, hasAttrOpFalse) {
|
||||
auto v = eval("{} ? a");
|
||||
ASSERT_THAT(v, IsFalse());
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, hasAttrOpFalse)
|
||||
{
|
||||
auto v = eval("{} ? a");
|
||||
ASSERT_THAT(v, IsFalse());
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, hasAttrOpTrue) {
|
||||
auto v = eval("{ a = 123; } ? a");
|
||||
ASSERT_THAT(v, IsTrue());
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, hasAttrOpTrue)
|
||||
{
|
||||
auto v = eval("{ a = 123; } ? a");
|
||||
ASSERT_THAT(v, IsTrue());
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, withFound) {
|
||||
auto v = eval("with { a = 23; }; a");
|
||||
ASSERT_THAT(v, IsIntEq(23));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, withFound)
|
||||
{
|
||||
auto v = eval("with { a = 23; }; a");
|
||||
ASSERT_THAT(v, IsIntEq(23));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, withNotFound) {
|
||||
ASSERT_THROW(eval("with {}; a"), Error);
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, withNotFound)
|
||||
{
|
||||
ASSERT_THROW(eval("with {}; a"), Error);
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, withOverride) {
|
||||
auto v = eval("with { a = 23; }; with { a = 42; }; a");
|
||||
ASSERT_THAT(v, IsIntEq(42));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, withOverride)
|
||||
{
|
||||
auto v = eval("with { a = 23; }; with { a = 42; }; a");
|
||||
ASSERT_THAT(v, IsIntEq(42));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, letOverWith) {
|
||||
auto v = eval("let a = 23; in with { a = 1; }; a");
|
||||
ASSERT_THAT(v, IsIntEq(23));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, letOverWith)
|
||||
{
|
||||
auto v = eval("let a = 23; in with { a = 1; }; a");
|
||||
ASSERT_THAT(v, IsIntEq(23));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, multipleLet) {
|
||||
auto v = eval("let a = 23; in let a = 42; in a");
|
||||
ASSERT_THAT(v, IsIntEq(42));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, multipleLet)
|
||||
{
|
||||
auto v = eval("let a = 23; in let a = 42; in a");
|
||||
ASSERT_THAT(v, IsIntEq(42));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, defaultFunctionArgs) {
|
||||
auto v = eval("({ a ? 123 }: a) {}");
|
||||
ASSERT_THAT(v, IsIntEq(123));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, defaultFunctionArgs)
|
||||
{
|
||||
auto v = eval("({ a ? 123 }: a) {}");
|
||||
ASSERT_THAT(v, IsIntEq(123));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, defaultFunctionArgsOverride) {
|
||||
auto v = eval("({ a ? 123 }: a) { a = 5; }");
|
||||
ASSERT_THAT(v, IsIntEq(5));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, defaultFunctionArgsOverride)
|
||||
{
|
||||
auto v = eval("({ a ? 123 }: a) { a = 5; }");
|
||||
ASSERT_THAT(v, IsIntEq(5));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureBack) {
|
||||
auto v = eval("({ a ? 123 }@args: args) {}");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(0));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureBack)
|
||||
{
|
||||
auto v = eval("({ a ? 123 }@args: args) {}");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(0));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureFront) {
|
||||
auto v = eval("(args@{ a ? 123 }: args) {}");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(0));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureFront)
|
||||
{
|
||||
auto v = eval("(args@{ a ? 123 }: args) {}");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(0));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, assertThrows) {
|
||||
ASSERT_THROW(eval("let x = arg: assert arg == 1; 123; in x 2"), Error);
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, assertThrows)
|
||||
{
|
||||
ASSERT_THROW(eval("let x = arg: assert arg == 1; 123; in x 2"), Error);
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, assertPassed) {
|
||||
auto v = eval("let x = arg: assert arg == 1; 123; in x 1");
|
||||
ASSERT_THAT(v, IsIntEq(123));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, assertPassed)
|
||||
{
|
||||
auto v = eval("let x = arg: assert arg == 1; 123; in x 1");
|
||||
ASSERT_THAT(v, IsIntEq(123));
|
||||
}
|
||||
|
||||
class AttrSetMergeTrvialExpressionTest :
|
||||
public TrivialExpressionTest,
|
||||
public testing::WithParamInterface<const char*>
|
||||
{};
|
||||
class AttrSetMergeTrvialExpressionTest : public TrivialExpressionTest, public testing::WithParamInterface<const char *>
|
||||
{};
|
||||
|
||||
TEST_P(AttrSetMergeTrvialExpressionTest, attrsetMergeLazy) {
|
||||
// Usually Nix rejects duplicate keys in an attrset but it does allow
|
||||
// so if it is an attribute set that contains disjoint sets of keys.
|
||||
// The below is equivalent to `{a.b = 1; a.c = 2; }`.
|
||||
// The attribute set `a` will be a Thunk at first as the attribuets
|
||||
// have to be merged (or otherwise computed) and that is done in a lazy
|
||||
// manner.
|
||||
TEST_P(AttrSetMergeTrvialExpressionTest, attrsetMergeLazy)
|
||||
{
|
||||
// Usually Nix rejects duplicate keys in an attrset but it does allow
|
||||
// so if it is an attribute set that contains disjoint sets of keys.
|
||||
// The below is equivalent to `{a.b = 1; a.c = 2; }`.
|
||||
// The attribute set `a` will be a Thunk at first as the attribuets
|
||||
// have to be merged (or otherwise computed) and that is done in a lazy
|
||||
// manner.
|
||||
|
||||
auto expr = GetParam();
|
||||
auto v = eval(expr);
|
||||
ASSERT_THAT(v, IsAttrsOfSize(1));
|
||||
auto expr = GetParam();
|
||||
auto v = eval(expr);
|
||||
ASSERT_THAT(v, IsAttrsOfSize(1));
|
||||
|
||||
auto a = v.attrs()->find(createSymbol("a"));
|
||||
ASSERT_NE(a, nullptr);
|
||||
auto a = v.attrs()->find(createSymbol("a"));
|
||||
ASSERT_NE(a, nullptr);
|
||||
|
||||
ASSERT_THAT(*a->value, IsThunk());
|
||||
state.forceValue(*a->value, noPos);
|
||||
ASSERT_THAT(*a->value, IsThunk());
|
||||
state.forceValue(*a->value, noPos);
|
||||
|
||||
ASSERT_THAT(*a->value, IsAttrsOfSize(2));
|
||||
ASSERT_THAT(*a->value, IsAttrsOfSize(2));
|
||||
|
||||
auto b = a->value->attrs()->find(createSymbol("b"));
|
||||
ASSERT_NE(b, nullptr);
|
||||
ASSERT_THAT(*b->value, IsIntEq(1));
|
||||
auto b = a->value->attrs()->find(createSymbol("b"));
|
||||
ASSERT_NE(b, nullptr);
|
||||
ASSERT_THAT(*b->value, IsIntEq(1));
|
||||
|
||||
auto c = a->value->attrs()->find(createSymbol("c"));
|
||||
ASSERT_NE(c, nullptr);
|
||||
ASSERT_THAT(*c->value, IsIntEq(2));
|
||||
}
|
||||
auto c = a->value->attrs()->find(createSymbol("c"));
|
||||
ASSERT_NE(c, nullptr);
|
||||
ASSERT_THAT(*c->value, IsIntEq(2));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
attrsetMergeLazy,
|
||||
AttrSetMergeTrvialExpressionTest,
|
||||
testing::Values(
|
||||
"{ a.b = 1; a.c = 2; }",
|
||||
"{ a = { b = 1; }; a = { c = 2; }; }"
|
||||
)
|
||||
);
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
attrsetMergeLazy,
|
||||
AttrSetMergeTrvialExpressionTest,
|
||||
testing::Values("{ a.b = 1; a.c = 2; }", "{ a = { b = 1; }; a = { c = 2; }; }"));
|
||||
|
||||
// The following macros ultimately define 48 tests (16 variations on three
|
||||
// templates). Each template tests an expression that can be written in 2^4
|
||||
@@ -199,28 +220,34 @@ namespace nix {
|
||||
// expanded.
|
||||
#define X_EXPAND_IF0(k, v) k "." v
|
||||
#define X_EXPAND_IF1(k, v) k " = { " v " };"
|
||||
#define X4(w, x, y, z) \
|
||||
TEST_F(TrivialExpressionTest, nestedAttrsetMerge##w##x##y##z) { \
|
||||
auto v = eval("{ a.b = { c = 1; d = 2; }; } == { " \
|
||||
X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \
|
||||
X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " }"); \
|
||||
ASSERT_THAT(v, IsTrue()); \
|
||||
}; \
|
||||
TEST_F(TrivialExpressionTest, nestedAttrsetMergeDup##w##x##y##z) { \
|
||||
ASSERT_THROW(eval("{ " \
|
||||
X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \
|
||||
X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "c = 2;")) " }"), Error); \
|
||||
}; \
|
||||
TEST_F(TrivialExpressionTest, nestedAttrsetMergeLet##w##x##y##z) { \
|
||||
auto v = eval("{ b = { c = 1; d = 2; }; } == (let " \
|
||||
X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \
|
||||
X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " in a)"); \
|
||||
ASSERT_THAT(v, IsTrue()); \
|
||||
#define X4(w, x, y, z) \
|
||||
TEST_F(TrivialExpressionTest, nestedAttrsetMerge##w##x##y##z) \
|
||||
{ \
|
||||
auto v = eval( \
|
||||
"{ a.b = { c = 1; d = 2; }; } == { " X_EXPAND_IF##w( \
|
||||
"a", X_EXPAND_IF##x("b", "c = 1;")) " " X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " }"); \
|
||||
ASSERT_THAT(v, IsTrue()); \
|
||||
}; \
|
||||
TEST_F(TrivialExpressionTest, nestedAttrsetMergeDup##w##x##y##z) \
|
||||
{ \
|
||||
ASSERT_THROW( \
|
||||
eval( \
|
||||
"{ " X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " X_EXPAND_IF##y( \
|
||||
"a", X_EXPAND_IF##z("b", "c = 2;")) " }"), \
|
||||
Error); \
|
||||
}; \
|
||||
TEST_F(TrivialExpressionTest, nestedAttrsetMergeLet##w##x##y##z) \
|
||||
{ \
|
||||
auto v = eval( \
|
||||
"{ b = { c = 1; d = 2; }; } == (let " X_EXPAND_IF##w( \
|
||||
"a", X_EXPAND_IF##x("b", "c = 1;")) " " X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " in a)"); \
|
||||
ASSERT_THAT(v, IsTrue()); \
|
||||
};
|
||||
#define X3(...) X4(__VA_ARGS__, 0) X4(__VA_ARGS__, 1)
|
||||
#define X2(...) X3(__VA_ARGS__, 0) X3(__VA_ARGS__, 1)
|
||||
#define X1(...) X2(__VA_ARGS__, 0) X2(__VA_ARGS__, 1)
|
||||
X1(0) X1(1)
|
||||
X1(0)
|
||||
X1(1)
|
||||
#undef X_EXPAND_IF0
|
||||
#undef X_EXPAND_IF1
|
||||
#undef X1
|
||||
@@ -228,74 +255,88 @@ namespace nix {
|
||||
#undef X3
|
||||
#undef X4
|
||||
|
||||
TEST_F(TrivialExpressionTest, functor) {
|
||||
auto v = eval("{ __functor = self: arg: self.v + arg; v = 10; } 5");
|
||||
ASSERT_THAT(v, IsIntEq(15));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, functor)
|
||||
{
|
||||
auto v = eval("{ __functor = self: arg: self.v + arg; v = 10; } 5");
|
||||
ASSERT_THAT(v, IsIntEq(15));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, forwardPipe) {
|
||||
auto v = eval("1 |> builtins.add 2 |> builtins.mul 3");
|
||||
ASSERT_THAT(v, IsIntEq(9));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, forwardPipe)
|
||||
{
|
||||
auto v = eval("1 |> builtins.add 2 |> builtins.mul 3");
|
||||
ASSERT_THAT(v, IsIntEq(9));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, backwardPipe) {
|
||||
auto v = eval("builtins.add 1 <| builtins.mul 2 <| 3");
|
||||
ASSERT_THAT(v, IsIntEq(7));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, backwardPipe)
|
||||
{
|
||||
auto v = eval("builtins.add 1 <| builtins.mul 2 <| 3");
|
||||
ASSERT_THAT(v, IsIntEq(7));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, forwardPipeEvaluationOrder) {
|
||||
auto v = eval("1 |> null |> (x: 2)");
|
||||
ASSERT_THAT(v, IsIntEq(2));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, forwardPipeEvaluationOrder)
|
||||
{
|
||||
auto v = eval("1 |> null |> (x: 2)");
|
||||
ASSERT_THAT(v, IsIntEq(2));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, backwardPipeEvaluationOrder) {
|
||||
auto v = eval("(x: 1) <| null <| 2");
|
||||
ASSERT_THAT(v, IsIntEq(1));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, backwardPipeEvaluationOrder)
|
||||
{
|
||||
auto v = eval("(x: 1) <| null <| 2");
|
||||
ASSERT_THAT(v, IsIntEq(1));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, differentPipeOperatorsDoNotAssociate) {
|
||||
ASSERT_THROW(eval("(x: 1) <| 2 |> (x: 3)"), ParseError);
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, differentPipeOperatorsDoNotAssociate)
|
||||
{
|
||||
ASSERT_THROW(eval("(x: 1) <| 2 |> (x: 3)"), ParseError);
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, differentPipeOperatorsParensLeft) {
|
||||
auto v = eval("((x: 1) <| 2) |> (x: 3)");
|
||||
ASSERT_THAT(v, IsIntEq(3));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, differentPipeOperatorsParensLeft)
|
||||
{
|
||||
auto v = eval("((x: 1) <| 2) |> (x: 3)");
|
||||
ASSERT_THAT(v, IsIntEq(3));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, differentPipeOperatorsParensRight) {
|
||||
auto v = eval("(x: 1) <| (2 |> (x: 3))");
|
||||
ASSERT_THAT(v, IsIntEq(1));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, differentPipeOperatorsParensRight)
|
||||
{
|
||||
auto v = eval("(x: 1) <| (2 |> (x: 3))");
|
||||
ASSERT_THAT(v, IsIntEq(1));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, forwardPipeLowestPrecedence) {
|
||||
auto v = eval("false -> true |> (x: !x)");
|
||||
ASSERT_THAT(v, IsFalse());
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, forwardPipeLowestPrecedence)
|
||||
{
|
||||
auto v = eval("false -> true |> (x: !x)");
|
||||
ASSERT_THAT(v, IsFalse());
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, backwardPipeLowestPrecedence) {
|
||||
auto v = eval("(x: !x) <| false -> true");
|
||||
ASSERT_THAT(v, IsFalse());
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, backwardPipeLowestPrecedence)
|
||||
{
|
||||
auto v = eval("(x: !x) <| false -> true");
|
||||
ASSERT_THAT(v, IsFalse());
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, forwardPipeStrongerThanElse) {
|
||||
auto v = eval("if true then 1 else 2 |> 3");
|
||||
ASSERT_THAT(v, IsIntEq(1));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, forwardPipeStrongerThanElse)
|
||||
{
|
||||
auto v = eval("if true then 1 else 2 |> 3");
|
||||
ASSERT_THAT(v, IsIntEq(1));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, backwardPipeStrongerThanElse) {
|
||||
auto v = eval("if true then 1 else 2 <| 3");
|
||||
ASSERT_THAT(v, IsIntEq(1));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, backwardPipeStrongerThanElse)
|
||||
{
|
||||
auto v = eval("if true then 1 else 2 <| 3");
|
||||
ASSERT_THAT(v, IsIntEq(1));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, bindOr) {
|
||||
auto v = eval("{ or = 1; }");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(1));
|
||||
auto b = v.attrs()->find(createSymbol("or"));
|
||||
ASSERT_NE(b, nullptr);
|
||||
ASSERT_THAT(*b->value, IsIntEq(1));
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, bindOr)
|
||||
{
|
||||
auto v = eval("{ or = 1; }");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(1));
|
||||
auto b = v.attrs()->find(createSymbol("or"));
|
||||
ASSERT_NE(b, nullptr);
|
||||
ASSERT_THAT(*b->value, IsIntEq(1));
|
||||
}
|
||||
|
||||
TEST_F(TrivialExpressionTest, orCantBeUsed) {
|
||||
ASSERT_THROW(eval("let or = 1; in or"), Error);
|
||||
}
|
||||
TEST_F(TrivialExpressionTest, orCantBeUsed)
|
||||
{
|
||||
ASSERT_THROW(eval("let or = 1; in or"), Error);
|
||||
}
|
||||
} /* namespace nix */
|
||||
|
||||
@@ -10,46 +10,42 @@ namespace nix {
|
||||
|
||||
// Test a few cases of invalid string context elements.
|
||||
|
||||
TEST(NixStringContextElemTest, empty_invalid) {
|
||||
EXPECT_THROW(
|
||||
NixStringContextElem::parse(""),
|
||||
BadNixStringContextElem);
|
||||
TEST(NixStringContextElemTest, empty_invalid)
|
||||
{
|
||||
EXPECT_THROW(NixStringContextElem::parse(""), BadNixStringContextElem);
|
||||
}
|
||||
|
||||
TEST(NixStringContextElemTest, single_bang_invalid) {
|
||||
EXPECT_THROW(
|
||||
NixStringContextElem::parse("!"),
|
||||
BadNixStringContextElem);
|
||||
TEST(NixStringContextElemTest, single_bang_invalid)
|
||||
{
|
||||
EXPECT_THROW(NixStringContextElem::parse("!"), BadNixStringContextElem);
|
||||
}
|
||||
|
||||
TEST(NixStringContextElemTest, double_bang_invalid) {
|
||||
EXPECT_THROW(
|
||||
NixStringContextElem::parse("!!/"),
|
||||
BadStorePath);
|
||||
TEST(NixStringContextElemTest, double_bang_invalid)
|
||||
{
|
||||
EXPECT_THROW(NixStringContextElem::parse("!!/"), BadStorePath);
|
||||
}
|
||||
|
||||
TEST(NixStringContextElemTest, eq_slash_invalid) {
|
||||
EXPECT_THROW(
|
||||
NixStringContextElem::parse("=/"),
|
||||
BadStorePath);
|
||||
TEST(NixStringContextElemTest, eq_slash_invalid)
|
||||
{
|
||||
EXPECT_THROW(NixStringContextElem::parse("=/"), BadStorePath);
|
||||
}
|
||||
|
||||
TEST(NixStringContextElemTest, slash_invalid) {
|
||||
EXPECT_THROW(
|
||||
NixStringContextElem::parse("/"),
|
||||
BadStorePath);
|
||||
TEST(NixStringContextElemTest, slash_invalid)
|
||||
{
|
||||
EXPECT_THROW(NixStringContextElem::parse("/"), BadStorePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Round trip (string <-> data structure) test for
|
||||
* `NixStringContextElem::Opaque`.
|
||||
*/
|
||||
TEST(NixStringContextElemTest, opaque) {
|
||||
TEST(NixStringContextElemTest, opaque)
|
||||
{
|
||||
std::string_view opaque = "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x";
|
||||
auto elem = NixStringContextElem::parse(opaque);
|
||||
auto * p = std::get_if<NixStringContextElem::Opaque>(&elem.raw);
|
||||
ASSERT_TRUE(p);
|
||||
ASSERT_EQ(p->path, StorePath { opaque });
|
||||
ASSERT_EQ(p->path, StorePath{opaque});
|
||||
ASSERT_EQ(elem.to_string(), opaque);
|
||||
}
|
||||
|
||||
@@ -57,12 +53,13 @@ TEST(NixStringContextElemTest, opaque) {
|
||||
* Round trip (string <-> data structure) test for
|
||||
* `NixStringContextElem::DrvDeep`.
|
||||
*/
|
||||
TEST(NixStringContextElemTest, drvDeep) {
|
||||
TEST(NixStringContextElemTest, drvDeep)
|
||||
{
|
||||
std::string_view drvDeep = "=g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv";
|
||||
auto elem = NixStringContextElem::parse(drvDeep);
|
||||
auto * p = std::get_if<NixStringContextElem::DrvDeep>(&elem.raw);
|
||||
ASSERT_TRUE(p);
|
||||
ASSERT_EQ(p->drvPath, StorePath { drvDeep.substr(1) });
|
||||
ASSERT_EQ(p->drvPath, StorePath{drvDeep.substr(1)});
|
||||
ASSERT_EQ(elem.to_string(), drvDeep);
|
||||
}
|
||||
|
||||
@@ -70,15 +67,18 @@ TEST(NixStringContextElemTest, drvDeep) {
|
||||
* Round trip (string <-> data structure) test for a simpler
|
||||
* `NixStringContextElem::Built`.
|
||||
*/
|
||||
TEST(NixStringContextElemTest, built_opaque) {
|
||||
TEST(NixStringContextElemTest, built_opaque)
|
||||
{
|
||||
std::string_view built = "!foo!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv";
|
||||
auto elem = NixStringContextElem::parse(built);
|
||||
auto * p = std::get_if<NixStringContextElem::Built>(&elem.raw);
|
||||
ASSERT_TRUE(p);
|
||||
ASSERT_EQ(p->output, "foo");
|
||||
ASSERT_EQ(*p->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque {
|
||||
.path = StorePath { built.substr(5) },
|
||||
}));
|
||||
ASSERT_EQ(
|
||||
*p->drvPath,
|
||||
((SingleDerivedPath) SingleDerivedPath::Opaque{
|
||||
.path = StorePath{built.substr(5)},
|
||||
}));
|
||||
ASSERT_EQ(elem.to_string(), built);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,8 @@ TEST(NixStringContextElemTest, built_opaque) {
|
||||
* Round trip (string <-> data structure) test for a more complex,
|
||||
* inductive `NixStringContextElem::Built`.
|
||||
*/
|
||||
TEST(NixStringContextElemTest, built_built) {
|
||||
TEST(NixStringContextElemTest, built_built)
|
||||
{
|
||||
/**
|
||||
* We set these in tests rather than the regular globals so we don't have
|
||||
* to worry about race conditions if the tests run concurrently.
|
||||
@@ -102,9 +103,11 @@ TEST(NixStringContextElemTest, built_built) {
|
||||
auto * drvPath = std::get_if<SingleDerivedPath::Built>(&*p->drvPath);
|
||||
ASSERT_TRUE(drvPath);
|
||||
ASSERT_EQ(drvPath->output, "bar");
|
||||
ASSERT_EQ(*drvPath->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque {
|
||||
.path = StorePath { built.substr(9) },
|
||||
}));
|
||||
ASSERT_EQ(
|
||||
*drvPath->drvPath,
|
||||
((SingleDerivedPath) SingleDerivedPath::Opaque{
|
||||
.path = StorePath{built.substr(9)},
|
||||
}));
|
||||
ASSERT_EQ(elem.to_string(), built);
|
||||
}
|
||||
|
||||
@@ -112,17 +115,15 @@ TEST(NixStringContextElemTest, built_built) {
|
||||
* Without the right experimental features enabled, we cannot parse a
|
||||
* complex inductive string context element.
|
||||
*/
|
||||
TEST(NixStringContextElemTest, built_built_xp) {
|
||||
TEST(NixStringContextElemTest, built_built_xp)
|
||||
{
|
||||
ASSERT_THROW(
|
||||
NixStringContextElem::parse("!foo!bar!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"), MissingExperimentalFeature);
|
||||
NixStringContextElem::parse("!foo!bar!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"), MissingExperimentalFeature);
|
||||
}
|
||||
|
||||
#ifndef COVERAGE
|
||||
|
||||
RC_GTEST_PROP(
|
||||
NixStringContextElemTest,
|
||||
prop_round_rip,
|
||||
(const NixStringContextElem & o))
|
||||
RC_GTEST_PROP(NixStringContextElemTest, prop_round_rip, (const NixStringContextElem & o))
|
||||
{
|
||||
ExperimentalFeatureSettings xpSettings;
|
||||
xpSettings.set("experimental-features", "dynamic-derivations");
|
||||
@@ -131,4 +132,4 @@ RC_GTEST_PROP(
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -106,14 +106,11 @@ TEST_F(ValuePrintingTests, vApp)
|
||||
|
||||
TEST_F(ValuePrintingTests, vLambda)
|
||||
{
|
||||
Env env {
|
||||
.up = nullptr,
|
||||
.values = { }
|
||||
};
|
||||
Env env{.up = nullptr, .values = {}};
|
||||
PosTable::Origin origin = state.positions.addOrigin(std::monostate(), 1);
|
||||
auto posIdx = state.positions.add(origin, 0);
|
||||
auto body = ExprInt(0);
|
||||
auto formals = Formals {};
|
||||
auto formals = Formals{};
|
||||
|
||||
ExprLambda eLambda(posIdx, createSymbol("a"), &formals, &body);
|
||||
|
||||
@@ -130,9 +127,7 @@ TEST_F(ValuePrintingTests, vLambda)
|
||||
TEST_F(ValuePrintingTests, vPrimOp)
|
||||
{
|
||||
Value vPrimOp;
|
||||
PrimOp primOp{
|
||||
.name = "puppy"
|
||||
};
|
||||
PrimOp primOp{.name = "puppy"};
|
||||
vPrimOp.mkPrimOp(&primOp);
|
||||
|
||||
test(vPrimOp, "«primop puppy»");
|
||||
@@ -140,9 +135,7 @@ TEST_F(ValuePrintingTests, vPrimOp)
|
||||
|
||||
TEST_F(ValuePrintingTests, vPrimOpApp)
|
||||
{
|
||||
PrimOp primOp{
|
||||
.name = "puppy"
|
||||
};
|
||||
PrimOp primOp{.name = "puppy"};
|
||||
Value vPrimOp;
|
||||
vPrimOp.mkPrimOp(&primOp);
|
||||
|
||||
@@ -161,16 +154,19 @@ TEST_F(ValuePrintingTests, vExternal)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string typeOf() const override
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
virtual std::ostream & print(std::ostream & str) const override
|
||||
{
|
||||
str << "testing-external!";
|
||||
return str;
|
||||
}
|
||||
} myExternal;
|
||||
|
||||
Value vExternal;
|
||||
vExternal.mkExternal(&myExternal);
|
||||
|
||||
@@ -220,10 +216,13 @@ TEST_F(ValuePrintingTests, depthAttrs)
|
||||
Value vNested;
|
||||
vNested.mkAttrs(builder2.finish());
|
||||
|
||||
test(vNested, "{ nested = { ... }; one = 1; two = 2; }", PrintOptions { .maxDepth = 1 });
|
||||
test(vNested, "{ nested = { nested = { ... }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions { .maxDepth = 2 });
|
||||
test(vNested, "{ nested = { nested = { }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions { .maxDepth = 3 });
|
||||
test(vNested, "{ nested = { nested = { }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions { .maxDepth = 4 });
|
||||
test(vNested, "{ nested = { ... }; one = 1; two = 2; }", PrintOptions{.maxDepth = 1});
|
||||
test(
|
||||
vNested,
|
||||
"{ nested = { nested = { ... }; one = 1; two = 2; }; one = 1; two = 2; }",
|
||||
PrintOptions{.maxDepth = 2});
|
||||
test(vNested, "{ nested = { nested = { }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions{.maxDepth = 3});
|
||||
test(vNested, "{ nested = { nested = { }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions{.maxDepth = 4});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, depthList)
|
||||
@@ -256,11 +255,11 @@ TEST_F(ValuePrintingTests, depthList)
|
||||
Value vList;
|
||||
vList.mkList(list);
|
||||
|
||||
test(vList, "[ 1 2 { ... } ]", PrintOptions { .maxDepth = 1 });
|
||||
test(vList, "[ 1 2 { nested = { ... }; one = 1; two = 2; } ]", PrintOptions { .maxDepth = 2 });
|
||||
test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions { .maxDepth = 3 });
|
||||
test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions { .maxDepth = 4 });
|
||||
test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions { .maxDepth = 5 });
|
||||
test(vList, "[ 1 2 { ... } ]", PrintOptions{.maxDepth = 1});
|
||||
test(vList, "[ 1 2 { nested = { ... }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 2});
|
||||
test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 3});
|
||||
test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 4});
|
||||
test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 5});
|
||||
}
|
||||
|
||||
struct StringPrintingTests : LibExprTest
|
||||
@@ -272,9 +271,7 @@ struct StringPrintingTests : LibExprTest
|
||||
v.mkString(literal);
|
||||
|
||||
std::stringstream out;
|
||||
printValue(state, out, v, PrintOptions {
|
||||
.maxStringLength = maxLength
|
||||
});
|
||||
printValue(state, out, v, PrintOptions{.maxStringLength = maxLength});
|
||||
ASSERT_EQ(out.str(), expected);
|
||||
}
|
||||
};
|
||||
@@ -305,15 +302,9 @@ TEST_F(ValuePrintingTests, attrsTypeFirst)
|
||||
Value vAttrs;
|
||||
vAttrs.mkAttrs(builder.finish());
|
||||
|
||||
test(vAttrs,
|
||||
"{ type = \"puppy\"; apple = \"apple\"; }",
|
||||
PrintOptions {
|
||||
.maxAttrs = 100
|
||||
});
|
||||
test(vAttrs, "{ type = \"puppy\"; apple = \"apple\"; }", PrintOptions{.maxAttrs = 100});
|
||||
|
||||
test(vAttrs,
|
||||
"{ apple = \"apple\"; type = \"puppy\"; }",
|
||||
PrintOptions { });
|
||||
test(vAttrs, "{ apple = \"apple\"; type = \"puppy\"; }", PrintOptions{});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsInt)
|
||||
@@ -321,11 +312,7 @@ TEST_F(ValuePrintingTests, ansiColorsInt)
|
||||
Value v;
|
||||
v.mkInt(10);
|
||||
|
||||
test(v,
|
||||
ANSI_CYAN "10" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(v, ANSI_CYAN "10" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsFloat)
|
||||
@@ -333,11 +320,7 @@ TEST_F(ValuePrintingTests, ansiColorsFloat)
|
||||
Value v;
|
||||
v.mkFloat(1.6);
|
||||
|
||||
test(v,
|
||||
ANSI_CYAN "1.6" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(v, ANSI_CYAN "1.6" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsBool)
|
||||
@@ -345,11 +328,7 @@ TEST_F(ValuePrintingTests, ansiColorsBool)
|
||||
Value v;
|
||||
v.mkBool(true);
|
||||
|
||||
test(v,
|
||||
ANSI_CYAN "true" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(v, ANSI_CYAN "true" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsString)
|
||||
@@ -357,11 +336,7 @@ TEST_F(ValuePrintingTests, ansiColorsString)
|
||||
Value v;
|
||||
v.mkString("puppy");
|
||||
|
||||
test(v,
|
||||
ANSI_MAGENTA "\"puppy\"" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(v, ANSI_MAGENTA "\"puppy\"" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsStringElided)
|
||||
@@ -369,12 +344,10 @@ TEST_F(ValuePrintingTests, ansiColorsStringElided)
|
||||
Value v;
|
||||
v.mkString("puppy");
|
||||
|
||||
test(v,
|
||||
ANSI_MAGENTA "\"pup\" " ANSI_FAINT "«2 bytes elided»" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.maxStringLength = 3
|
||||
});
|
||||
test(
|
||||
v,
|
||||
ANSI_MAGENTA "\"pup\" " ANSI_FAINT "«2 bytes elided»" ANSI_NORMAL,
|
||||
PrintOptions{.ansiColors = true, .maxStringLength = 3});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsPath)
|
||||
@@ -382,11 +355,7 @@ TEST_F(ValuePrintingTests, ansiColorsPath)
|
||||
Value v;
|
||||
v.mkPath(state.rootPath(CanonPath("puppy")));
|
||||
|
||||
test(v,
|
||||
ANSI_GREEN "/puppy" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(v, ANSI_GREEN "/puppy" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsNull)
|
||||
@@ -394,11 +363,7 @@ TEST_F(ValuePrintingTests, ansiColorsNull)
|
||||
Value v;
|
||||
v.mkNull();
|
||||
|
||||
test(v,
|
||||
ANSI_CYAN "null" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(v, ANSI_CYAN "null" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsAttrs)
|
||||
@@ -416,11 +381,10 @@ TEST_F(ValuePrintingTests, ansiColorsAttrs)
|
||||
Value vAttrs;
|
||||
vAttrs.mkAttrs(builder.finish());
|
||||
|
||||
test(vAttrs,
|
||||
"{ one = " ANSI_CYAN "1" ANSI_NORMAL "; two = " ANSI_CYAN "2" ANSI_NORMAL "; }",
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(
|
||||
vAttrs,
|
||||
"{ one = " ANSI_CYAN "1" ANSI_NORMAL "; two = " ANSI_CYAN "2" ANSI_NORMAL "; }",
|
||||
PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsDerivation)
|
||||
@@ -434,20 +398,15 @@ TEST_F(ValuePrintingTests, ansiColorsDerivation)
|
||||
Value vAttrs;
|
||||
vAttrs.mkAttrs(builder.finish());
|
||||
|
||||
test(vAttrs,
|
||||
ANSI_GREEN "«derivation»" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.force = true,
|
||||
.derivationPaths = true
|
||||
});
|
||||
test(
|
||||
vAttrs,
|
||||
ANSI_GREEN "«derivation»" ANSI_NORMAL,
|
||||
PrintOptions{.ansiColors = true, .force = true, .derivationPaths = true});
|
||||
|
||||
test(vAttrs,
|
||||
"{ type = " ANSI_MAGENTA "\"derivation\"" ANSI_NORMAL "; }",
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.force = true
|
||||
});
|
||||
test(
|
||||
vAttrs,
|
||||
"{ type = " ANSI_MAGENTA "\"derivation\"" ANSI_NORMAL "; }",
|
||||
PrintOptions{.ansiColors = true, .force = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsError)
|
||||
@@ -458,14 +417,13 @@ TEST_F(ValuePrintingTests, ansiColorsError)
|
||||
Value vError;
|
||||
vError.mkApp(&throw_, &message);
|
||||
|
||||
test(vError,
|
||||
ANSI_RED
|
||||
"«error: uh oh!»"
|
||||
ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.force = true,
|
||||
});
|
||||
test(
|
||||
vError,
|
||||
ANSI_RED "«error: uh oh!»" ANSI_NORMAL,
|
||||
PrintOptions{
|
||||
.ansiColors = true,
|
||||
.force = true,
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsDerivationError)
|
||||
@@ -486,30 +444,20 @@ TEST_F(ValuePrintingTests, ansiColorsDerivationError)
|
||||
Value vAttrs;
|
||||
vAttrs.mkAttrs(builder.finish());
|
||||
|
||||
test(vAttrs,
|
||||
"{ drvPath = "
|
||||
ANSI_RED
|
||||
"«error: uh oh!»"
|
||||
ANSI_NORMAL
|
||||
"; type = "
|
||||
ANSI_MAGENTA
|
||||
"\"derivation\""
|
||||
ANSI_NORMAL
|
||||
"; }",
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.force = true
|
||||
});
|
||||
test(
|
||||
vAttrs,
|
||||
"{ drvPath = " ANSI_RED "«error: uh oh!»" ANSI_NORMAL "; type = " ANSI_MAGENTA "\"derivation\"" ANSI_NORMAL
|
||||
"; }",
|
||||
PrintOptions{.ansiColors = true, .force = true});
|
||||
|
||||
test(vAttrs,
|
||||
ANSI_RED
|
||||
"«error: uh oh!»"
|
||||
ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.force = true,
|
||||
.derivationPaths = true,
|
||||
});
|
||||
test(
|
||||
vAttrs,
|
||||
ANSI_RED "«error: uh oh!»" ANSI_NORMAL,
|
||||
PrintOptions{
|
||||
.ansiColors = true,
|
||||
.force = true,
|
||||
.derivationPaths = true,
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsAssert)
|
||||
@@ -523,12 +471,7 @@ TEST_F(ValuePrintingTests, ansiColorsAssert)
|
||||
Value v;
|
||||
state.mkThunk_(v, &expr);
|
||||
|
||||
test(v,
|
||||
ANSI_RED "«error: assertion 'false' failed»" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.force = true
|
||||
});
|
||||
test(v, ANSI_RED "«error: assertion 'false' failed»" ANSI_NORMAL, PrintOptions{.ansiColors = true, .force = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsList)
|
||||
@@ -545,77 +488,51 @@ TEST_F(ValuePrintingTests, ansiColorsList)
|
||||
Value vList;
|
||||
vList.mkList(list);
|
||||
|
||||
test(vList,
|
||||
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_CYAN "2" ANSI_NORMAL " " ANSI_MAGENTA "«nullptr»" ANSI_NORMAL " ]",
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(
|
||||
vList,
|
||||
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_CYAN "2" ANSI_NORMAL " " ANSI_MAGENTA "«nullptr»" ANSI_NORMAL " ]",
|
||||
PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsLambda)
|
||||
{
|
||||
Env env {
|
||||
.up = nullptr,
|
||||
.values = { }
|
||||
};
|
||||
Env env{.up = nullptr, .values = {}};
|
||||
PosTable::Origin origin = state.positions.addOrigin(std::monostate(), 1);
|
||||
auto posIdx = state.positions.add(origin, 0);
|
||||
auto body = ExprInt(0);
|
||||
auto formals = Formals {};
|
||||
auto formals = Formals{};
|
||||
|
||||
ExprLambda eLambda(posIdx, createSymbol("a"), &formals, &body);
|
||||
|
||||
Value vLambda;
|
||||
vLambda.mkLambda(&env, &eLambda);
|
||||
|
||||
test(vLambda,
|
||||
ANSI_BLUE "«lambda @ «none»:1:1»" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.force = true
|
||||
});
|
||||
test(vLambda, ANSI_BLUE "«lambda @ «none»:1:1»" ANSI_NORMAL, PrintOptions{.ansiColors = true, .force = true});
|
||||
|
||||
eLambda.setName(createSymbol("puppy"));
|
||||
|
||||
test(vLambda,
|
||||
ANSI_BLUE "«lambda puppy @ «none»:1:1»" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.force = true
|
||||
});
|
||||
test(vLambda, ANSI_BLUE "«lambda puppy @ «none»:1:1»" ANSI_NORMAL, PrintOptions{.ansiColors = true, .force = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsPrimOp)
|
||||
{
|
||||
PrimOp primOp{
|
||||
.name = "puppy"
|
||||
};
|
||||
PrimOp primOp{.name = "puppy"};
|
||||
Value v;
|
||||
v.mkPrimOp(&primOp);
|
||||
|
||||
test(v,
|
||||
ANSI_BLUE "«primop puppy»" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(v, ANSI_BLUE "«primop puppy»" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsPrimOpApp)
|
||||
{
|
||||
PrimOp primOp{
|
||||
.name = "puppy"
|
||||
};
|
||||
PrimOp primOp{.name = "puppy"};
|
||||
Value vPrimOp;
|
||||
vPrimOp.mkPrimOp(&primOp);
|
||||
|
||||
Value v;
|
||||
v.mkPrimOpApp(&vPrimOp, nullptr);
|
||||
|
||||
test(v,
|
||||
ANSI_BLUE "«partially applied primop puppy»" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(v, ANSI_BLUE "«partially applied primop puppy»" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsThunk)
|
||||
@@ -623,11 +540,7 @@ TEST_F(ValuePrintingTests, ansiColorsThunk)
|
||||
Value v;
|
||||
v.mkThunk(nullptr, nullptr);
|
||||
|
||||
test(v,
|
||||
ANSI_MAGENTA "«thunk»" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(v, ANSI_MAGENTA "«thunk»" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsBlackhole)
|
||||
@@ -635,11 +548,7 @@ TEST_F(ValuePrintingTests, ansiColorsBlackhole)
|
||||
Value v;
|
||||
v.mkBlackhole();
|
||||
|
||||
test(v,
|
||||
ANSI_RED "«potential infinite recursion»" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(v, ANSI_RED "«potential infinite recursion»" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsAttrsRepeated)
|
||||
@@ -656,11 +565,7 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsRepeated)
|
||||
Value vAttrs;
|
||||
vAttrs.mkAttrs(builder.finish());
|
||||
|
||||
test(vAttrs,
|
||||
"{ a = { }; b = " ANSI_MAGENTA "«repeated»" ANSI_NORMAL "; }",
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(vAttrs, "{ a = { }; b = " ANSI_MAGENTA "«repeated»" ANSI_NORMAL "; }", PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsListRepeated)
|
||||
@@ -676,11 +581,7 @@ TEST_F(ValuePrintingTests, ansiColorsListRepeated)
|
||||
Value vList;
|
||||
vList.mkList(list);
|
||||
|
||||
test(vList,
|
||||
"[ { } " ANSI_MAGENTA "«repeated»" ANSI_NORMAL " ]",
|
||||
PrintOptions {
|
||||
.ansiColors = true
|
||||
});
|
||||
test(vList, "[ { } " ANSI_MAGENTA "«repeated»" ANSI_NORMAL " ]", PrintOptions{.ansiColors = true});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, listRepeated)
|
||||
@@ -696,12 +597,8 @@ TEST_F(ValuePrintingTests, listRepeated)
|
||||
Value vList;
|
||||
vList.mkList(list);
|
||||
|
||||
test(vList, "[ { } «repeated» ]", PrintOptions { });
|
||||
test(vList,
|
||||
"[ { } { } ]",
|
||||
PrintOptions {
|
||||
.trackRepeated = false
|
||||
});
|
||||
test(vList, "[ { } «repeated» ]", PrintOptions{});
|
||||
test(vList, "[ { } { } ]", PrintOptions{.trackRepeated = false});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsAttrsElided)
|
||||
@@ -719,12 +616,10 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsElided)
|
||||
Value vAttrs;
|
||||
vAttrs.mkAttrs(builder.finish());
|
||||
|
||||
test(vAttrs,
|
||||
"{ one = " ANSI_CYAN "1" ANSI_NORMAL "; " ANSI_FAINT "«1 attribute elided»" ANSI_NORMAL " }",
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.maxAttrs = 1
|
||||
});
|
||||
test(
|
||||
vAttrs,
|
||||
"{ one = " ANSI_CYAN "1" ANSI_NORMAL "; " ANSI_FAINT "«1 attribute elided»" ANSI_NORMAL " }",
|
||||
PrintOptions{.ansiColors = true, .maxAttrs = 1});
|
||||
|
||||
Value vThree;
|
||||
vThree.mkInt(3);
|
||||
@@ -732,12 +627,10 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsElided)
|
||||
builder.insert(state.symbols.create("three"), &vThree);
|
||||
vAttrs.mkAttrs(builder.finish());
|
||||
|
||||
test(vAttrs,
|
||||
"{ one = " ANSI_CYAN "1" ANSI_NORMAL "; " ANSI_FAINT "«2 attributes elided»" ANSI_NORMAL " }",
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.maxAttrs = 1
|
||||
});
|
||||
test(
|
||||
vAttrs,
|
||||
"{ one = " ANSI_CYAN "1" ANSI_NORMAL "; " ANSI_FAINT "«2 attributes elided»" ANSI_NORMAL " }",
|
||||
PrintOptions{.ansiColors = true, .maxAttrs = 1});
|
||||
}
|
||||
|
||||
TEST_F(ValuePrintingTests, ansiColorsListElided)
|
||||
@@ -751,37 +644,33 @@ TEST_F(ValuePrintingTests, ansiColorsListElided)
|
||||
vTwo.mkInt(2);
|
||||
|
||||
{
|
||||
auto list = state.buildList(2);
|
||||
list.elems[0] = &vOne;
|
||||
list.elems[1] = &vTwo;
|
||||
Value vList;
|
||||
vList.mkList(list);
|
||||
auto list = state.buildList(2);
|
||||
list.elems[0] = &vOne;
|
||||
list.elems[1] = &vTwo;
|
||||
Value vList;
|
||||
vList.mkList(list);
|
||||
|
||||
test(vList,
|
||||
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«1 item elided»" ANSI_NORMAL " ]",
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.maxListItems = 1
|
||||
});
|
||||
test(
|
||||
vList,
|
||||
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«1 item elided»" ANSI_NORMAL " ]",
|
||||
PrintOptions{.ansiColors = true, .maxListItems = 1});
|
||||
}
|
||||
|
||||
Value vThree;
|
||||
vThree.mkInt(3);
|
||||
|
||||
{
|
||||
auto list = state.buildList(3);
|
||||
list.elems[0] = &vOne;
|
||||
list.elems[1] = &vTwo;
|
||||
list.elems[2] = &vThree;
|
||||
Value vList;
|
||||
vList.mkList(list);
|
||||
auto list = state.buildList(3);
|
||||
list.elems[0] = &vOne;
|
||||
list.elems[1] = &vTwo;
|
||||
list.elems[2] = &vThree;
|
||||
Value vList;
|
||||
vList.mkList(list);
|
||||
|
||||
test(vList,
|
||||
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«2 items elided»" ANSI_NORMAL " ]",
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
.maxListItems = 1
|
||||
});
|
||||
test(
|
||||
vList,
|
||||
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«2 items elided»" ANSI_NORMAL " ]",
|
||||
PrintOptions{.ansiColors = true, .maxListItems = 1});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#include "nix/expr/attr-path.hh"
|
||||
#include "nix/expr/eval-inline.hh"
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
static Strings parseAttrPath(std::string_view s)
|
||||
{
|
||||
Strings res;
|
||||
@@ -19,18 +17,19 @@ static Strings parseAttrPath(std::string_view s)
|
||||
while (1) {
|
||||
if (i == s.end())
|
||||
throw ParseError("missing closing quote in selection path '%1%'", s);
|
||||
if (*i == '"') break;
|
||||
if (*i == '"')
|
||||
break;
|
||||
cur.push_back(*i++);
|
||||
}
|
||||
} else
|
||||
cur.push_back(*i);
|
||||
++i;
|
||||
}
|
||||
if (!cur.empty()) res.push_back(cur);
|
||||
if (!cur.empty())
|
||||
res.push_back(cur);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
std::vector<Symbol> parseAttrPath(EvalState & state, std::string_view s)
|
||||
{
|
||||
std::vector<Symbol> res;
|
||||
@@ -39,9 +38,8 @@ std::vector<Symbol> parseAttrPath(EvalState & state, std::string_view s)
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::string & attrPath,
|
||||
Bindings & autoArgs, Value & vIn)
|
||||
std::pair<Value *, PosIdx>
|
||||
findAlongAttrPath(EvalState & state, const std::string & attrPath, Bindings & autoArgs, Value & vIn)
|
||||
{
|
||||
Strings tokens = parseAttrPath(attrPath);
|
||||
|
||||
@@ -65,10 +63,12 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
||||
if (!attrIndex) {
|
||||
|
||||
if (v->type() != nAttrs)
|
||||
state.error<TypeError>(
|
||||
"the expression selected by the selection path '%1%' should be a set but is %2%",
|
||||
attrPath,
|
||||
showType(*v)).debugThrow();
|
||||
state
|
||||
.error<TypeError>(
|
||||
"the expression selected by the selection path '%1%' should be a set but is %2%",
|
||||
attrPath,
|
||||
showType(*v))
|
||||
.debugThrow();
|
||||
if (attr.empty())
|
||||
throw Error("empty attribute name in selection path '%1%'", attrPath);
|
||||
|
||||
@@ -79,7 +79,8 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
||||
attrNames.insert(std::string(state.symbols[attr.name]));
|
||||
|
||||
auto suggestions = Suggestions::bestMatches(attrNames, attr);
|
||||
throw AttrPathNotFound(suggestions, "attribute '%1%' in selection path '%2%' not found", attr, attrPath);
|
||||
throw AttrPathNotFound(
|
||||
suggestions, "attribute '%1%' in selection path '%2%' not found", attr, attrPath);
|
||||
}
|
||||
v = &*a->value;
|
||||
pos = a->pos;
|
||||
@@ -88,23 +89,23 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
||||
else {
|
||||
|
||||
if (!v->isList())
|
||||
state.error<TypeError>(
|
||||
"the expression selected by the selection path '%1%' should be a list but is %2%",
|
||||
attrPath,
|
||||
showType(*v)).debugThrow();
|
||||
state
|
||||
.error<TypeError>(
|
||||
"the expression selected by the selection path '%1%' should be a list but is %2%",
|
||||
attrPath,
|
||||
showType(*v))
|
||||
.debugThrow();
|
||||
if (*attrIndex >= v->listSize())
|
||||
throw AttrPathNotFound("list index %1% in selection path '%2%' is out of range", *attrIndex, attrPath);
|
||||
|
||||
v = v->listElems()[*attrIndex];
|
||||
pos = noPos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {v, pos};
|
||||
}
|
||||
|
||||
|
||||
std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v, std::string what)
|
||||
{
|
||||
Value * v2;
|
||||
@@ -118,17 +119,17 @@ std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v
|
||||
// FIXME: is it possible to extract the Pos object instead of doing this
|
||||
// toString + parsing?
|
||||
NixStringContext context;
|
||||
auto path = state.coerceToPath(noPos, *v2, context, "while evaluating the 'meta.position' attribute of a derivation");
|
||||
auto path =
|
||||
state.coerceToPath(noPos, *v2, context, "while evaluating the 'meta.position' attribute of a derivation");
|
||||
|
||||
auto fn = path.path.abs();
|
||||
|
||||
auto fail = [fn]() {
|
||||
throw ParseError("cannot parse 'meta.position' attribute '%s'", fn);
|
||||
};
|
||||
auto fail = [fn]() { throw ParseError("cannot parse 'meta.position' attribute '%s'", fn); };
|
||||
|
||||
try {
|
||||
auto colon = fn.rfind(':');
|
||||
if (colon == std::string::npos) fail();
|
||||
if (colon == std::string::npos)
|
||||
fail();
|
||||
auto lineno = std::stoi(std::string(fn, colon + 1, std::string::npos));
|
||||
return {SourcePath{path.accessor, CanonPath(fn.substr(0, colon))}, lineno};
|
||||
} catch (std::invalid_argument & e) {
|
||||
@@ -137,5 +138,4 @@ std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -3,11 +3,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
|
||||
/* Allocate a new array of attributes for an attribute set with a specific
|
||||
capacity. The space is implicitly reserved after the Bindings
|
||||
structure. */
|
||||
@@ -22,7 +19,6 @@ Bindings * EvalState::allocBindings(size_t capacity)
|
||||
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity);
|
||||
}
|
||||
|
||||
|
||||
Value & BindingsBuilder::alloc(Symbol name, PosIdx pos)
|
||||
{
|
||||
auto value = state.allocValue();
|
||||
@@ -30,24 +26,21 @@ Value & BindingsBuilder::alloc(Symbol name, PosIdx pos)
|
||||
return *value;
|
||||
}
|
||||
|
||||
|
||||
Value & BindingsBuilder::alloc(std::string_view name, PosIdx pos)
|
||||
{
|
||||
return alloc(state.symbols.create(name), pos);
|
||||
}
|
||||
|
||||
|
||||
void Bindings::sort()
|
||||
{
|
||||
if (size_) std::sort(begin(), end());
|
||||
if (size_)
|
||||
std::sort(begin(), end());
|
||||
}
|
||||
|
||||
|
||||
Value & Value::mkAttrs(BindingsBuilder & bindings)
|
||||
{
|
||||
mkAttrs(bindings.finish());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -11,8 +11,10 @@ namespace nix::eval_cache {
|
||||
|
||||
CachedEvalError::CachedEvalError(ref<AttrCursor> cursor, Symbol attr)
|
||||
: EvalError(cursor->root->state, "cached failure of attribute '%s'", cursor->getAttrPathStr(attr))
|
||||
, cursor(cursor), attr(attr)
|
||||
{ }
|
||||
, cursor(cursor)
|
||||
, attr(attr)
|
||||
{
|
||||
}
|
||||
|
||||
void CachedEvalError::force()
|
||||
{
|
||||
@@ -25,7 +27,8 @@ void CachedEvalError::force()
|
||||
}
|
||||
|
||||
// Shouldn't happen.
|
||||
throw EvalError(state, "evaluation of cached failed attribute '%s' unexpectedly succeeded", cursor->getAttrPathStr(attr));
|
||||
throw EvalError(
|
||||
state, "evaluation of cached failed attribute '%s' unexpectedly succeeded", cursor->getAttrPathStr(attr));
|
||||
}
|
||||
|
||||
static const char * schema = R"sql(
|
||||
@@ -59,10 +62,7 @@ struct AttrDb
|
||||
|
||||
SymbolTable & symbols;
|
||||
|
||||
AttrDb(
|
||||
const StoreDirConfig & cfg,
|
||||
const Hash & fingerprint,
|
||||
SymbolTable & symbols)
|
||||
AttrDb(const StoreDirConfig & cfg, const Hash & fingerprint, SymbolTable & symbols)
|
||||
: cfg(cfg)
|
||||
, _state(std::make_unique<Sync<State>>())
|
||||
, symbols(symbols)
|
||||
@@ -78,17 +78,16 @@ struct AttrDb
|
||||
state->db.isCache();
|
||||
state->db.exec(schema);
|
||||
|
||||
state->insertAttribute.create(state->db,
|
||||
"insert or replace into Attributes(parent, name, type, value) values (?, ?, ?, ?)");
|
||||
state->insertAttribute.create(
|
||||
state->db, "insert or replace into Attributes(parent, name, type, value) values (?, ?, ?, ?)");
|
||||
|
||||
state->insertAttributeWithContext.create(state->db,
|
||||
"insert or replace into Attributes(parent, name, type, value, context) values (?, ?, ?, ?, ?)");
|
||||
state->insertAttributeWithContext.create(
|
||||
state->db, "insert or replace into Attributes(parent, name, type, value, context) values (?, ?, ?, ?, ?)");
|
||||
|
||||
state->queryAttribute.create(state->db,
|
||||
"select rowid, type, value, context from Attributes where parent = ? and name = ?");
|
||||
state->queryAttribute.create(
|
||||
state->db, "select rowid, type, value, context from Attributes where parent = ? and name = ?");
|
||||
|
||||
state->queryAttributes.create(state->db,
|
||||
"select name from Attributes where parent = ?");
|
||||
state->queryAttributes.create(state->db, "select name from Attributes where parent = ?");
|
||||
|
||||
state->txn = std::make_unique<SQLiteTxn>(state->db);
|
||||
}
|
||||
@@ -108,7 +107,8 @@ struct AttrDb
|
||||
template<typename F>
|
||||
AttrId doSQLite(F && fun)
|
||||
{
|
||||
if (failed) return 0;
|
||||
if (failed)
|
||||
return 0;
|
||||
try {
|
||||
return fun();
|
||||
} catch (SQLiteError &) {
|
||||
@@ -118,116 +118,76 @@ struct AttrDb
|
||||
}
|
||||
}
|
||||
|
||||
AttrId setAttrs(
|
||||
AttrKey key,
|
||||
const std::vector<Symbol> & attrs)
|
||||
AttrId setAttrs(AttrKey key, const std::vector<Symbol> & attrs)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
{
|
||||
return doSQLite([&]() {
|
||||
auto state(_state->lock());
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::FullAttrs)
|
||||
(0, false).exec();
|
||||
state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::FullAttrs) (0, false).exec();
|
||||
|
||||
AttrId rowId = state->db.getLastInsertedRowId();
|
||||
assert(rowId);
|
||||
|
||||
for (auto & attr : attrs)
|
||||
state->insertAttribute.use()
|
||||
(rowId)
|
||||
(symbols[attr])
|
||||
(AttrType::Placeholder)
|
||||
(0, false).exec();
|
||||
state->insertAttribute.use()(rowId)(symbols[attr])(AttrType::Placeholder) (0, false).exec();
|
||||
|
||||
return rowId;
|
||||
});
|
||||
}
|
||||
|
||||
AttrId setString(
|
||||
AttrKey key,
|
||||
std::string_view s,
|
||||
const char * * context = nullptr)
|
||||
AttrId setString(AttrKey key, std::string_view s, const char ** context = nullptr)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
{
|
||||
return doSQLite([&]() {
|
||||
auto state(_state->lock());
|
||||
|
||||
if (context) {
|
||||
std::string ctx;
|
||||
for (const char * * p = context; *p; ++p) {
|
||||
if (p != context) ctx.push_back(' ');
|
||||
for (const char ** p = context; *p; ++p) {
|
||||
if (p != context)
|
||||
ctx.push_back(' ');
|
||||
ctx.append(*p);
|
||||
}
|
||||
state->insertAttributeWithContext.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::String)
|
||||
(s)
|
||||
(ctx).exec();
|
||||
state->insertAttributeWithContext.use()(key.first)(symbols[key.second])(AttrType::String) (s) (ctx)
|
||||
.exec();
|
||||
} else {
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::String)
|
||||
(s).exec();
|
||||
state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::String) (s).exec();
|
||||
}
|
||||
|
||||
return state->db.getLastInsertedRowId();
|
||||
});
|
||||
}
|
||||
|
||||
AttrId setBool(
|
||||
AttrKey key,
|
||||
bool b)
|
||||
AttrId setBool(AttrKey key, bool b)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
{
|
||||
return doSQLite([&]() {
|
||||
auto state(_state->lock());
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::Bool)
|
||||
(b ? 1 : 0).exec();
|
||||
state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Bool) (b ? 1 : 0).exec();
|
||||
|
||||
return state->db.getLastInsertedRowId();
|
||||
});
|
||||
}
|
||||
|
||||
AttrId setInt(
|
||||
AttrKey key,
|
||||
int n)
|
||||
AttrId setInt(AttrKey key, int n)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
{
|
||||
return doSQLite([&]() {
|
||||
auto state(_state->lock());
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::Int)
|
||||
(n).exec();
|
||||
state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Int) (n).exec();
|
||||
|
||||
return state->db.getLastInsertedRowId();
|
||||
});
|
||||
}
|
||||
|
||||
AttrId setListOfStrings(
|
||||
AttrKey key,
|
||||
const std::vector<std::string> & l)
|
||||
AttrId setListOfStrings(AttrKey key, const std::vector<std::string> & l)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
{
|
||||
return doSQLite([&]() {
|
||||
auto state(_state->lock());
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::ListOfStrings)
|
||||
(dropEmptyInitThenConcatStringsSep("\t", l)).exec();
|
||||
state->insertAttribute
|
||||
.use()(key.first)(symbols[key.second])(
|
||||
AttrType::ListOfStrings) (dropEmptyInitThenConcatStringsSep("\t", l))
|
||||
.exec();
|
||||
|
||||
return state->db.getLastInsertedRowId();
|
||||
});
|
||||
@@ -235,15 +195,10 @@ struct AttrDb
|
||||
|
||||
AttrId setPlaceholder(AttrKey key)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
{
|
||||
return doSQLite([&]() {
|
||||
auto state(_state->lock());
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::Placeholder)
|
||||
(0, false).exec();
|
||||
state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Placeholder) (0, false).exec();
|
||||
|
||||
return state->db.getLastInsertedRowId();
|
||||
});
|
||||
@@ -251,15 +206,10 @@ struct AttrDb
|
||||
|
||||
AttrId setMissing(AttrKey key)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
{
|
||||
return doSQLite([&]() {
|
||||
auto state(_state->lock());
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::Missing)
|
||||
(0, false).exec();
|
||||
state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Missing) (0, false).exec();
|
||||
|
||||
return state->db.getLastInsertedRowId();
|
||||
});
|
||||
@@ -267,15 +217,10 @@ struct AttrDb
|
||||
|
||||
AttrId setMisc(AttrKey key)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
{
|
||||
return doSQLite([&]() {
|
||||
auto state(_state->lock());
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::Misc)
|
||||
(0, false).exec();
|
||||
state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Misc) (0, false).exec();
|
||||
|
||||
return state->db.getLastInsertedRowId();
|
||||
});
|
||||
@@ -283,15 +228,10 @@ struct AttrDb
|
||||
|
||||
AttrId setFailed(AttrKey key)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
{
|
||||
return doSQLite([&]() {
|
||||
auto state(_state->lock());
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::Failed)
|
||||
(0, false).exec();
|
||||
state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Failed) (0, false).exec();
|
||||
|
||||
return state->db.getLastInsertedRowId();
|
||||
});
|
||||
@@ -302,51 +242,49 @@ struct AttrDb
|
||||
auto state(_state->lock());
|
||||
|
||||
auto queryAttribute(state->queryAttribute.use()(key.first)(symbols[key.second]));
|
||||
if (!queryAttribute.next()) return {};
|
||||
if (!queryAttribute.next())
|
||||
return {};
|
||||
|
||||
auto rowId = (AttrId) queryAttribute.getInt(0);
|
||||
auto type = (AttrType) queryAttribute.getInt(1);
|
||||
|
||||
switch (type) {
|
||||
case AttrType::Placeholder:
|
||||
return {{rowId, placeholder_t()}};
|
||||
case AttrType::FullAttrs: {
|
||||
// FIXME: expensive, should separate this out.
|
||||
std::vector<Symbol> attrs;
|
||||
auto queryAttributes(state->queryAttributes.use()(rowId));
|
||||
while (queryAttributes.next())
|
||||
attrs.emplace_back(symbols.create(queryAttributes.getStr(0)));
|
||||
return {{rowId, attrs}};
|
||||
}
|
||||
case AttrType::String: {
|
||||
NixStringContext context;
|
||||
if (!queryAttribute.isNull(3))
|
||||
for (auto & s : tokenizeString<std::vector<std::string>>(queryAttribute.getStr(3), ";"))
|
||||
context.insert(NixStringContextElem::parse(s));
|
||||
return {{rowId, string_t{queryAttribute.getStr(2), context}}};
|
||||
}
|
||||
case AttrType::Bool:
|
||||
return {{rowId, queryAttribute.getInt(2) != 0}};
|
||||
case AttrType::Int:
|
||||
return {{rowId, int_t{NixInt{queryAttribute.getInt(2)}}}};
|
||||
case AttrType::ListOfStrings:
|
||||
return {{rowId, tokenizeString<std::vector<std::string>>(queryAttribute.getStr(2), "\t")}};
|
||||
case AttrType::Missing:
|
||||
return {{rowId, missing_t()}};
|
||||
case AttrType::Misc:
|
||||
return {{rowId, misc_t()}};
|
||||
case AttrType::Failed:
|
||||
return {{rowId, failed_t()}};
|
||||
default:
|
||||
throw Error("unexpected type in evaluation cache");
|
||||
case AttrType::Placeholder:
|
||||
return {{rowId, placeholder_t()}};
|
||||
case AttrType::FullAttrs: {
|
||||
// FIXME: expensive, should separate this out.
|
||||
std::vector<Symbol> attrs;
|
||||
auto queryAttributes(state->queryAttributes.use()(rowId));
|
||||
while (queryAttributes.next())
|
||||
attrs.emplace_back(symbols.create(queryAttributes.getStr(0)));
|
||||
return {{rowId, attrs}};
|
||||
}
|
||||
case AttrType::String: {
|
||||
NixStringContext context;
|
||||
if (!queryAttribute.isNull(3))
|
||||
for (auto & s : tokenizeString<std::vector<std::string>>(queryAttribute.getStr(3), ";"))
|
||||
context.insert(NixStringContextElem::parse(s));
|
||||
return {{rowId, string_t{queryAttribute.getStr(2), context}}};
|
||||
}
|
||||
case AttrType::Bool:
|
||||
return {{rowId, queryAttribute.getInt(2) != 0}};
|
||||
case AttrType::Int:
|
||||
return {{rowId, int_t{NixInt{queryAttribute.getInt(2)}}}};
|
||||
case AttrType::ListOfStrings:
|
||||
return {{rowId, tokenizeString<std::vector<std::string>>(queryAttribute.getStr(2), "\t")}};
|
||||
case AttrType::Missing:
|
||||
return {{rowId, missing_t()}};
|
||||
case AttrType::Misc:
|
||||
return {{rowId, misc_t()}};
|
||||
case AttrType::Failed:
|
||||
return {{rowId, failed_t()}};
|
||||
default:
|
||||
throw Error("unexpected type in evaluation cache");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static std::shared_ptr<AttrDb> makeAttrDb(
|
||||
const StoreDirConfig & cfg,
|
||||
const Hash & fingerprint,
|
||||
SymbolTable & symbols)
|
||||
static std::shared_ptr<AttrDb> makeAttrDb(const StoreDirConfig & cfg, const Hash & fingerprint, SymbolTable & symbols)
|
||||
{
|
||||
try {
|
||||
return std::make_shared<AttrDb>(cfg, fingerprint, symbols);
|
||||
@@ -357,9 +295,7 @@ static std::shared_ptr<AttrDb> makeAttrDb(
|
||||
}
|
||||
|
||||
EvalCache::EvalCache(
|
||||
std::optional<std::reference_wrapper<const Hash>> useCache,
|
||||
EvalState & state,
|
||||
RootLoader rootLoader)
|
||||
std::optional<std::reference_wrapper<const Hash>> useCache, EvalState & state, RootLoader rootLoader)
|
||||
: db(useCache ? makeAttrDb(*state.store, *useCache, state.symbols) : nullptr)
|
||||
, state(state)
|
||||
, rootLoader(rootLoader)
|
||||
@@ -381,11 +317,10 @@ ref<AttrCursor> EvalCache::getRoot()
|
||||
}
|
||||
|
||||
AttrCursor::AttrCursor(
|
||||
ref<EvalCache> root,
|
||||
Parent parent,
|
||||
Value * value,
|
||||
std::optional<std::pair<AttrId, AttrValue>> && cachedValue)
|
||||
: root(root), parent(parent), cachedValue(std::move(cachedValue))
|
||||
ref<EvalCache> root, Parent parent, Value * value, std::optional<std::pair<AttrId, AttrValue>> && cachedValue)
|
||||
: root(root)
|
||||
, parent(parent)
|
||||
, cachedValue(std::move(cachedValue))
|
||||
{
|
||||
if (value)
|
||||
_value = allocRootValue(value);
|
||||
@@ -470,13 +405,11 @@ Value & AttrCursor::forceValue()
|
||||
|
||||
if (root->db && (!cachedValue || std::get_if<placeholder_t>(&cachedValue->second))) {
|
||||
if (v.type() == nString)
|
||||
cachedValue = {root->db->setString(getKey(), v.c_str(), v.context()),
|
||||
string_t{v.c_str(), {}}};
|
||||
cachedValue = {root->db->setString(getKey(), v.c_str(), v.context()), string_t{v.c_str(), {}}};
|
||||
else if (v.type() == nPath) {
|
||||
auto path = v.path().path;
|
||||
cachedValue = {root->db->setString(getKey(), path.abs()), string_t{path.abs(), {}}};
|
||||
}
|
||||
else if (v.type() == nBool)
|
||||
} else if (v.type() == nBool)
|
||||
cachedValue = {root->db->setBool(getKey(), v.boolean()), v.boolean()};
|
||||
else if (v.type() == nInt)
|
||||
cachedValue = {root->db->setInt(getKey(), v.integer().value), int_t{v.integer()}};
|
||||
@@ -518,14 +451,14 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name)
|
||||
else if (std::get_if<failed_t>(&attr->second))
|
||||
throw CachedEvalError(ref(shared_from_this()), name);
|
||||
else
|
||||
return std::make_shared<AttrCursor>(root,
|
||||
std::make_pair(ref(shared_from_this()), name), nullptr, std::move(attr));
|
||||
return std::make_shared<AttrCursor>(
|
||||
root, std::make_pair(ref(shared_from_this()), name), nullptr, std::move(attr));
|
||||
}
|
||||
// Incomplete attrset, so need to fall thru and
|
||||
// evaluate to see whether 'name' exists
|
||||
} else
|
||||
return nullptr;
|
||||
//error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
// error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,7 +466,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name)
|
||||
|
||||
if (v.type() != nAttrs)
|
||||
return nullptr;
|
||||
//error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
// error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
|
||||
auto attr = v.attrs()->get(name);
|
||||
|
||||
@@ -618,17 +551,15 @@ string_t AttrCursor::getStringWithContext()
|
||||
if (auto s = std::get_if<string_t>(&cachedValue->second)) {
|
||||
bool valid = true;
|
||||
for (auto & c : s->second) {
|
||||
const StorePath & path = std::visit(overloaded {
|
||||
[&](const NixStringContextElem::DrvDeep & d) -> const StorePath & {
|
||||
return d.drvPath;
|
||||
const StorePath & path = std::visit(
|
||||
overloaded{
|
||||
[&](const NixStringContextElem::DrvDeep & d) -> const StorePath & { return d.drvPath; },
|
||||
[&](const NixStringContextElem::Built & b) -> const StorePath & {
|
||||
return b.drvPath->getBaseStorePath();
|
||||
},
|
||||
[&](const NixStringContextElem::Opaque & o) -> const StorePath & { return o.path; },
|
||||
},
|
||||
[&](const NixStringContextElem::Built & b) -> const StorePath & {
|
||||
return b.drvPath->getBaseStorePath();
|
||||
},
|
||||
[&](const NixStringContextElem::Opaque & o) -> const StorePath & {
|
||||
return o.path;
|
||||
},
|
||||
}, c.raw);
|
||||
c.raw);
|
||||
if (!root->state.store->isValidPath(path)) {
|
||||
valid = false;
|
||||
break;
|
||||
@@ -649,8 +580,7 @@ string_t AttrCursor::getStringWithContext()
|
||||
NixStringContext context;
|
||||
copyContext(v, context);
|
||||
return {v.c_str(), std::move(context)};
|
||||
}
|
||||
else if (v.type() == nPath)
|
||||
} else if (v.type() == nPath)
|
||||
return {v.path().to_string(), {}};
|
||||
else
|
||||
root->state.error<TypeError>("'%s' is not a string but %s", getAttrPathStr(), showType(v)).debugThrow();
|
||||
@@ -722,7 +652,8 @@ std::vector<std::string> AttrCursor::getListOfStrings()
|
||||
std::vector<std::string> res;
|
||||
|
||||
for (auto & elem : v.listItems())
|
||||
res.push_back(std::string(root->state.forceStringNoCtx(*elem, noPos, "while evaluating an attribute for caching")));
|
||||
res.push_back(
|
||||
std::string(root->state.forceStringNoCtx(*elem, noPos, "while evaluating an attribute for caching")));
|
||||
|
||||
if (root->db)
|
||||
cachedValue = {root->db->setListOfStrings(getKey(), res), res};
|
||||
@@ -778,10 +709,10 @@ StorePath AttrCursor::forceDerivation()
|
||||
been garbage-collected. So force it to be regenerated. */
|
||||
aDrvPath->forceValue();
|
||||
if (!root->state.store->isValidPath(drvPath))
|
||||
throw Error("don't know how to recreate store derivation '%s'!",
|
||||
root->state.store->printStorePath(drvPath));
|
||||
throw Error(
|
||||
"don't know how to recreate store derivation '%s'!", root->state.store->printStorePath(drvPath));
|
||||
}
|
||||
return drvPath;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix::eval_cache
|
||||
|
||||
@@ -44,12 +44,13 @@ EvalErrorBuilder<T> & EvalErrorBuilder<T>::withFrame(const Env & env, const Expr
|
||||
// NOTE: This is abusing side-effects.
|
||||
// TODO: check compatibility with nested debugger calls.
|
||||
// TODO: What side-effects??
|
||||
error.state.debugTraces.push_front(DebugTrace{
|
||||
.pos = expr.getPos(),
|
||||
.expr = expr,
|
||||
.env = env,
|
||||
.hint = HintFmt("Fake frame for debugging purposes"),
|
||||
.isError = true});
|
||||
error.state.debugTraces.push_front(
|
||||
DebugTrace{
|
||||
.pos = expr.getPos(),
|
||||
.expr = expr,
|
||||
.env = env,
|
||||
.hint = HintFmt("Fake frame for debugging purposes"),
|
||||
.isError = true});
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -96,7 +97,8 @@ template<class T>
|
||||
void EvalErrorBuilder<T>::panic()
|
||||
{
|
||||
logError(error.info());
|
||||
printError("This is a bug! An unexpected condition occurred, causing the Nix evaluator to have to stop. If you could share a reproducible example or a core dump, please open an issue at https://github.com/NixOS/nix/issues");
|
||||
printError(
|
||||
"This is a bug! An unexpected condition occurred, causing the Nix evaluator to have to stop. If you could share a reproducible example or a core dump, please open an issue at https://github.com/NixOS/nix/issues");
|
||||
abort();
|
||||
}
|
||||
|
||||
@@ -112,4 +114,4 @@ template class EvalErrorBuilder<InfiniteRecursionError>;
|
||||
template class EvalErrorBuilder<InvalidPathError>;
|
||||
template class EvalErrorBuilder<IFDError>;
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -19,12 +19,14 @@ Strings EvalSettings::parseNixPath(const std::string & s)
|
||||
auto start2 = p;
|
||||
|
||||
while (p != s.end() && *p != ':') {
|
||||
if (*p == '=') start2 = p + 1;
|
||||
if (*p == '=')
|
||||
start2 = p + 1;
|
||||
++p;
|
||||
}
|
||||
|
||||
if (p == s.end()) {
|
||||
if (p != start) res.push_back(std::string(start, p));
|
||||
if (p != start)
|
||||
res.push_back(std::string(start, p));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -32,10 +34,12 @@ Strings EvalSettings::parseNixPath(const std::string & s)
|
||||
auto prefix = std::string(start2, s.end());
|
||||
if (EvalSettings::isPseudoUrl(prefix) || hasPrefix(prefix, "flake:")) {
|
||||
++p;
|
||||
while (p != s.end() && *p != ':') ++p;
|
||||
while (p != s.end() && *p != ':')
|
||||
++p;
|
||||
}
|
||||
res.push_back(std::string(start, p));
|
||||
if (p == s.end()) break;
|
||||
if (p == s.end())
|
||||
break;
|
||||
}
|
||||
|
||||
++p;
|
||||
@@ -75,11 +79,14 @@ Strings EvalSettings::getDefaultNixPath()
|
||||
|
||||
bool EvalSettings::isPseudoUrl(std::string_view s)
|
||||
{
|
||||
if (s.compare(0, 8, "channel:") == 0) return true;
|
||||
if (s.compare(0, 8, "channel:") == 0)
|
||||
return true;
|
||||
size_t pos = s.find("://");
|
||||
if (pos == std::string::npos) return false;
|
||||
if (pos == std::string::npos)
|
||||
return false;
|
||||
std::string scheme(s, 0, pos);
|
||||
return scheme == "http" || scheme == "https" || scheme == "file" || scheme == "channel" || scheme == "git" || scheme == "s3" || scheme == "ssh";
|
||||
return scheme == "http" || scheme == "https" || scheme == "file" || scheme == "channel" || scheme == "git"
|
||||
|| scheme == "s3" || scheme == "ssh";
|
||||
}
|
||||
|
||||
std::string EvalSettings::resolvePseudoUrl(std::string_view url)
|
||||
@@ -98,9 +105,7 @@ const std::string & EvalSettings::getCurrentSystem() const
|
||||
|
||||
Path getNixDefExpr()
|
||||
{
|
||||
return settings.useXDGBaseDirectories
|
||||
? getStateDir() + "/defexpr"
|
||||
: getHome() + "/.nix-defexpr";
|
||||
return settings.useXDGBaseDirectories ? getStateDir() + "/defexpr" : getHome() + "/.nix-defexpr";
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
1176
src/libexpr/eval.cc
1176
src/libexpr/eval.cc
File diff suppressed because it is too large
Load Diff
@@ -3,16 +3,19 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
FunctionCallTrace::FunctionCallTrace(const Pos & pos) : pos(pos) {
|
||||
FunctionCallTrace::FunctionCallTrace(const Pos & pos)
|
||||
: pos(pos)
|
||||
{
|
||||
auto duration = std::chrono::high_resolution_clock::now().time_since_epoch();
|
||||
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration);
|
||||
printMsg(lvlInfo, "function-trace entered %1% at %2%", pos, ns.count());
|
||||
}
|
||||
|
||||
FunctionCallTrace::~FunctionCallTrace() {
|
||||
FunctionCallTrace::~FunctionCallTrace()
|
||||
{
|
||||
auto duration = std::chrono::high_resolution_clock::now().time_since_epoch();
|
||||
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration);
|
||||
printMsg(lvlInfo, "function-trace exited %1% at %2%", pos, ns.count());
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -7,18 +7,19 @@
|
||||
#include <cstring>
|
||||
#include <regex>
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
PackageInfo::PackageInfo(EvalState & state, std::string attrPath, const Bindings * attrs)
|
||||
: state(&state), attrs(attrs), attrPath(std::move(attrPath))
|
||||
: state(&state)
|
||||
, attrs(attrs)
|
||||
, attrPath(std::move(attrPath))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PackageInfo::PackageInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs)
|
||||
: state(&state), attrs(nullptr), attrPath("")
|
||||
: state(&state)
|
||||
, attrs(nullptr)
|
||||
, attrPath("")
|
||||
{
|
||||
auto [drvPath, selectedOutputs] = parsePathWithOutputs(*store, drvPathWithOutputs);
|
||||
|
||||
@@ -31,10 +32,7 @@ PackageInfo::PackageInfo(EvalState & state, ref<Store> store, const std::string
|
||||
if (selectedOutputs.size() > 1)
|
||||
throw Error("building more than one derivation output is not supported, in '%s'", drvPathWithOutputs);
|
||||
|
||||
outputName =
|
||||
selectedOutputs.empty()
|
||||
? getOr(drv.env, "outputName", "out")
|
||||
: *selectedOutputs.begin();
|
||||
outputName = selectedOutputs.empty() ? getOr(drv.env, "outputName", "out") : *selectedOutputs.begin();
|
||||
|
||||
auto i = drv.outputs.find(outputName);
|
||||
if (i == drv.outputs.end())
|
||||
@@ -44,34 +42,36 @@ PackageInfo::PackageInfo(EvalState & state, ref<Store> store, const std::string
|
||||
outPath = {output.path(*store, drv.name, outputName)};
|
||||
}
|
||||
|
||||
|
||||
std::string PackageInfo::queryName() const
|
||||
{
|
||||
if (name == "" && attrs) {
|
||||
auto i = attrs->find(state->sName);
|
||||
if (i == attrs->end()) state->error<TypeError>("derivation name missing").debugThrow();
|
||||
if (i == attrs->end())
|
||||
state->error<TypeError>("derivation name missing").debugThrow();
|
||||
name = state->forceStringNoCtx(*i->value, noPos, "while evaluating the 'name' attribute of a derivation");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
std::string PackageInfo::querySystem() const
|
||||
{
|
||||
if (system == "" && attrs) {
|
||||
auto i = attrs->find(state->sSystem);
|
||||
system = i == attrs->end() ? "unknown" : state->forceStringNoCtx(*i->value, i->pos, "while evaluating the 'system' attribute of a derivation");
|
||||
system =
|
||||
i == attrs->end()
|
||||
? "unknown"
|
||||
: state->forceStringNoCtx(*i->value, i->pos, "while evaluating the 'system' attribute of a derivation");
|
||||
}
|
||||
return system;
|
||||
}
|
||||
|
||||
|
||||
std::optional<StorePath> PackageInfo::queryDrvPath() const
|
||||
{
|
||||
if (!drvPath && attrs) {
|
||||
if (auto i = attrs->get(state->sDrvPath)) {
|
||||
NixStringContext context;
|
||||
auto found = state->coerceToStorePath(i->pos, *i->value, context, "while evaluating the 'drvPath' attribute of a derivation");
|
||||
auto found = state->coerceToStorePath(
|
||||
i->pos, *i->value, context, "while evaluating the 'drvPath' attribute of a derivation");
|
||||
try {
|
||||
found.requireDerivation();
|
||||
} catch (Error & e) {
|
||||
@@ -85,7 +85,6 @@ std::optional<StorePath> PackageInfo::queryDrvPath() const
|
||||
return drvPath.value_or(std::nullopt);
|
||||
}
|
||||
|
||||
|
||||
StorePath PackageInfo::requireDrvPath() const
|
||||
{
|
||||
if (auto drvPath = queryDrvPath())
|
||||
@@ -93,21 +92,20 @@ StorePath PackageInfo::requireDrvPath() const
|
||||
throw Error("derivation does not contain a 'drvPath' attribute");
|
||||
}
|
||||
|
||||
|
||||
StorePath PackageInfo::queryOutPath() const
|
||||
{
|
||||
if (!outPath && attrs) {
|
||||
auto i = attrs->find(state->sOutPath);
|
||||
NixStringContext context;
|
||||
if (i != attrs->end())
|
||||
outPath = state->coerceToStorePath(i->pos, *i->value, context, "while evaluating the output path of a derivation");
|
||||
outPath = state->coerceToStorePath(
|
||||
i->pos, *i->value, context, "while evaluating the output path of a derivation");
|
||||
}
|
||||
if (!outPath)
|
||||
throw UnimplementedError("CA derivations are not yet supported");
|
||||
return *outPath;
|
||||
}
|
||||
|
||||
|
||||
PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsToInstall)
|
||||
{
|
||||
if (outputs.empty()) {
|
||||
@@ -118,19 +116,25 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT
|
||||
|
||||
/* For each output... */
|
||||
for (auto elem : i->value->listItems()) {
|
||||
std::string output(state->forceStringNoCtx(*elem, i->pos, "while evaluating the name of an output of a derivation"));
|
||||
std::string output(
|
||||
state->forceStringNoCtx(*elem, i->pos, "while evaluating the name of an output of a derivation"));
|
||||
|
||||
if (withPaths) {
|
||||
/* Evaluate the corresponding set. */
|
||||
auto out = attrs->get(state->symbols.create(output));
|
||||
if (!out) continue; // FIXME: throw error?
|
||||
if (!out)
|
||||
continue; // FIXME: throw error?
|
||||
state->forceAttrs(*out->value, i->pos, "while evaluating an output of a derivation");
|
||||
|
||||
/* And evaluate its ‘outPath’ attribute. */
|
||||
auto outPath = out->value->attrs()->get(state->sOutPath);
|
||||
if (!outPath) continue; // FIXME: throw error?
|
||||
if (!outPath)
|
||||
continue; // FIXME: throw error?
|
||||
NixStringContext context;
|
||||
outputs.emplace(output, state->coerceToStorePath(outPath->pos, *outPath->value, context, "while evaluating an output path of a derivation"));
|
||||
outputs.emplace(
|
||||
output,
|
||||
state->coerceToStorePath(
|
||||
outPath->pos, *outPath->value, context, "while evaluating an output path of a derivation"));
|
||||
} else
|
||||
outputs.emplace(output, std::nullopt);
|
||||
}
|
||||
@@ -142,7 +146,8 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT
|
||||
return outputs;
|
||||
|
||||
const Attr * i;
|
||||
if (attrs && (i = attrs->get(state->sOutputSpecified)) && state->forceBool(*i->value, i->pos, "while evaluating the 'outputSpecified' attribute of a derivation")) {
|
||||
if (attrs && (i = attrs->get(state->sOutputSpecified))
|
||||
&& state->forceBool(*i->value, i->pos, "while evaluating the 'outputSpecified' attribute of a derivation")) {
|
||||
Outputs result;
|
||||
auto out = outputs.find(queryOutputName());
|
||||
if (out == outputs.end())
|
||||
@@ -154,95 +159,103 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT
|
||||
else {
|
||||
/* Check for `meta.outputsToInstall` and return `outputs` reduced to that. */
|
||||
const Value * outTI = queryMeta("outputsToInstall");
|
||||
if (!outTI) return outputs;
|
||||
if (!outTI)
|
||||
return outputs;
|
||||
auto errMsg = Error("this derivation has bad 'meta.outputsToInstall'");
|
||||
/* ^ this shows during `nix-env -i` right under the bad derivation */
|
||||
if (!outTI->isList()) throw errMsg;
|
||||
/* ^ this shows during `nix-env -i` right under the bad derivation */
|
||||
if (!outTI->isList())
|
||||
throw errMsg;
|
||||
Outputs result;
|
||||
for (auto elem : outTI->listItems()) {
|
||||
if (elem->type() != nString) throw errMsg;
|
||||
if (elem->type() != nString)
|
||||
throw errMsg;
|
||||
auto out = outputs.find(elem->c_str());
|
||||
if (out == outputs.end()) throw errMsg;
|
||||
if (out == outputs.end())
|
||||
throw errMsg;
|
||||
result.insert(*out);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string PackageInfo::queryOutputName() const
|
||||
{
|
||||
if (outputName == "" && attrs) {
|
||||
auto i = attrs->get(state->sOutputName);
|
||||
outputName = i ? state->forceStringNoCtx(*i->value, noPos, "while evaluating the output name of a derivation") : "";
|
||||
outputName =
|
||||
i ? state->forceStringNoCtx(*i->value, noPos, "while evaluating the output name of a derivation") : "";
|
||||
}
|
||||
return outputName;
|
||||
}
|
||||
|
||||
|
||||
const Bindings * PackageInfo::getMeta()
|
||||
{
|
||||
if (meta) return meta;
|
||||
if (!attrs) return 0;
|
||||
if (meta)
|
||||
return meta;
|
||||
if (!attrs)
|
||||
return 0;
|
||||
auto a = attrs->get(state->sMeta);
|
||||
if (!a) return 0;
|
||||
if (!a)
|
||||
return 0;
|
||||
state->forceAttrs(*a->value, a->pos, "while evaluating the 'meta' attribute of a derivation");
|
||||
meta = a->value->attrs();
|
||||
return meta;
|
||||
}
|
||||
|
||||
|
||||
StringSet PackageInfo::queryMetaNames()
|
||||
{
|
||||
StringSet res;
|
||||
if (!getMeta()) return res;
|
||||
if (!getMeta())
|
||||
return res;
|
||||
for (auto & i : *meta)
|
||||
res.emplace(state->symbols[i.name]);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool PackageInfo::checkMeta(Value & v)
|
||||
{
|
||||
state->forceValue(v, v.determinePos(noPos));
|
||||
if (v.type() == nList) {
|
||||
for (auto elem : v.listItems())
|
||||
if (!checkMeta(*elem)) return false;
|
||||
if (!checkMeta(*elem))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
else if (v.type() == nAttrs) {
|
||||
if (v.attrs()->get(state->sOutPath)) return false;
|
||||
} else if (v.type() == nAttrs) {
|
||||
if (v.attrs()->get(state->sOutPath))
|
||||
return false;
|
||||
for (auto & i : *v.attrs())
|
||||
if (!checkMeta(*i.value)) return false;
|
||||
if (!checkMeta(*i.value))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
else return v.type() == nInt || v.type() == nBool || v.type() == nString ||
|
||||
v.type() == nFloat;
|
||||
} else
|
||||
return v.type() == nInt || v.type() == nBool || v.type() == nString || v.type() == nFloat;
|
||||
}
|
||||
|
||||
|
||||
Value * PackageInfo::queryMeta(const std::string & name)
|
||||
{
|
||||
if (!getMeta()) return 0;
|
||||
if (!getMeta())
|
||||
return 0;
|
||||
auto a = meta->get(state->symbols.create(name));
|
||||
if (!a || !checkMeta(*a->value)) return 0;
|
||||
if (!a || !checkMeta(*a->value))
|
||||
return 0;
|
||||
return a->value;
|
||||
}
|
||||
|
||||
|
||||
std::string PackageInfo::queryMetaString(const std::string & name)
|
||||
{
|
||||
Value * v = queryMeta(name);
|
||||
if (!v || v->type() != nString) return "";
|
||||
if (!v || v->type() != nString)
|
||||
return "";
|
||||
return v->c_str();
|
||||
}
|
||||
|
||||
|
||||
NixInt PackageInfo::queryMetaInt(const std::string & name, NixInt def)
|
||||
{
|
||||
Value * v = queryMeta(name);
|
||||
if (!v) return def;
|
||||
if (v->type() == nInt) return v->integer();
|
||||
if (!v)
|
||||
return def;
|
||||
if (v->type() == nInt)
|
||||
return v->integer();
|
||||
if (v->type() == nString) {
|
||||
/* Backwards compatibility with before we had support for
|
||||
integer meta fields. */
|
||||
@@ -255,8 +268,10 @@ NixInt PackageInfo::queryMetaInt(const std::string & name, NixInt def)
|
||||
NixFloat PackageInfo::queryMetaFloat(const std::string & name, NixFloat def)
|
||||
{
|
||||
Value * v = queryMeta(name);
|
||||
if (!v) return def;
|
||||
if (v->type() == nFloat) return v->fpoint();
|
||||
if (!v)
|
||||
return def;
|
||||
if (v->type() == nFloat)
|
||||
return v->fpoint();
|
||||
if (v->type() == nString) {
|
||||
/* Backwards compatibility with before we had support for
|
||||
float meta fields. */
|
||||
@@ -266,22 +281,24 @@ NixFloat PackageInfo::queryMetaFloat(const std::string & name, NixFloat def)
|
||||
return def;
|
||||
}
|
||||
|
||||
|
||||
bool PackageInfo::queryMetaBool(const std::string & name, bool def)
|
||||
{
|
||||
Value * v = queryMeta(name);
|
||||
if (!v) return def;
|
||||
if (v->type() == nBool) return v->boolean();
|
||||
if (!v)
|
||||
return def;
|
||||
if (v->type() == nBool)
|
||||
return v->boolean();
|
||||
if (v->type() == nString) {
|
||||
/* Backwards compatibility with before we had support for
|
||||
Boolean meta fields. */
|
||||
if (v->string_view() == "true") return true;
|
||||
if (v->string_view() == "false") return false;
|
||||
if (v->string_view() == "true")
|
||||
return true;
|
||||
if (v->string_view() == "false")
|
||||
return false;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
|
||||
void PackageInfo::setMeta(const std::string & name, Value * v)
|
||||
{
|
||||
getMeta();
|
||||
@@ -291,30 +308,35 @@ void PackageInfo::setMeta(const std::string & name, Value * v)
|
||||
for (auto i : *meta)
|
||||
if (i.name != sym)
|
||||
attrs.insert(i);
|
||||
if (v) attrs.insert(sym, v);
|
||||
if (v)
|
||||
attrs.insert(sym, v);
|
||||
meta = attrs.finish();
|
||||
}
|
||||
|
||||
|
||||
/* Cache for already considered attrsets. */
|
||||
typedef std::set<const Bindings *> Done;
|
||||
|
||||
|
||||
/* Evaluate value `v'. If it evaluates to a set of type `derivation',
|
||||
then put information about it in `drvs' (unless it's already in `done').
|
||||
The result boolean indicates whether it makes sense
|
||||
for the caller to recursively search for derivations in `v'. */
|
||||
static bool getDerivation(EvalState & state, Value & v,
|
||||
const std::string & attrPath, PackageInfos & drvs, Done & done,
|
||||
static bool getDerivation(
|
||||
EvalState & state,
|
||||
Value & v,
|
||||
const std::string & attrPath,
|
||||
PackageInfos & drvs,
|
||||
Done & done,
|
||||
bool ignoreAssertionFailures)
|
||||
{
|
||||
try {
|
||||
state.forceValue(v, v.determinePos(noPos));
|
||||
if (!state.isDerivation(v)) return true;
|
||||
if (!state.isDerivation(v))
|
||||
return true;
|
||||
|
||||
/* Remove spurious duplicates (e.g., a set like `rec { x =
|
||||
derivation {...}; y = x;}'. */
|
||||
if (!done.insert(v.attrs()).second) return false;
|
||||
if (!done.insert(v.attrs()).second)
|
||||
return false;
|
||||
|
||||
PackageInfo drv(state, attrPath, v.attrs());
|
||||
|
||||
@@ -325,42 +347,44 @@ static bool getDerivation(EvalState & state, Value & v,
|
||||
return false;
|
||||
|
||||
} catch (AssertionError & e) {
|
||||
if (ignoreAssertionFailures) return false;
|
||||
if (ignoreAssertionFailures)
|
||||
return false;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::optional<PackageInfo> getDerivation(EvalState & state, Value & v,
|
||||
bool ignoreAssertionFailures)
|
||||
std::optional<PackageInfo> getDerivation(EvalState & state, Value & v, bool ignoreAssertionFailures)
|
||||
{
|
||||
Done done;
|
||||
PackageInfos drvs;
|
||||
getDerivation(state, v, "", drvs, done, ignoreAssertionFailures);
|
||||
if (drvs.size() != 1) return {};
|
||||
if (drvs.size() != 1)
|
||||
return {};
|
||||
return std::move(drvs.front());
|
||||
}
|
||||
|
||||
|
||||
static std::string addToPath(const std::string & s1, std::string_view s2)
|
||||
{
|
||||
return s1.empty() ? std::string(s2) : s1 + "." + s2;
|
||||
}
|
||||
|
||||
|
||||
static std::regex attrRegex("[A-Za-z_][A-Za-z0-9-_+]*");
|
||||
|
||||
|
||||
static void getDerivations(EvalState & state, Value & vIn,
|
||||
const std::string & pathPrefix, Bindings & autoArgs,
|
||||
PackageInfos & drvs, Done & done,
|
||||
static void getDerivations(
|
||||
EvalState & state,
|
||||
Value & vIn,
|
||||
const std::string & pathPrefix,
|
||||
Bindings & autoArgs,
|
||||
PackageInfos & drvs,
|
||||
Done & done,
|
||||
bool ignoreAssertionFailures)
|
||||
{
|
||||
Value v;
|
||||
state.autoCallFunction(autoArgs, vIn, v);
|
||||
|
||||
/* Process the expression. */
|
||||
if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures)) ;
|
||||
if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures))
|
||||
;
|
||||
|
||||
else if (v.type() == nAttrs) {
|
||||
|
||||
@@ -388,8 +412,11 @@ static void getDerivations(EvalState & state, Value & vIn,
|
||||
`recurseForDerivations = true' attribute. */
|
||||
if (i->value->type() == nAttrs) {
|
||||
auto j = i->value->attrs()->get(state.sRecurseForDerivations);
|
||||
if (j && state.forceBool(*j->value, j->pos, "while evaluating the attribute `recurseForDerivations`"))
|
||||
getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
|
||||
if (j
|
||||
&& state.forceBool(
|
||||
*j->value, j->pos, "while evaluating the attribute `recurseForDerivations`"))
|
||||
getDerivations(
|
||||
state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
|
||||
}
|
||||
}
|
||||
} catch (Error & e) {
|
||||
@@ -411,13 +438,16 @@ static void getDerivations(EvalState & state, Value & vIn,
|
||||
state.error<TypeError>("expression does not evaluate to a derivation (or a set or list of those)").debugThrow();
|
||||
}
|
||||
|
||||
|
||||
void getDerivations(EvalState & state, Value & v, const std::string & pathPrefix,
|
||||
Bindings & autoArgs, PackageInfos & drvs, bool ignoreAssertionFailures)
|
||||
void getDerivations(
|
||||
EvalState & state,
|
||||
Value & v,
|
||||
const std::string & pathPrefix,
|
||||
Bindings & autoArgs,
|
||||
PackageInfos & drvs,
|
||||
bool ignoreAssertionFailures)
|
||||
{
|
||||
Done done;
|
||||
getDerivations(state, v, pathPrefix, autoArgs, drvs, done, ignoreAssertionFailures);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -11,11 +11,8 @@ namespace nix {
|
||||
MakeError(AttrPathNotFound, Error);
|
||||
MakeError(NoPositionInfo, Error);
|
||||
|
||||
std::pair<Value *, PosIdx> findAlongAttrPath(
|
||||
EvalState & state,
|
||||
const std::string & attrPath,
|
||||
Bindings & autoArgs,
|
||||
Value & vIn);
|
||||
std::pair<Value *, PosIdx>
|
||||
findAlongAttrPath(EvalState & state, const std::string & attrPath, Bindings & autoArgs, Value & vIn);
|
||||
|
||||
/**
|
||||
* Heuristic to find the filename and lineno or a nix value.
|
||||
@@ -24,4 +21,4 @@ std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v
|
||||
|
||||
std::vector<Symbol> parseAttrPath(EvalState & state, std::string_view s);
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
class EvalState;
|
||||
struct Value;
|
||||
|
||||
@@ -25,15 +24,19 @@ struct Attr
|
||||
PosIdx pos;
|
||||
Value * value;
|
||||
Attr(Symbol name, Value * value, PosIdx pos = noPos)
|
||||
: name(name), pos(pos), value(value) { };
|
||||
Attr() { };
|
||||
auto operator <=> (const Attr & a) const
|
||||
: name(name)
|
||||
, pos(pos)
|
||||
, value(value) {};
|
||||
Attr() {};
|
||||
|
||||
auto operator<=>(const Attr & a) const
|
||||
{
|
||||
return name <=> a.name;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(Attr) == 2 * sizeof(uint32_t) + sizeof(Value *),
|
||||
static_assert(
|
||||
sizeof(Attr) == 2 * sizeof(uint32_t) + sizeof(Value *),
|
||||
"performance of the evaluator is highly sensitive to the size of Attr. "
|
||||
"avoid introducing any padding into Attr if at all possible, and do not "
|
||||
"introduce new fields that need not be present for almost every instance.");
|
||||
@@ -54,13 +57,24 @@ private:
|
||||
size_t size_, capacity_;
|
||||
Attr attrs[0];
|
||||
|
||||
Bindings(size_t capacity) : size_(0), capacity_(capacity) { }
|
||||
Bindings(size_t capacity)
|
||||
: size_(0)
|
||||
, capacity_(capacity)
|
||||
{
|
||||
}
|
||||
|
||||
Bindings(const Bindings & bindings) = delete;
|
||||
|
||||
public:
|
||||
size_t size() const { return size_; }
|
||||
size_t size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
bool empty() const { return !size_; }
|
||||
bool empty() const
|
||||
{
|
||||
return !size_;
|
||||
}
|
||||
|
||||
typedef Attr * iterator;
|
||||
|
||||
@@ -76,7 +90,8 @@ public:
|
||||
{
|
||||
Attr key(name, 0);
|
||||
const_iterator i = std::lower_bound(begin(), end(), key);
|
||||
if (i != end() && i->name == name) return i;
|
||||
if (i != end() && i->name == name)
|
||||
return i;
|
||||
return end();
|
||||
}
|
||||
|
||||
@@ -84,15 +99,30 @@ public:
|
||||
{
|
||||
Attr key(name, 0);
|
||||
const_iterator i = std::lower_bound(begin(), end(), key);
|
||||
if (i != end() && i->name == name) return &*i;
|
||||
if (i != end() && i->name == name)
|
||||
return &*i;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
iterator begin() { return &attrs[0]; }
|
||||
iterator end() { return &attrs[size_]; }
|
||||
iterator begin()
|
||||
{
|
||||
return &attrs[0];
|
||||
}
|
||||
|
||||
const_iterator begin() const { return &attrs[0]; }
|
||||
const_iterator end() const { return &attrs[size_]; }
|
||||
iterator end()
|
||||
{
|
||||
return &attrs[size_];
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return &attrs[0];
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return &attrs[size_];
|
||||
}
|
||||
|
||||
Attr & operator[](size_t pos)
|
||||
{
|
||||
@@ -106,7 +136,10 @@ public:
|
||||
|
||||
void sort();
|
||||
|
||||
size_t capacity() const { return capacity_; }
|
||||
size_t capacity() const
|
||||
{
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attributes in lexicographically sorted order.
|
||||
@@ -143,8 +176,10 @@ public:
|
||||
EvalState & state;
|
||||
|
||||
BindingsBuilder(EvalState & state, Bindings * bindings)
|
||||
: bindings(bindings), state(state)
|
||||
{ }
|
||||
: bindings(bindings)
|
||||
, state(state)
|
||||
{
|
||||
}
|
||||
|
||||
void insert(Symbol name, Value * value, PosIdx pos = noPos)
|
||||
{
|
||||
@@ -191,4 +226,4 @@ public:
|
||||
friend struct ExprAttrs;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -43,10 +43,7 @@ class EvalCache : public std::enable_shared_from_this<EvalCache>
|
||||
|
||||
public:
|
||||
|
||||
EvalCache(
|
||||
std::optional<std::reference_wrapper<const Hash>> useCache,
|
||||
EvalState & state,
|
||||
RootLoader rootLoader);
|
||||
EvalCache(std::optional<std::reference_wrapper<const Hash>> useCache, EvalState & state, RootLoader rootLoader);
|
||||
|
||||
ref<AttrCursor> getRoot();
|
||||
};
|
||||
@@ -63,11 +60,23 @@ enum AttrType {
|
||||
Int = 8,
|
||||
};
|
||||
|
||||
struct placeholder_t {};
|
||||
struct missing_t {};
|
||||
struct misc_t {};
|
||||
struct failed_t {};
|
||||
struct int_t { NixInt x; };
|
||||
struct placeholder_t
|
||||
{};
|
||||
|
||||
struct missing_t
|
||||
{};
|
||||
|
||||
struct misc_t
|
||||
{};
|
||||
|
||||
struct failed_t
|
||||
{};
|
||||
|
||||
struct int_t
|
||||
{
|
||||
NixInt x;
|
||||
};
|
||||
|
||||
typedef uint64_t AttrId;
|
||||
typedef std::pair<AttrId, Symbol> AttrKey;
|
||||
typedef std::pair<std::string, NixStringContext> string_t;
|
||||
@@ -81,8 +90,8 @@ typedef std::variant<
|
||||
failed_t,
|
||||
bool,
|
||||
int_t,
|
||||
std::vector<std::string>
|
||||
> AttrValue;
|
||||
std::vector<std::string>>
|
||||
AttrValue;
|
||||
|
||||
class AttrCursor : public std::enable_shared_from_this<AttrCursor>
|
||||
{
|
||||
@@ -161,4 +170,4 @@ public:
|
||||
StorePath forceDerivation();
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nix::eval_cache
|
||||
|
||||
@@ -60,6 +60,7 @@ struct InvalidPathError : public EvalError
|
||||
{
|
||||
public:
|
||||
Path path;
|
||||
|
||||
InvalidPathError(EvalState & state, const Path & path)
|
||||
: EvalError(state, "path '%s' is not valid", path)
|
||||
{
|
||||
@@ -119,4 +120,4 @@ public:
|
||||
[[gnu::noinline, gnu::noreturn]] void panic();
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -23,11 +23,11 @@ inline void * allocBytes(size_t n)
|
||||
#else
|
||||
p = calloc(n, 1);
|
||||
#endif
|
||||
if (!p) throw std::bad_alloc();
|
||||
if (!p)
|
||||
throw std::bad_alloc();
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
[[gnu::always_inline]]
|
||||
Value * EvalState::allocValue()
|
||||
{
|
||||
@@ -38,7 +38,8 @@ Value * EvalState::allocValue()
|
||||
have to explicitly clear the first word of every object we take. */
|
||||
if (!*valueAllocCache) {
|
||||
*valueAllocCache = GC_malloc_many(sizeof(Value));
|
||||
if (!*valueAllocCache) throw std::bad_alloc();
|
||||
if (!*valueAllocCache)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
/* GC_NEXT is a convenience macro for accessing the first word of an object.
|
||||
@@ -54,7 +55,6 @@ Value * EvalState::allocValue()
|
||||
return (Value *) p;
|
||||
}
|
||||
|
||||
|
||||
[[gnu::always_inline]]
|
||||
Env & EvalState::allocEnv(size_t size)
|
||||
{
|
||||
@@ -68,7 +68,8 @@ Env & EvalState::allocEnv(size_t size)
|
||||
/* see allocValue for explanations. */
|
||||
if (!*env1AllocCache) {
|
||||
*env1AllocCache = GC_malloc_many(sizeof(Env) + sizeof(Value *));
|
||||
if (!*env1AllocCache) throw std::bad_alloc();
|
||||
if (!*env1AllocCache)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
void * p = *env1AllocCache;
|
||||
@@ -84,7 +85,6 @@ Env & EvalState::allocEnv(size_t size)
|
||||
return *env;
|
||||
}
|
||||
|
||||
|
||||
[[gnu::always_inline]]
|
||||
void EvalState::forceValue(Value & v, const PosIdx pos)
|
||||
{
|
||||
@@ -94,7 +94,7 @@ void EvalState::forceValue(Value & v, const PosIdx pos)
|
||||
Expr * expr = v.payload.thunk.expr;
|
||||
try {
|
||||
v.mkBlackhole();
|
||||
//checkInterrupt();
|
||||
// checkInterrupt();
|
||||
if (env) [[likely]]
|
||||
expr->eval(*this, *env, v);
|
||||
else
|
||||
@@ -104,54 +104,47 @@ void EvalState::forceValue(Value & v, const PosIdx pos)
|
||||
tryFixupBlackHolePos(v, pos);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else if (v.isApp())
|
||||
} else if (v.isApp())
|
||||
callFunction(*v.payload.app.left, *v.payload.app.right, v, pos);
|
||||
}
|
||||
|
||||
|
||||
[[gnu::always_inline]]
|
||||
inline void EvalState::forceAttrs(Value & v, const PosIdx pos, std::string_view errorCtx)
|
||||
{
|
||||
forceAttrs(v, [&]() { return pos; }, errorCtx);
|
||||
}
|
||||
|
||||
|
||||
template <typename Callable>
|
||||
template<typename Callable>
|
||||
[[gnu::always_inline]]
|
||||
inline void EvalState::forceAttrs(Value & v, Callable getPos, std::string_view errorCtx)
|
||||
{
|
||||
PosIdx pos = getPos();
|
||||
forceValue(v, pos);
|
||||
if (v.type() != nAttrs) {
|
||||
error<TypeError>(
|
||||
"expected a set but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
).withTrace(pos, errorCtx).debugThrow();
|
||||
error<TypeError>("expected a set but found %1%: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions))
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[[gnu::always_inline]]
|
||||
inline void EvalState::forceList(Value & v, const PosIdx pos, std::string_view errorCtx)
|
||||
{
|
||||
forceValue(v, pos);
|
||||
if (!v.isList()) {
|
||||
error<TypeError>(
|
||||
"expected a list but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
).withTrace(pos, errorCtx).debugThrow();
|
||||
error<TypeError>("expected a list but found %1%: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions))
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
[[gnu::always_inline]]
|
||||
inline CallDepth EvalState::addCallDepth(const PosIdx pos) {
|
||||
inline CallDepth EvalState::addCallDepth(const PosIdx pos)
|
||||
{
|
||||
if (callDepth > settings.maxCallDepth)
|
||||
error<EvalBaseError>("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow();
|
||||
|
||||
return CallDepth(callDepth);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
@@ -73,7 +73,9 @@ struct EvalSettings : Config
|
||||
)"};
|
||||
|
||||
Setting<Strings> nixPath{
|
||||
this, {}, "nix-path",
|
||||
this,
|
||||
{},
|
||||
"nix-path",
|
||||
R"(
|
||||
List of search paths to use for [lookup path](@docroot@/language/constructs/lookup-path.md) resolution.
|
||||
This setting determines the value of
|
||||
@@ -106,10 +108,14 @@ struct EvalSettings : Config
|
||||
> If [restricted evaluation](@docroot@/command-ref/conf-file.md#conf-restrict-eval) is enabled, the default value is empty.
|
||||
>
|
||||
> If [pure evaluation](#conf-pure-eval) is enabled, `builtins.nixPath` *always* evaluates to the empty list `[ ]`.
|
||||
)", {}, false};
|
||||
)",
|
||||
{},
|
||||
false};
|
||||
|
||||
Setting<std::string> currentSystem{
|
||||
this, "", "eval-system",
|
||||
this,
|
||||
"",
|
||||
"eval-system",
|
||||
R"(
|
||||
This option defines
|
||||
[`builtins.currentSystem`](@docroot@/language/builtins.md#builtins-currentSystem)
|
||||
@@ -129,7 +135,9 @@ struct EvalSettings : Config
|
||||
const std::string & getCurrentSystem() const;
|
||||
|
||||
Setting<bool> restrictEval{
|
||||
this, false, "restrict-eval",
|
||||
this,
|
||||
false,
|
||||
"restrict-eval",
|
||||
R"(
|
||||
If set to `true`, the Nix evaluator will not allow access to any
|
||||
files outside of
|
||||
@@ -138,7 +146,10 @@ struct EvalSettings : Config
|
||||
[`allowed-uris`](@docroot@/command-ref/conf-file.md#conf-allowed-uris).
|
||||
)"};
|
||||
|
||||
Setting<bool> pureEval{this, false, "pure-eval",
|
||||
Setting<bool> pureEval{
|
||||
this,
|
||||
false,
|
||||
"pure-eval",
|
||||
R"(
|
||||
Pure evaluation mode ensures that the result of Nix expressions is fully determined by explicitly declared inputs, and not influenced by external state:
|
||||
|
||||
@@ -148,11 +159,12 @@ struct EvalSettings : Config
|
||||
- [`builtins.currentTime`](@docroot@/language/builtins.md#builtins-currentTime)
|
||||
- [`builtins.nixPath`](@docroot@/language/builtins.md#builtins-nixPath)
|
||||
- [`builtins.storePath`](@docroot@/language/builtins.md#builtins-storePath)
|
||||
)"
|
||||
};
|
||||
)"};
|
||||
|
||||
Setting<bool> enableImportFromDerivation{
|
||||
this, true, "allow-import-from-derivation",
|
||||
this,
|
||||
true,
|
||||
"allow-import-from-derivation",
|
||||
R"(
|
||||
By default, Nix allows [Import from Derivation](@docroot@/language/import-from-derivation.md).
|
||||
|
||||
@@ -162,7 +174,10 @@ struct EvalSettings : Config
|
||||
regardless of the state of the store.
|
||||
)"};
|
||||
|
||||
Setting<Strings> allowedUris{this, {}, "allowed-uris",
|
||||
Setting<Strings> allowedUris{
|
||||
this,
|
||||
{},
|
||||
"allowed-uris",
|
||||
R"(
|
||||
A list of URI prefixes to which access is allowed in restricted
|
||||
evaluation mode. For example, when set to
|
||||
@@ -175,7 +190,10 @@ struct EvalSettings : Config
|
||||
- or the prefix is a URI scheme ended by a colon `:` and the URI has the same scheme.
|
||||
)"};
|
||||
|
||||
Setting<bool> traceFunctionCalls{this, false, "trace-function-calls",
|
||||
Setting<bool> traceFunctionCalls{
|
||||
this,
|
||||
false,
|
||||
"trace-function-calls",
|
||||
R"(
|
||||
If set to `true`, the Nix evaluator will trace every function call.
|
||||
Nix will print a log message at the "vomit" level for every function
|
||||
@@ -193,26 +211,38 @@ struct EvalSettings : Config
|
||||
`flamegraph.pl`.
|
||||
)"};
|
||||
|
||||
Setting<bool> useEvalCache{this, true, "eval-cache",
|
||||
Setting<bool> useEvalCache{
|
||||
this,
|
||||
true,
|
||||
"eval-cache",
|
||||
R"(
|
||||
Whether to use the flake evaluation cache.
|
||||
Certain commands won't have to evaluate when invoked for the second time with a particular version of a flake.
|
||||
Intermediate results are not cached.
|
||||
)"};
|
||||
|
||||
Setting<bool> ignoreExceptionsDuringTry{this, false, "ignore-try",
|
||||
Setting<bool> ignoreExceptionsDuringTry{
|
||||
this,
|
||||
false,
|
||||
"ignore-try",
|
||||
R"(
|
||||
If set to true, ignore exceptions inside 'tryEval' calls when evaluating nix expressions in
|
||||
debug mode (using the --debugger flag). By default the debugger will pause on all exceptions.
|
||||
)"};
|
||||
|
||||
Setting<bool> traceVerbose{this, false, "trace-verbose",
|
||||
Setting<bool> traceVerbose{
|
||||
this,
|
||||
false,
|
||||
"trace-verbose",
|
||||
"Whether `builtins.traceVerbose` should trace its first argument when evaluated."};
|
||||
|
||||
Setting<unsigned int> maxCallDepth{this, 10000, "max-call-depth",
|
||||
"The maximum function call depth to allow before erroring."};
|
||||
Setting<unsigned int> maxCallDepth{
|
||||
this, 10000, "max-call-depth", "The maximum function call depth to allow before erroring."};
|
||||
|
||||
Setting<bool> builtinsTraceDebugger{this, false, "debugger-on-trace",
|
||||
Setting<bool> builtinsTraceDebugger{
|
||||
this,
|
||||
false,
|
||||
"debugger-on-trace",
|
||||
R"(
|
||||
If set to true and the `--debugger` flag is given, the following functions
|
||||
will enter the debugger like [`builtins.break`](@docroot@/language/builtins.md#builtins-break).
|
||||
@@ -225,7 +255,10 @@ struct EvalSettings : Config
|
||||
This is useful for debugging warnings in third-party Nix code.
|
||||
)"};
|
||||
|
||||
Setting<bool> builtinsDebuggerOnWarn{this, false, "debugger-on-warn",
|
||||
Setting<bool> builtinsDebuggerOnWarn{
|
||||
this,
|
||||
false,
|
||||
"debugger-on-warn",
|
||||
R"(
|
||||
If set to true and the `--debugger` flag is given, [`builtins.warn`](@docroot@/language/builtins.md#builtins-warn)
|
||||
will enter the debugger like [`builtins.break`](@docroot@/language/builtins.md#builtins-break).
|
||||
@@ -235,7 +268,10 @@ struct EvalSettings : Config
|
||||
Use [`debugger-on-trace`](#conf-debugger-on-trace) to also enter the debugger on legacy warnings that are logged with [`builtins.trace`](@docroot@/language/builtins.md#builtins-trace).
|
||||
)"};
|
||||
|
||||
Setting<bool> builtinsAbortOnWarn{this, false, "abort-on-warn",
|
||||
Setting<bool> builtinsAbortOnWarn{
|
||||
this,
|
||||
false,
|
||||
"abort-on-warn",
|
||||
R"(
|
||||
If set to true, [`builtins.warn`](@docroot@/language/builtins.md#builtins-warn) will throw an error when logging a warning.
|
||||
|
||||
@@ -254,4 +290,4 @@ struct EvalSettings : Config
|
||||
*/
|
||||
Path getNixDefExpr();
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user