diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 2220649ca..00244700a 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -1,4 +1,3 @@ -# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json # Disable CodeRabbit auto-review to prevent verbose comments on PRs. # When enabled: false, CodeRabbit won't attempt reviews and won't post # "Review skipped" or other automated comments. @@ -13,6 +12,3 @@ reviews: tools: github-checks: enabled: false -chat: - art: false - auto_reply: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a299b765..67e97b188 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -125,13 +125,13 @@ jobs: cat coverage-reports/index.txt >> $GITHUB_STEP_SUMMARY if: ${{ matrix.instrumented }} - name: Upload coverage reports - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v4 with: name: coverage-reports path: coverage-reports/ if: ${{ matrix.instrumented }} - name: Upload installer tarball - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v4 with: name: installer-${{matrix.os}} path: out/* @@ -164,7 +164,7 @@ jobs: steps: - uses: actions/checkout@v5 - name: Download installer tarball - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v5 with: name: installer-${{matrix.os}} path: out @@ -174,7 +174,7 @@ jobs: echo "installer-url=file://$GITHUB_WORKSPACE/out" >> "$GITHUB_OUTPUT" TARBALL_PATH="$(find "$GITHUB_WORKSPACE/out" -name 'nix*.tar.xz' -print | head -n 1)" echo "tarball-path=file://$TARBALL_PATH" >> "$GITHUB_OUTPUT" - - uses: cachix/install-nix-action@456688f15bc354bef6d396e4a35f4f89d40bf2b7 # v31.8.2 + - uses: cachix/install-nix-action@c134e4c9e34bac6cab09cf239815f9339aaaf84e # v31.5.1 if: ${{ !matrix.experimental-installer }} with: install_url: ${{ format('{0}/install', steps.installer-tarball-url.outputs.installer-url) }} diff --git a/ci/gha/tests/default.nix b/ci/gha/tests/default.nix index 6100f2f41..0c5c103bf 100644 --- a/ci/gha/tests/default.nix +++ b/ci/gha/tests/default.nix @@ -107,29 +107,12 @@ rec { }; }; - disable = - let - inherit (pkgs.stdenv) hostPlatform; - in - args@{ - pkgName, - testName, - test, - }: - lib.any (b: b) [ - # FIXME: Nix manual is impure and does not produce all settings on darwin - (hostPlatform.isDarwin && pkgName == "nix-manual" && testName == "linkcheck") - ]; - componentTests = (lib.concatMapAttrs ( pkgName: pkg: - lib.concatMapAttrs ( - testName: test: - lib.optionalAttrs (!disable { inherit pkgName testName test; }) { - "${componentTestsPrefix}${pkgName}-${testName}" = test; - } - ) (pkg.tests or { }) + lib.concatMapAttrs (testName: test: { + "${componentTestsPrefix}${pkgName}-${testName}" = test; + }) (pkg.tests or { }) ) nixComponentsInstrumented) // lib.optionalAttrs (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) { "${componentTestsPrefix}nix-functional-tests" = nixComponentsInstrumented.nix-functional-tests; diff --git a/doc/manual/anchors.jq b/doc/manual/anchors.jq index 4ee2bc130..72309779c 100755 --- a/doc/manual/anchors.jq +++ b/doc/manual/anchors.jq @@ -3,7 +3,7 @@ def transform_anchors_html: - . | gsub($empty_anchor_regex; "") + . | gsub($empty_anchor_regex; "") | gsub($anchor_regex; "" + .text + ""); diff --git a/doc/manual/package.nix b/doc/manual/package.nix index 81061b7a1..7d29df3c3 100644 --- a/doc/manual/package.nix +++ b/doc/manual/package.nix @@ -18,9 +18,6 @@ # Configuration Options version, - - # `tests` attribute - testers, }: let @@ -40,11 +37,9 @@ mkMesonDerivation (finalAttrs: { ../../src/libutil-tests/data/hash ../../src/libstore-tests/data/content-address ../../src/libstore-tests/data/store-path - ../../src/libstore-tests/data/realisation ../../src/libstore-tests/data/derived-path ../../src/libstore-tests/data/path-info ../../src/libstore-tests/data/nar-info - ../../src/libstore-tests/data/build-result # Too many different types of files to filter for now ../../doc/manual ./. @@ -92,29 +87,6 @@ mkMesonDerivation (finalAttrs: { echo "doc manual ''$out/share/doc/nix/manual" >> ''$out/nix-support/hydra-build-products ''; - /** - The root of the HTML manual. - E.g. "${nix-manual.site}/index.html" exists. - */ - passthru.site = finalAttrs.finalPackage + "/share/doc/nix/manual"; - - passthru.tests = { - # https://nixos.org/manual/nixpkgs/stable/index.html#tester-lycheeLinkCheck - linkcheck = testers.lycheeLinkCheck { - inherit (finalAttrs.finalPackage) site; - extraConfig = { - exclude = [ - # Exclude auto-generated JSON schema documentation which has - # auto-generated fragment IDs that don't match the link references - ".*/protocols/json/.*\\.html" - # Exclude undocumented builtins - ".*/language/builtins\\.html#builtins-addErrorContext" - ".*/language/builtins\\.html#builtins-appendContext" - ]; - }; - }; - }; - meta = { platforms = lib.platforms.all; }; diff --git a/doc/manual/rl-next/json-format-changes.md b/doc/manual/rl-next/json-format-changes.md deleted file mode 100644 index c5518ee1b..000000000 --- a/doc/manual/rl-next/json-format-changes.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -synopsis: "JSON format changes for store path info and derivations" -prs: [] -issues: [] ---- - -JSON formats for store path info and derivations have been updated with new versions and structured fields. - -## Store Path Info JSON (Version 2) - -The store path info JSON format has been updated from version 1 to version 2: - -- **Added `version` field**: - - All store path info JSON now includes `"version": 2`. - -- **Structured `ca` field**: - - Content address is now a structured JSON object instead of a string: - - - Old: `"ca": "fixed:r:sha256:1abc..."` - - New: `"ca": {"method": "nar", "hash": {"algorithm": "sha256", "format": "base64", "hash": "EMIJ+giQ..."}}` - - Still `null` values for input-addressed store objects - -Version 1 format is still accepted when reading for backward compatibility. - -**Affected command**: `nix path-info --json` - -## Derivation JSON (Version 4) - -The derivation JSON format has been updated from version 3 to version 4: - -- **Restructured inputs**: - - Inputs are now nested under an `inputs` object: - - - Old: `"inputSrcs": [...], "inputDrvs": {...}` - - New: `"inputs": {"srcs": [...], "drvs": {...}}` - -- **Consistent content addresses**: - - Floating content-addressed outputs now use structured JSON format. - This is the same format as `ca` in in store path info (after the new version). - -Version 3 and earlier formats are *not* accepted when reading. - -**Affected command**: `nix derivation`, namely it's `show` and `add` sub-commands. diff --git a/doc/manual/source/SUMMARY.md.in b/doc/manual/source/SUMMARY.md.in index 5be3d6a90..b87bf93a3 100644 --- a/doc/manual/source/SUMMARY.md.in +++ b/doc/manual/source/SUMMARY.md.in @@ -126,8 +126,6 @@ - [Store Object Info](protocols/json/store-object-info.md) - [Derivation](protocols/json/derivation.md) - [Deriving Path](protocols/json/deriving-path.md) - - [Build Trace Entry](protocols/json/build-trace-entry.md) - - [Build Result](protocols/json/build-result.md) - [Serving Tarball Flakes](protocols/tarball-fetcher.md) - [Store Path Specification](protocols/store-path.md) - [Nix Archive (NAR) Format](protocols/nix-archive/index.md) diff --git a/doc/manual/source/command-ref/nix-channel.md b/doc/manual/source/command-ref/nix-channel.md index 3d02a7d40..ed9cbb41f 100644 --- a/doc/manual/source/command-ref/nix-channel.md +++ b/doc/manual/source/command-ref/nix-channel.md @@ -14,7 +14,7 @@ The moving parts of channels are: - The official channels listed at - The user-specific list of [subscribed channels](#subscribed-channels) - The [downloaded channel contents](#channels) -- The [Nix expression search path](@docroot@/command-ref/conf-file.md#conf-nix-path), set with the [`-I` option](#opt-I) or the [`NIX_PATH` environment variable](#env-NIX_PATH) +- The [Nix expression search path](@docroot@/command-ref/conf-file.md#conf-nix-path), set with the [`-I` option](#opt-i) or the [`NIX_PATH` environment variable](#env-NIX_PATH) > **Note** > diff --git a/doc/manual/source/command-ref/nix-env/upgrade.md b/doc/manual/source/command-ref/nix-env/upgrade.md index bf4c1a8ed..2779363c3 100644 --- a/doc/manual/source/command-ref/nix-env/upgrade.md +++ b/doc/manual/source/command-ref/nix-env/upgrade.md @@ -22,7 +22,7 @@ left untouched; this is not an error. It is also not an error if an element of *args* matches no installed derivations. For a description of how *args* is mapped to a set of store paths, see -[`--install`](./install.md). If *args* describes multiple +[`--install`](#operation---install). If *args* describes multiple store paths with the same symbolic name, only the one with the highest version is installed. diff --git a/doc/manual/source/development/building.md b/doc/manual/source/development/building.md index eb65a7247..889d81d80 100644 --- a/doc/manual/source/development/building.md +++ b/doc/manual/source/development/building.md @@ -66,7 +66,7 @@ You can also build Nix for one of the [supported platforms](#platforms). This section assumes you are using Nix with the [`flakes`] and [`nix-command`] experimental features enabled. [`flakes`]: @docroot@/development/experimental-features.md#xp-feature-flakes -[`nix-command`]: @docroot@/development/experimental-features.md#xp-feature-nix-command +[`nix-command`]: @docroot@/development/experimental-features.md#xp-nix-command To build all dependencies and start a shell in which all environment variables are set up so that those dependencies can be found: @@ -256,7 +256,7 @@ You can use any of the other supported environments in place of `nix-cli-ccacheS ## Editor integration The `clangd` LSP server is installed by default on the `clang`-based `devShell`s. -See [supported compilation environments](#compilation-environments) and instructions how to set up a shell [with flakes](#building-nix-with-flakes) or in [classic Nix](#building-nix). +See [supported compilation environments](#compilation-environments) and instructions how to set up a shell [with flakes](#nix-with-flakes) or in [classic Nix](#classic-nix). To use the LSP with your editor, you will want a `compile_commands.json` file telling `clangd` how we are compiling the code. Meson's configure always produces this inside the build directory. diff --git a/doc/manual/source/development/testing.md b/doc/manual/source/development/testing.md index 7c2cbbb5d..c0b130155 100644 --- a/doc/manual/source/development/testing.md +++ b/doc/manual/source/development/testing.md @@ -119,7 +119,7 @@ This will: 3. Stop the program when the test fails, allowing the user to then issue arbitrary commands to GDB. -### Characterisation testing { #characterisation-testing-unit } +### Characterisation testing { #characaterisation-testing-unit } See [functional characterisation testing](#characterisation-testing-functional) for a broader discussion of characterisation testing. diff --git a/doc/manual/source/glossary.md b/doc/manual/source/glossary.md index 502e6d4de..e6a294e7d 100644 --- a/doc/manual/source/glossary.md +++ b/doc/manual/source/glossary.md @@ -208,7 +208,7 @@ - [impure derivation]{#gloss-impure-derivation} - [An experimental feature](@docroot@/development/experimental-features.md#xp-feature-impure-derivations) that allows derivations to be explicitly marked as impure, + [An experimental feature](#@docroot@/development/experimental-features.md#xp-feature-impure-derivations) that allows derivations to be explicitly marked as impure, so that they are always rebuilt, and their outputs not reused by subsequent calls to realise them. - [Nix database]{#gloss-nix-database} @@ -279,7 +279,7 @@ See [References](@docroot@/store/store-object.md#references) for details. -- [referrer]{#gloss-referrer} +- [referrer]{#gloss-reference} A reversed edge from one [store object] to another. @@ -367,8 +367,8 @@ Nix represents files as [file system objects][file system object], and how they belong together is encoded as [references][reference] between [store objects][store object] that contain these file system objects. - The [Nix language] allows denoting packages in terms of [attribute sets](@docroot@/language/types.md#type-attrs) containing: - - attributes that refer to the files of a package, typically in the form of [derivation outputs](#gloss-output), + The [Nix language] allows denoting packages in terms of [attribute sets](@docroot@/language/types.md#attribute-set) containing: + - attributes that refer to the files of a package, typically in the form of [derivation outputs](#output), - attributes with metadata, such as information about how the package is supposed to be used. The exact shape of these attribute sets is up to convention. @@ -383,7 +383,7 @@ [string]: ./language/types.md#type-string [path]: ./language/types.md#type-path - [attribute name]: ./language/types.md#type-attrs + [attribute name]: ./language/types.md#attribute-set - [base directory]{#gloss-base-directory} diff --git a/doc/manual/source/language/advanced-attributes.md b/doc/manual/source/language/advanced-attributes.md index f0b1a4c73..c9d64f060 100644 --- a/doc/manual/source/language/advanced-attributes.md +++ b/doc/manual/source/language/advanced-attributes.md @@ -333,7 +333,7 @@ Here is more information on the `output*` attributes, and what values they may b `outputHashAlgo` can only be `null` when `outputHash` follows the SRI format, because in that case the choice of hash algorithm is determined by `outputHash`. - - [`outputHash`]{#adv-attr-outputHash} + - [`outputHash`]{#adv-attr-outputHashAlgo}; [`outputHash`]{#adv-attr-outputHashMode} This will specify the output hash of the single output of a [fixed-output derivation]. diff --git a/doc/manual/source/language/derivations.md b/doc/manual/source/language/derivations.md index 2403183fc..43eec680b 100644 --- a/doc/manual/source/language/derivations.md +++ b/doc/manual/source/language/derivations.md @@ -16,7 +16,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect - [`name`]{#attr-name} ([String](@docroot@/language/types.md#type-string)) A symbolic name for the derivation. - See [derivation outputs](@docroot@/store/derivation/outputs/index.md#outputs) for what this is affects. + See [derivation outputs](@docroot@/store/derivation/index.md#outputs) for what this is affects. [store path]: @docroot@/store/store-path.md diff --git a/doc/manual/source/language/identifiers.md b/doc/manual/source/language/identifiers.md index 67bb1eeec..584a2f861 100644 --- a/doc/manual/source/language/identifiers.md +++ b/doc/manual/source/language/identifiers.md @@ -16,7 +16,7 @@ An *identifier* is an [ASCII](https://en.wikipedia.org/wiki/ASCII) character seq # Names -A *name* can be written as an [identifier](#identifiers) or a [string literal](./string-literals.md). +A *name* can be written as an [identifier](#identifier) or a [string literal](./string-literals.md). > **Syntax** > diff --git a/doc/manual/source/language/index.md b/doc/manual/source/language/index.md index 116f928dc..1eb14e96d 100644 --- a/doc/manual/source/language/index.md +++ b/doc/manual/source/language/index.md @@ -137,7 +137,7 @@ This is an incomplete overview of language features, by example. - [Booleans](@docroot@/language/types.md#type-bool) + [Booleans](@docroot@/language/types.md#type-boolean) @@ -245,7 +245,7 @@ This is an incomplete overview of language features, by example. - An [attribute set](@docroot@/language/types.md#type-attrs) with attributes named `x` and `y` + An [attribute set](@docroot@/language/types.md#attribute-set) with attributes named `x` and `y` @@ -285,7 +285,7 @@ This is an incomplete overview of language features, by example. - [Lists](@docroot@/language/types.md#type-list) with three elements. + [Lists](@docroot@/language/types.md#list) with three elements. @@ -369,7 +369,7 @@ This is an incomplete overview of language features, by example. - [Attribute selection](@docroot@/language/types.md#type-attrs) (evaluates to `1`) + [Attribute selection](@docroot@/language/types.md#attribute-set) (evaluates to `1`) @@ -381,7 +381,7 @@ This is an incomplete overview of language features, by example. - [Attribute selection](@docroot@/language/types.md#type-attrs) with default (evaluates to `3`) + [Attribute selection](@docroot@/language/types.md#attribute-set) with default (evaluates to `3`) diff --git a/doc/manual/source/language/string-context.md b/doc/manual/source/language/string-context.md index 65c59d865..0d8fcdefa 100644 --- a/doc/manual/source/language/string-context.md +++ b/doc/manual/source/language/string-context.md @@ -111,7 +111,7 @@ It creates an [attribute set] representing the string context, which can be insp [`builtins.hasContext`]: ./builtins.md#builtins-hasContext [`builtins.getContext`]: ./builtins.md#builtins-getContext -[attribute set]: ./types.md#type-attrs +[attribute set]: ./types.md#attribute-set ## Clearing string contexts diff --git a/doc/manual/source/language/string-interpolation.md b/doc/manual/source/language/string-interpolation.md index 8e25d2b63..a503d5f04 100644 --- a/doc/manual/source/language/string-interpolation.md +++ b/doc/manual/source/language/string-interpolation.md @@ -6,7 +6,7 @@ Such a construct is called *interpolated string*, and the expression inside is a [string]: ./types.md#type-string [path]: ./types.md#type-path -[attribute set]: ./types.md#type-attrs +[attribute set]: ./types.md#attribute-set > **Syntax** > diff --git a/doc/manual/source/language/syntax.md b/doc/manual/source/language/syntax.md index b127aca14..85162db74 100644 --- a/doc/manual/source/language/syntax.md +++ b/doc/manual/source/language/syntax.md @@ -51,7 +51,7 @@ See [String literals](string-literals.md). Path literals can also include [string interpolation], besides being [interpolated into other expressions]. - [interpolated into other expressions]: ./string-interpolation.md#interpolated-expression + [interpolated into other expressions]: ./string-interpolation.md#interpolated-expressions At least one slash (`/`) must appear *before* any interpolated expression for the result to be recognized as a path. @@ -235,7 +235,7 @@ of object-oriented programming, for example. ## Recursive sets -Recursive sets are like normal [attribute sets](./types.md#type-attrs), but the attributes can refer to each other. +Recursive sets are like normal [attribute sets](./types.md#attribute-set), but the attributes can refer to each other. > *rec-attrset* = `rec {` [ *name* `=` *expr* `;` `]`... `}` @@ -287,7 +287,7 @@ This evaluates to `"foobar"`. ## Inheriting attributes -When defining an [attribute set](./types.md#type-attrs) or in a [let-expression](#let-expressions) it is often convenient to copy variables from the surrounding lexical scope (e.g., when you want to propagate attributes). +When defining an [attribute set](./types.md#attribute-set) or in a [let-expression](#let-expressions) it is often convenient to copy variables from the surrounding lexical scope (e.g., when you want to propagate attributes). This can be shortened using the `inherit` keyword. Example: diff --git a/doc/manual/source/protocols/json/build-result.md b/doc/manual/source/protocols/json/build-result.md deleted file mode 100644 index 527e7bcc0..000000000 --- a/doc/manual/source/protocols/json/build-result.md +++ /dev/null @@ -1,21 +0,0 @@ -{{#include build-result-v1-fixed.md}} - -## Examples - -### Successful build - -```json -{{#include schema/build-result-v1/success.json}} -``` - -### Failed build (output rejected) - -```json -{{#include schema/build-result-v1/output-rejected.json}} -``` - -### Failed build (non-deterministic) - -```json -{{#include schema/build-result-v1/not-deterministic.json}} -``` \ No newline at end of file diff --git a/doc/manual/source/protocols/json/build-trace-entry.md b/doc/manual/source/protocols/json/build-trace-entry.md deleted file mode 100644 index 8050a2840..000000000 --- a/doc/manual/source/protocols/json/build-trace-entry.md +++ /dev/null @@ -1,27 +0,0 @@ -{{#include build-trace-entry-v1-fixed.md}} - -## Examples - -### Simple build trace entry - -```json -{{#include schema/build-trace-entry-v1/simple.json}} -``` - -### Build trace entry with dependencies - -```json -{{#include schema/build-trace-entry-v1/with-dependent-realisations.json}} -``` - -### Build trace entry with signature - -```json -{{#include schema/build-trace-entry-v1/with-signature.json}} -``` - - \ No newline at end of file diff --git a/doc/manual/source/protocols/json/derivation.md b/doc/manual/source/protocols/json/derivation.md index 6eafb255e..a4a4ea79d 100644 --- a/doc/manual/source/protocols/json/derivation.md +++ b/doc/manual/source/protocols/json/derivation.md @@ -1,7 +1,7 @@ -{{#include derivation-v4-fixed.md}} +{{#include derivation-v3-fixed.md}} diff --git a/doc/manual/source/protocols/json/meson.build b/doc/manual/source/protocols/json/meson.build index 4ab94c63b..7ebcff697 100644 --- a/doc/manual/source/protocols/json/meson.build +++ b/doc/manual/source/protocols/json/meson.build @@ -12,11 +12,9 @@ schemas = [ 'hash-v1', 'content-address-v1', 'store-path-v1', - 'store-object-info-v2', - 'derivation-v4', + 'store-object-info-v1', + 'derivation-v3', 'deriving-path-v1', - 'build-trace-entry-v1', - 'build-result-v1', ] schema_files = files() diff --git a/doc/manual/source/protocols/json/schema/build-result-v1 b/doc/manual/source/protocols/json/schema/build-result-v1 deleted file mode 120000 index a143d2c50..000000000 --- a/doc/manual/source/protocols/json/schema/build-result-v1 +++ /dev/null @@ -1 +0,0 @@ -../../../../../../src/libstore-tests/data/build-result \ No newline at end of file diff --git a/doc/manual/source/protocols/json/schema/build-result-v1.yaml b/doc/manual/source/protocols/json/schema/build-result-v1.yaml deleted file mode 100644 index 31f59a44d..000000000 --- a/doc/manual/source/protocols/json/schema/build-result-v1.yaml +++ /dev/null @@ -1,136 +0,0 @@ -"$schema": "http://json-schema.org/draft-04/schema" -"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/build-result-v1.json" -title: Build Result -description: | - This schema describes the JSON representation of Nix's `BuildResult` type, which represents the result of building a derivation or substituting store paths. - - Build results can represent either successful builds (with built outputs) or various types of failures. - -oneOf: - - "$ref": "#/$defs/success" - - "$ref": "#/$defs/failure" -type: object -required: - - success - - status -properties: - timesBuilt: - type: integer - minimum: 0 - title: Times built - description: | - How many times this build was performed. - - startTime: - type: integer - minimum: 0 - title: Start time - description: | - The start time of the build (or one of the rounds, if it was repeated), as a Unix timestamp. - - stopTime: - type: integer - minimum: 0 - title: Stop time - description: | - The stop time of the build (or one of the rounds, if it was repeated), as a Unix timestamp. - - cpuUser: - type: integer - minimum: 0 - title: User CPU time - description: | - User CPU time the build took, in microseconds. - - cpuSystem: - type: integer - minimum: 0 - title: System CPU time - description: | - System CPU time the build took, in microseconds. - -"$defs": - success: - type: object - title: Successful Build Result - description: | - Represents a successful build with built outputs. - required: - - success - - status - - builtOutputs - properties: - success: - const: true - title: Success indicator - description: | - Always true for successful build results. - - status: - type: string - title: Success status - description: | - Status string for successful builds. - enum: - - "Built" - - "Substituted" - - "AlreadyValid" - - "ResolvesToAlreadyValid" - - builtOutputs: - type: object - title: Built outputs - description: | - A mapping from output names to their build trace entries. - additionalProperties: - "$ref": "build-trace-entry-v1.yaml" - - failure: - type: object - title: Failed Build Result - description: | - Represents a failed build with error information. - required: - - success - - status - - errorMsg - properties: - success: - const: false - title: Success indicator - description: | - Always false for failed build results. - - status: - type: string - title: Failure status - description: | - Status string for failed builds. - enum: - - "PermanentFailure" - - "InputRejected" - - "OutputRejected" - - "TransientFailure" - - "CachedFailure" - - "TimedOut" - - "MiscFailure" - - "DependencyFailed" - - "LogLimitExceeded" - - "NotDeterministic" - - "NoSubstituters" - - "HashMismatch" - - errorMsg: - type: string - title: Error message - description: | - Information about the error if the build failed. - - isNonDeterministic: - type: boolean - title: Non-deterministic flag - description: | - If timesBuilt > 1, whether some builds did not produce the same result. - - Note that 'isNonDeterministic = false' does not mean the build is deterministic, - just that we don't have evidence of non-determinism. diff --git a/doc/manual/source/protocols/json/schema/build-trace-entry-v1 b/doc/manual/source/protocols/json/schema/build-trace-entry-v1 deleted file mode 120000 index 0d02880a5..000000000 --- a/doc/manual/source/protocols/json/schema/build-trace-entry-v1 +++ /dev/null @@ -1 +0,0 @@ -../../../../../../src/libstore-tests/data/realisation \ No newline at end of file diff --git a/doc/manual/source/protocols/json/schema/build-trace-entry-v1.yaml b/doc/manual/source/protocols/json/schema/build-trace-entry-v1.yaml deleted file mode 100644 index cabf2c350..000000000 --- a/doc/manual/source/protocols/json/schema/build-trace-entry-v1.yaml +++ /dev/null @@ -1,74 +0,0 @@ -"$schema": "http://json-schema.org/draft-04/schema" -"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/build-trace-entry-v1.json" -title: Build Trace Entry -description: | - A record of a successful build outcome for a specific derivation output. - - This schema describes the JSON representation of a [build trace entry](@docroot@/store/build-trace.md) entry. - - > **Warning** - > - > This JSON format is currently - > [**experimental**](@docroot@/development/experimental-features.md#xp-feature-ca-derivations) - > and subject to change. - -type: object -required: - - id - - outPath - - dependentRealisations - - signatures -properties: - id: - type: string - title: Derivation Output ID - pattern: "^sha256:[0-9a-f]{64}![a-zA-Z_][a-zA-Z0-9_-]*$" - description: | - Unique identifier for the derivation output that was built. - - Format: `{hash-quotient-drv}!{output-name}` - - - **hash-quotient-drv**: SHA-256 [hash of the quotient derivation](@docroot@/store/derivation/outputs/input-address.md#hash-quotient-drv). - Begins with `sha256:`. - - - **output-name**: Name of the specific output (e.g., "out", "dev", "doc") - - Example: `"sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad!foo"` - - outPath: - "$ref": "store-path-v1.yaml" - title: Output Store Path - description: | - The path to the store object that resulted from building this derivation for the given output name. - - dependentRealisations: - type: object - title: Underlying Base Build Trace - description: | - This is for [*derived*](@docroot@/store/build-trace.md#derived) build trace entries to ensure coherence. - - Keys are derivation output IDs (same format as the main `id` field). - Values are the store paths that those dependencies resolved to. - - As described in the linked section on derived build trace traces, derived build trace entries must be kept in addition and not instead of the underlying base build entries. - This is the set of base build trace entries that this derived build trace is derived from. - (The set is also a map since this miniature base build trace must be coherent, mapping each key to a single value.) - - patternProperties: - "^sha256:[0-9a-f]{64}![a-zA-Z_][a-zA-Z0-9_-]*$": - $ref: "store-path-v1.yaml" - title: Dependent Store Path - description: Store path that this dependency resolved to during the build - additionalProperties: false - - signatures: - type: array - title: Build Signatures - description: | - A set of cryptographic signatures attesting to the authenticity of this build trace entry. - items: - type: string - title: Signature - description: A single cryptographic signature - -additionalProperties: false diff --git a/doc/manual/source/protocols/json/schema/derivation-v4.yaml b/doc/manual/source/protocols/json/schema/derivation-v3.yaml similarity index 78% rename from doc/manual/source/protocols/json/schema/derivation-v4.yaml rename to doc/manual/source/protocols/json/schema/derivation-v3.yaml index 2528f7502..fa68adcb1 100644 --- a/doc/manual/source/protocols/json/schema/derivation-v4.yaml +++ b/doc/manual/source/protocols/json/schema/derivation-v3.yaml @@ -1,8 +1,8 @@ "$schema": "http://json-schema.org/draft-04/schema" -"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/derivation-v4.json" +"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/derivation-v3.json" title: Derivation description: | - Experimental JSON representation of a Nix derivation (version 4). + Experimental JSON representation of a Nix derivation (version 3). This schema describes the JSON representation of Nix's `Derivation` type. @@ -17,7 +17,8 @@ required: - name - version - outputs - - inputs + - inputSrcs + - inputDrvs - system - builder - args @@ -31,10 +32,10 @@ properties: Used when calculating store paths for the derivation’s outputs. version: - const: 4 - title: Format version (must be 4) + const: 3 + title: Format version (must be 3) description: | - Must be `4`. + Must be `3`. This is a guard that allows us to continue evolving this format. The choice of `3` is fairly arbitrary, but corresponds to this informal version: @@ -46,12 +47,6 @@ properties: - Version 3: Drop store dir from store paths, just include base name. - - Version 4: Two cleanups, batched together to lesson churn: - - - Reorganize inputs into nested structure (`inputs.srcs` and `inputs.drvs`) - - - Use canonical content address JSON format for floating content addressed derivation outputs. - Note that while this format is experimental, the maintenance of versions is best-effort, and not promised to identify every change. outputs: @@ -75,56 +70,47 @@ properties: additionalProperties: "$ref": "#/$defs/output/overall" - inputs: - type: object - title: Derivation inputs + inputSrcs: + type: array + title: Input source paths description: | - Input dependencies for the derivation, organized into source paths and derivation dependencies. - required: - - srcs - - drvs - properties: - srcs: - type: array - title: Input source paths - description: | - List of store paths on which this derivation depends. + List of store paths on which this derivation depends. - > **Example** - > - > ```json - > "srcs": [ - > "47y241wqdhac3jm5l7nv0x4975mb1975-separate-debug-info.sh", - > "56d0w71pjj9bdr363ym3wj1zkwyqq97j-fix-pop-var-context-error.patch" - > ] - > ``` - items: - $ref: "store-path-v1.yaml" - drvs: - type: object - title: Input derivations - description: | - Mapping of derivation paths to lists of output names they provide. + > **Example** + > + > ```json + > "inputSrcs": [ + > "47y241wqdhac3jm5l7nv0x4975mb1975-separate-debug-info.sh", + > "56d0w71pjj9bdr363ym3wj1zkwyqq97j-fix-pop-var-context-error.patch" + > ] + > ``` + items: + $ref: "store-path-v1.yaml" - > **Example** - > - > ```json - > "drvs": { - > "6lkh5yi7nlb7l6dr8fljlli5zfd9hq58-curl-7.73.0.drv": ["dev"], - > "fn3kgnfzl5dzym26j8g907gq3kbm8bfh-unzip-6.0.drv": ["out"] - > } - > ``` - > - > specifies that this derivation depends on the `dev` output of `curl`, and the `out` output of `unzip`. - patternProperties: - "^[0123456789abcdfghijklmnpqrsvwxyz]{32}-.+\\.drv$": - title: Store Path - description: | - A store path to a derivation, mapped to the outputs of that derivation. - oneOf: - - "$ref": "#/$defs/outputNames" - - "$ref": "#/$defs/dynamicOutputs" - additionalProperties: false + inputDrvs: + type: object + title: Input derivations + description: | + Mapping of derivation paths to lists of output names they provide. + + > **Example** + > + > ```json + > "inputDrvs": { + > "6lkh5yi7nlb7l6dr8fljlli5zfd9hq58-curl-7.73.0.drv": ["dev"], + > "fn3kgnfzl5dzym26j8g907gq3kbm8bfh-unzip-6.0.drv": ["out"] + > } + > ``` + > + > specifies that this derivation depends on the `dev` output of `curl`, and the `out` output of `unzip`. + patternProperties: + "^[0123456789abcdfghijklmnpqrsvwxyz]{32}-.+\\.drv$": + title: Store Path + description: | + A store path to a derivation, mapped to the outputs of that derivation. + oneOf: + - "$ref": "#/$defs/outputNames" + - "$ref": "#/$defs/dynamicOutputs" additionalProperties: false system: @@ -203,18 +189,24 @@ properties: The output is content-addressed, and the content-address is fixed in advance. See [Fixed-output content-addressing](@docroot@/store/derivation/outputs/content-address.md#fixed) for more details. - "$ref": "./content-address-v1.yaml" + type: object required: - method + - hashAlgo - hash properties: method: + "$ref": "./content-address-v1.yaml#/$defs/method" description: | Method of content addressing used for this output. + hashAlgo: + title: Hash algorithm + "$ref": "./hash-v1.yaml#/$defs/algorithm" hash: + type: string title: Expected hash value description: | - The expected content hash. + The expected content hash in base-16. additionalProperties: false caFloating: diff --git a/doc/manual/source/protocols/json/schema/hash-v1.yaml b/doc/manual/source/protocols/json/schema/hash-v1.yaml index 821546dee..316fb6d73 100644 --- a/doc/manual/source/protocols/json/schema/hash-v1.yaml +++ b/doc/manual/source/protocols/json/schema/hash-v1.yaml @@ -51,4 +51,4 @@ additionalProperties: false description: | The hash algorithm used to compute the hash value. - `blake3` is currently experimental and requires the [`blake-hashing`](@docroot@/development/experimental-features.md#xp-feature-blake3-hashes) experimental feature. + `blake3` is currently experimental and requires the [`blake-hashing`](@docroot@/development/experimental-features.md#xp-feature-blake-hashing) experimental feature. diff --git a/doc/manual/source/protocols/json/schema/store-object-info-v2 b/doc/manual/source/protocols/json/schema/store-object-info-v1 similarity index 100% rename from doc/manual/source/protocols/json/schema/store-object-info-v2 rename to doc/manual/source/protocols/json/schema/store-object-info-v1 diff --git a/doc/manual/source/protocols/json/schema/store-object-info-v2.yaml b/doc/manual/source/protocols/json/schema/store-object-info-v1.yaml similarity index 91% rename from doc/manual/source/protocols/json/schema/store-object-info-v2.yaml rename to doc/manual/source/protocols/json/schema/store-object-info-v1.yaml index 4f442e0c3..d79f25043 100644 --- a/doc/manual/source/protocols/json/schema/store-object-info-v2.yaml +++ b/doc/manual/source/protocols/json/schema/store-object-info-v1.yaml @@ -1,6 +1,6 @@ -"$schema": "http://json-schema.org/draft-04/schema" -"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/store-object-info-v2.json" -title: Store Object Info v2 +"$schema": "http://json-schema.org/draft-07/schema" +"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/store-object-info-v1.json" +title: Store Object Info description: | Information about a [store object](@docroot@/store/store-object.md). @@ -41,27 +41,11 @@ $defs: This is the minimal set of fields that describe what a store object contains. type: object required: - - version - narHash - narSize - references - ca properties: - version: - type: integer - const: 2 - title: Format version (must be 2) - description: | - Must be `2`. - This is a guard that allows us to continue evolving this format. - Here is the rough version history: - - - Version 0: `.narinfo` line-oriented format - - - Version 1: Original JSON format, with ugly `"r:sha256"` inherited from `.narinfo` format. - - - Version 2: Use structured JSON type for `ca` - path: type: string title: Store Path @@ -92,10 +76,7 @@ $defs: type: string ca: - oneOf: - - type: "null" - const: null - - "$ref": "./content-address-v1.yaml" + type: ["string", "null"] title: Content Address description: | If the store object is [content-addressed](@docroot@/store/store-object/content-address.md), @@ -110,7 +91,6 @@ $defs: In other words, the same store object in different stores could have different values for these impure fields. type: object required: - - version - narHash - narSize - references @@ -121,7 +101,6 @@ $defs: - ultimate - signatures properties: - version: { $ref: "#/$defs/base/properties/version" } path: { $ref: "#/$defs/base/properties/path" } narHash: { $ref: "#/$defs/base/properties/narHash" } narSize: { $ref: "#/$defs/base/properties/narSize" } @@ -185,7 +164,6 @@ $defs: This download information, being specific to how the store object happens to be stored and transferred, is also considered to be non-intrinsic / impure. type: object required: - - version - narHash - narSize - references @@ -201,7 +179,6 @@ $defs: - downloadHash - downloadSize properties: - version: { $ref: "#/$defs/base/properties/version" } path: { $ref: "#/$defs/base/properties/path" } narHash: { $ref: "#/$defs/base/properties/narHash" } narSize: { $ref: "#/$defs/base/properties/narSize" } diff --git a/doc/manual/source/protocols/json/store-object-info.md b/doc/manual/source/protocols/json/store-object-info.md index 6a101ab0f..4673dd773 100644 --- a/doc/manual/source/protocols/json/store-object-info.md +++ b/doc/manual/source/protocols/json/store-object-info.md @@ -1,29 +1,29 @@ -{{#include store-object-info-v2-fixed.md}} +{{#include store-object-info-v1-fixed.md}} ## Examples ### Minimal store object (content-addressed) ```json -{{#include schema/store-object-info-v2/pure.json}} +{{#include schema/store-object-info-v1/pure.json}} ``` ### Store object with impure fields ```json -{{#include schema/store-object-info-v2/impure.json}} +{{#include schema/store-object-info-v1/impure.json}} ``` ### Minimal store object (empty) ```json -{{#include schema/store-object-info-v2/empty_pure.json}} +{{#include schema/store-object-info-v1/empty_pure.json}} ``` ### Store object with all impure fields ```json -{{#include schema/store-object-info-v2/empty_impure.json}} +{{#include schema/store-object-info-v1/empty_impure.json}} ``` ### NAR info (minimal) @@ -41,5 +41,5 @@ diff --git a/doc/manual/source/protocols/nix-archive/index.md b/doc/manual/source/protocols/nix-archive/index.md index bd2a8e833..4d25f63e2 100644 --- a/doc/manual/source/protocols/nix-archive/index.md +++ b/doc/manual/source/protocols/nix-archive/index.md @@ -4,7 +4,7 @@ This is the complete specification of the [Nix Archive] format. The Nix Archive format closely follows the abstract specification of a [file system object] tree, because it is designed to serialize exactly that data structure. -[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive +[Nix Archive]: @docroot@/store/file-system-object/content-address.md#nix-archive [file system object]: @docroot@/store/file-system-object.md The format of this specification is close to [Extended Backus–Naur form](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form), with the exception of the `str(..)` function / parameterized rule, which length-prefixes and pads strings. diff --git a/doc/manual/source/release-notes/rl-2.18.md b/doc/manual/source/release-notes/rl-2.18.md index 71b25f408..eb26fc9e7 100644 --- a/doc/manual/source/release-notes/rl-2.18.md +++ b/doc/manual/source/release-notes/rl-2.18.md @@ -13,7 +13,7 @@ - The `discard-references` feature has been stabilized. This means that the - [unsafeDiscardReferences](@docroot@/language/advanced-attributes.md#adv-attr-unsafeDiscardReferences) + [unsafeDiscardReferences](@docroot@/development/experimental-features.md#xp-feature-discard-references) attribute is no longer guarded by an experimental flag and can be used freely. diff --git a/doc/manual/source/release-notes/rl-2.19.md b/doc/manual/source/release-notes/rl-2.19.md index 04f8c9c28..06c704324 100644 --- a/doc/manual/source/release-notes/rl-2.19.md +++ b/doc/manual/source/release-notes/rl-2.19.md @@ -17,8 +17,8 @@ - `nix-shell` shebang lines now support single-quoted arguments. -- `builtins.fetchTree` is now its own experimental feature, [`fetch-tree`](@docroot@/development/experimental-features.md#xp-feature-fetch-tree). - This allows stabilising it independently of the rest of what is encompassed by [`flakes`](@docroot@/development/experimental-features.md#xp-feature-flakes). +- `builtins.fetchTree` is now its own experimental feature, [`fetch-tree`](@docroot@/development/experimental-features.md#xp-fetch-tree). + This allows stabilising it independently of the rest of what is encompassed by [`flakes`](@docroot@/development/experimental-features.md#xp-fetch-tree). - The interface for creating and updating lock files has been overhauled: diff --git a/doc/manual/source/release-notes/rl-2.23.md b/doc/manual/source/release-notes/rl-2.23.md index b358a0fdc..e6b0e9ffc 100644 --- a/doc/manual/source/release-notes/rl-2.23.md +++ b/doc/manual/source/release-notes/rl-2.23.md @@ -14,7 +14,7 @@ - Modify `nix derivation {add,show}` JSON format [#9866](https://github.com/NixOS/nix/issues/9866) [#10722](https://github.com/NixOS/nix/pull/10722) - The JSON format for derivations has been slightly revised to better conform to our [JSON guidelines](@docroot@/development/json-guideline.md). + The JSON format for derivations has been slightly revised to better conform to our [JSON guidelines](@docroot@/development/cli-guideline.md#returning-future-proof-json). In particular, the hash algorithm and content addressing method of content-addressed derivation outputs are now separated into two fields `hashAlgo` and `method`, rather than one field with an arcane `:`-separated format. diff --git a/doc/manual/source/release-notes/rl-2.24.md b/doc/manual/source/release-notes/rl-2.24.md index e9b46bb22..d4af3cb51 100644 --- a/doc/manual/source/release-notes/rl-2.24.md +++ b/doc/manual/source/release-notes/rl-2.24.md @@ -93,7 +93,7 @@ - Support unit prefixes in configuration settings [#10668](https://github.com/NixOS/nix/pull/10668) - Configuration settings in Nix now support unit prefixes, allowing for more intuitive and readable configurations. For example, you can now specify [`--min-free 1G`](@docroot@/command-ref/conf-file.md#conf-min-free) to set the minimum free space to 1 gigabyte. + Configuration settings in Nix now support unit prefixes, allowing for more intuitive and readable configurations. For example, you can now specify [`--min-free 1G`](@docroot@/command-ref/opt-common.md#opt-min-free) to set the minimum free space to 1 gigabyte. This enhancement was extracted from [#7851](https://github.com/NixOS/nix/pull/7851) and is also useful for PR [#10661](https://github.com/NixOS/nix/pull/10661). diff --git a/doc/manual/source/store/build-trace.md b/doc/manual/source/store/build-trace.md index a879d37d2..1086dcb88 100644 --- a/doc/manual/source/store/build-trace.md +++ b/doc/manual/source/store/build-trace.md @@ -29,7 +29,7 @@ And even in that case, a different result doesn't mean the original entry was a As such, the decision of whether to trust a counterparty's build trace is a fundamentally subject policy choice. Build trace entries are typically *signed* in order to enable arbitrary public-key-based trust polices. -## Derived build traces {#derived} +## Derived build traces Implementations that wish to memoize the above may also keep additional *derived* build trace entries that do map unresolved derivations. But if they do so, they *must* also keep the underlying base entries with resolved derivation keys around. @@ -40,13 +40,13 @@ Unlike with base build traces, incoherence with derived build traces is possible The key ingredient is that derivation resolution is only deterministic with respect to a fixed base build trace. Without fixing the base build trace, it inherits the subjectivity of base build traces themselves. -Concretely, suppose there are three derivations \\(a\\), \\(b\\), and \\(c\\). -Let \\(a\\) be a resolved derivation, but let \\(b\\) and \\(c\\) be unresolved and both take as an input an output of \\(a\\). -Now suppose that derived entries are made for \\(b\\) and \\(c\\) based on two different entries of \\(a\\). +Concretely, suppose there are three derivations \\(a\\), \\(b\\), and \((c\\). +Let \\(a\\) be a resolved derivation, but let \\(b\\) and \((c\\) be unresolved and both take as an input an output of \\(a\\). +Now suppose that derived entries are made for \\(b\\) and \((c\\) based on two different entries of \\(a\\). (This could happen if \\(a\\) is non-deterministic, \\(a\\) and \\(b\\) are built in one store, \\(a\\) and \\(c\\) are built in another store, and then a third store substitutes from both of the first two stores.) -If trusting the derived build trace entries for \\(b\\) and \\(c\\) requires that each's underlying entry for \\(a\\) be also trusted, the two different mappings for \\(a\\) will be caught. -However, if \\(b\\) and \\(c\\)'s entries can be combined in isolation, there will be nothing to catch the contradiction in their hidden assumptions about \\(a\\)'s output. +If trusting the derived build trace entries for \\(b\\) and \((c\\) requires that each's underlying entry for \\(a\\) be also trusted, the two different mappings for \\(a\\) will be caught. +However, if \\(b\\) and \((c\\)'s entries can be combined in isolation, there will be nothing to catch the contradiction in their hidden assumptions about \\(a\\)'s output. [derivation]: ./derivation/index.md [output]: ./derivation/outputs/index.md diff --git a/doc/manual/source/store/building.md b/doc/manual/source/store/building.md index f2d470e99..dbfe6b5ca 100644 --- a/doc/manual/source/store/building.md +++ b/doc/manual/source/store/building.md @@ -8,7 +8,7 @@ - Once this is done, the derivation is *normalized*, replacing each input deriving path with its store path, which we now know from realising the input. -## Builder Execution {#builder-execution} +## Builder Execution The [`builder`](./derivation/index.md#builder) is executed as follows: diff --git a/doc/manual/source/store/derivation/index.md b/doc/manual/source/store/derivation/index.md index 670f3b2bd..61c5335ff 100644 --- a/doc/manual/source/store/derivation/index.md +++ b/doc/manual/source/store/derivation/index.md @@ -102,7 +102,7 @@ But rather than somehow scanning all the other fields for inputs, Nix requires t ### System {#system} -The system type on which the [`builder`](#builder) executable is meant to be run. +The system type on which the [`builder`](#attr-builder) executable is meant to be run. A necessary condition for Nix to schedule a given derivation on some [Nix instance] is for the "system" of that derivation to match that instance's [`system` configuration option] or [`extra-platforms` configuration option]. diff --git a/doc/manual/source/store/derivation/outputs/index.md b/doc/manual/source/store/derivation/outputs/index.md index ca2ce6665..0683f5703 100644 --- a/doc/manual/source/store/derivation/outputs/index.md +++ b/doc/manual/source/store/derivation/outputs/index.md @@ -43,7 +43,7 @@ In particular, the specification decides: - if the content is content-addressed, how is it content addressed -- if the content is content-addressed, [what is its content address](./content-address.md#fixed) (and thus what is its [store path]) +- if the content is content-addressed, [what is its content address](./content-address.md#fixed-content-addressing) (and thus what is its [store path]) ## Types of derivations diff --git a/doc/manual/source/store/store-object/content-address.md b/doc/manual/source/store/store-object/content-address.md index 7834ac510..36e841fa3 100644 --- a/doc/manual/source/store/store-object/content-address.md +++ b/doc/manual/source/store/store-object/content-address.md @@ -1,7 +1,7 @@ # Content-Addressing Store Objects Just [like][fso-ca] [File System Objects][File System Object], -[Store Objects][Store Object] can also be [content-addressed](@docroot@/glossary.md#gloss-content-address), +[Store Objects][Store Object] can also be [content-addressed](@docroot@/glossary.md#gloss-content-addressed), unless they are [input-addressed](@docroot@/glossary.md#gloss-input-addressed-store-object). For store objects, the content address we produce will take the form of a [Store Path] rather than regular hash. @@ -107,7 +107,7 @@ References (to other store objects and self-references alike) are supported so l > > This method is part of the [`git-hashing`][xp-feature-git-hashing] experimental feature. -This uses the corresponding [Git](../file-system-object/content-address.md#git) method of file system object content addressing. +This uses the corresponding [Git](../file-system-object/content-address.md#serial-git) method of file system object content addressing. References are not supported. diff --git a/doc/manual/source/store/store-path.md b/doc/manual/source/store/store-path.md index 4061f3653..beec2389b 100644 --- a/doc/manual/source/store/store-path.md +++ b/doc/manual/source/store/store-path.md @@ -6,7 +6,7 @@ > > A rendered store path -Nix implements references to [store objects](./store-object.md) as *store paths*. +Nix implements references to [store objects](./index.md#store-object) as *store paths*. Think of a store path as an [opaque], [unique identifier]: The only way to obtain store path is by adding or building store objects. diff --git a/flake.nix b/flake.nix index 08f518983..a70617b74 100644 --- a/flake.nix +++ b/flake.nix @@ -485,10 +485,10 @@ open-manual = { type = "app"; program = "${pkgs.writeShellScript "open-nix-manual" '' - path="${self.packages.${system}.nix-manual.site}/index.html" - if ! ${opener} "$path"; then + manual_path="${self.packages.${system}.nix-manual}/share/doc/nix/manual/index.html" + if ! ${opener} "$manual_path"; then echo "Failed to open manual with ${opener}. Manual is located at:" - echo "$path" + echo "$manual_path" fi ''}"; meta.description = "Open the Nix manual in your browser"; diff --git a/meson.build b/meson.build index f3158ea6d..c493dfad6 100644 --- a/meson.build +++ b/meson.build @@ -61,3 +61,4 @@ if get_option('unit-tests') endif subproject('nix-functional-tests') subproject('json-schema-checks') +subproject('kaitai-struct-checks') diff --git a/packaging/dev-shell.nix b/packaging/dev-shell.nix index 153e7a3eb..ea12e079f 100644 --- a/packaging/dev-shell.nix +++ b/packaging/dev-shell.nix @@ -109,6 +109,7 @@ pkgs.nixComponents2.nix-util.overrideAttrs ( ++ pkgs.nixComponents2.nix-external-api-docs.nativeBuildInputs ++ pkgs.nixComponents2.nix-functional-tests.externalNativeBuildInputs ++ pkgs.nixComponents2.nix-json-schema-checks.externalNativeBuildInputs + ++ pkgs.nixComponents2.nix-kaitai-struct-checks.externalNativeBuildInputs ++ lib.optional ( !buildCanExecuteHost # Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479 @@ -148,6 +149,7 @@ pkgs.nixComponents2.nix-util.overrideAttrs ( ++ pkgs.nixComponents2.nix-expr.externalPropagatedBuildInputs ++ pkgs.nixComponents2.nix-cmd.buildInputs ++ lib.optionals havePerl pkgs.nixComponents2.nix-perl-bindings.externalBuildInputs - ++ lib.optional havePerl pkgs.perl; + ++ lib.optional havePerl pkgs.perl + ++ pkgs.nixComponents2.nix-kaitai-struct-checks.externalBuildInputs; } ) diff --git a/src/json-schema-checks/build-result b/src/json-schema-checks/build-result deleted file mode 120000 index 8010d0fdd..000000000 --- a/src/json-schema-checks/build-result +++ /dev/null @@ -1 +0,0 @@ -../../src/libstore-tests/data/build-result \ No newline at end of file diff --git a/src/json-schema-checks/build-trace-entry b/src/json-schema-checks/build-trace-entry deleted file mode 120000 index 9175e750e..000000000 --- a/src/json-schema-checks/build-trace-entry +++ /dev/null @@ -1 +0,0 @@ -../../src/libstore-tests/data/realisation \ No newline at end of file diff --git a/src/json-schema-checks/meson.build b/src/json-schema-checks/meson.build index f72affb0b..67f553162 100644 --- a/src/json-schema-checks/meson.build +++ b/src/json-schema-checks/meson.build @@ -54,15 +54,6 @@ schemas = [ 'single_built_built.json', ], }, - { - 'stem' : 'build-trace-entry', - 'schema' : schema_dir / 'build-trace-entry-v1.yaml', - 'files' : [ - 'simple.json', - 'with-dependent-realisations.json', - 'with-signature.json', - ], - }, ] # Derivation and Derivation output @@ -70,7 +61,7 @@ schemas += [ # Match overall { 'stem' : 'derivation', - 'schema' : schema_dir / 'derivation-v4.yaml', + 'schema' : schema_dir / 'derivation-v3.yaml', 'files' : [ 'dyn-dep-derivation.json', 'simple-derivation.json', @@ -78,7 +69,7 @@ schemas += [ }, { 'stem' : 'derivation', - 'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/overall', + 'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/overall', 'files' : [ 'output-caFixedFlat.json', 'output-caFixedNAR.json', @@ -92,14 +83,14 @@ schemas += [ # Match exact variant { 'stem' : 'derivation', - 'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/inputAddressed', + 'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/inputAddressed', 'files' : [ 'output-inputAddressed.json', ], }, { 'stem' : 'derivation', - 'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/caFixed', + 'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/caFixed', 'files' : [ 'output-caFixedFlat.json', 'output-caFixedNAR.json', @@ -108,21 +99,21 @@ schemas += [ }, { 'stem' : 'derivation', - 'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/caFloating', + 'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/caFloating', 'files' : [ 'output-caFloating.json', ], }, { 'stem' : 'derivation', - 'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/deferred', + 'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/deferred', 'files' : [ 'output-deferred.json', ], }, { 'stem' : 'derivation', - 'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/impure', + 'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/impure', 'files' : [ 'output-impure.json', ], @@ -134,7 +125,7 @@ schemas += [ # Match overall { 'stem' : 'store-object-info', - 'schema' : schema_dir / 'store-object-info-v2.yaml', + 'schema' : schema_dir / 'store-object-info-v1.yaml', 'files' : [ 'pure.json', 'impure.json', @@ -144,25 +135,16 @@ schemas += [ }, { 'stem' : 'nar-info', - 'schema' : schema_dir / 'store-object-info-v2.yaml', + 'schema' : schema_dir / 'store-object-info-v1.yaml', 'files' : [ 'pure.json', 'impure.json', ], }, - { - 'stem' : 'build-result', - 'schema' : schema_dir / 'build-result-v1.yaml', - 'files' : [ - 'success.json', - 'output-rejected.json', - 'not-deterministic.json', - ], - }, # Match exact variant { 'stem' : 'store-object-info', - 'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/base', + 'schema' : schema_dir / 'store-object-info-v1.yaml#/$defs/base', 'files' : [ 'pure.json', 'empty_pure.json', @@ -170,7 +152,7 @@ schemas += [ }, { 'stem' : 'store-object-info', - 'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/impure', + 'schema' : schema_dir / 'store-object-info-v1.yaml#/$defs/impure', 'files' : [ 'impure.json', 'empty_impure.json', @@ -178,14 +160,14 @@ schemas += [ }, { 'stem' : 'nar-info', - 'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/base', + 'schema' : schema_dir / 'store-object-info-v1.yaml#/$defs/base', 'files' : [ 'pure.json', ], }, { 'stem' : 'nar-info', - 'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/narInfo', + 'schema' : schema_dir / 'store-object-info-v1.yaml#/$defs/narInfo', 'files' : [ 'impure.json', ], diff --git a/src/json-schema-checks/package.nix b/src/json-schema-checks/package.nix index 5365fe75e..160db003f 100644 --- a/src/json-schema-checks/package.nix +++ b/src/json-schema-checks/package.nix @@ -23,12 +23,10 @@ mkMesonDerivation (finalAttrs: { ../../src/libutil-tests/data/hash ../../src/libstore-tests/data/content-address ../../src/libstore-tests/data/store-path - ../../src/libstore-tests/data/realisation ../../src/libstore-tests/data/derivation ../../src/libstore-tests/data/derived-path ../../src/libstore-tests/data/path-info ../../src/libstore-tests/data/nar-info - ../../src/libstore-tests/data/build-result ./. ]; diff --git a/src/kaitai-struct-checks/package.nix b/src/kaitai-struct-checks/package.nix index 97d56aabd..263dd6fd1 100644 --- a/src/kaitai-struct-checks/package.nix +++ b/src/kaitai-struct-checks/package.nix @@ -1,5 +1,4 @@ # Run with: nix build .#nix-kaitai-struct-checks -# or: `nix develop .#nix-kaitai-struct-checks` to enter a dev shell { lib, mkMesonDerivation, diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc index 0372d6cc1..887b2946f 100644 --- a/src/libexpr/eval-cache.cc +++ b/src/libexpr/eval-cache.cc @@ -136,19 +136,17 @@ struct AttrDb }); } - AttrId setString(AttrKey key, std::string_view s, const Value::StringWithContext::Context * context = nullptr) + AttrId setString(AttrKey key, std::string_view s, Value::StringWithContext::Context context = nullptr) { return doSQLite([&]() { auto state(_state->lock()); if (context) { std::string ctx; - bool first = true; - for (auto * elem : *context) { - if (!first) + for (Value::StringWithContext::Context p = context; *p; ++p) { + if (p != context) ctx.push_back(' '); - ctx.append(elem); - first = false; + ctx.append(*p); } state->insertAttributeWithContext.use()(key.first)(symbols[key.second])(AttrType::String) (s) (ctx) .exec(); diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 47880b9c5..f25a72511 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -821,18 +821,15 @@ void Value::mkString(std::string_view s) mkStringNoCopy(makeImmutableString(s)); } -Value::StringWithContext::Context * Value::StringWithContext::Context::fromBuilder(const NixStringContext & context) +static Value::StringWithContext::Context encodeContext(const NixStringContext & context) { if (!context.empty()) { - auto ctx = (Value::StringWithContext::Context *) allocBytes(sizeof(size_t) + context.size() * sizeof(char *)); - ctx->size = context.size(); - /* Mapping the original iterator to turn references into - pointers is necessary to make sure that enumerate doesn't - accidently copy the elements when it returns tuples by value. - */ - for (auto [n, i] : enumerate(context | std::views::transform([](const auto & r) { return &r; }))) { - ctx->elems[n] = makeImmutableString({i->to_string()}); + size_t n = 0; + auto ctx = (Value::StringWithContext::Context) allocBytes((context.size() + 1) * sizeof(char *)); + for (auto & i : context) { + ctx[n++] = makeImmutableString({i.to_string()}); } + ctx[n] = nullptr; return ctx; } else return nullptr; @@ -840,12 +837,12 @@ Value::StringWithContext::Context * Value::StringWithContext::Context::fromBuild void Value::mkString(std::string_view s, const NixStringContext & context) { - mkStringNoCopy(makeImmutableString(s), Value::StringWithContext::Context::fromBuilder(context)); + mkStringNoCopy(makeImmutableString(s), encodeContext(context)); } void Value::mkStringMove(const char * s, const NixStringContext & context) { - mkStringNoCopy(s, Value::StringWithContext::Context::fromBuilder(context)); + mkStringNoCopy(s, encodeContext(context)); } void Value::mkPath(const SourcePath & path) @@ -2290,9 +2287,9 @@ std::string_view EvalState::forceString(Value & v, const PosIdx pos, std::string void copyContext(const Value & v, NixStringContext & context, const ExperimentalFeatureSettings & xpSettings) { - if (auto * ctx = v.context()) - for (auto * elem : *ctx) - context.insert(NixStringContextElem::parse(elem, xpSettings)); + if (v.context()) + for (Value::StringWithContext::Context p = v.context(); *p; ++p) + context.insert(NixStringContextElem::parse(*p, xpSettings)); } std::string_view EvalState::forceString( @@ -2312,9 +2309,7 @@ std::string_view EvalState::forceStringNoCtx(Value & v, const PosIdx pos, std::s auto s = forceString(v, pos, errorCtx); if (v.context()) { error( - "the string '%1%' is not allowed to refer to a store path (such as '%2%')", - v.string_view(), - *v.context()->begin()) + "the string '%1%' is not allowed to refer to a store path (such as '%2%')", v.string_view(), v.context()[0]) .withTrace(pos, errorCtx) .debugThrow(); } @@ -3221,8 +3216,8 @@ Expr * EvalState::parse( docComments = &it->second; } - auto result = - parseExprFromBuf(text, length, origin, basePath, mem.exprs, symbols, settings, positions, *docComments, rootFS); + auto result = parseExprFromBuf( + text, length, origin, basePath, mem.exprs.alloc, symbols, settings, positions, *docComments, rootFS); result->bindVars(*this, staticEnv); diff --git a/src/libexpr/include/nix/expr/nixexpr.hh b/src/libexpr/include/nix/expr/nixexpr.hh index 08d39cd87..fd7ed2a67 100644 --- a/src/libexpr/include/nix/expr/nixexpr.hh +++ b/src/libexpr/include/nix/expr/nixexpr.hh @@ -91,6 +91,13 @@ std::string showAttrPath(const SymbolTable & symbols, std::span using UpdateQueue = SmallTemporaryValueVector; +class Exprs +{ + std::pmr::monotonic_buffer_resource buffer; +public: + std::pmr::polymorphic_allocator alloc{&buffer}; +}; + /* Abstract syntax of Nix expressions. */ struct Expr @@ -630,8 +637,8 @@ struct ExprLet : Expr struct ExprWith : Expr { PosIdx pos; - uint32_t prevWith; Expr *attrs, *body; + size_t prevWith; ExprWith * parentWith; ExprWith(const PosIdx & pos, Expr * attrs, Expr * body) : pos(pos) @@ -753,19 +760,11 @@ struct ExprConcatStrings : Expr { PosIdx pos; bool forceString; - std::span> es; - - ExprConcatStrings( - std::pmr::polymorphic_allocator & alloc, - const PosIdx & pos, - bool forceString, - const std::vector> & es) + std::vector> es; + ExprConcatStrings(const PosIdx & pos, bool forceString, std::vector> && es) : pos(pos) , forceString(forceString) - , es({alloc.allocate_object>(es.size()), es.size()}) - { - std::ranges::copy(es, this->es.begin()); - }; + , es(std::move(es)) {}; PosIdx getPos() const override { @@ -803,49 +802,6 @@ struct ExprBlackHole : Expr extern ExprBlackHole eBlackHole; -class Exprs -{ - std::pmr::monotonic_buffer_resource buffer; -public: - std::pmr::polymorphic_allocator alloc{&buffer}; - - template - [[gnu::always_inline]] - C * add(auto &&... args) - { - return alloc.new_object(std::forward(args)...); - } - - // we define some calls to add explicitly so that the argument can be passed in as initializer lists - template - [[gnu::always_inline]] - C * add(const PosIdx & pos, Expr * fun, std::vector && args) - requires(std::same_as) - { - return alloc.new_object(pos, fun, std::move(args)); - } - - template - [[gnu::always_inline]] - C * add(const PosIdx & pos, Expr * fun, std::vector && args, PosIdx && cursedOrEndPos) - requires(std::same_as) - { - return alloc.new_object(pos, fun, std::move(args), std::move(cursedOrEndPos)); - } - - template - [[gnu::always_inline]] - C * - add(std::pmr::polymorphic_allocator & alloc, - const PosIdx & pos, - bool forceString, - const std::vector> & es) - requires(std::same_as) - { - return alloc.new_object(alloc, pos, forceString, es); - } -}; - /* Static environments are used to map variable names onto (level, displacement) pairs used to obtain the value of the variable at runtime. */ diff --git a/src/libexpr/include/nix/expr/parser-state.hh b/src/libexpr/include/nix/expr/parser-state.hh index 89c424f82..4cffaa497 100644 --- a/src/libexpr/include/nix/expr/parser-state.hh +++ b/src/libexpr/include/nix/expr/parser-state.hh @@ -78,7 +78,7 @@ struct LexerState struct ParserState { const LexerState & lexerState; - Exprs & exprs; + std::pmr::polymorphic_allocator & alloc; SymbolTable & symbols; PosTable & positions; Expr * result; @@ -132,11 +132,11 @@ inline void ParserState::addAttr( dupAttr(attrPath, pos, j->second.pos); } } else { - nested = exprs.add(); + nested = new ExprAttrs; attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos); } } else { - nested = exprs.add(); + nested = new ExprAttrs; attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, nested, pos)); } attrs = nested; @@ -240,7 +240,7 @@ inline Expr * ParserState::stripIndentation(const PosIdx pos, std::vector>> && es) { if (es.empty()) - return exprs.add(""); + return new ExprString(""); /* Figure out the minimum indentation. Note that by design whitespace-only final lines are not taken into account. (So @@ -322,7 +322,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vectorfirst, exprs.add(exprs.alloc, s2)); + es2.emplace_back(i->first, new ExprString(alloc, s2)); } }; for (; i != es.end(); ++i, --n) { @@ -332,7 +332,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vector(""); + auto * const result = new ExprString(""); return result; } @@ -341,7 +341,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vector(exprs.alloc, pos, true, std::move(es2)); + return new ExprConcatStrings(pos, true, std::move(es2)); } inline PosIdx LexerState::at(const ParserLocation & loc) diff --git a/src/libexpr/include/nix/expr/value.hh b/src/libexpr/include/nix/expr/value.hh index c3a45d4d2..65204b642 100644 --- a/src/libexpr/include/nix/expr/value.hh +++ b/src/libexpr/include/nix/expr/value.hh @@ -220,55 +220,18 @@ struct ValueBase struct StringWithContext { const char * c_str; - /** * The type of the context itself. * - * Currently, it is length-prefixed array of pointers to - * null-terminated strings. The strings are specially formatted - * to represent a flattening of the recursive sum type that is a - * context element. + * Currently, it is pointer to an array of pointers to strings. + * The strings are specially formatted to represent a flattening + * of the recursive sum type that is s context element. * * @See NixStringContext for an more easily understood type, * that of the "builder" for this data structure. */ - struct Context - { - using Elem = const char *; - - /** - * Number of items in the array - */ - size_t size; - - private: - /** - * must be in sorted order - */ - Elem elems[/*size*/]; - public: - - const Elem * begin() const - { - return elems; - } - - const Elem * end() const - { - return &elems[size]; - } - - /** - * @note returns a null pointer to more concisely encode the - * empty context - */ - static Context * fromBuilder(const NixStringContext & context); - }; - - /** - * May be null for a string without context. - */ - const Context * context; + using Context = const char **; + Context context; // must be in sorted order }; struct Path @@ -1039,7 +1002,7 @@ public: setStorage(b); } - void mkStringNoCopy(const char * s, const Value::StringWithContext::Context * context = nullptr) noexcept + void mkStringNoCopy(const char * s, Value::StringWithContext::Context context = 0) noexcept { setStorage(StringWithContext{.c_str = s, .context = context}); } @@ -1165,7 +1128,7 @@ public: return getStorage().c_str; } - const Value::StringWithContext::Context * context() const noexcept + Value::StringWithContext::Context context() const noexcept { return getStorage().context; } diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index db5e52c3a..a1d1b7e4b 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -523,7 +523,6 @@ void ExprWith::bindVars(EvalState & es, const std::shared_ptr & prevWith = 0; for (curEnv = env.get(), level = 1; curEnv; curEnv = curEnv->up.get(), level++) if (curEnv->isWith) { - assert(level <= std::numeric_limits::max()); prevWith = level; break; } diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 8b56eba15..29586ed98 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -63,7 +63,7 @@ Expr * parseExprFromBuf( size_t length, Pos::Origin origin, const SourcePath & basePath, - Exprs & exprs, + std::pmr::polymorphic_allocator & alloc, SymbolTable & symbols, const EvalSettings & settings, PosTable & positions, @@ -113,12 +113,12 @@ static void setDocPosition(const LexerState & lexerState, ExprLambda * lambda, P } } -static Expr * makeCall(Exprs & exprs, PosIdx pos, Expr * fn, Expr * arg) { +static Expr * makeCall(PosIdx pos, Expr * fn, Expr * arg) { if (auto e2 = dynamic_cast(fn)) { e2->args.push_back(arg); return fn; } - return exprs.add(pos, fn, {arg}); + return new ExprCall(pos, fn, {arg}); } @@ -179,14 +179,14 @@ expr: expr_function; expr_function : ID ':' expr_function - { auto me = state->exprs.add(CUR_POS, state->symbols.create($1), $3); + { auto me = new ExprLambda(CUR_POS, state->symbols.create($1), $3); $$ = me; SET_DOC_POS(me, @1); } | formal_set ':' expr_function[body] { state->validateFormals($formal_set); - auto me = state->exprs.add(state->positions, state->exprs.alloc, CUR_POS, std::move($formal_set), $body); + auto me = new ExprLambda(state->positions, state->alloc, CUR_POS, std::move($formal_set), $body); $$ = me; SET_DOC_POS(me, @1); } @@ -194,7 +194,7 @@ expr_function { auto arg = state->symbols.create($ID); state->validateFormals($formal_set, CUR_POS, arg); - auto me = state->exprs.add(state->positions, state->exprs.alloc, CUR_POS, arg, std::move($formal_set), $body); + auto me = new ExprLambda(state->positions, state->alloc, CUR_POS, arg, std::move($formal_set), $body); $$ = me; SET_DOC_POS(me, @1); } @@ -202,67 +202,67 @@ expr_function { auto arg = state->symbols.create($ID); state->validateFormals($formal_set, CUR_POS, arg); - auto me = state->exprs.add(state->positions, state->exprs.alloc, CUR_POS, arg, std::move($formal_set), $body); + auto me = new ExprLambda(state->positions, state->alloc, CUR_POS, arg, std::move($formal_set), $body); $$ = me; SET_DOC_POS(me, @1); } | ASSERT expr ';' expr_function - { $$ = state->exprs.add(CUR_POS, $2, $4); } + { $$ = new ExprAssert(CUR_POS, $2, $4); } | WITH expr ';' expr_function - { $$ = state->exprs.add(CUR_POS, $2, $4); } + { $$ = new ExprWith(CUR_POS, $2, $4); } | LET binds IN_KW expr_function { if (!$2->dynamicAttrs.empty()) throw ParseError({ .msg = HintFmt("dynamic attributes not allowed in let"), .pos = state->positions[CUR_POS] }); - $$ = state->exprs.add($2, $4); + $$ = new ExprLet($2, $4); } | expr_if ; expr_if - : IF expr THEN expr ELSE expr { $$ = state->exprs.add(CUR_POS, $2, $4, $6); } + : IF expr THEN expr ELSE expr { $$ = new ExprIf(CUR_POS, $2, $4, $6); } | expr_pipe_from | expr_pipe_into | expr_op ; expr_pipe_from - : expr_op PIPE_FROM expr_pipe_from { $$ = makeCall(state->exprs, state->at(@2), $1, $3); } - | expr_op PIPE_FROM expr_op { $$ = makeCall(state->exprs, state->at(@2), $1, $3); } + : expr_op PIPE_FROM expr_pipe_from { $$ = makeCall(state->at(@2), $1, $3); } + | expr_op PIPE_FROM expr_op { $$ = makeCall(state->at(@2), $1, $3); } ; expr_pipe_into - : expr_pipe_into PIPE_INTO expr_op { $$ = makeCall(state->exprs, state->at(@2), $3, $1); } - | expr_op PIPE_INTO expr_op { $$ = makeCall(state->exprs, state->at(@2), $3, $1); } + : expr_pipe_into PIPE_INTO expr_op { $$ = makeCall(state->at(@2), $3, $1); } + | expr_op PIPE_INTO expr_op { $$ = makeCall(state->at(@2), $3, $1); } ; expr_op - : '!' expr_op %prec NOT { $$ = state->exprs.add($2); } - | '-' expr_op %prec NEGATE { $$ = state->exprs.add(CUR_POS, state->exprs.add(state->s.sub), {state->exprs.add(0), $2}); } - | expr_op EQ expr_op { $$ = state->exprs.add($1, $3); } - | expr_op NEQ expr_op { $$ = state->exprs.add($1, $3); } - | expr_op '<' expr_op { $$ = state->exprs.add(state->at(@2), state->exprs.add(state->s.lessThan), {$1, $3}); } - | expr_op LEQ expr_op { $$ = state->exprs.add(state->exprs.add(state->at(@2), state->exprs.add(state->s.lessThan), {$3, $1})); } - | expr_op '>' expr_op { $$ = state->exprs.add(state->at(@2), state->exprs.add(state->s.lessThan), {$3, $1}); } - | expr_op GEQ expr_op { $$ = state->exprs.add(state->exprs.add(state->at(@2), state->exprs.add(state->s.lessThan), {$1, $3})); } - | expr_op AND expr_op { $$ = state->exprs.add(state->at(@2), $1, $3); } - | expr_op OR expr_op { $$ = state->exprs.add(state->at(@2), $1, $3); } - | expr_op IMPL expr_op { $$ = state->exprs.add(state->at(@2), $1, $3); } - | expr_op UPDATE expr_op { $$ = state->exprs.add(state->at(@2), $1, $3); } - | expr_op '?' attrpath { $$ = state->exprs.add(state->exprs.alloc, $1, std::move($3)); } + : '!' expr_op %prec NOT { $$ = new ExprOpNot($2); } + | '-' expr_op %prec NEGATE { $$ = new ExprCall(CUR_POS, new ExprVar(state->s.sub), {new ExprInt(0), $2}); } + | expr_op EQ expr_op { $$ = new ExprOpEq($1, $3); } + | expr_op NEQ expr_op { $$ = new ExprOpNEq($1, $3); } + | expr_op '<' expr_op { $$ = new ExprCall(state->at(@2), new ExprVar(state->s.lessThan), {$1, $3}); } + | expr_op LEQ expr_op { $$ = new ExprOpNot(new ExprCall(state->at(@2), new ExprVar(state->s.lessThan), {$3, $1})); } + | expr_op '>' expr_op { $$ = new ExprCall(state->at(@2), new ExprVar(state->s.lessThan), {$3, $1}); } + | expr_op GEQ expr_op { $$ = new ExprOpNot(new ExprCall(state->at(@2), new ExprVar(state->s.lessThan), {$1, $3})); } + | expr_op AND expr_op { $$ = new ExprOpAnd(state->at(@2), $1, $3); } + | expr_op OR expr_op { $$ = new ExprOpOr(state->at(@2), $1, $3); } + | expr_op IMPL expr_op { $$ = new ExprOpImpl(state->at(@2), $1, $3); } + | expr_op UPDATE expr_op { $$ = new ExprOpUpdate(state->at(@2), $1, $3); } + | expr_op '?' attrpath { $$ = new ExprOpHasAttr(state->alloc, $1, std::move($3)); } | expr_op '+' expr_op - { $$ = state->exprs.add(state->exprs.alloc, state->at(@2), false, {{state->at(@1), $1}, {state->at(@3), $3}}); } - | expr_op '-' expr_op { $$ = state->exprs.add(state->at(@2), state->exprs.add(state->s.sub), {$1, $3}); } - | expr_op '*' expr_op { $$ = state->exprs.add(state->at(@2), state->exprs.add(state->s.mul), {$1, $3}); } - | expr_op '/' expr_op { $$ = state->exprs.add(state->at(@2), state->exprs.add(state->s.div), {$1, $3}); } - | expr_op CONCAT expr_op { $$ = state->exprs.add(state->at(@2), $1, $3); } + { $$ = new ExprConcatStrings(state->at(@2), false, {{state->at(@1), $1}, {state->at(@3), $3}}); } + | expr_op '-' expr_op { $$ = new ExprCall(state->at(@2), new ExprVar(state->s.sub), {$1, $3}); } + | expr_op '*' expr_op { $$ = new ExprCall(state->at(@2), new ExprVar(state->s.mul), {$1, $3}); } + | expr_op '/' expr_op { $$ = new ExprCall(state->at(@2), new ExprVar(state->s.div), {$1, $3}); } + | expr_op CONCAT expr_op { $$ = new ExprOpConcatLists(state->at(@2), $1, $3); } | expr_app ; expr_app - : expr_app expr_select { $$ = makeCall(state->exprs, CUR_POS, $1, $2); $2->warnIfCursedOr(state->symbols, state->positions); } + : expr_app expr_select { $$ = makeCall(CUR_POS, $1, $2); $2->warnIfCursedOr(state->symbols, state->positions); } | /* Once a ‘cursed or’ reaches this nonterminal, it is no longer cursed, because the uncursed parse would also produce an expr_app. But we need to remove the cursed status in order to prevent valid things like @@ -272,9 +272,9 @@ expr_app expr_select : expr_simple '.' attrpath - { $$ = state->exprs.add(state->exprs.alloc, CUR_POS, $1, std::move($3), nullptr); } + { $$ = new ExprSelect(state->alloc, CUR_POS, $1, std::move($3), nullptr); } | expr_simple '.' attrpath OR_KW expr_select - { $$ = state->exprs.add(state->exprs.alloc, CUR_POS, $1, std::move($3), $5); $5->warnIfCursedOr(state->symbols, state->positions); } + { $$ = new ExprSelect(state->alloc, CUR_POS, $1, std::move($3), $5); $5->warnIfCursedOr(state->symbols, state->positions); } | /* Backwards compatibility: because Nixpkgs has a function named ‘or’, allow stuff like ‘map or [...]’. This production is problematic (see https://github.com/NixOS/nix/issues/11118) and will be refactored in the @@ -283,7 +283,7 @@ expr_select the ExprCall with data (establishing that it is a ‘cursed or’) that can be used to emit a warning when an affected expression is parsed. */ expr_simple OR_KW - { $$ = state->exprs.add(CUR_POS, $1, {state->exprs.add(CUR_POS, state->s.or_)}, state->positions.add(state->origin, @$.endOffset)); } + { $$ = new ExprCall(CUR_POS, $1, {new ExprVar(CUR_POS, state->s.or_)}, state->positions.add(state->origin, @$.endOffset)); } | expr_simple ; @@ -291,15 +291,15 @@ expr_simple : ID { std::string_view s = "__curPos"; if ($1.l == s.size() && strncmp($1.p, s.data(), s.size()) == 0) - $$ = state->exprs.add(CUR_POS); + $$ = new ExprPos(CUR_POS); else - $$ = state->exprs.add(CUR_POS, state->symbols.create($1)); + $$ = new ExprVar(CUR_POS, state->symbols.create($1)); } - | INT_LIT { $$ = state->exprs.add($1); } - | FLOAT_LIT { $$ = state->exprs.add($1); } + | INT_LIT { $$ = new ExprInt($1); } + | FLOAT_LIT { $$ = new ExprFloat($1); } | '"' string_parts '"' { std::visit(overloaded{ - [&](std::string_view str) { $$ = state->exprs.add(state->exprs.alloc, str); }, + [&](std::string_view str) { $$ = new ExprString(state->alloc, str); }, [&](Expr * expr) { $$ = expr; }}, $2); } @@ -309,14 +309,14 @@ expr_simple | path_start PATH_END | path_start string_parts_interpolated PATH_END { $2.insert($2.begin(), {state->at(@1), $1}); - $$ = state->exprs.add(state->exprs.alloc, CUR_POS, false, std::move($2)); + $$ = new ExprConcatStrings(CUR_POS, false, std::move($2)); } | SPATH { std::string_view path($1.p + 1, $1.l - 2); - $$ = state->exprs.add(CUR_POS, - state->exprs.add(state->s.findFile), - {state->exprs.add(state->s.nixPath), - state->exprs.add(state->exprs.alloc, path)}); + $$ = new ExprCall(CUR_POS, + new ExprVar(state->s.findFile), + {new ExprVar(state->s.nixPath), + new ExprString(state->alloc, path)}); } | URI { static bool noURLLiterals = experimentalFeatureSettings.isEnabled(Xp::NoUrlLiterals); @@ -325,35 +325,35 @@ expr_simple .msg = HintFmt("URL literals are disabled"), .pos = state->positions[CUR_POS] }); - $$ = state->exprs.add(state->exprs.alloc, $1); + $$ = new ExprString(state->alloc, $1); } | '(' expr ')' { $$ = $2; } /* Let expressions `let {..., body = ...}' are just desugared into `(rec {..., body = ...}).body'. */ | LET '{' binds '}' - { $3->recursive = true; $3->pos = CUR_POS; $$ = state->exprs.add(state->exprs.alloc, noPos, $3, state->s.body); } + { $3->recursive = true; $3->pos = CUR_POS; $$ = new ExprSelect(state->alloc, noPos, $3, state->s.body); } | REC '{' binds '}' { $3->recursive = true; $3->pos = CUR_POS; $$ = $3; } | '{' binds1 '}' { $2->pos = CUR_POS; $$ = $2; } | '{' '}' - { $$ = state->exprs.add(CUR_POS); } - | '[' list ']' { $$ = state->exprs.add(state->exprs.alloc, std::move($2)); } + { $$ = new ExprAttrs(CUR_POS); } + | '[' list ']' { $$ = new ExprList(state->alloc, std::move($2)); } ; string_parts : STR { $$ = $1; } - | string_parts_interpolated { $$ = state->exprs.add(state->exprs.alloc, CUR_POS, true, std::move($1)); } + | string_parts_interpolated { $$ = new ExprConcatStrings(CUR_POS, true, std::move($1)); } | { $$ = std::string_view(); } ; string_parts_interpolated : string_parts_interpolated STR - { $$ = std::move($1); $$.emplace_back(state->at(@2), state->exprs.add(state->exprs.alloc, $2)); } + { $$ = std::move($1); $$.emplace_back(state->at(@2), new ExprString(state->alloc, $2)); } | string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = std::move($1); $$.emplace_back(state->at(@2), $3); } | DOLLAR_CURLY expr '}' { $$.emplace_back(state->at(@1), $2); } | STR DOLLAR_CURLY expr '}' { - $$.emplace_back(state->at(@1), state->exprs.add(state->exprs.alloc, $1)); + $$.emplace_back(state->at(@1), new ExprString(state->alloc, $1)); $$.emplace_back(state->at(@2), $3); } ; @@ -379,8 +379,8 @@ path_start root filesystem accessor, rather than the accessor of the current Nix expression. */ literal.front() == '/' - ? state->exprs.add(state->exprs.alloc, state->rootFS, path) - : state->exprs.add(state->exprs.alloc, state->basePath.accessor, path); + ? new ExprPath(state->alloc, state->rootFS, path) + : new ExprPath(state->alloc, state->basePath.accessor, path); } | HPATH { if (state->settings.pureEval) { @@ -390,7 +390,7 @@ path_start ); } Path path(getHome() + std::string($1.p + 1, $1.l - 1)); - $$ = state->exprs.add(state->exprs.alloc, ref(state->rootFS), path); + $$ = new ExprPath(state->alloc, ref(state->rootFS), path); } ; @@ -402,7 +402,7 @@ ind_string_parts binds : binds1 - | { $$ = state->exprs.add(); } + | { $$ = new ExprAttrs; } ; binds1 @@ -417,7 +417,7 @@ binds1 state->dupAttr(i.symbol, iPos, $accum->attrs[i.symbol].pos); $accum->attrs.emplace( i.symbol, - ExprAttrs::AttrDef(state->exprs.add(iPos, i.symbol), iPos, ExprAttrs::AttrDef::Kind::Inherited)); + ExprAttrs::AttrDef(new ExprVar(iPos, i.symbol), iPos, ExprAttrs::AttrDef::Kind::Inherited)); } } | binds[accum] INHERIT '(' expr ')' attrs ';' @@ -432,13 +432,13 @@ binds1 $accum->attrs.emplace( i.symbol, ExprAttrs::AttrDef( - state->exprs.add(state->exprs.alloc, iPos, from, i.symbol), + new ExprSelect(state->alloc, iPos, from, i.symbol), iPos, ExprAttrs::AttrDef::Kind::InheritedFrom)); } } | attrpath '=' expr ';' - { $$ = state->exprs.add(); + { $$ = new ExprAttrs; state->addAttr($$, std::move($attrpath), @attrpath, $expr, @expr); } ; @@ -525,7 +525,7 @@ Expr * parseExprFromBuf( size_t length, Pos::Origin origin, const SourcePath & basePath, - Exprs & exprs, + std::pmr::polymorphic_allocator & alloc, SymbolTable & symbols, const EvalSettings & settings, PosTable & positions, @@ -540,7 +540,7 @@ Expr * parseExprFromBuf( }; ParserState state { .lexerState = lexerState, - .exprs = exprs, + .alloc = alloc, .symbols = symbols, .positions = positions, .basePath = basePath, diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index d1aae64fa..96e79fedd 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -825,10 +825,10 @@ static RegisterPrimOp primop_genericClosure( - [Int](@docroot@/language/types.md#type-int) - [Float](@docroot@/language/types.md#type-float) - - [Boolean](@docroot@/language/types.md#type-bool) + - [Boolean](@docroot@/language/types.md#type-boolean) - [String](@docroot@/language/types.md#type-string) - [Path](@docroot@/language/types.md#type-path) - - [List](@docroot@/language/types.md#type-list) + - [List](@docroot@/language/types.md#list) The result is produced by calling the `operator` on each `item` that has not been called yet, including newly added items, until no new items are added. Items are compared by their `key` attribute. @@ -2103,7 +2103,7 @@ static RegisterPrimOp primop_findFile( builtins.findFile builtins.nixPath "nixpkgs" ``` - A search path is represented as a list of [attribute sets](./types.md#type-attrs) with two attributes: + A search path is represented as a list of [attribute sets](./types.md#attribute-set) with two attributes: - `prefix` is a relative path. - `path` denotes a file system location @@ -2395,7 +2395,7 @@ static RegisterPrimOp primop_outputOf({ returns an input placeholder for the output of the output of `myDrv`. - This primop corresponds to the `^` sigil for [deriving paths](@docroot@/glossary.md#gloss-deriving-path), e.g. as part of installable syntax on the command line. + This primop corresponds to the `^` sigil for [deriving paths](@docroot@/glossary.md#gloss-deriving-paths), e.g. as part of installable syntax on the command line. )", .fun = prim_outputOf, .experimentalFeature = Xp::DynamicDerivations, @@ -4966,7 +4966,7 @@ static RegisterPrimOp primop_compareVersions({ version *s1* is older than version *s2*, `0` if they are the same, and `1` if *s1* is newer than *s2*. The version comparison algorithm is the same as the one used by [`nix-env - -u`](../command-ref/nix-env/upgrade.md). + -u`](../command-ref/nix-env.md#operation---upgrade). )", .fun = prim_compareVersions, }); @@ -4995,7 +4995,7 @@ static RegisterPrimOp primop_splitVersion({ .doc = R"( Split a string representing a version into its components, by the same version splitting logic underlying the version comparison in - [`nix-env -u`](../command-ref/nix-env/upgrade.md). + [`nix-env -u`](../command-ref/nix-env.md#operation---upgrade). )", .fun = prim_splitVersion, }); @@ -5045,9 +5045,9 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) Primitive value. It can be returned by - [comparison operators](@docroot@/language/operators.md#comparison) + [comparison operators](@docroot@/language/operators.md#Comparison) and used in - [conditional expressions](@docroot@/language/syntax.md#conditionals). + [conditional expressions](@docroot@/language/syntax.md#Conditionals). The name `true` is not special, and can be shadowed: @@ -5068,9 +5068,9 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) Primitive value. It can be returned by - [comparison operators](@docroot@/language/operators.md#comparison) + [comparison operators](@docroot@/language/operators.md#Comparison) and used in - [conditional expressions](@docroot@/language/syntax.md#conditionals). + [conditional expressions](@docroot@/language/syntax.md#Conditionals). The name `false` is not special, and can be shadowed: diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc index 8a9fe42e8..12b8ffdf9 100644 --- a/src/libexpr/primops/context.cc +++ b/src/libexpr/primops/context.cc @@ -79,7 +79,7 @@ static RegisterPrimOp primop_unsafeDiscardOutputDependency( Create a copy of the given string where every [derivation deep](@docroot@/language/string-context.md#string-context-element-derivation-deep) string context element is turned into a - [constant](@docroot@/language/string-context.md#string-context-constant) + [constant](@docroot@/language/string-context.md#string-context-element-constant) string context element. This is the opposite of [`builtins.addDrvOutputDependencies`](#builtins-addDrvOutputDependencies). @@ -145,7 +145,7 @@ static RegisterPrimOp primop_addDrvOutputDependencies( .args = {"s"}, .doc = R"( Create a copy of the given string where a single - [constant](@docroot@/language/string-context.md#string-context-constant) + [constant](@docroot@/language/string-context.md#string-context-element-constant) string context element is turned into a [derivation deep](@docroot@/language/string-context.md#string-context-element-derivation-deep) string context element. diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 1bd5b0b94..65587b43a 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -10,8 +10,6 @@ #include "nix/util/fs-sink.hh" #include "nix/util/sync.hh" #include "nix/util/util.hh" -#include "nix/util/thread-pool.hh" -#include "nix/util/pool.hh" #include #include @@ -35,14 +33,12 @@ #include #include -#include #include #include #include #include #include #include -#include namespace std { @@ -231,16 +227,12 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this { /** Location of the repository on disk. */ std::filesystem::path path; - - bool bare; - /** * libgit2 repository. Note that new objects are not written to disk, * because we are using a mempack backend. For writing to disk, see * `flush()`, which is also called by `GitFileSystemObjectSink::sync()`. */ Repository repo; - /** * In-memory object store for efficient batched writing to packfiles. * Owned by `repo`. @@ -249,7 +241,6 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this GitRepoImpl(std::filesystem::path _path, bool create, bool bare) : path(std::move(_path)) - , bare(bare) { initLibGit2(); @@ -326,56 +317,32 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this checkInterrupt(); } - /** - * Return a connection pool for this repo. Useful for - * multithreaded access. - */ - Pool getPool() - { - // TODO: as an optimization, it would be nice to include `this` in the pool. - return Pool(std::numeric_limits::max(), [this]() -> ref { - return make_ref(path, false, bare); - }); - } - uint64_t getRevCount(const Hash & rev) override { - boost::concurrent_flat_set> done; + boost::unordered_flat_set> done; + std::queue todo; - auto startCommit = peelObject(lookupObject(*this, hashToOID(rev)).get(), GIT_OBJECT_COMMIT); - auto startOid = *git_commit_id(startCommit.get()); - done.insert(startOid); + todo.push(peelObject(lookupObject(*this, hashToOID(rev)).get(), GIT_OBJECT_COMMIT)); - auto repoPool(getPool()); + while (auto commit = pop(todo)) { + if (!done.insert(*git_commit_id(commit->get())).second) + continue; - ThreadPool pool; - - auto process = [&done, &pool, &repoPool](this const auto & process, const git_oid & oid) -> void { - auto repo(repoPool.get()); - - auto _commit = lookupObject(*repo, oid, GIT_OBJECT_COMMIT); - auto commit = (const git_commit *) &*_commit; - - for (auto n : std::views::iota(0U, git_commit_parentcount(commit))) { - auto parentOid = git_commit_parent_id(commit, n); - if (!parentOid) { + for (size_t n = 0; n < git_commit_parentcount(commit->get()); ++n) { + git_commit * parent; + if (git_commit_parent(&parent, commit->get(), n)) { throw Error( "Failed to retrieve the parent of Git commit '%s': %s. " "This may be due to an incomplete repository history. " "To resolve this, either enable the shallow parameter in your flake URL (?shallow=1) " "or add set the shallow parameter to true in builtins.fetchGit, " "or fetch the complete history for this branch.", - *git_commit_id(commit), + *git_commit_id(commit->get()), git_error_last()->message); } - if (done.insert(*parentOid)) - pool.enqueue(std::bind(process, *parentOid)); + todo.push(Commit(parent)); } - }; - - pool.enqueue(std::bind(process, startOid)); - - pool.process(); + } return done.size(); } @@ -582,15 +549,25 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this // then use code that was removed in this commit (see blame) auto dir = this->path; - Strings gitArgs{"-C", dir.string(), "--git-dir", ".", "fetch", "--progress", "--force"}; + Strings gitArgs{"-C", dir.string(), "--git-dir", ".", "fetch", "--quiet", "--force"}; if (shallow) append(gitArgs, {"--depth", "1"}); append(gitArgs, {std::string("--"), url, refspec}); - auto status = runProgram(RunOptions{.program = "git", .args = gitArgs, .isInteractive = true}).first; + auto [status, output] = runProgram( + RunOptions{ + .program = "git", + .lookupPath = true, + // FIXME: git stderr messes up our progress indicator, so + // we're using --quiet for now. Should process its stderr. + .args = gitArgs, + .input = {}, + .mergeStderrToStdout = true, + .isInteractive = true}); - if (status > 0) - throw Error("Failed to fetch git repository '%s'", url); + if (status > 0) { + throw Error("Failed to fetch git repository %s : %s", url, output); + } } void verifyCommit(const Hash & rev, const std::vector & publicKeys) override diff --git a/src/libfetchers/include/nix/fetchers/registry.hh b/src/libfetchers/include/nix/fetchers/registry.hh index f705f709d..90fc3d853 100644 --- a/src/libfetchers/include/nix/fetchers/registry.hh +++ b/src/libfetchers/include/nix/fetchers/registry.hh @@ -2,7 +2,6 @@ ///@file #include "nix/util/types.hh" -#include "nix/util/source-path.hh" #include "nix/fetchers/fetchers.hh" namespace nix { @@ -40,7 +39,7 @@ struct Registry { } - static std::shared_ptr read(const Settings & settings, const SourcePath & path, RegistryType type); + static std::shared_ptr read(const Settings & settings, const Path & path, RegistryType type); void write(const Path & path); diff --git a/src/libfetchers/registry.cc b/src/libfetchers/registry.cc index 2b0b5f390..e570fc84b 100644 --- a/src/libfetchers/registry.cc +++ b/src/libfetchers/registry.cc @@ -10,18 +10,18 @@ namespace nix::fetchers { -std::shared_ptr Registry::read(const Settings & settings, const SourcePath & path, RegistryType type) +std::shared_ptr Registry::read(const Settings & settings, const Path & path, RegistryType type) { debug("reading registry '%s'", path); auto registry = std::make_shared(settings, type); - if (!path.pathExists()) + if (!pathExists(path)) return std::make_shared(settings, type); try { - auto json = nlohmann::json::parse(path.readFile()); + auto json = nlohmann::json::parse(readFile(path)); auto version = json.value("version", 0); @@ -97,10 +97,7 @@ static Path getSystemRegistryPath() static std::shared_ptr getSystemRegistry(const Settings & settings) { - static auto systemRegistry = Registry::read( - settings, - SourcePath{getFSSourceAccessor(), CanonPath{getSystemRegistryPath()}}.resolveSymlinks(), - Registry::System); + static auto systemRegistry = Registry::read(settings, getSystemRegistryPath(), Registry::System); return systemRegistry; } @@ -111,17 +108,13 @@ Path getUserRegistryPath() std::shared_ptr getUserRegistry(const Settings & settings) { - static auto userRegistry = Registry::read( - settings, - SourcePath{getFSSourceAccessor(), CanonPath{getUserRegistryPath()}}.resolveSymlinks(), - Registry::User); + static auto userRegistry = Registry::read(settings, getUserRegistryPath(), Registry::User); return userRegistry; } std::shared_ptr getCustomRegistry(const Settings & settings, const Path & p) { - static auto customRegistry = - Registry::read(settings, SourcePath{getFSSourceAccessor(), CanonPath{p}}.resolveSymlinks(), Registry::Custom); + static auto customRegistry = Registry::read(settings, p, Registry::Custom); return customRegistry; } @@ -144,19 +137,14 @@ static std::shared_ptr getGlobalRegistry(const Settings & settings, re return std::make_shared(settings, Registry::Global); // empty registry } - return Registry::read( - settings, - [&] -> SourcePath { - if (!isAbsolute(path)) { - auto storePath = downloadFile(store, settings, path, "flake-registry.json").storePath; - if (auto store2 = store.dynamic_pointer_cast()) - store2->addPermRoot(storePath, getCacheDir() + "/flake-registry.json"); - return {store->requireStoreObjectAccessor(storePath)}; - } else { - return SourcePath{getFSSourceAccessor(), CanonPath{path}}.resolveSymlinks(); - } - }(), - Registry::Global); + if (!isAbsolute(path)) { + auto storePath = downloadFile(store, settings, path, "flake-registry.json").storePath; + if (auto store2 = store.dynamic_pointer_cast()) + store2->addPermRoot(storePath, getCacheDir() + "/flake-registry.json"); + path = store->toRealPath(storePath); + } + + return Registry::read(settings, path, Registry::Global); }(); return reg; diff --git a/src/libflake/flakeref.cc b/src/libflake/flakeref.cc index ed6b657ac..a26f269c3 100644 --- a/src/libflake/flakeref.cc +++ b/src/libflake/flakeref.cc @@ -109,8 +109,7 @@ std::pair parsePathFlakeRefWithFragment( std::smatch match; auto succeeds = std::regex_match(url, match, pathFlakeRegex); - if (!succeeds) - throw Error("invalid flakeref '%s'", url); + assert(succeeds); auto path = match[1].str(); auto query = decodeQuery(match[3].str(), /*lenient=*/true); auto fragment = percentDecode(match[5].str()); diff --git a/src/libstore-c/nix_api_store.cc b/src/libstore-c/nix_api_store.cc index 024ed9785..313a77563 100644 --- a/src/libstore-c/nix_api_store.cc +++ b/src/libstore-c/nix_api_store.cc @@ -7,7 +7,6 @@ #include "nix/store/store-api.hh" #include "nix/store/store-open.hh" #include "nix/store/build-result.hh" -#include "nix/store/local-fs-store.hh" #include "nix/store/globals.hh" @@ -110,8 +109,7 @@ nix_err nix_store_real_path( if (context) context->last_err_code = NIX_OK; try { - auto store2 = store->ptr.dynamic_pointer_cast(); - auto res = store2 ? store2->toRealPath(path->path) : store->ptr->printStorePath(path->path); + auto res = store->ptr->toRealPath(path->path); return call_nix_get_string_callback(res, callback, user_data); } NIXC_CATCH_ERRS diff --git a/src/libstore-tests/build-result.cc b/src/libstore-tests/build-result.cc deleted file mode 100644 index 85e799c2a..000000000 --- a/src/libstore-tests/build-result.cc +++ /dev/null @@ -1,108 +0,0 @@ -#include - -#include "nix/store/build-result.hh" -#include "nix/util/tests/json-characterization.hh" - -namespace nix { - -class BuildResultTest : public virtual CharacterizationTest -{ - std::filesystem::path unitTestData = getUnitTestData() / "build-result"; - -public: - std::filesystem::path goldenMaster(std::string_view testStem) const override - { - return unitTestData / testStem; - } -}; - -using nlohmann::json; - -struct BuildResultJsonTest : BuildResultTest, - JsonCharacterizationTest, - ::testing::WithParamInterface> -{}; - -TEST_P(BuildResultJsonTest, from_json) -{ - auto & [name, expected] = GetParam(); - readJsonTest(name, expected); -} - -TEST_P(BuildResultJsonTest, to_json) -{ - auto & [name, value] = GetParam(); - writeJsonTest(name, value); -} - -using namespace std::literals::chrono_literals; - -INSTANTIATE_TEST_SUITE_P( - BuildResultJSON, - BuildResultJsonTest, - ::testing::Values( - std::pair{ - "not-deterministic", - BuildResult{ - .inner{BuildResult::Failure{ - .status = BuildResult::Failure::NotDeterministic, - .errorMsg = "no idea why", - .isNonDeterministic = false, // Note: This field is separate from the status - }}, - .timesBuilt = 1, - }, - }, - std::pair{ - "output-rejected", - BuildResult{ - .inner{BuildResult::Failure{ - .status = BuildResult::Failure::OutputRejected, - .errorMsg = "no idea why", - .isNonDeterministic = false, - }}, - .timesBuilt = 3, - .startTime = 30, - .stopTime = 50, - }, - }, - std::pair{ - "success", - BuildResult{ - .inner{BuildResult::Success{ - .status = BuildResult::Success::Built, - .builtOutputs{ - { - "foo", - { - { - .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, - }, - DrvOutput{ - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "foo", - }, - }, - }, - { - "bar", - { - { - .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"}, - }, - DrvOutput{ - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "bar", - }, - }, - }, - }, - }}, - .timesBuilt = 3, - .startTime = 30, - .stopTime = 50, - .cpuUser = std::chrono::microseconds(500s), - .cpuSystem = std::chrono::microseconds(604s), - }, - })); - -} // namespace nix diff --git a/src/libstore-tests/common-protocol.cc b/src/libstore-tests/common-protocol.cc index 7c40e8cdb..2c001957b 100644 --- a/src/libstore-tests/common-protocol.cc +++ b/src/libstore-tests/common-protocol.cc @@ -111,31 +111,16 @@ CHARACTERIZATION_TEST( realisation, "realisation", (std::tuple{ - Realisation{ - { - .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, - }, - { - .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), - .outputName = "baz", - }, - }, Realisation{ { .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, .signatures = {"asdf", "qwer"}, }, - { + DrvOutput{ .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), .outputName = "baz", }, }, - })) - -CHARACTERIZATION_TEST( - realisation_with_deps, - "realisation-with-deps", - (std::tuple{ Realisation{ { .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, diff --git a/src/libstore-tests/data/build-result/not-deterministic.json b/src/libstore-tests/data/build-result/not-deterministic.json deleted file mode 100644 index c24a15795..000000000 --- a/src/libstore-tests/data/build-result/not-deterministic.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "errorMsg": "no idea why", - "isNonDeterministic": false, - "startTime": 0, - "status": "NotDeterministic", - "stopTime": 0, - "success": false, - "timesBuilt": 1 -} diff --git a/src/libstore-tests/data/build-result/output-rejected.json b/src/libstore-tests/data/build-result/output-rejected.json deleted file mode 100644 index 9494bf4ec..000000000 --- a/src/libstore-tests/data/build-result/output-rejected.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "errorMsg": "no idea why", - "isNonDeterministic": false, - "startTime": 30, - "status": "OutputRejected", - "stopTime": 50, - "success": false, - "timesBuilt": 3 -} diff --git a/src/libstore-tests/data/build-result/success.json b/src/libstore-tests/data/build-result/success.json deleted file mode 100644 index 4baadb547..000000000 --- a/src/libstore-tests/data/build-result/success.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "builtOutputs": { - "bar": { - "dependentRealisations": {}, - "id": "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!bar", - "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", - "signatures": [] - }, - "foo": { - "dependentRealisations": {}, - "id": "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!foo", - "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", - "signatures": [] - } - }, - "cpuSystem": 604000000, - "cpuUser": 500000000, - "startTime": 30, - "status": "Built", - "stopTime": 50, - "success": true, - "timesBuilt": 3 -} diff --git a/src/libstore-tests/data/common-protocol/realisation-with-deps.bin b/src/libstore-tests/data/common-protocol/realisation-with-deps.bin deleted file mode 100644 index 54a78b64e..000000000 Binary files a/src/libstore-tests/data/common-protocol/realisation-with-deps.bin and /dev/null differ diff --git a/src/libstore-tests/data/common-protocol/realisation.bin b/src/libstore-tests/data/common-protocol/realisation.bin index 3a0b2b2d8..2176c6c4a 100644 Binary files a/src/libstore-tests/data/common-protocol/realisation.bin and b/src/libstore-tests/data/common-protocol/realisation.bin differ diff --git a/src/libstore-tests/data/derivation/ca/advanced-attributes-defaults.json b/src/libstore-tests/data/derivation/ca/advanced-attributes-defaults.json index 781b4cb14..eb4bd4f3d 100644 --- a/src/libstore-tests/data/derivation/ca/advanced-attributes-defaults.json +++ b/src/libstore-tests/data/derivation/ca/advanced-attributes-defaults.json @@ -12,10 +12,8 @@ "outputHashMode": "recursive", "system": "my-system" }, - "inputs": { - "drvs": {}, - "srcs": [] - }, + "inputDrvs": {}, + "inputSrcs": [], "name": "advanced-attributes-defaults", "outputs": { "out": { @@ -24,5 +22,5 @@ } }, "system": "my-system", - "version": 4 + "version": 3 } diff --git a/src/libstore-tests/data/derivation/ca/advanced-attributes-structured-attrs-defaults.json b/src/libstore-tests/data/derivation/ca/advanced-attributes-structured-attrs-defaults.json index 7437b51ef..3a4a3079b 100644 --- a/src/libstore-tests/data/derivation/ca/advanced-attributes-structured-attrs-defaults.json +++ b/src/libstore-tests/data/derivation/ca/advanced-attributes-structured-attrs-defaults.json @@ -8,10 +8,8 @@ "dev": "/02qcpld1y6xhs5gz9bchpxaw0xdhmsp5dv88lh25r2ss44kh8dxz", "out": "/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9" }, - "inputs": { - "drvs": {}, - "srcs": [] - }, + "inputDrvs": {}, + "inputSrcs": [], "name": "advanced-attributes-structured-attrs-defaults", "outputs": { "dev": { @@ -35,5 +33,5 @@ "system": "my-system" }, "system": "my-system", - "version": 4 + "version": 3 } diff --git a/src/libstore-tests/data/derivation/ca/advanced-attributes-structured-attrs.json b/src/libstore-tests/data/derivation/ca/advanced-attributes-structured-attrs.json index 2a4e70558..b10355af7 100644 --- a/src/libstore-tests/data/derivation/ca/advanced-attributes-structured-attrs.json +++ b/src/libstore-tests/data/derivation/ca/advanced-attributes-structured-attrs.json @@ -9,27 +9,25 @@ "dev": "/02qcpld1y6xhs5gz9bchpxaw0xdhmsp5dv88lh25r2ss44kh8dxz", "out": "/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9" }, - "inputs": { - "drvs": { - "j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv": { - "dynamicOutputs": {}, - "outputs": [ - "dev", - "out" - ] - }, - "qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv": { - "dynamicOutputs": {}, - "outputs": [ - "dev", - "out" - ] - } + "inputDrvs": { + "j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv": { + "dynamicOutputs": {}, + "outputs": [ + "dev", + "out" + ] }, - "srcs": [ - "qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv" - ] + "qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv": { + "dynamicOutputs": {}, + "outputs": [ + "dev", + "out" + ] + } }, + "inputSrcs": [ + "qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv" + ], "name": "advanced-attributes-structured-attrs", "outputs": { "bin": { @@ -103,5 +101,5 @@ "system": "my-system" }, "system": "my-system", - "version": 4 + "version": 3 } diff --git a/src/libstore-tests/data/derivation/ca/advanced-attributes.json b/src/libstore-tests/data/derivation/ca/advanced-attributes.json index 55dbe62e0..d66882036 100644 --- a/src/libstore-tests/data/derivation/ca/advanced-attributes.json +++ b/src/libstore-tests/data/derivation/ca/advanced-attributes.json @@ -25,27 +25,25 @@ "requiredSystemFeatures": "rainbow uid-range", "system": "my-system" }, - "inputs": { - "drvs": { - "j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv": { - "dynamicOutputs": {}, - "outputs": [ - "dev", - "out" - ] - }, - "qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv": { - "dynamicOutputs": {}, - "outputs": [ - "dev", - "out" - ] - } + "inputDrvs": { + "j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv": { + "dynamicOutputs": {}, + "outputs": [ + "dev", + "out" + ] }, - "srcs": [ - "qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv" - ] + "qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv": { + "dynamicOutputs": {}, + "outputs": [ + "dev", + "out" + ] + } }, + "inputSrcs": [ + "qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv" + ], "name": "advanced-attributes", "outputs": { "out": { @@ -54,5 +52,5 @@ } }, "system": "my-system", - "version": 4 + "version": 3 } diff --git a/src/libstore-tests/data/derivation/ca/all_set.json b/src/libstore-tests/data/derivation/ca/all_set.json deleted file mode 100644 index e06eada01..000000000 --- a/src/libstore-tests/data/derivation/ca/all_set.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "additionalSandboxProfile": "sandcastle", - "allowLocalNetworking": true, - "allowSubstitutes": false, - "exportReferencesGraph": { - "refs1": [ - "/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9" - ], - "refs2": [ - "/nix/store/qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv" - ] - }, - "impureEnvVars": [ - "UNICORN" - ], - "impureHostDeps": [ - "/usr/bin/ditto" - ], - "noChroot": true, - "outputChecks": { - "forAllOutputs": { - "allowedReferences": [ - "/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9" - ], - "allowedRequisites": [ - "/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z" - ], - "disallowedReferences": [ - "/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g" - ], - "disallowedRequisites": [ - "/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8" - ], - "ignoreSelfRefs": true, - "maxClosureSize": null, - "maxSize": null - } - }, - "passAsFile": [], - "preferLocalBuild": true, - "requiredSystemFeatures": [ - "rainbow", - "uid-range" - ], - "unsafeDiscardReferences": {} -} diff --git a/src/libstore-tests/data/derivation/ca/self-contained.json b/src/libstore-tests/data/derivation/ca/self-contained.json index c05710140..331beb7be 100644 --- a/src/libstore-tests/data/derivation/ca/self-contained.json +++ b/src/libstore-tests/data/derivation/ca/self-contained.json @@ -10,10 +10,8 @@ "out": "/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9", "system": "x86_64-linux" }, - "inputs": { - "drvs": {}, - "srcs": [] - }, + "inputDrvs": {}, + "inputSrcs": [], "name": "myname", "outputs": { "out": { @@ -22,5 +20,5 @@ } }, "system": "x86_64-linux", - "version": 4 + "version": 3 } diff --git a/src/libstore-tests/data/derivation/ca/structuredAttrs_all_set.json b/src/libstore-tests/data/derivation/ca/structuredAttrs_all_set.json deleted file mode 100644 index 2a321897c..000000000 --- a/src/libstore-tests/data/derivation/ca/structuredAttrs_all_set.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "additionalSandboxProfile": "sandcastle", - "allowLocalNetworking": true, - "allowSubstitutes": false, - "exportReferencesGraph": { - "refs1": [ - "/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9" - ], - "refs2": [ - "/nix/store/qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv" - ] - }, - "impureEnvVars": [ - "UNICORN" - ], - "impureHostDeps": [ - "/usr/bin/ditto" - ], - "noChroot": true, - "outputChecks": { - "perOutput": { - "bin": { - "allowedReferences": null, - "allowedRequisites": null, - "disallowedReferences": [ - "/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g" - ], - "disallowedRequisites": [ - "/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8" - ], - "ignoreSelfRefs": false, - "maxClosureSize": null, - "maxSize": null - }, - "dev": { - "allowedReferences": null, - "allowedRequisites": null, - "disallowedReferences": [], - "disallowedRequisites": [], - "ignoreSelfRefs": false, - "maxClosureSize": 5909, - "maxSize": 789 - }, - "out": { - "allowedReferences": [ - "/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9" - ], - "allowedRequisites": [ - "/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z" - ], - "disallowedReferences": [], - "disallowedRequisites": [], - "ignoreSelfRefs": false, - "maxClosureSize": null, - "maxSize": null - } - } - }, - "passAsFile": [], - "preferLocalBuild": true, - "requiredSystemFeatures": [ - "rainbow", - "uid-range" - ], - "unsafeDiscardReferences": {} -} diff --git a/src/libstore-tests/data/derivation/dyn-dep-derivation.json b/src/libstore-tests/data/derivation/dyn-dep-derivation.json index 1793c5f2d..1a9f54c53 100644 --- a/src/libstore-tests/data/derivation/dyn-dep-derivation.json +++ b/src/libstore-tests/data/derivation/dyn-dep-derivation.json @@ -7,35 +7,33 @@ "env": { "BIG_BAD": "WOLF" }, - "inputs": { - "drvs": { - "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": { - "dynamicOutputs": { - "cat": { - "dynamicOutputs": {}, - "outputs": [ - "kitten" - ] - }, - "goose": { - "dynamicOutputs": {}, - "outputs": [ - "gosling" - ] - } + "inputDrvs": { + "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": { + "dynamicOutputs": { + "cat": { + "dynamicOutputs": {}, + "outputs": [ + "kitten" + ] }, - "outputs": [ - "cat", - "dog" - ] - } - }, - "srcs": [ - "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1" - ] + "goose": { + "dynamicOutputs": {}, + "outputs": [ + "gosling" + ] + } + }, + "outputs": [ + "cat", + "dog" + ] + } }, + "inputSrcs": [ + "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1" + ], "name": "dyn-dep-derivation", "outputs": {}, "system": "wasm-sel4", - "version": 4 + "version": 3 } diff --git a/src/libstore-tests/data/derivation/ia/advanced-attributes-defaults.json b/src/libstore-tests/data/derivation/ia/advanced-attributes-defaults.json index 898762123..0fa543f21 100644 --- a/src/libstore-tests/data/derivation/ia/advanced-attributes-defaults.json +++ b/src/libstore-tests/data/derivation/ia/advanced-attributes-defaults.json @@ -10,10 +10,8 @@ "out": "/nix/store/1qsc7svv43m4dw2prh6mvyf7cai5czji-advanced-attributes-defaults", "system": "my-system" }, - "inputs": { - "drvs": {}, - "srcs": [] - }, + "inputDrvs": {}, + "inputSrcs": [], "name": "advanced-attributes-defaults", "outputs": { "out": { @@ -21,5 +19,5 @@ } }, "system": "my-system", - "version": 4 + "version": 3 } diff --git a/src/libstore-tests/data/derivation/ia/advanced-attributes-structured-attrs-defaults.json b/src/libstore-tests/data/derivation/ia/advanced-attributes-structured-attrs-defaults.json index c51095986..e02392ea1 100644 --- a/src/libstore-tests/data/derivation/ia/advanced-attributes-structured-attrs-defaults.json +++ b/src/libstore-tests/data/derivation/ia/advanced-attributes-structured-attrs-defaults.json @@ -8,10 +8,8 @@ "dev": "/nix/store/8bazivnbipbyi569623skw5zm91z6kc2-advanced-attributes-structured-attrs-defaults-dev", "out": "/nix/store/f8f8nvnx32bxvyxyx2ff7akbvwhwd9dw-advanced-attributes-structured-attrs-defaults" }, - "inputs": { - "drvs": {}, - "srcs": [] - }, + "inputDrvs": {}, + "inputSrcs": [], "name": "advanced-attributes-structured-attrs-defaults", "outputs": { "dev": { @@ -31,5 +29,5 @@ "system": "my-system" }, "system": "my-system", - "version": 4 + "version": 3 } diff --git a/src/libstore-tests/data/derivation/ia/advanced-attributes-structured-attrs.json b/src/libstore-tests/data/derivation/ia/advanced-attributes-structured-attrs.json index e07d1294b..9230b06b6 100644 --- a/src/libstore-tests/data/derivation/ia/advanced-attributes-structured-attrs.json +++ b/src/libstore-tests/data/derivation/ia/advanced-attributes-structured-attrs.json @@ -9,27 +9,25 @@ "dev": "/nix/store/wyfgwsdi8rs851wmy1xfzdxy7y5vrg5l-advanced-attributes-structured-attrs-dev", "out": "/nix/store/7cxy4zx1vqc885r4jl2l64pymqbdmhii-advanced-attributes-structured-attrs" }, - "inputs": { - "drvs": { - "afc3vbjbzql750v2lp8gxgaxsajphzih-foo.drv": { - "dynamicOutputs": {}, - "outputs": [ - "dev", - "out" - ] - }, - "vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv": { - "dynamicOutputs": {}, - "outputs": [ - "dev", - "out" - ] - } + "inputDrvs": { + "afc3vbjbzql750v2lp8gxgaxsajphzih-foo.drv": { + "dynamicOutputs": {}, + "outputs": [ + "dev", + "out" + ] }, - "srcs": [ - "vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv" - ] + "vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv": { + "dynamicOutputs": {}, + "outputs": [ + "dev", + "out" + ] + } }, + "inputSrcs": [ + "vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv" + ], "name": "advanced-attributes-structured-attrs", "outputs": { "bin": { @@ -98,5 +96,5 @@ "system": "my-system" }, "system": "my-system", - "version": 4 + "version": 3 } diff --git a/src/libstore-tests/data/derivation/ia/advanced-attributes.json b/src/libstore-tests/data/derivation/ia/advanced-attributes.json index 372b4fbb9..ba5911c91 100644 --- a/src/libstore-tests/data/derivation/ia/advanced-attributes.json +++ b/src/libstore-tests/data/derivation/ia/advanced-attributes.json @@ -23,27 +23,25 @@ "requiredSystemFeatures": "rainbow uid-range", "system": "my-system" }, - "inputs": { - "drvs": { - "afc3vbjbzql750v2lp8gxgaxsajphzih-foo.drv": { - "dynamicOutputs": {}, - "outputs": [ - "dev", - "out" - ] - }, - "vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv": { - "dynamicOutputs": {}, - "outputs": [ - "dev", - "out" - ] - } + "inputDrvs": { + "afc3vbjbzql750v2lp8gxgaxsajphzih-foo.drv": { + "dynamicOutputs": {}, + "outputs": [ + "dev", + "out" + ] }, - "srcs": [ - "vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv" - ] + "vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv": { + "dynamicOutputs": {}, + "outputs": [ + "dev", + "out" + ] + } }, + "inputSrcs": [ + "vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv" + ], "name": "advanced-attributes", "outputs": { "out": { @@ -51,5 +49,5 @@ } }, "system": "my-system", - "version": 4 + "version": 3 } diff --git a/src/libstore-tests/data/derivation/ia/all_set.json b/src/libstore-tests/data/derivation/ia/all_set.json deleted file mode 100644 index 62b6cdf97..000000000 --- a/src/libstore-tests/data/derivation/ia/all_set.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "additionalSandboxProfile": "sandcastle", - "allowLocalNetworking": true, - "allowSubstitutes": false, - "exportReferencesGraph": { - "refs1": [ - "/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo" - ], - "refs2": [ - "/nix/store/vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv" - ] - }, - "impureEnvVars": [ - "UNICORN" - ], - "impureHostDeps": [ - "/usr/bin/ditto" - ], - "noChroot": true, - "outputChecks": { - "forAllOutputs": { - "allowedReferences": [ - "/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo" - ], - "allowedRequisites": [ - "/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev" - ], - "disallowedReferences": [ - "/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar" - ], - "disallowedRequisites": [ - "/nix/store/9b61w26b4avv870dw0ymb6rw4r1hzpws-bar-dev" - ], - "ignoreSelfRefs": true, - "maxClosureSize": null, - "maxSize": null - } - }, - "passAsFile": [], - "preferLocalBuild": true, - "requiredSystemFeatures": [ - "rainbow", - "uid-range" - ], - "unsafeDiscardReferences": {} -} diff --git a/src/libstore-tests/data/derivation/ia/defaults.json b/src/libstore-tests/data/derivation/ia/defaults.json deleted file mode 100644 index 79a68989c..000000000 --- a/src/libstore-tests/data/derivation/ia/defaults.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "additionalSandboxProfile": "", - "allowLocalNetworking": false, - "allowSubstitutes": true, - "exportReferencesGraph": {}, - "impureEnvVars": [], - "impureHostDeps": [], - "noChroot": false, - "outputChecks": { - "forAllOutputs": { - "allowedReferences": null, - "allowedRequisites": null, - "disallowedReferences": [], - "disallowedRequisites": [], - "ignoreSelfRefs": true, - "maxClosureSize": null, - "maxSize": null - } - }, - "passAsFile": [], - "preferLocalBuild": false, - "requiredSystemFeatures": [], - "unsafeDiscardReferences": {} -} diff --git a/src/libstore-tests/data/derivation/ia/structuredAttrs_all_set.json b/src/libstore-tests/data/derivation/ia/structuredAttrs_all_set.json deleted file mode 100644 index 0fa383589..000000000 --- a/src/libstore-tests/data/derivation/ia/structuredAttrs_all_set.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "additionalSandboxProfile": "sandcastle", - "allowLocalNetworking": true, - "allowSubstitutes": false, - "exportReferencesGraph": { - "refs1": [ - "/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo" - ], - "refs2": [ - "/nix/store/vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv" - ] - }, - "impureEnvVars": [ - "UNICORN" - ], - "impureHostDeps": [ - "/usr/bin/ditto" - ], - "noChroot": true, - "outputChecks": { - "perOutput": { - "bin": { - "allowedReferences": null, - "allowedRequisites": null, - "disallowedReferences": [ - "/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar" - ], - "disallowedRequisites": [ - "/nix/store/9b61w26b4avv870dw0ymb6rw4r1hzpws-bar-dev" - ], - "ignoreSelfRefs": false, - "maxClosureSize": null, - "maxSize": null - }, - "dev": { - "allowedReferences": null, - "allowedRequisites": null, - "disallowedReferences": [], - "disallowedRequisites": [], - "ignoreSelfRefs": false, - "maxClosureSize": 5909, - "maxSize": 789 - }, - "out": { - "allowedReferences": [ - "/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo" - ], - "allowedRequisites": [ - "/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev" - ], - "disallowedReferences": [], - "disallowedRequisites": [], - "ignoreSelfRefs": false, - "maxClosureSize": null, - "maxSize": null - } - } - }, - "passAsFile": [], - "preferLocalBuild": true, - "requiredSystemFeatures": [ - "rainbow", - "uid-range" - ], - "unsafeDiscardReferences": {} -} diff --git a/src/libstore-tests/data/derivation/ia/structuredAttrs_defaults.json b/src/libstore-tests/data/derivation/ia/structuredAttrs_defaults.json deleted file mode 100644 index d898d85f5..000000000 --- a/src/libstore-tests/data/derivation/ia/structuredAttrs_defaults.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "additionalSandboxProfile": "", - "allowLocalNetworking": false, - "allowSubstitutes": true, - "exportReferencesGraph": {}, - "impureEnvVars": [], - "impureHostDeps": [], - "noChroot": false, - "outputChecks": { - "perOutput": {} - }, - "passAsFile": [], - "preferLocalBuild": false, - "requiredSystemFeatures": [], - "unsafeDiscardReferences": {} -} diff --git a/src/libstore-tests/data/derivation/output-caFixedFlat.json b/src/libstore-tests/data/derivation/output-caFixedFlat.json index 9a38608b3..e6a0123f6 100644 --- a/src/libstore-tests/data/derivation/output-caFixedFlat.json +++ b/src/libstore-tests/data/derivation/output-caFixedFlat.json @@ -1,8 +1,5 @@ { - "hash": { - "algorithm": "sha256", - "format": "base64", - "hash": "iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8=" - }, + "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", + "hashAlgo": "sha256", "method": "flat" } diff --git a/src/libstore-tests/data/derivation/output-caFixedNAR.json b/src/libstore-tests/data/derivation/output-caFixedNAR.json index 767c605a3..b57e065a9 100644 --- a/src/libstore-tests/data/derivation/output-caFixedNAR.json +++ b/src/libstore-tests/data/derivation/output-caFixedNAR.json @@ -1,8 +1,5 @@ { - "hash": { - "algorithm": "sha256", - "format": "base64", - "hash": "iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8=" - }, + "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", + "hashAlgo": "sha256", "method": "nar" } diff --git a/src/libstore-tests/data/derivation/output-caFixedText.json b/src/libstore-tests/data/derivation/output-caFixedText.json index a04f1ff2a..84778509e 100644 --- a/src/libstore-tests/data/derivation/output-caFixedText.json +++ b/src/libstore-tests/data/derivation/output-caFixedText.json @@ -1,8 +1,5 @@ { - "hash": { - "algorithm": "sha256", - "format": "base64", - "hash": "iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8=" - }, + "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", + "hashAlgo": "sha256", "method": "text" } diff --git a/src/libstore-tests/data/derivation/simple-derivation.json b/src/libstore-tests/data/derivation/simple-derivation.json index 04129a096..41a049aef 100644 --- a/src/libstore-tests/data/derivation/simple-derivation.json +++ b/src/libstore-tests/data/derivation/simple-derivation.json @@ -7,22 +7,20 @@ "env": { "BIG_BAD": "WOLF" }, - "inputs": { - "drvs": { - "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": { - "dynamicOutputs": {}, - "outputs": [ - "cat", - "dog" - ] - } - }, - "srcs": [ - "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1" - ] + "inputDrvs": { + "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": { + "dynamicOutputs": {}, + "outputs": [ + "cat", + "dog" + ] + } }, + "inputSrcs": [ + "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1" + ], "name": "simple-derivation", "outputs": {}, "system": "wasm-sel4", - "version": 4 + "version": 3 } diff --git a/src/libstore-tests/data/nar-info/impure.json b/src/libstore-tests/data/nar-info/impure.json index f35ff990b..bb9791a6a 100644 --- a/src/libstore-tests/data/nar-info/impure.json +++ b/src/libstore-tests/data/nar-info/impure.json @@ -1,12 +1,5 @@ { - "ca": { - "hash": { - "algorithm": "sha256", - "format": "base64", - "hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=" - }, - "method": "nar" - }, + "ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh", "compression": "xz", "deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", "downloadHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", @@ -23,6 +16,5 @@ "qwer" ], "ultimate": true, - "url": "nar/1w1fff338fvdw53sqgamddn1b2xgds473pv6y13gizdbqjv4i5p3.nar.xz", - "version": 2 + "url": "nar/1w1fff338fvdw53sqgamddn1b2xgds473pv6y13gizdbqjv4i5p3.nar.xz" } diff --git a/src/libstore-tests/data/nar-info/pure.json b/src/libstore-tests/data/nar-info/pure.json index 2c5cb3bde..955baec31 100644 --- a/src/libstore-tests/data/nar-info/pure.json +++ b/src/libstore-tests/data/nar-info/pure.json @@ -1,17 +1,9 @@ { - "ca": { - "hash": { - "algorithm": "sha256", - "format": "base64", - "hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=" - }, - "method": "nar" - }, + "ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh", "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", "narSize": 34878, "references": [ "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", "/nix/store/n5wkd9frr45pa74if5gpz9j7mifg27fh-foo" - ], - "version": 2 + ] } diff --git a/src/libstore-tests/data/path-info/empty_impure.json b/src/libstore-tests/data/path-info/empty_impure.json index 381acaa03..be982dcef 100644 --- a/src/libstore-tests/data/path-info/empty_impure.json +++ b/src/libstore-tests/data/path-info/empty_impure.json @@ -6,6 +6,5 @@ "references": [], "registrationTime": null, "signatures": [], - "ultimate": false, - "version": 2 + "ultimate": false } diff --git a/src/libstore-tests/data/path-info/empty_pure.json b/src/libstore-tests/data/path-info/empty_pure.json index 6d3fa646b..10d9f508a 100644 --- a/src/libstore-tests/data/path-info/empty_pure.json +++ b/src/libstore-tests/data/path-info/empty_pure.json @@ -2,6 +2,5 @@ "ca": null, "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", "narSize": 0, - "references": [], - "version": 2 + "references": [] } diff --git a/src/libstore-tests/data/path-info/impure.json b/src/libstore-tests/data/path-info/impure.json index 141b38a16..0c452cc49 100644 --- a/src/libstore-tests/data/path-info/impure.json +++ b/src/libstore-tests/data/path-info/impure.json @@ -1,12 +1,5 @@ { - "ca": { - "hash": { - "algorithm": "sha256", - "format": "base64", - "hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=" - }, - "method": "nar" - }, + "ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh", "deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", "narSize": 34878, @@ -19,6 +12,5 @@ "asdf", "qwer" ], - "ultimate": true, - "version": 2 + "ultimate": true } diff --git a/src/libstore-tests/data/path-info/pure.json b/src/libstore-tests/data/path-info/pure.json index 2c5cb3bde..955baec31 100644 --- a/src/libstore-tests/data/path-info/pure.json +++ b/src/libstore-tests/data/path-info/pure.json @@ -1,17 +1,9 @@ { - "ca": { - "hash": { - "algorithm": "sha256", - "format": "base64", - "hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=" - }, - "method": "nar" - }, + "ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh", "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", "narSize": 34878, "references": [ "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", "/nix/store/n5wkd9frr45pa74if5gpz9j7mifg27fh-foo" - ], - "version": 2 + ] } diff --git a/src/libstore-tests/data/serve-protocol/realisation-with-deps.bin b/src/libstore-tests/data/serve-protocol/realisation-with-deps.bin deleted file mode 100644 index 54a78b64e..000000000 Binary files a/src/libstore-tests/data/serve-protocol/realisation-with-deps.bin and /dev/null differ diff --git a/src/libstore-tests/data/serve-protocol/realisation.bin b/src/libstore-tests/data/serve-protocol/realisation.bin index 3a0b2b2d8..2176c6c4a 100644 Binary files a/src/libstore-tests/data/serve-protocol/realisation.bin and b/src/libstore-tests/data/serve-protocol/realisation.bin differ diff --git a/src/libstore-tests/data/worker-protocol/realisation-with-deps.bin b/src/libstore-tests/data/worker-protocol/realisation-with-deps.bin deleted file mode 100644 index 54a78b64e..000000000 Binary files a/src/libstore-tests/data/worker-protocol/realisation-with-deps.bin and /dev/null differ diff --git a/src/libstore-tests/data/worker-protocol/realisation.bin b/src/libstore-tests/data/worker-protocol/realisation.bin index 3a0b2b2d8..2176c6c4a 100644 Binary files a/src/libstore-tests/data/worker-protocol/realisation.bin and b/src/libstore-tests/data/worker-protocol/realisation.bin differ diff --git a/src/libstore-tests/derivation-advanced-attrs.cc b/src/libstore-tests/derivation-advanced-attrs.cc index 41538cdcc..02bc8fa24 100644 --- a/src/libstore-tests/derivation-advanced-attrs.cc +++ b/src/libstore-tests/derivation-advanced-attrs.cc @@ -10,15 +10,13 @@ #include "nix/util/json-utils.hh" #include "nix/store/tests/libstore.hh" -#include "nix/util/tests/json-characterization.hh" +#include "nix/util/tests/characterization.hh" namespace nix { using namespace nlohmann; -class DerivationAdvancedAttrsTest : public JsonCharacterizationTest, - public JsonCharacterizationTest, - public LibStoreTest +class DerivationAdvancedAttrsTest : public CharacterizationTest, public LibStoreTest { protected: std::filesystem::path unitTestData = getUnitTestData() / "derivation" / "ia"; @@ -34,33 +32,6 @@ public: * to worry about race conditions if the tests run concurrently. */ ExperimentalFeatureSettings mockXpSettings; - - /** - * Helper function to test getRequiredSystemFeatures for a given derivation file - */ - void testRequiredSystemFeatures(const std::string & fileName, const StringSet & expectedFeatures) - { - this->readTest(fileName, [&](auto encoded) { - auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); - DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); - EXPECT_EQ(options.getRequiredSystemFeatures(got), expectedFeatures); - }); - } - - /** - * Helper function to test DerivationOptions parsing and comparison - */ - void testDerivationOptions( - const std::string & fileName, const DerivationOptions & expected, const StringSet & expectedSystemFeatures) - { - this->readTest(fileName, [&](auto encoded) { - auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); - DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); - - EXPECT_EQ(options, expected); - EXPECT_EQ(options.getRequiredSystemFeatures(got), expectedSystemFeatures); - }); - } }; class CaDerivationAdvancedAttrsTest : public DerivationAdvancedAttrsTest @@ -129,35 +100,33 @@ TEST_ATERM_JSON(advancedAttributes_structuredAttrs_defaults, "advanced-attribute using ExportReferencesMap = decltype(DerivationOptions::exportReferencesGraph); -static const DerivationOptions advancedAttributes_defaults = { - .outputChecks = - DerivationOptions::OutputChecks{ - .ignoreSelfRefs = true, - }, - .unsafeDiscardReferences = {}, - .passAsFile = {}, - .exportReferencesGraph = {}, - .additionalSandboxProfile = "", - .noChroot = false, - .impureHostDeps = {}, - .impureEnvVars = {}, - .allowLocalNetworking = false, - .requiredSystemFeatures = {}, - .preferLocalBuild = false, - .allowSubstitutes = true, -}; - TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes_defaults) { this->readTest("advanced-attributes-defaults.drv", [&](auto encoded) { auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); EXPECT_TRUE(!got.structuredAttrs); - EXPECT_EQ(options, advancedAttributes_defaults); + EXPECT_EQ(options.additionalSandboxProfile, ""); + EXPECT_EQ(options.noChroot, false); + EXPECT_EQ(options.impureHostDeps, StringSet{}); + EXPECT_EQ(options.impureEnvVars, StringSet{}); + EXPECT_EQ(options.allowLocalNetworking, false); + EXPECT_EQ(options.exportReferencesGraph, ExportReferencesMap{}); + { + auto * checksForAllOutputs_ = std::get_if<0>(&options.outputChecks); + ASSERT_TRUE(checksForAllOutputs_ != nullptr); + auto & checksForAllOutputs = *checksForAllOutputs_; + EXPECT_EQ(checksForAllOutputs.allowedReferences, std::nullopt); + EXPECT_EQ(checksForAllOutputs.allowedRequisites, std::nullopt); + EXPECT_EQ(checksForAllOutputs.disallowedReferences, StringSet{}); + EXPECT_EQ(checksForAllOutputs.disallowedRequisites, StringSet{}); + } EXPECT_EQ(options.canBuildLocally(*this->store, got), false); EXPECT_EQ(options.willBuildLocally(*this->store, got), false); EXPECT_EQ(options.substitutesAllowed(), true); @@ -167,124 +136,152 @@ TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes_defaults) TEST_F(DerivationAdvancedAttrsTest, advancedAttributes_defaults) { - testRequiredSystemFeatures("advanced-attributes-defaults.drv", {}); + this->readTest("advanced-attributes-defaults.drv", [&](auto encoded) { + auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); + + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); + + EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet{}); + }); }; TEST_F(CaDerivationAdvancedAttrsTest, advancedAttributes_defaults) { - testRequiredSystemFeatures("advanced-attributes-defaults.drv", {"ca-derivations"}); + this->readTest("advanced-attributes-defaults.drv", [&](auto encoded) { + auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); + + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); + + EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet{"ca-derivations"}); + }); }; TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes) { - DerivationOptions expected = { - .outputChecks = - DerivationOptions::OutputChecks{ - .ignoreSelfRefs = true, - }, - .unsafeDiscardReferences = {}, - .passAsFile = {}, - .additionalSandboxProfile = "sandcastle", - .noChroot = true, - .impureHostDeps = {"/usr/bin/ditto"}, - .impureEnvVars = {"UNICORN"}, - .allowLocalNetworking = true, - .requiredSystemFeatures = {"rainbow", "uid-range"}, - .preferLocalBuild = true, - .allowSubstitutes = false, - }; - this->readTest("advanced-attributes.drv", [&](auto encoded) { auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); EXPECT_TRUE(!got.structuredAttrs); - // Reset fields that vary between test cases to enable whole-object comparison - options.outputChecks = DerivationOptions::OutputChecks{.ignoreSelfRefs = true}; - options.exportReferencesGraph = {}; - - EXPECT_EQ(options, expected); - + EXPECT_EQ(options.additionalSandboxProfile, "sandcastle"); + EXPECT_EQ(options.noChroot, true); + EXPECT_EQ(options.impureHostDeps, StringSet{"/usr/bin/ditto"}); + EXPECT_EQ(options.impureEnvVars, StringSet{"UNICORN"}); + EXPECT_EQ(options.allowLocalNetworking, true); + EXPECT_EQ(options.canBuildLocally(*this->store, got), false); + EXPECT_EQ(options.willBuildLocally(*this->store, got), false); EXPECT_EQ(options.substitutesAllowed(), false); EXPECT_EQ(options.useUidRange(got), true); }); }; -DerivationOptions advancedAttributes_ia = { - .outputChecks = - DerivationOptions::OutputChecks{ - .ignoreSelfRefs = true, - .allowedReferences = StringSet{"/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo"}, - .disallowedReferences = StringSet{"/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar"}, - .allowedRequisites = StringSet{"/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev"}, - .disallowedRequisites = StringSet{"/nix/store/9b61w26b4avv870dw0ymb6rw4r1hzpws-bar-dev"}, - }, - .unsafeDiscardReferences = {}, - .passAsFile = {}, - .exportReferencesGraph{ - {"refs1", {"/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo"}}, - {"refs2", {"/nix/store/vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv"}}, - }, - .additionalSandboxProfile = "sandcastle", - .noChroot = true, - .impureHostDeps = {"/usr/bin/ditto"}, - .impureEnvVars = {"UNICORN"}, - .allowLocalNetworking = true, - .requiredSystemFeatures = {"rainbow", "uid-range"}, - .preferLocalBuild = true, - .allowSubstitutes = false, -}; - -TEST_F(DerivationAdvancedAttrsTest, advancedAttributes_ia) +TEST_F(DerivationAdvancedAttrsTest, advancedAttributes) { - testDerivationOptions("advanced-attributes.drv", advancedAttributes_ia, {"rainbow", "uid-range"}); -}; + this->readTest("advanced-attributes.drv", [&](auto encoded) { + auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); -DerivationOptions advancedAttributes_ca = { - .outputChecks = - DerivationOptions::OutputChecks{ - .ignoreSelfRefs = true, - .allowedReferences = StringSet{"/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9"}, - .disallowedReferences = StringSet{"/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g"}, - .allowedRequisites = StringSet{"/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z"}, - .disallowedRequisites = StringSet{"/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8"}, - }, - .unsafeDiscardReferences = {}, - .passAsFile = {}, - .exportReferencesGraph{ - {"refs1", {"/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9"}}, - {"refs2", {"/nix/store/qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv"}}, - }, - .additionalSandboxProfile = "sandcastle", - .noChroot = true, - .impureHostDeps = {"/usr/bin/ditto"}, - .impureEnvVars = {"UNICORN"}, - .allowLocalNetworking = true, - .requiredSystemFeatures = {"rainbow", "uid-range"}, - .preferLocalBuild = true, - .allowSubstitutes = false, + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); + + EXPECT_EQ( + options.exportReferencesGraph, + (ExportReferencesMap{ + { + "refs1", + { + "/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo", + }, + }, + { + "refs2", + { + "/nix/store/vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv", + }, + }, + })); + + { + auto * checksForAllOutputs_ = std::get_if<0>(&options.outputChecks); + ASSERT_TRUE(checksForAllOutputs_ != nullptr); + auto & checksForAllOutputs = *checksForAllOutputs_; + + EXPECT_EQ( + checksForAllOutputs.allowedReferences, StringSet{"/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo"}); + EXPECT_EQ( + checksForAllOutputs.allowedRequisites, + StringSet{"/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev"}); + EXPECT_EQ( + checksForAllOutputs.disallowedReferences, StringSet{"/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar"}); + EXPECT_EQ( + checksForAllOutputs.disallowedRequisites, + StringSet{"/nix/store/9b61w26b4avv870dw0ymb6rw4r1hzpws-bar-dev"}); + } + + StringSet systemFeatures{"rainbow", "uid-range"}; + + EXPECT_EQ(options.getRequiredSystemFeatures(got), systemFeatures); + }); }; TEST_F(CaDerivationAdvancedAttrsTest, advancedAttributes) { - testDerivationOptions("advanced-attributes.drv", advancedAttributes_ca, {"rainbow", "uid-range", "ca-derivations"}); -}; + this->readTest("advanced-attributes.drv", [&](auto encoded) { + auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); -DerivationOptions advancedAttributes_structuredAttrs_defaults = { - .outputChecks = std::map{}, - .unsafeDiscardReferences = {}, - .passAsFile = {}, - .exportReferencesGraph = {}, - .additionalSandboxProfile = "", - .noChroot = false, - .impureHostDeps = {}, - .impureEnvVars = {}, - .allowLocalNetworking = false, - .requiredSystemFeatures = {}, - .preferLocalBuild = false, - .allowSubstitutes = true, + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); + + EXPECT_EQ( + options.exportReferencesGraph, + (ExportReferencesMap{ + { + "refs1", + { + "/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9", + }, + }, + { + "refs2", + { + "/nix/store/qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv", + }, + }, + })); + + { + auto * checksForAllOutputs_ = std::get_if<0>(&options.outputChecks); + ASSERT_TRUE(checksForAllOutputs_ != nullptr); + auto & checksForAllOutputs = *checksForAllOutputs_; + + EXPECT_EQ( + checksForAllOutputs.allowedReferences, + StringSet{"/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9"}); + EXPECT_EQ( + checksForAllOutputs.allowedRequisites, + StringSet{"/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z"}); + EXPECT_EQ( + checksForAllOutputs.disallowedReferences, + StringSet{"/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g"}); + EXPECT_EQ( + checksForAllOutputs.disallowedRequisites, + StringSet{"/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8"}); + } + + StringSet systemFeatures{"rainbow", "uid-range"}; + systemFeatures.insert("ca-derivations"); + + EXPECT_EQ(options.getRequiredSystemFeatures(got), systemFeatures); + }); }; TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes_structuredAttrs_defaults) @@ -292,11 +289,26 @@ TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes_structuredAttrs_d this->readTest("advanced-attributes-structured-attrs-defaults.drv", [&](auto encoded) { auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); EXPECT_TRUE(got.structuredAttrs); - EXPECT_EQ(options, advancedAttributes_structuredAttrs_defaults); + EXPECT_EQ(options.additionalSandboxProfile, ""); + EXPECT_EQ(options.noChroot, false); + EXPECT_EQ(options.impureHostDeps, StringSet{}); + EXPECT_EQ(options.impureEnvVars, StringSet{}); + EXPECT_EQ(options.allowLocalNetworking, false); + EXPECT_EQ(options.exportReferencesGraph, ExportReferencesMap{}); + + { + auto * checksPerOutput_ = std::get_if<1>(&options.outputChecks); + ASSERT_TRUE(checksPerOutput_ != nullptr); + auto & checksPerOutput = *checksPerOutput_; + + EXPECT_EQ(checksPerOutput.size(), 0u); + } EXPECT_EQ(options.canBuildLocally(*this->store, got), false); EXPECT_EQ(options.willBuildLocally(*this->store, got), false); @@ -307,61 +319,55 @@ TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes_structuredAttrs_d TEST_F(DerivationAdvancedAttrsTest, advancedAttributes_structuredAttrs_defaults) { - testRequiredSystemFeatures("advanced-attributes-structured-attrs-defaults.drv", {}); + this->readTest("advanced-attributes-structured-attrs-defaults.drv", [&](auto encoded) { + auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); + + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); + + EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet{}); + }); }; TEST_F(CaDerivationAdvancedAttrsTest, advancedAttributes_structuredAttrs_defaults) { - testRequiredSystemFeatures("advanced-attributes-structured-attrs-defaults.drv", {"ca-derivations"}); + this->readTest("advanced-attributes-structured-attrs-defaults.drv", [&](auto encoded) { + auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); + + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); + + EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet{"ca-derivations"}); + }); }; TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes_structuredAttrs) { - DerivationOptions expected = { - .outputChecks = - std::map{ - {"dev", - DerivationOptions::OutputChecks{ - .maxSize = 789, - .maxClosureSize = 5909, - }}, - }, - .unsafeDiscardReferences = {}, - .passAsFile = {}, - .exportReferencesGraph = {}, - .additionalSandboxProfile = "sandcastle", - .noChroot = true, - .impureHostDeps = {"/usr/bin/ditto"}, - .impureEnvVars = {"UNICORN"}, - .allowLocalNetworking = true, - .requiredSystemFeatures = {"rainbow", "uid-range"}, - .preferLocalBuild = true, - .allowSubstitutes = false, - }; - this->readTest("advanced-attributes-structured-attrs.drv", [&](auto encoded) { auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); EXPECT_TRUE(got.structuredAttrs); - // Reset fields that vary between test cases to enable whole-object comparison - { - // Delete all keys but "dev" in options.outputChecks - auto * outputChecksMapP = - std::get_if>(&options.outputChecks); - ASSERT_TRUE(outputChecksMapP); - auto & outputChecksMap = *outputChecksMapP; - auto devEntry = outputChecksMap.find("dev"); - ASSERT_TRUE(devEntry != outputChecksMap.end()); - auto devChecks = devEntry->second; - outputChecksMap.clear(); - outputChecksMap.emplace("dev", std::move(devChecks)); - } - options.exportReferencesGraph = {}; + EXPECT_EQ(options.additionalSandboxProfile, "sandcastle"); + EXPECT_EQ(options.noChroot, true); + EXPECT_EQ(options.impureHostDeps, StringSet{"/usr/bin/ditto"}); + EXPECT_EQ(options.impureEnvVars, StringSet{"UNICORN"}); + EXPECT_EQ(options.allowLocalNetworking, true); - EXPECT_EQ(options, expected); + { + auto output_ = get(std::get<1>(options.outputChecks), "dev"); + ASSERT_TRUE(output_); + auto & output = *output_; + + EXPECT_EQ(output.maxSize, 789); + EXPECT_EQ(output.maxClosureSize, 5909); + } EXPECT_EQ(options.canBuildLocally(*this->store, got), false); EXPECT_EQ(options.willBuildLocally(*this->store, got), false); @@ -370,109 +376,112 @@ TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes_structuredAttrs) }); }; -DerivationOptions advancedAttributes_structuredAttrs_ia = { - .outputChecks = - std::map{ - {"out", - DerivationOptions::OutputChecks{ - .allowedReferences = StringSet{"/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo"}, - .allowedRequisites = StringSet{"/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev"}, - }}, - {"bin", - DerivationOptions::OutputChecks{ - .disallowedReferences = StringSet{"/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar"}, - .disallowedRequisites = StringSet{"/nix/store/9b61w26b4avv870dw0ymb6rw4r1hzpws-bar-dev"}, - }}, - {"dev", - DerivationOptions::OutputChecks{ - .maxSize = 789, - .maxClosureSize = 5909, - }}, - }, - .unsafeDiscardReferences = {}, - .passAsFile = {}, - .exportReferencesGraph = - { - {"refs1", {"/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo"}}, - {"refs2", {"/nix/store/vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv"}}, - }, - .additionalSandboxProfile = "sandcastle", - .noChroot = true, - .impureHostDeps = {"/usr/bin/ditto"}, - .impureEnvVars = {"UNICORN"}, - .allowLocalNetworking = true, - .requiredSystemFeatures = {"rainbow", "uid-range"}, - .preferLocalBuild = true, - .allowSubstitutes = false, -}; - TEST_F(DerivationAdvancedAttrsTest, advancedAttributes_structuredAttrs) { - testDerivationOptions( - "advanced-attributes-structured-attrs.drv", advancedAttributes_structuredAttrs_ia, {"rainbow", "uid-range"}); -}; + this->readTest("advanced-attributes-structured-attrs.drv", [&](auto encoded) { + auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); + + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); + + EXPECT_EQ( + options.exportReferencesGraph, + (ExportReferencesMap{ + { + "refs1", + { + "/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo", + }, + }, + { + "refs2", + { + "/nix/store/vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv", + }, + }, + })); -DerivationOptions advancedAttributes_structuredAttrs_ca = { - .outputChecks = - std::map{ - {"out", - DerivationOptions::OutputChecks{ - .allowedReferences = StringSet{"/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9"}, - .allowedRequisites = StringSet{"/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z"}, - }}, - {"bin", - DerivationOptions::OutputChecks{ - .disallowedReferences = StringSet{"/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g"}, - .disallowedRequisites = StringSet{"/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8"}, - }}, - {"dev", - DerivationOptions::OutputChecks{ - .maxSize = 789, - .maxClosureSize = 5909, - }}, - }, - .unsafeDiscardReferences = {}, - .passAsFile = {}, - .exportReferencesGraph = { - {"refs1", {"/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9"}}, - {"refs2", {"/nix/store/qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv"}}, - }, - .additionalSandboxProfile = "sandcastle", - .noChroot = true, - .impureHostDeps = {"/usr/bin/ditto"}, - .impureEnvVars = {"UNICORN"}, - .allowLocalNetworking = true, - .requiredSystemFeatures = {"rainbow", "uid-range"}, - .preferLocalBuild = true, - .allowSubstitutes = false, + { + auto output_ = get(std::get<1>(options.outputChecks), "out"); + ASSERT_TRUE(output_); + auto & output = *output_; + + EXPECT_EQ(output.allowedReferences, StringSet{"/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo"}); + EXPECT_EQ(output.allowedRequisites, StringSet{"/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev"}); + } + + { + auto output_ = get(std::get<1>(options.outputChecks), "bin"); + ASSERT_TRUE(output_); + auto & output = *output_; + + EXPECT_EQ(output.disallowedReferences, StringSet{"/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar"}); + EXPECT_EQ( + output.disallowedRequisites, StringSet{"/nix/store/9b61w26b4avv870dw0ymb6rw4r1hzpws-bar-dev"}); + } + } + + StringSet systemFeatures{"rainbow", "uid-range"}; + + EXPECT_EQ(options.getRequiredSystemFeatures(got), systemFeatures); + }); }; TEST_F(CaDerivationAdvancedAttrsTest, advancedAttributes_structuredAttrs) { - testDerivationOptions( - "advanced-attributes-structured-attrs.drv", - advancedAttributes_structuredAttrs_ca, - {"rainbow", "uid-range", "ca-derivations"}); + this->readTest("advanced-attributes-structured-attrs.drv", [&](auto encoded) { + auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings); + + auto drvPath = writeDerivation(*this->store, got, NoRepair, true); + + DerivationOptions options = DerivationOptions::fromStructuredAttrs(got.env, got.structuredAttrs); + + EXPECT_EQ( + options.exportReferencesGraph, + (ExportReferencesMap{ + { + "refs1", + { + "/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9", + }, + }, + { + "refs2", + { + "/nix/store/qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv", + }, + }, + })); + + { + { + auto output_ = get(std::get<1>(options.outputChecks), "out"); + ASSERT_TRUE(output_); + auto & output = *output_; + + EXPECT_EQ(output.allowedReferences, StringSet{"/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9"}); + EXPECT_EQ(output.allowedRequisites, StringSet{"/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z"}); + } + + { + auto output_ = get(std::get<1>(options.outputChecks), "bin"); + ASSERT_TRUE(output_); + auto & output = *output_; + + EXPECT_EQ( + output.disallowedReferences, StringSet{"/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g"}); + EXPECT_EQ( + output.disallowedRequisites, StringSet{"/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8"}); + } + } + + StringSet systemFeatures{"rainbow", "uid-range"}; + systemFeatures.insert("ca-derivations"); + + EXPECT_EQ(options.getRequiredSystemFeatures(got), systemFeatures); + }); }; -#define TEST_JSON_OPTIONS(FIXUTURE, VAR, VAR2) \ - TEST_F(FIXUTURE, DerivationOptions_##VAR##_from_json) \ - { \ - this->JsonCharacterizationTest::readJsonTest(#VAR, advancedAttributes_##VAR2); \ - } \ - TEST_F(FIXUTURE, DerivationOptions_##VAR##_to_json) \ - { \ - this->JsonCharacterizationTest::writeJsonTest(#VAR, advancedAttributes_##VAR2); \ - } - -TEST_JSON_OPTIONS(DerivationAdvancedAttrsTest, defaults, defaults) -TEST_JSON_OPTIONS(DerivationAdvancedAttrsTest, all_set, ia) -TEST_JSON_OPTIONS(CaDerivationAdvancedAttrsTest, all_set, ca) -TEST_JSON_OPTIONS(DerivationAdvancedAttrsTest, structuredAttrs_defaults, structuredAttrs_defaults) -TEST_JSON_OPTIONS(DerivationAdvancedAttrsTest, structuredAttrs_all_set, structuredAttrs_ia) -TEST_JSON_OPTIONS(CaDerivationAdvancedAttrsTest, structuredAttrs_all_set, structuredAttrs_ca) - -#undef TEST_JSON_OPTIONS - } // namespace nix diff --git a/src/libstore-tests/meson.build b/src/libstore-tests/meson.build index f76df8bcb..4d464ad89 100644 --- a/src/libstore-tests/meson.build +++ b/src/libstore-tests/meson.build @@ -54,7 +54,6 @@ deps_private += gtest subdir('nix-meson-build-support/common') sources = files( - 'build-result.cc', 'common-protocol.cc', 'content-address.cc', 'derivation-advanced-attrs.cc', diff --git a/src/libstore-tests/nix_api_store.cc b/src/libstore-tests/nix_api_store.cc index bf411053a..228b8069f 100644 --- a/src/libstore-tests/nix_api_store.cc +++ b/src/libstore-tests/nix_api_store.cc @@ -636,7 +636,7 @@ TEST_F(NixApiStoreTestWithRealisedPath, nix_store_realise_output_ordering) auto outj_ph = nix::hashPlaceholder("outj"); std::string drvJson = R"({ - "version": 4, + "version": 3, "name": "multi-output-test", "system": ")" + nix::settings.thisSystem.get() + R"(", @@ -668,10 +668,8 @@ TEST_F(NixApiStoreTestWithRealisedPath, nix_store_realise_output_ordering) "outa": ")" + outa_ph + R"(" }, - "inputs": { - "drvs": {}, - "srcs": [] - }, + "inputDrvs": {}, + "inputSrcs": [], "outputs": { "outd": { "hashAlgo": "sha256", "method": "nar" }, "outf": { "hashAlgo": "sha256", "method": "nar" }, diff --git a/src/libstore-tests/serve-protocol.cc b/src/libstore-tests/serve-protocol.cc index a7b69821c..10aa21e9d 100644 --- a/src/libstore-tests/serve-protocol.cc +++ b/src/libstore-tests/serve-protocol.cc @@ -94,15 +94,6 @@ VERSIONED_CHARACTERIZATION_TEST( "realisation", defaultVersion, (std::tuple{ - Realisation{ - { - .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, - }, - { - .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), - .outputName = "baz", - }, - }, Realisation{ { .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, @@ -113,14 +104,6 @@ VERSIONED_CHARACTERIZATION_TEST( .outputName = "baz", }, }, - })) - -VERSIONED_CHARACTERIZATION_TEST( - ServeProtoTest, - realisation_with_deps, - "realisation-with-deps", - defaultVersion, - (std::tuple{ Realisation{ { .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, diff --git a/src/libstore-tests/worker-protocol.cc b/src/libstore-tests/worker-protocol.cc index 8f70e937b..c4afde3bd 100644 --- a/src/libstore-tests/worker-protocol.cc +++ b/src/libstore-tests/worker-protocol.cc @@ -147,33 +147,16 @@ VERSIONED_CHARACTERIZATION_TEST( "realisation", defaultVersion, (std::tuple{ - Realisation{ - { - .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, - }, - { - .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), - .outputName = "baz", - }, - }, Realisation{ { .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, .signatures = {"asdf", "qwer"}, }, - { + DrvOutput{ .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), .outputName = "baz", }, }, - })) - -VERSIONED_CHARACTERIZATION_TEST( - WorkerProtoTest, - realisation_with_deps, - "realisation-with-deps", - defaultVersion, - (std::tuple{ Realisation{ { .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, @@ -189,7 +172,7 @@ VERSIONED_CHARACTERIZATION_TEST( }, }, }, - { + DrvOutput{ .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), .outputName = "baz", }, diff --git a/src/libstore/build-result.cc b/src/libstore/build-result.cc index e3d9e9085..ecbd27b49 100644 --- a/src/libstore/build-result.cc +++ b/src/libstore/build-result.cc @@ -1,6 +1,4 @@ #include "nix/store/build-result.hh" -#include "nix/util/json-utils.hh" -#include namespace nix { @@ -13,144 +11,4 @@ std::strong_ordering BuildResult::Success::operator<=>(const BuildResult::Succes bool BuildResult::Failure::operator==(const BuildResult::Failure &) const noexcept = default; std::strong_ordering BuildResult::Failure::operator<=>(const BuildResult::Failure &) const noexcept = default; -static constexpr std::array, 4> successStatusStrings{{ -#define ENUM_ENTRY(e) {BuildResult::Success::e, #e} - ENUM_ENTRY(Built), - ENUM_ENTRY(Substituted), - ENUM_ENTRY(AlreadyValid), - ENUM_ENTRY(ResolvesToAlreadyValid), -#undef ENUM_ENTRY -}}; - -static std::string_view successStatusToString(BuildResult::Success::Status status) -{ - for (const auto & [enumVal, str] : successStatusStrings) { - if (enumVal == status) - return str; - } - throw Error("unknown success status: %d", static_cast(status)); -} - -static BuildResult::Success::Status successStatusFromString(std::string_view str) -{ - for (const auto & [enumVal, enumStr] : successStatusStrings) { - if (enumStr == str) - return enumVal; - } - throw Error("unknown built result success status '%s'", str); -} - -static constexpr std::array, 12> failureStatusStrings{{ -#define ENUM_ENTRY(e) {BuildResult::Failure::e, #e} - ENUM_ENTRY(PermanentFailure), - ENUM_ENTRY(InputRejected), - ENUM_ENTRY(OutputRejected), - ENUM_ENTRY(TransientFailure), - ENUM_ENTRY(CachedFailure), - ENUM_ENTRY(TimedOut), - ENUM_ENTRY(MiscFailure), - ENUM_ENTRY(DependencyFailed), - ENUM_ENTRY(LogLimitExceeded), - ENUM_ENTRY(NotDeterministic), - ENUM_ENTRY(NoSubstituters), - ENUM_ENTRY(HashMismatch), -#undef ENUM_ENTRY -}}; - -static std::string_view failureStatusToString(BuildResult::Failure::Status status) -{ - for (const auto & [enumVal, str] : failureStatusStrings) { - if (enumVal == status) - return str; - } - throw Error("unknown failure status: %d", static_cast(status)); -} - -static BuildResult::Failure::Status failureStatusFromString(std::string_view str) -{ - for (const auto & [enumVal, enumStr] : failureStatusStrings) { - if (enumStr == str) - return enumVal; - } - throw Error("unknown built result failure status '%s'", str); -} - } // namespace nix - -namespace nlohmann { - -using namespace nix; - -void adl_serializer::to_json(json & res, const BuildResult & br) -{ - res = json::object(); - - // Common fields - res["timesBuilt"] = br.timesBuilt; - res["startTime"] = br.startTime; - res["stopTime"] = br.stopTime; - - if (br.cpuUser.has_value()) { - res["cpuUser"] = br.cpuUser->count(); - } - if (br.cpuSystem.has_value()) { - res["cpuSystem"] = br.cpuSystem->count(); - } - - // Handle success or failure variant - std::visit( - overloaded{ - [&](const BuildResult::Success & success) { - res["success"] = true; - res["status"] = successStatusToString(success.status); - res["builtOutputs"] = success.builtOutputs; - }, - [&](const BuildResult::Failure & failure) { - res["success"] = false; - res["status"] = failureStatusToString(failure.status); - res["errorMsg"] = failure.errorMsg; - res["isNonDeterministic"] = failure.isNonDeterministic; - }, - }, - br.inner); -} - -BuildResult adl_serializer::from_json(const json & _json) -{ - auto & json = getObject(_json); - - BuildResult br; - - // Common fields - br.timesBuilt = getUnsigned(valueAt(json, "timesBuilt")); - br.startTime = getUnsigned(valueAt(json, "startTime")); - br.stopTime = getUnsigned(valueAt(json, "stopTime")); - - if (auto cpuUser = optionalValueAt(json, "cpuUser")) { - br.cpuUser = std::chrono::microseconds(getUnsigned(*cpuUser)); - } - if (auto cpuSystem = optionalValueAt(json, "cpuSystem")) { - br.cpuSystem = std::chrono::microseconds(getUnsigned(*cpuSystem)); - } - - // Determine success or failure based on success field - bool success = getBoolean(valueAt(json, "success")); - std::string statusStr = getString(valueAt(json, "status")); - - if (success) { - BuildResult::Success s; - s.status = successStatusFromString(statusStr); - s.builtOutputs = valueAt(json, "builtOutputs"); - br.inner = std::move(s); - } else { - BuildResult::Failure f; - f.status = failureStatusFromString(statusStr); - f.errorMsg = getString(valueAt(json, "errorMsg")); - f.isNonDeterministic = getBoolean(valueAt(json, "isNonDeterministic")); - br.inner = std::move(f); - } - - return br; -} - -} // namespace nlohmann diff --git a/src/libstore/build/derivation-building-goal.cc b/src/libstore/build/derivation-building-goal.cc index c72130142..164948390 100644 --- a/src/libstore/build/derivation-building-goal.cc +++ b/src/libstore/build/derivation-building-goal.cc @@ -286,7 +286,7 @@ Goal::Co DerivationBuildingGoal::tryToBuild() PathSet lockFiles; /* FIXME: Should lock something like the drv itself so we don't build same CA drv concurrently */ - if (auto * localStore = dynamic_cast(&worker.store)) { + if (dynamic_cast(&worker.store)) { /* If we aren't a local store, we might need to use the local store as a build remote, but that would cause a deadlock. */ /* FIXME: Make it so we can use ourselves as a build remote even if we @@ -296,9 +296,9 @@ Goal::Co DerivationBuildingGoal::tryToBuild() */ for (auto & i : drv->outputsAndOptPaths(worker.store)) { if (i.second.second) - lockFiles.insert(localStore->toRealPath(*i.second.second)); + lockFiles.insert(worker.store.Store::toRealPath(*i.second.second)); else - lockFiles.insert(localStore->toRealPath(drvPath) + "." + i.first); + lockFiles.insert(worker.store.Store::toRealPath(drvPath) + "." + i.first); } } @@ -331,14 +331,12 @@ Goal::Co DerivationBuildingGoal::tryToBuild() /* If any of the outputs already exist but are not valid, delete them. */ - if (auto * localStore = dynamic_cast(&worker.store)) { - for (auto & [_, status] : initialOutputs) { - if (!status.known || status.known->isValid()) - continue; - auto storePath = status.known->path; - debug("removing invalid path '%s'", worker.store.printStorePath(status.known->path)); - deletePath(localStore->toRealPath(storePath)); - } + for (auto & [_, status] : initialOutputs) { + if (!status.known || status.known->isValid()) + continue; + auto storePath = status.known->path; + debug("removing invalid path '%s'", worker.store.printStorePath(status.known->path)); + deletePath(worker.store.Store::toRealPath(storePath)); } /* Don't do a remote build if the derivation has the attribute diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 937946134..e6efd6c09 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -896,7 +896,7 @@ static void performOp( auto path = WorkerProto::Serialise::read(*store, rconn); logger->startWork(); logger->stopWork(); - store->narFromPath(path, conn.to); + dumpPath(store->toRealPath(path), conn.to); break; } diff --git a/src/libstore/derivation-options.cc b/src/libstore/derivation-options.cc index 75313841c..bd9704b44 100644 --- a/src/libstore/derivation-options.cc +++ b/src/libstore/derivation-options.cc @@ -176,26 +176,13 @@ DerivationOptions::fromStructuredAttrs(const StringMap & env, const StructuredAt return {}; }; - res.insert_or_assign( - outputName, - OutputChecks{ - .maxSize = [&]() -> std::optional { - if (auto maxSize = get(output, "maxSize")) - return maxSize->get(); - else - return std::nullopt; - }(), - .maxClosureSize = [&]() -> std::optional { - if (auto maxClosureSize = get(output, "maxClosureSize")) - return maxClosureSize->get(); - else - return std::nullopt; - }(), - .allowedReferences = get_("allowedReferences"), - .disallowedReferences = get_("disallowedReferences").value_or(StringSet{}), - .allowedRequisites = get_("allowedRequisites"), - .disallowedRequisites = get_("disallowedRequisites").value_or(StringSet{}), - }); + checks.allowedReferences = get_("allowedReferences"); + checks.allowedRequisites = get_("allowedRequisites"); + checks.disallowedReferences = get_("disallowedReferences").value_or(StringSet{}); + checks.disallowedRequisites = get_("disallowedRequisites").value_or(StringSet{}); + ; + + res.insert_or_assign(outputName, std::move(checks)); } } return res; @@ -377,7 +364,6 @@ DerivationOptions adl_serializer::from_json(const json & json .unsafeDiscardReferences = valueAt(json, "unsafeDiscardReferences"), .passAsFile = getStringSet(valueAt(json, "passAsFile")), - .exportReferencesGraph = getMap(getObject(valueAt(json, "exportReferencesGraph")), getStringSet), .additionalSandboxProfile = getString(valueAt(json, "additionalSandboxProfile")), .noChroot = getBoolean(valueAt(json, "noChroot")), @@ -410,7 +396,6 @@ void adl_serializer::to_json(json & json, const DerivationOpt json["unsafeDiscardReferences"] = o.unsafeDiscardReferences; json["passAsFile"] = o.passAsFile; - json["exportReferencesGraph"] = o.exportReferencesGraph; json["additionalSandboxProfile"] = o.additionalSandboxProfile; json["noChroot"] = o.noChroot; @@ -438,8 +423,6 @@ DerivationOptions::OutputChecks adl_serializer: return { .ignoreSelfRefs = getBoolean(valueAt(json, "ignoreSelfRefs")), - .maxSize = ptrToOwned(getNullable(valueAt(json, "maxSize"))), - .maxClosureSize = ptrToOwned(getNullable(valueAt(json, "maxClosureSize"))), .allowedReferences = ptrToOwned(getNullable(valueAt(json, "allowedReferences"))), .disallowedReferences = getStringSet(valueAt(json, "disallowedReferences")), .allowedRequisites = ptrToOwned(getNullable(valueAt(json, "allowedRequisites"))), @@ -450,8 +433,6 @@ DerivationOptions::OutputChecks adl_serializer: void adl_serializer::to_json(json & json, const DerivationOptions::OutputChecks & c) { json["ignoreSelfRefs"] = c.ignoreSelfRefs; - json["maxSize"] = c.maxSize; - json["maxClosureSize"] = c.maxClosureSize; json["allowedReferences"] = c.allowedReferences; json["disallowedReferences"] = c.disallowedReferences; json["allowedRequisites"] = c.allowedRequisites; diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 31ca167f9..726143db2 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -1293,13 +1293,15 @@ void adl_serializer::to_json(json & res, const DerivationOutpu overloaded{ [&](const DerivationOutput::InputAddressed & doi) { res["path"] = doi.path; }, [&](const DerivationOutput::CAFixed & dof) { - res = dof.ca; - // FIXME print refs? - /* it would be nice to output the path for user convenience, but - this would require us to know the store dir. */ + /* it would be nice to output the path for user convenience, but + this would require us to know the store dir. */ #if 0 res["path"] = dof.path(store, drvName, outputName); #endif + res["method"] = std::string{dof.ca.method.render()}; + res["hashAlgo"] = printHashAlgo(dof.ca.hash.algo); + res["hash"] = dof.ca.hash.to_string(HashFormat::Base16, false); + // FIXME print refs? }, [&](const DerivationOutput::CAFloating & dof) { res["method"] = std::string{dof.method.render()}; @@ -1339,12 +1341,15 @@ adl_serializer::from_json(const json & _json, const Experiment }; } - else if (keys == (std::set{"method", "hash"})) { + else if (keys == (std::set{"method", "hashAlgo", "hash"})) { + auto [method, hashAlgo] = methodAlgo(); auto dof = DerivationOutput::CAFixed{ - .ca = static_cast(_json), + .ca = + ContentAddress{ + .method = std::move(method), + .hash = Hash::parseNonSRIUnprefixed(getString(valueAt(json, "hash")), hashAlgo), + }, }; - if (dof.ca.method == ContentAddressMethod::Raw::Text) - xpSettings.require(Xp::DynamicDerivations, "text-hashed derivation output in JSON"); /* We no longer produce this (denormalized) field (for the reasons described above), so we don't need to check it. */ #if 0 @@ -1387,7 +1392,7 @@ void adl_serializer::to_json(json & res, const Derivation & d) res["name"] = d.name; - res["version"] = 4; + res["version"] = 3; { nlohmann::json & outputsObj = res["outputs"]; @@ -1398,16 +1403,13 @@ void adl_serializer::to_json(json & res, const Derivation & d) } { - auto & inputsObj = res["inputs"]; - inputsObj = nlohmann::json::object(); - - { - auto & inputsList = inputsObj["srcs"]; - inputsList = nlohmann::json::array(); - for (auto & input : d.inputSrcs) - inputsList.emplace_back(input); - } + auto & inputsList = res["inputSrcs"]; + inputsList = nlohmann::json ::array(); + for (auto & input : d.inputSrcs) + inputsList.emplace_back(input); + } + { auto doInput = [&](this const auto & doInput, const auto & inputNode) -> nlohmann::json { auto value = nlohmann::json::object(); value["outputs"] = inputNode.value; @@ -1419,11 +1421,12 @@ void adl_serializer::to_json(json & res, const Derivation & d) } return value; }; - - auto & inputDrvsObj = inputsObj["drvs"]; - inputDrvsObj = nlohmann::json::object(); - for (auto & [inputDrv, inputNode] : d.inputDrvs.map) { - inputDrvsObj[inputDrv.to_string()] = doInput(inputNode); + { + auto & inputDrvsObj = res["inputDrvs"]; + inputDrvsObj = nlohmann::json::object(); + for (auto & [inputDrv, inputNode] : d.inputDrvs.map) { + inputDrvsObj[inputDrv.to_string()] = doInput(inputNode); + } } } @@ -1446,8 +1449,8 @@ Derivation adl_serializer::from_json(const json & _json, const Exper res.name = getString(valueAt(json, "name")); - if (valueAt(json, "version") != 4) - throw Error("Only derivation format version 4 is currently supported."); + if (valueAt(json, "version") != 3) + throw Error("Only derivation format version 3 is currently supported."); try { auto outputs = getObject(valueAt(json, "outputs")); @@ -1460,39 +1463,32 @@ Derivation adl_serializer::from_json(const json & _json, const Exper } try { - auto inputsObj = getObject(valueAt(json, "inputs")); - - try { - auto inputSrcs = getArray(valueAt(inputsObj, "srcs")); - for (auto & input : inputSrcs) - res.inputSrcs.insert(input); - } catch (Error & e) { - e.addTrace({}, "while reading key 'srcs'"); - throw; - } - - try { - auto doInput = [&](this const auto & doInput, const auto & _json) -> DerivedPathMap::ChildNode { - auto & json = getObject(_json); - DerivedPathMap::ChildNode node; - node.value = getStringSet(valueAt(json, "outputs")); - auto drvs = getObject(valueAt(json, "dynamicOutputs")); - for (auto & [outputId, childNode] : drvs) { - xpSettings.require( - Xp::DynamicDerivations, [&] { return fmt("dynamic output '%s' in JSON", outputId); }); - node.childMap[outputId] = doInput(childNode); - } - return node; - }; - auto drvs = getObject(valueAt(inputsObj, "drvs")); - for (auto & [inputDrvPath, inputOutputs] : drvs) - res.inputDrvs.map[StorePath{inputDrvPath}] = doInput(inputOutputs); - } catch (Error & e) { - e.addTrace({}, "while reading key 'drvs'"); - throw; - } + auto inputSrcs = getArray(valueAt(json, "inputSrcs")); + for (auto & input : inputSrcs) + res.inputSrcs.insert(input); } catch (Error & e) { - e.addTrace({}, "while reading key 'inputs'"); + e.addTrace({}, "while reading key 'inputSrcs'"); + throw; + } + + try { + auto doInput = [&](this const auto & doInput, const auto & _json) -> DerivedPathMap::ChildNode { + auto & json = getObject(_json); + DerivedPathMap::ChildNode node; + node.value = getStringSet(valueAt(json, "outputs")); + auto drvs = getObject(valueAt(json, "dynamicOutputs")); + for (auto & [outputId, childNode] : drvs) { + xpSettings.require( + Xp::DynamicDerivations, [&] { return fmt("dynamic output '%s' in JSON", outputId); }); + node.childMap[outputId] = doInput(childNode); + } + return node; + }; + auto drvs = getObject(valueAt(json, "inputDrvs")); + for (auto & [inputDrvPath, inputOutputs] : drvs) + res.inputDrvs.map[StorePath{inputDrvPath}] = doInput(inputOutputs); + } catch (Error & e) { + e.addTrace({}, "while reading key 'inputDrvs'"); throw; } diff --git a/src/libstore/include/nix/store/build-result.hh b/src/libstore/include/nix/store/build-result.hh index 4739232f8..0446c4038 100644 --- a/src/libstore/include/nix/store/build-result.hh +++ b/src/libstore/include/nix/store/build-result.hh @@ -7,7 +7,6 @@ #include "nix/store/derived-path.hh" #include "nix/store/realisation.hh" -#include "nix/util/json-impls.hh" namespace nix { @@ -176,5 +175,3 @@ struct KeyedBuildResult : BuildResult }; } // namespace nix - -JSON_IMPL(nix::BuildResult) diff --git a/src/libstore/include/nix/store/build/derivation-builder.hh b/src/libstore/include/nix/store/build/derivation-builder.hh index 5eed38462..5fad26e83 100644 --- a/src/libstore/include/nix/store/build/derivation-builder.hh +++ b/src/libstore/include/nix/store/build/derivation-builder.hh @@ -62,7 +62,7 @@ struct DerivationBuilderParams /** * The derivation stored at drvPath. */ - const BasicDerivation & drv; + const Derivation & drv; /** * The derivation options of `drv`. diff --git a/src/libstore/include/nix/store/globals.hh b/src/libstore/include/nix/store/globals.hh index 5ddfbee30..8aa82c4a2 100644 --- a/src/libstore/include/nix/store/globals.hh +++ b/src/libstore/include/nix/store/globals.hh @@ -189,7 +189,7 @@ public: 0, "cores", R"( - Sets the value of the `NIX_BUILD_CORES` environment variable in the [invocation of the `builder` executable](@docroot@/store/building.md#builder-execution) of a derivation. + Sets the value of the `NIX_BUILD_CORES` environment variable in the [invocation of the `builder` executable](@docroot@/language/derivations.md#builder-execution) of a derivation. The `builder` executable can use this variable to control its own maximum amount of parallelism.