1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-08 11:36:03 +01:00

Compare commits

...

59 commits

Author SHA1 Message Date
John Ericson
e6afa20c67 Encapsulate and slightly optimize string contexts
These steps are done (originally in order, but I squashed it as the end
result is still pretty small, and the churn in the code comments was a
bit annoying to keep straight).

1. Create proper struct type for string contexts on the heap

   This will make it easier to change this type in the future.

2. Make `Value::StringWithContext` iterable

   This make some for loops a lot more terse.

3. Encapsulate `Value::StringWithContext::Context::elems`

   It turns out the iterators we just exposed are sufficient.

4. Make `StringWithContext::Context` length-prefixed instead

   Rather than having a null pointer at the end, have a `size_t` at the
   beginning. This is the exact same size (note that null pointer is
   longer than null byte) and thus takes no more space!

Also, see the new TODO on naming. The thing we already so-named is a
builder type for string contexts, not the on-heap type. The
`fromBuilder` static method reflects what the names ought to be too.
2025-11-07 13:58:45 -05:00
John Ericson
5b15544bdd
Merge pull request #14493 from obsidiansystems/drv-and-path-info-new-fmts
Modifications to the JSON formats for `Derivation` and `ValidPathInfo`
2025-11-06 21:09:27 +00:00
John Ericson
8cc3ede0fa Add change-log entry for derivation format changes 2025-11-06 15:19:44 -05:00
John Ericson
caa196e31d Make the store path info ca field structured in JSON
The old string format is a holdover from the pre JSON days. It is not
friendly to users who need to get the information out of it.

Also introduce the sort of versioning we have for derivation for this
format too.
2025-11-06 15:19:44 -05:00
John Ericson
0c37a62207 Change JSON derivation format in two ways
- Use canonical content address JSON format for floating content
  addressed derivation outputs

  This keeps it more consistent.

- Reorganize inputs into nested structure (`inputs.srcs` and
  `inputs.drvs`)

  This will allow for an easier to use, but less compact, alternative
  where `srcs` is just a list of derived paths.

  It also allows for other experiments for derivations with a different
  input structure, as I suspect will be needed for secure build traces.
2025-11-06 15:19:44 -05:00
John Ericson
147e183c68
Merge pull request #14426 from obsidiansystems/json-schema-build-result
JSON Impl and schema for BuildResult
2025-11-06 18:40:35 +00:00
Eelco Dolstra
52b2909fd2
Merge pull request #14491 from NixOS/fix-14311
Don't crash on flakerefs containing newlines
2025-11-06 18:29:44 +00:00
Jörg Thalheim
34c77ffe38
Merge pull request #14471 from obsidiansystems/derivation-options-json-test
FIx `DerivationOptions` JSON and clean up unit tests
2025-11-06 18:21:15 +00:00
John Ericson
af8e44821e
Merge pull request #14490 from obsidiansystems/derivation-builder-no-inputs
`DerivationBuilderParams` have reference to `BasicDerivation`
2025-11-06 18:15:56 +00:00
Jörg Thalheim
70fbd1cdf4
Merge pull request #14465 from obsidiansystems/split-realisation-protocol-tests
Split realisation protocol unit tests
2025-11-06 18:14:25 +00:00
Jörg Thalheim
daace78239
Merge pull request #14425 from obsidiansystems/json-schema-build-trace
JSON Schema for build trace entry
2025-11-06 18:06:57 +00:00
Sergei Zimmerman
d596b9754e
Merge pull request #14472 from Radvendii/exprs-alloc
libexpr: allocate the Exprs themselves in Exprs::alloc
2025-11-06 17:29:09 +00:00
Eelco Dolstra
c1317017e9 Don't crash on flakerefs containing newlines
Fixes #14311.
2025-11-06 13:06:38 +01:00
Jörg Thalheim
3f18cad5f1
Merge pull request #14459 from jfroche/fix/macos-ipcs
Fix macOS IPC cleanup in builder
2025-11-06 09:31:53 +00:00
Jörg Thalheim
41b62aa979
Merge pull request #14445 from CyberShadow/nix-flake-check-log-success
nix flake check: log success in verbose mode
2025-11-06 09:30:55 +00:00
Jörg Thalheim
af41eccb31
Merge pull request #14469 from roberth/doc-check-link-fragments
Manual: fix and check link fragments
2025-11-06 09:27:19 +00:00
John Ericson
e7b274f85a DerivationBuilderParams have reference to BasicDerivation
Have one to that instead of one to `Derivation`. `DerivationBuilder`
doesn't need `inputDrvs`, so `BasicDerivation` suffices.

(In fact, it doesn't need `inputSrcs` either, but we don't yet hve a
type to exclude that.)
2025-11-05 23:41:47 -05:00
John Ericson
6bd92d47e5
Merge pull request #14488 from Mic92/kaitai-struct
nix-kaitai-struct: make it not longer part of the devshell
2025-11-05 21:57:29 +00:00
Sergei Zimmerman
b5302fc111
Merge pull request #14487 from NixOS/git-show-progress
Git fetcher: Restore progress indication
2025-11-05 21:32:58 +00:00
Jörg Thalheim
724086005a nix-kaitai-struct: make it not longer part of the devshell
just now pulls in jdk in
2025-11-05 22:22:45 +01:00
Eelco Dolstra
038d74edf7 Git fetcher: Restore progress indication
We were calling git with `--quiet` in order not to mess up Nix's
progress bar. However, `runProgram()` already suspends the progress
bar (since git may be interactive) so that's no longer an issue. So we
can just run with `--progress` instead.
2025-11-05 21:59:07 +01:00
Eelco Dolstra
b177354c35
Merge pull request #14482 from NixOS/fix-nix-flake-check-crash-upstream
nix flake check: Remove incorrect assertion
2025-11-05 19:15:29 +00:00
John Ericson
2039235f6e
Merge pull request #14484 from NixOS/fix-typo
manual: Fix MathJax typo
2025-11-05 18:24:51 +00:00
John Ericson
0fd3b6fee6
Merge pull request #14483 from NixOS/purge-toRealPath
Relegate `toRealPath` to `LocalFSStore`
2025-11-05 17:20:36 +00:00
Taeer Bar-Yam
b2f0472fe2 parser.y: allocate Exprs in the allocator 2025-11-05 17:10:35 +01:00
John Ericson
91af29f37a manual: Fix MathJax typo
Thanks to @cafkafk for catching my mistake.
2025-11-05 11:08:36 -05:00
John Ericson
099af7578f Relegate toRealPath to LocalFSStore
Fix #14480

This method is not well-defined for arbitrary stores, which do not have
a notion of a "real path" -- it is only well-defined for local file
systems stores, which do have exactly that notion, and so it is moved to
that sub-interface instead.

Some call-sites had to be fixed up for this, but in all cases the
changes are positive. Using `getFSSourceAccessor` allows for more other
stores to work properly. `nix-channel` was straight-up wrong in the case
of redirected local stores. And the building logic with remote building
and a non-local store is also fixed, properly gating some deletions on
store type.

Co-authored-by: Robert Hensing <robert@roberthensing.nl>
2025-11-05 10:44:25 -05:00
John Ericson
948c89b367
Merge pull request #14481 from Radvendii/exprs-alloc-pre
parser.y: abstract `new` into a function on Exprs
2025-11-05 14:49:00 +00:00
Robert Hensing
7e84ce3904 ci/gha: Disable linkcheck on darwin
Does not reproduce all settings on darwin. (Pre-existing issue)

Build with `nix build .#nix-manual.tests.linkcheck`
2025-11-05 15:38:23 +01:00
Eelco Dolstra
a828cf777a nix flake check: Remove incorrect assertion
The assumption that no unknown paths can be returned is incorrect. It
can happen if a derivation has outputs that are substitutable, but
that have references that cannot be substituted (i.e. an incomplete
closure in the binary cache). This can easily happen with
magic-nix-cache.
2025-11-05 15:24:36 +01:00
Taeer Bar-Yam
687dd38998 parser.y: abstract new into a function on Exprs
so it can easily be swapped out for other implementations
2025-11-04 23:59:45 +01:00
Taeer Bar-Yam
62729ff472 parser.y: pass all of Exprs in, not just alloc 2025-11-04 23:59:45 +01:00
Jean-François Roche
0507674a13 Document the new cleanup function using a Doxygen-style comment 2025-11-04 20:57:40 +00:00
Jean-François Roche
4f85cfe824 fix(darwin): extend IPC cleanup to message queues and semaphores
Previously, only shared memory segments were cleaned up.
This could lead to leaked message queues and semaphore sets when builds use System V IPC, exhausting kernel IPC limits over time.

This commit extends the cleanup to all three System V IPC types:
1. Shared memory segments
2. Message queues
3. Semaphores

Additionally, we stop removing IPC objects during iteration, as it could corrupt the kernel's iterator state and cause some objects to be skipped. The new implementation uses a two-pass approach where we list first and then remove them in a separate pass.

The IPC IDs are now extracted during iteration using actual system calls (shmget, msgget, semget) rather than being looked up later, ensuring the objects exist when we capture their IDs.
2025-11-04 20:57:40 +00:00
Jean-François Roche
7d5567a8d7 Fix macOS IPC cleanup using sysctl: shared memory segments
In Linux, IPC objects are automatically cleaned up when the IPC namespace is destroyed.
On Darwin, since there are no IPC namespaces, the IPC objects may sometimes persist after the build user's processes are killed.

This patch modifies the cleanup logic to use sysctl calls to identify and remove left over shm segments associated with the build user.

Fixes: #12548
2025-11-04 20:57:40 +00:00
Sergei Zimmerman
3ed42cd354
Merge pull request #14474 from xokdvium/shut-up-ai-slop
.coderabbit.yaml: Kill chats
2025-11-04 19:57:07 +00:00
Sergei Zimmerman
4a888b4138
.coderabbit.yaml: Kill chats
Stops stupid spam on issues.
2025-11-04 22:55:18 +03:00
John Ericson
f2436a47bb
Merge pull request #14388 from NixOS/dependabot/github_actions/actions/upload-artifact-5
build(deps): bump actions/upload-artifact from 4 to 5
2025-11-04 18:14:06 +00:00
John Ericson
83ddfaebf4
Merge pull request #14389 from NixOS/dependabot/github_actions/actions/download-artifact-6
build(deps): bump actions/download-artifact from 5 to 6
2025-11-04 18:13:45 +00:00
John Ericson
2b382b171c
Merge pull request #14453 from Radvendii/exprwith-alloc
libexpr: shrink ExprWith by 8 bytes
2025-11-04 18:04:25 +00:00
John Ericson
b7553378a4
Merge pull request #14467 from NixOS/dependabot/github_actions/cachix/install-nix-action-31.8.2
build(deps): bump cachix/install-nix-action from 31.5.1 to 31.8.2
2025-11-04 18:03:44 +00:00
John Ericson
d40f66109b
Merge pull request #14462 from NixOS/parallel-revcount
GitRepo::getRevCount(): Compute revcount in parallel
2025-11-04 17:31:18 +00:00
Eelco Dolstra
9657feaf8c GitRepo::getRevCount(): Compute revcount in parallel
For repos with a lot of non-linearity in the commit graph (like
Nixpkgs), this speeds up getting the revcount a lot, e.g. `nix flake
metadata /path/to/nixpkgs?rev=9dc7035bbee85ffc740d893e02cb64460f11989f` went
from 9.1s to 3.7s.
2025-11-04 14:50:57 +01:00
John Ericson
d05e85e5be Fix DerivationOptions JSON implementation and test 2025-11-04 03:04:59 -05:00
John Ericson
9daef9cca2 Clean up DerivationOptions unit tests
We now test equality on whole strucks much more often, which avoids
forgetting to test for specific fields.
2025-11-04 02:48:16 -05:00
John Ericson
341c42f321
Merge pull request #14454 from Radvendii/exprconcatstrings-alloc
libexpr: move ExprConcatStrings data to Exprs::alloc
2025-11-04 04:21:16 +00:00
Taeer Bar-Yam
631fb6c9ad libexpr: move ExprConcatStrings data to Exprs::alloc
ExprConcatStrings no longer consumes the vector argument

Co-authored-by: John Ericson <git@JohnEricson.me>
2025-11-04 04:17:35 +01:00
Taeer Bar-Yam
11e19ee690 libexpr: shrink ExprWith by 8 bytes
Correct bound on prevWith

Co-authored-by: John Ericson <git@JohnEricson.me>
2025-11-04 04:16:20 +01:00
Robert Hensing
9f322398b4 Run linkcheck as regular passthru test
... and add nix-manual.site attribute for a nice and DRY aftertaste.
2025-11-04 01:17:39 +01:00
Robert Hensing
e07510e504 Make nix check .#linkcheck pass
It's not quite perfect yet, with two kinds of excludes, but at least
we won't regress!
2025-11-04 00:31:46 +01:00
Robert Hensing
ae15d4eaf3 Fix links in the manual 2025-11-04 00:31:46 +01:00
Robert Hensing
469123eda1 doc: Check link fragments with lychee 2025-11-04 00:31:46 +01:00
John Ericson
389bcba97a JSON Impl and schema for BuildResult 2025-11-03 18:25:16 -05:00
dependabot[bot]
c3d4c5f69d
build(deps): bump cachix/install-nix-action from 31.5.1 to 31.8.2
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 31.5.1 to 31.8.2.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Changelog](https://github.com/cachix/install-nix-action/blob/master/RELEASE.md)
- [Commits](c134e4c9e3...456688f15b)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-version: 31.8.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 22:00:54 +00:00
John Ericson
144c66215b JSON Schema for build trace entry
Note, starting to make progress on #11895 by calling it this in the
manual.
2025-11-03 15:59:50 -05:00
John Ericson
0d7b16da4d Split realisation protocol unit tests
This will allow us to more accurately test dropping support for
dependent realisations, by separating the tests that should not change
from the tests that should.

I do that change in PR #14247, but even if for some reasons we don't end
up doing this soon, I think it is still good to separate the test data
this way so we have the option of doing that at some point.
2025-11-03 15:43:38 -05:00
Vladimir Panteleev
d8cec03fce
nix flake check: log success in verbose mode
The rule of silence can be a little surprising. As a compromise to
changing the default behavior, this adds printing a success message in
verbose mode, where we don't really have a reason to be silent about
our success.
2025-11-01 21:45:42 +00:00
dependabot[bot]
ccc06451df
build(deps): bump actions/download-artifact from 5 to 6
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 22:35:42 +00:00
dependabot[bot]
3775a2a226
build(deps): bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 22:22:54 +00:00
137 changed files with 2274 additions and 851 deletions

View file

@ -1,3 +1,4 @@
# 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.
@ -12,3 +13,6 @@ reviews:
tools:
github-checks:
enabled: false
chat:
art: false
auto_reply: false

View file

@ -125,13 +125,13 @@ jobs:
cat coverage-reports/index.txt >> $GITHUB_STEP_SUMMARY
if: ${{ matrix.instrumented }}
- name: Upload coverage reports
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: coverage-reports
path: coverage-reports/
if: ${{ matrix.instrumented }}
- name: Upload installer tarball
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
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@v5
uses: actions/download-artifact@v6
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@c134e4c9e34bac6cab09cf239815f9339aaaf84e # v31.5.1
- uses: cachix/install-nix-action@456688f15bc354bef6d396e4a35f4f89d40bf2b7 # v31.8.2
if: ${{ !matrix.experimental-installer }}
with:
install_url: ${{ format('{0}/install', steps.installer-tarball-url.outputs.installer-url) }}

View file

@ -107,12 +107,29 @@ 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: {
"${componentTestsPrefix}${pkgName}-${testName}" = test;
}) (pkg.tests or { })
lib.concatMapAttrs (
testName: test:
lib.optionalAttrs (!disable { inherit pkgName 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;

View file

@ -3,7 +3,7 @@
def transform_anchors_html:
. | gsub($empty_anchor_regex; "<a name=\"" + .anchor + "\"></a>")
. | gsub($empty_anchor_regex; "<a id=\"" + .anchor + "\"></a>")
| gsub($anchor_regex; "<a href=\"#" + .anchor + "\" id=\"" + .anchor + "\">" + .text + "</a>");

View file

@ -18,6 +18,9 @@
# Configuration Options
version,
# `tests` attribute
testers,
}:
let
@ -37,9 +40,11 @@ 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
./.
@ -87,6 +92,29 @@ 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;
};

View file

@ -0,0 +1,47 @@
---
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.

View file

@ -126,6 +126,8 @@
- [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)

View file

@ -14,7 +14,7 @@ The moving parts of channels are:
- The official channels listed at <https://nixos.org/channels>
- 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**
>

View file

@ -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`](#operation---install). If *args* describes multiple
[`--install`](./install.md). If *args* describes multiple
store paths with the same symbolic name, only the one with the highest
version is installed.

View file

@ -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-nix-command
[`nix-command`]: @docroot@/development/experimental-features.md#xp-feature-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](#nix-with-flakes) or in [classic Nix](#classic-nix).
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).
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.

View file

@ -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 { #characaterisation-testing-unit }
### Characterisation testing { #characterisation-testing-unit }
See [functional characterisation testing](#characterisation-testing-functional) for a broader discussion of characterisation testing.

View file

@ -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-reference}
- [referrer]{#gloss-referrer}
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#attribute-set) containing:
- attributes that refer to the files of a package, typically in the form of [derivation outputs](#output),
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),
- 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#attribute-set
[attribute name]: ./language/types.md#type-attrs
- [base directory]{#gloss-base-directory}

View file

@ -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-outputHashAlgo}; [`outputHash`]{#adv-attr-outputHashMode}
- [`outputHash`]{#adv-attr-outputHash}
This will specify the output hash of the single output of a [fixed-output derivation].

View file

@ -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/index.md#outputs) for what this is affects.
See [derivation outputs](@docroot@/store/derivation/outputs/index.md#outputs) for what this is affects.
[store path]: @docroot@/store/store-path.md

View file

@ -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](#identifier) or a [string literal](./string-literals.md).
A *name* can be written as an [identifier](#identifiers) or a [string literal](./string-literals.md).
> **Syntax**
>

View file

@ -137,7 +137,7 @@ This is an incomplete overview of language features, by example.
</td>
<td>
[Booleans](@docroot@/language/types.md#type-boolean)
[Booleans](@docroot@/language/types.md#type-bool)
</td>
</tr>
@ -245,7 +245,7 @@ This is an incomplete overview of language features, by example.
</td>
<td>
An [attribute set](@docroot@/language/types.md#attribute-set) with attributes named `x` and `y`
An [attribute set](@docroot@/language/types.md#type-attrs) with attributes named `x` and `y`
</td>
</tr>
@ -285,7 +285,7 @@ This is an incomplete overview of language features, by example.
</td>
<td>
[Lists](@docroot@/language/types.md#list) with three elements.
[Lists](@docroot@/language/types.md#type-list) with three elements.
</td>
</tr>
@ -369,7 +369,7 @@ This is an incomplete overview of language features, by example.
</td>
<td>
[Attribute selection](@docroot@/language/types.md#attribute-set) (evaluates to `1`)
[Attribute selection](@docroot@/language/types.md#type-attrs) (evaluates to `1`)
</td>
</tr>
@ -381,7 +381,7 @@ This is an incomplete overview of language features, by example.
</td>
<td>
[Attribute selection](@docroot@/language/types.md#attribute-set) with default (evaluates to `3`)
[Attribute selection](@docroot@/language/types.md#type-attrs) with default (evaluates to `3`)
</td>
</tr>

View file

@ -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#attribute-set
[attribute set]: ./types.md#type-attrs
## Clearing string contexts

View file

@ -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#attribute-set
[attribute set]: ./types.md#type-attrs
> **Syntax**
>

View file

@ -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-expressions
[interpolated into other expressions]: ./string-interpolation.md#interpolated-expression
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#attribute-set), but the attributes can refer to each other.
Recursive sets are like normal [attribute sets](./types.md#type-attrs), 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#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).
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).
This can be shortened using the `inherit` keyword.
Example:

View file

@ -0,0 +1,21 @@
{{#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}}
```

View file

@ -0,0 +1,27 @@
{{#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}}
```
<!--
## Raw Schema
[JSON Schema for Build Trace Entry v1](schema/build-trace-entry-v1.json)
-->

View file

@ -1,7 +1,7 @@
{{#include derivation-v3-fixed.md}}
{{#include derivation-v4-fixed.md}}
<!-- need to convert YAML to JSON first
## Raw Schema
[JSON Schema for Derivation v3](schema/derivation-v3.json)
[JSON Schema for Derivation v3](schema/derivation-v4.json)
-->

View file

@ -12,9 +12,11 @@ schemas = [
'hash-v1',
'content-address-v1',
'store-path-v1',
'store-object-info-v1',
'derivation-v3',
'store-object-info-v2',
'derivation-v4',
'deriving-path-v1',
'build-trace-entry-v1',
'build-result-v1',
]
schema_files = files()

View file

@ -0,0 +1 @@
../../../../../../src/libstore-tests/data/build-result

View file

@ -0,0 +1,136 @@
"$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.

View file

@ -0,0 +1 @@
../../../../../../src/libstore-tests/data/realisation

View file

@ -0,0 +1,74 @@
"$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

View file

@ -1,8 +1,8 @@
"$schema": "http://json-schema.org/draft-04/schema"
"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/derivation-v3.json"
"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/derivation-v4.json"
title: Derivation
description: |
Experimental JSON representation of a Nix derivation (version 3).
Experimental JSON representation of a Nix derivation (version 4).
This schema describes the JSON representation of Nix's `Derivation` type.
@ -17,8 +17,7 @@ required:
- name
- version
- outputs
- inputSrcs
- inputDrvs
- inputs
- system
- builder
- args
@ -32,10 +31,10 @@ properties:
Used when calculating store paths for the derivations outputs.
version:
const: 3
title: Format version (must be 3)
const: 4
title: Format version (must be 4)
description: |
Must be `3`.
Must be `4`.
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:
@ -47,6 +46,12 @@ 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:
@ -70,47 +75,56 @@ properties:
additionalProperties:
"$ref": "#/$defs/output/overall"
inputSrcs:
type: array
title: Input source paths
description: |
List of store paths on which this derivation depends.
> **Example**
>
> ```json
> "inputSrcs": [
> "47y241wqdhac3jm5l7nv0x4975mb1975-separate-debug-info.sh",
> "56d0w71pjj9bdr363ym3wj1zkwyqq97j-fix-pop-var-context-error.patch"
> ]
> ```
items:
$ref: "store-path-v1.yaml"
inputDrvs:
inputs:
type: object
title: Input derivations
title: Derivation inputs
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
Input dependencies for the derivation, organized into source paths and derivation dependencies.
required:
- srcs
- drvs
properties:
srcs:
type: array
title: Input source paths
description: |
A store path to a derivation, mapped to the outputs of that derivation.
oneOf:
- "$ref": "#/$defs/outputNames"
- "$ref": "#/$defs/dynamicOutputs"
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
> "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
additionalProperties: false
system:
@ -189,24 +203,18 @@ 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.
type: object
"$ref": "./content-address-v1.yaml"
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 in base-16.
The expected content hash.
additionalProperties: false
caFloating:

View file

@ -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-blake-hashing) experimental feature.
`blake3` is currently experimental and requires the [`blake-hashing`](@docroot@/development/experimental-features.md#xp-feature-blake3-hashes) experimental feature.

View file

@ -1,6 +1,6 @@
"$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
"$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
description: |
Information about a [store object](@docroot@/store/store-object.md).
@ -41,11 +41,27 @@ $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
@ -76,7 +92,10 @@ $defs:
type: string
ca:
type: ["string", "null"]
oneOf:
- type: "null"
const: null
- "$ref": "./content-address-v1.yaml"
title: Content Address
description: |
If the store object is [content-addressed](@docroot@/store/store-object/content-address.md),
@ -91,6 +110,7 @@ $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
@ -101,6 +121,7 @@ $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" }
@ -164,6 +185,7 @@ $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
@ -179,6 +201,7 @@ $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" }

View file

@ -1,29 +1,29 @@
{{#include store-object-info-v1-fixed.md}}
{{#include store-object-info-v2-fixed.md}}
## Examples
### Minimal store object (content-addressed)
```json
{{#include schema/store-object-info-v1/pure.json}}
{{#include schema/store-object-info-v2/pure.json}}
```
### Store object with impure fields
```json
{{#include schema/store-object-info-v1/impure.json}}
{{#include schema/store-object-info-v2/impure.json}}
```
### Minimal store object (empty)
```json
{{#include schema/store-object-info-v1/empty_pure.json}}
{{#include schema/store-object-info-v2/empty_pure.json}}
```
### Store object with all impure fields
```json
{{#include schema/store-object-info-v1/empty_impure.json}}
{{#include schema/store-object-info-v2/empty_impure.json}}
```
### NAR info (minimal)
@ -41,5 +41,5 @@
<!-- need to convert YAML to JSON first
## Raw Schema
[JSON Schema for Store Object Info v1](schema/store-object-info-v1.json)
[JSON Schema for Store Object Info v1](schema/store-object-info-v2.json)
-->

View file

@ -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#nix-archive
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive
[file system object]: @docroot@/store/file-system-object.md
The format of this specification is close to [Extended BackusNaur 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.

View file

@ -13,7 +13,7 @@
- The `discard-references` feature has been stabilized.
This means that the
[unsafeDiscardReferences](@docroot@/development/experimental-features.md#xp-feature-discard-references)
[unsafeDiscardReferences](@docroot@/language/advanced-attributes.md#adv-attr-unsafeDiscardReferences)
attribute is no longer guarded by an experimental flag and can be used
freely.

View file

@ -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-fetch-tree).
This allows stabilising it independently of the rest of what is encompassed by [`flakes`](@docroot@/development/experimental-features.md#xp-fetch-tree).
- `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).
- The interface for creating and updating lock files has been overhauled:

View file

@ -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/cli-guideline.md#returning-future-proof-json).
The JSON format for derivations has been slightly revised to better conform to our [JSON guidelines](@docroot@/development/json-guideline.md).
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.

View file

@ -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/opt-common.md#opt-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/conf-file.md#conf-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).

View file

@ -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 build traces {#derived}
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

View file

@ -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:

View file

@ -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`](#attr-builder) executable is meant to be run.
The system type on which the [`builder`](#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].

View file

@ -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-content-addressing) (and thus what is its [store path])
- if the content is content-addressed, [what is its content address](./content-address.md#fixed) (and thus what is its [store path])
## Types of derivations

View file

@ -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-addressed),
[Store Objects][Store Object] can also be [content-addressed](@docroot@/glossary.md#gloss-content-address),
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#serial-git) method of file system object content addressing.
This uses the corresponding [Git](../file-system-object/content-address.md#git) method of file system object content addressing.
References are not supported.

View file

@ -6,7 +6,7 @@
>
> A rendered store path
Nix implements references to [store objects](./index.md#store-object) as *store paths*.
Nix implements references to [store objects](./store-object.md) 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.

View file

@ -485,10 +485,10 @@
open-manual = {
type = "app";
program = "${pkgs.writeShellScript "open-nix-manual" ''
manual_path="${self.packages.${system}.nix-manual}/share/doc/nix/manual/index.html"
if ! ${opener} "$manual_path"; then
path="${self.packages.${system}.nix-manual.site}/index.html"
if ! ${opener} "$path"; then
echo "Failed to open manual with ${opener}. Manual is located at:"
echo "$manual_path"
echo "$path"
fi
''}";
meta.description = "Open the Nix manual in your browser";

View file

@ -61,4 +61,3 @@ if get_option('unit-tests')
endif
subproject('nix-functional-tests')
subproject('json-schema-checks')
subproject('kaitai-struct-checks')

View file

@ -109,7 +109,6 @@ 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
@ -149,7 +148,6 @@ 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
++ pkgs.nixComponents2.nix-kaitai-struct-checks.externalBuildInputs;
++ lib.optional havePerl pkgs.perl;
}
)

View file

@ -0,0 +1 @@
../../src/libstore-tests/data/build-result

View file

@ -0,0 +1 @@
../../src/libstore-tests/data/realisation

View file

@ -54,6 +54,15 @@ 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
@ -61,7 +70,7 @@ schemas += [
# Match overall
{
'stem' : 'derivation',
'schema' : schema_dir / 'derivation-v3.yaml',
'schema' : schema_dir / 'derivation-v4.yaml',
'files' : [
'dyn-dep-derivation.json',
'simple-derivation.json',
@ -69,7 +78,7 @@ schemas += [
},
{
'stem' : 'derivation',
'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/overall',
'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/overall',
'files' : [
'output-caFixedFlat.json',
'output-caFixedNAR.json',
@ -83,14 +92,14 @@ schemas += [
# Match exact variant
{
'stem' : 'derivation',
'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/inputAddressed',
'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/inputAddressed',
'files' : [
'output-inputAddressed.json',
],
},
{
'stem' : 'derivation',
'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/caFixed',
'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/caFixed',
'files' : [
'output-caFixedFlat.json',
'output-caFixedNAR.json',
@ -99,21 +108,21 @@ schemas += [
},
{
'stem' : 'derivation',
'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/caFloating',
'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/caFloating',
'files' : [
'output-caFloating.json',
],
},
{
'stem' : 'derivation',
'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/deferred',
'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/deferred',
'files' : [
'output-deferred.json',
],
},
{
'stem' : 'derivation',
'schema' : schema_dir / 'derivation-v3.yaml#/$defs/output/impure',
'schema' : schema_dir / 'derivation-v4.yaml#/$defs/output/impure',
'files' : [
'output-impure.json',
],
@ -125,7 +134,7 @@ schemas += [
# Match overall
{
'stem' : 'store-object-info',
'schema' : schema_dir / 'store-object-info-v1.yaml',
'schema' : schema_dir / 'store-object-info-v2.yaml',
'files' : [
'pure.json',
'impure.json',
@ -135,16 +144,25 @@ schemas += [
},
{
'stem' : 'nar-info',
'schema' : schema_dir / 'store-object-info-v1.yaml',
'schema' : schema_dir / 'store-object-info-v2.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-v1.yaml#/$defs/base',
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/base',
'files' : [
'pure.json',
'empty_pure.json',
@ -152,7 +170,7 @@ schemas += [
},
{
'stem' : 'store-object-info',
'schema' : schema_dir / 'store-object-info-v1.yaml#/$defs/impure',
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/impure',
'files' : [
'impure.json',
'empty_impure.json',
@ -160,14 +178,14 @@ schemas += [
},
{
'stem' : 'nar-info',
'schema' : schema_dir / 'store-object-info-v1.yaml#/$defs/base',
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/base',
'files' : [
'pure.json',
],
},
{
'stem' : 'nar-info',
'schema' : schema_dir / 'store-object-info-v1.yaml#/$defs/narInfo',
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/narInfo',
'files' : [
'impure.json',
],

View file

@ -23,10 +23,12 @@ 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
./.
];

View file

@ -1,4 +1,5 @@
# Run with: nix build .#nix-kaitai-struct-checks
# or: `nix develop .#nix-kaitai-struct-checks` to enter a dev shell
{
lib,
mkMesonDerivation,

View file

@ -136,17 +136,19 @@ struct AttrDb
});
}
AttrId setString(AttrKey key, std::string_view s, const char ** context = nullptr)
AttrId setString(AttrKey key, std::string_view s, const Value::StringWithContext::Context * context = nullptr)
{
return doSQLite([&]() {
auto state(_state->lock());
if (context) {
std::string ctx;
for (const char ** p = context; *p; ++p) {
if (p != context)
bool first = true;
for (auto * elem : *context) {
if (!first)
ctx.push_back(' ');
ctx.append(*p);
ctx.append(elem);
first = false;
}
state->insertAttributeWithContext.use()(key.first)(symbols[key.second])(AttrType::String) (s) (ctx)
.exec();

View file

@ -821,15 +821,18 @@ void Value::mkString(std::string_view s)
mkStringNoCopy(makeImmutableString(s));
}
static const char ** encodeContext(const NixStringContext & context)
Value::StringWithContext::Context * Value::StringWithContext::Context::fromBuilder(const NixStringContext & context)
{
if (!context.empty()) {
size_t n = 0;
auto ctx = (const char **) allocBytes((context.size() + 1) * sizeof(char *));
for (auto & i : context) {
ctx[n++] = makeImmutableString({i.to_string()});
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()});
}
ctx[n] = nullptr;
return ctx;
} else
return nullptr;
@ -837,12 +840,12 @@ static const char ** encodeContext(const NixStringContext & context)
void Value::mkString(std::string_view s, const NixStringContext & context)
{
mkStringNoCopy(makeImmutableString(s), encodeContext(context));
mkStringNoCopy(makeImmutableString(s), Value::StringWithContext::Context::fromBuilder(context));
}
void Value::mkStringMove(const char * s, const NixStringContext & context)
{
mkStringNoCopy(s, encodeContext(context));
mkStringNoCopy(s, Value::StringWithContext::Context::fromBuilder(context));
}
void Value::mkPath(const SourcePath & path)
@ -2287,9 +2290,9 @@ std::string_view EvalState::forceString(Value & v, const PosIdx pos, std::string
void copyContext(const Value & v, NixStringContext & context, const ExperimentalFeatureSettings & xpSettings)
{
if (v.context())
for (const char ** p = v.context(); *p; ++p)
context.insert(NixStringContextElem::parse(*p, xpSettings));
if (auto * ctx = v.context())
for (auto * elem : *ctx)
context.insert(NixStringContextElem::parse(elem, xpSettings));
}
std::string_view EvalState::forceString(
@ -2309,7 +2312,9 @@ std::string_view EvalState::forceStringNoCtx(Value & v, const PosIdx pos, std::s
auto s = forceString(v, pos, errorCtx);
if (v.context()) {
error<EvalError>(
"the string '%1%' is not allowed to refer to a store path (such as '%2%')", v.string_view(), v.context()[0])
"the string '%1%' is not allowed to refer to a store path (such as '%2%')",
v.string_view(),
*v.context()->begin())
.withTrace(pos, errorCtx)
.debugThrow();
}
@ -3216,8 +3221,8 @@ Expr * EvalState::parse(
docComments = &it->second;
}
auto result = parseExprFromBuf(
text, length, origin, basePath, mem.exprs.alloc, symbols, settings, positions, *docComments, rootFS);
auto result =
parseExprFromBuf(text, length, origin, basePath, mem.exprs, symbols, settings, positions, *docComments, rootFS);
result->bindVars(*this, staticEnv);

View file

@ -91,13 +91,6 @@ std::string showAttrPath(const SymbolTable & symbols, std::span<const AttrName>
using UpdateQueue = SmallTemporaryValueVector<conservativeStackReservation>;
class Exprs
{
std::pmr::monotonic_buffer_resource buffer;
public:
std::pmr::polymorphic_allocator<char> alloc{&buffer};
};
/* Abstract syntax of Nix expressions. */
struct Expr
@ -637,8 +630,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)
@ -760,11 +753,19 @@ struct ExprConcatStrings : Expr
{
PosIdx pos;
bool forceString;
std::vector<std::pair<PosIdx, Expr *>> es;
ExprConcatStrings(const PosIdx & pos, bool forceString, std::vector<std::pair<PosIdx, Expr *>> && es)
std::span<std::pair<PosIdx, Expr *>> es;
ExprConcatStrings(
std::pmr::polymorphic_allocator<char> & alloc,
const PosIdx & pos,
bool forceString,
const std::vector<std::pair<PosIdx, Expr *>> & es)
: pos(pos)
, forceString(forceString)
, es(std::move(es)) {};
, es({alloc.allocate_object<std::pair<PosIdx, Expr *>>(es.size()), es.size()})
{
std::ranges::copy(es, this->es.begin());
};
PosIdx getPos() const override
{
@ -802,6 +803,49 @@ struct ExprBlackHole : Expr
extern ExprBlackHole eBlackHole;
class Exprs
{
std::pmr::monotonic_buffer_resource buffer;
public:
std::pmr::polymorphic_allocator<char> alloc{&buffer};
template<class C>
[[gnu::always_inline]]
C * add(auto &&... args)
{
return alloc.new_object<C>(std::forward<decltype(args)>(args)...);
}
// we define some calls to add explicitly so that the argument can be passed in as initializer lists
template<class C>
[[gnu::always_inline]]
C * add(const PosIdx & pos, Expr * fun, std::vector<Expr *> && args)
requires(std::same_as<C, ExprCall>)
{
return alloc.new_object<C>(pos, fun, std::move(args));
}
template<class C>
[[gnu::always_inline]]
C * add(const PosIdx & pos, Expr * fun, std::vector<Expr *> && args, PosIdx && cursedOrEndPos)
requires(std::same_as<C, ExprCall>)
{
return alloc.new_object<C>(pos, fun, std::move(args), std::move(cursedOrEndPos));
}
template<class C>
[[gnu::always_inline]]
C *
add(std::pmr::polymorphic_allocator<char> & alloc,
const PosIdx & pos,
bool forceString,
const std::vector<std::pair<PosIdx, Expr *>> & es)
requires(std::same_as<C, ExprConcatStrings>)
{
return alloc.new_object<C>(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. */

View file

@ -78,7 +78,7 @@ struct LexerState
struct ParserState
{
const LexerState & lexerState;
std::pmr::polymorphic_allocator<char> & alloc;
Exprs & exprs;
SymbolTable & symbols;
PosTable & positions;
Expr * result;
@ -132,11 +132,11 @@ inline void ParserState::addAttr(
dupAttr(attrPath, pos, j->second.pos);
}
} else {
nested = new ExprAttrs;
nested = exprs.add<ExprAttrs>();
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
}
} else {
nested = new ExprAttrs;
nested = exprs.add<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<std::pair<PosIdx, std::variant<Expr *, StringToken>>> && es)
{
if (es.empty())
return new ExprString("");
return exprs.add<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::vector<std::pair<PosIdx, st
// Ignore empty strings for a minor optimisation and AST simplification
if (s2 != "") {
es2.emplace_back(i->first, new ExprString(alloc, s2));
es2.emplace_back(i->first, exprs.add<ExprString>(exprs.alloc, s2));
}
};
for (; i != es.end(); ++i, --n) {
@ -332,7 +332,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vector<std::pair<PosIdx, st
// If there is nothing at all, return the empty string directly.
// This also ensures that equivalent empty strings result in the same ast, which is helpful when testing formatters.
if (es2.size() == 0) {
auto * const result = new ExprString("");
auto * const result = exprs.add<ExprString>("");
return result;
}
@ -341,7 +341,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vector<std::pair<PosIdx, st
auto * const result = (es2)[0].second;
return result;
}
return new ExprConcatStrings(pos, true, std::move(es2));
return exprs.add<ExprConcatStrings>(exprs.alloc, pos, true, std::move(es2));
}
inline PosIdx LexerState::at(const ParserLocation & loc)

View file

@ -220,7 +220,55 @@ struct ValueBase
struct StringWithContext
{
const char * c_str;
const char ** context; // must be in sorted order
/**
* 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.
*
* @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;
};
struct Path
@ -991,7 +1039,7 @@ public:
setStorage(b);
}
void mkStringNoCopy(const char * s, const char ** context = 0) noexcept
void mkStringNoCopy(const char * s, const Value::StringWithContext::Context * context = nullptr) noexcept
{
setStorage(StringWithContext{.c_str = s, .context = context});
}
@ -1117,7 +1165,7 @@ public:
return getStorage<StringWithContext>().c_str;
}
const char ** context() const noexcept
const Value::StringWithContext::Context * context() const noexcept
{
return getStorage<StringWithContext>().context;
}

View file

@ -24,6 +24,14 @@ public:
}
};
/**
* @todo This should be reamed to `StringContextBuilderElem`, since:
*
* 1. We use `*Builder` for off-heap temporary data structures
*
* 2. The `Nix*` is totally redundant. (And my mistake from a long time
* ago.)
*/
struct NixStringContextElem
{
/**
@ -77,6 +85,11 @@ struct NixStringContextElem
std::string to_string() const;
};
/**
* @todo This should be renamed to `StringContextBuilder`.
*
* @see NixStringContextElem for explanation why.
*/
typedef std::set<NixStringContextElem> NixStringContext;
} // namespace nix

View file

@ -523,6 +523,7 @@ void ExprWith::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
prevWith = 0;
for (curEnv = env.get(), level = 1; curEnv; curEnv = curEnv->up.get(), level++)
if (curEnv->isWith) {
assert(level <= std::numeric_limits<uint32_t>::max());
prevWith = level;
break;
}

View file

@ -63,7 +63,7 @@ Expr * parseExprFromBuf(
size_t length,
Pos::Origin origin,
const SourcePath & basePath,
std::pmr::polymorphic_allocator<char> & alloc,
Exprs & exprs,
SymbolTable & symbols,
const EvalSettings & settings,
PosTable & positions,
@ -113,12 +113,12 @@ static void setDocPosition(const LexerState & lexerState, ExprLambda * lambda, P
}
}
static Expr * makeCall(PosIdx pos, Expr * fn, Expr * arg) {
static Expr * makeCall(Exprs & exprs, PosIdx pos, Expr * fn, Expr * arg) {
if (auto e2 = dynamic_cast<ExprCall *>(fn)) {
e2->args.push_back(arg);
return fn;
}
return new ExprCall(pos, fn, {arg});
return exprs.add<ExprCall>(pos, fn, {arg});
}
@ -179,14 +179,14 @@ expr: expr_function;
expr_function
: ID ':' expr_function
{ auto me = new ExprLambda(CUR_POS, state->symbols.create($1), $3);
{ auto me = state->exprs.add<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 = new ExprLambda(state->positions, state->alloc, CUR_POS, std::move($formal_set), $body);
auto me = state->exprs.add<ExprLambda>(state->positions, state->exprs.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 = new ExprLambda(state->positions, state->alloc, CUR_POS, arg, std::move($formal_set), $body);
auto me = state->exprs.add<ExprLambda>(state->positions, state->exprs.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 = new ExprLambda(state->positions, state->alloc, CUR_POS, arg, std::move($formal_set), $body);
auto me = state->exprs.add<ExprLambda>(state->positions, state->exprs.alloc, CUR_POS, arg, std::move($formal_set), $body);
$$ = me;
SET_DOC_POS(me, @1);
}
| ASSERT expr ';' expr_function
{ $$ = new ExprAssert(CUR_POS, $2, $4); }
{ $$ = state->exprs.add<ExprAssert>(CUR_POS, $2, $4); }
| WITH expr ';' expr_function
{ $$ = new ExprWith(CUR_POS, $2, $4); }
{ $$ = state->exprs.add<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]
});
$$ = new ExprLet($2, $4);
$$ = state->exprs.add<ExprLet>($2, $4);
}
| expr_if
;
expr_if
: IF expr THEN expr ELSE expr { $$ = new ExprIf(CUR_POS, $2, $4, $6); }
: IF expr THEN expr ELSE expr { $$ = state->exprs.add<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->at(@2), $1, $3); }
| expr_op PIPE_FROM expr_op { $$ = makeCall(state->at(@2), $1, $3); }
: 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_pipe_into
: 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_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_op
: '!' 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 %prec NOT { $$ = state->exprs.add<ExprOpNot>($2); }
| '-' expr_op %prec NEGATE { $$ = state->exprs.add<ExprCall>(CUR_POS, state->exprs.add<ExprVar>(state->s.sub), {state->exprs.add<ExprInt>(0), $2}); }
| expr_op EQ expr_op { $$ = state->exprs.add<ExprOpEq>($1, $3); }
| expr_op NEQ expr_op { $$ = state->exprs.add<ExprOpNEq>($1, $3); }
| expr_op '<' expr_op { $$ = state->exprs.add<ExprCall>(state->at(@2), state->exprs.add<ExprVar>(state->s.lessThan), {$1, $3}); }
| expr_op LEQ expr_op { $$ = state->exprs.add<ExprOpNot>(state->exprs.add<ExprCall>(state->at(@2), state->exprs.add<ExprVar>(state->s.lessThan), {$3, $1})); }
| expr_op '>' expr_op { $$ = state->exprs.add<ExprCall>(state->at(@2), state->exprs.add<ExprVar>(state->s.lessThan), {$3, $1}); }
| expr_op GEQ expr_op { $$ = state->exprs.add<ExprOpNot>(state->exprs.add<ExprCall>(state->at(@2), state->exprs.add<ExprVar>(state->s.lessThan), {$1, $3})); }
| expr_op AND expr_op { $$ = state->exprs.add<ExprOpAnd>(state->at(@2), $1, $3); }
| expr_op OR expr_op { $$ = state->exprs.add<ExprOpOr>(state->at(@2), $1, $3); }
| expr_op IMPL expr_op { $$ = state->exprs.add<ExprOpImpl>(state->at(@2), $1, $3); }
| expr_op UPDATE expr_op { $$ = state->exprs.add<ExprOpUpdate>(state->at(@2), $1, $3); }
| expr_op '?' attrpath { $$ = state->exprs.add<ExprOpHasAttr>(state->exprs.alloc, $1, std::move($3)); }
| expr_op '+' expr_op
{ $$ = 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); }
{ $$ = state->exprs.add<ExprConcatStrings>(state->exprs.alloc, state->at(@2), false, {{state->at(@1), $1}, {state->at(@3), $3}}); }
| expr_op '-' expr_op { $$ = state->exprs.add<ExprCall>(state->at(@2), state->exprs.add<ExprVar>(state->s.sub), {$1, $3}); }
| expr_op '*' expr_op { $$ = state->exprs.add<ExprCall>(state->at(@2), state->exprs.add<ExprVar>(state->s.mul), {$1, $3}); }
| expr_op '/' expr_op { $$ = state->exprs.add<ExprCall>(state->at(@2), state->exprs.add<ExprVar>(state->s.div), {$1, $3}); }
| expr_op CONCAT expr_op { $$ = state->exprs.add<ExprOpConcatLists>(state->at(@2), $1, $3); }
| expr_app
;
expr_app
: expr_app expr_select { $$ = makeCall(CUR_POS, $1, $2); $2->warnIfCursedOr(state->symbols, state->positions); }
: expr_app expr_select { $$ = makeCall(state->exprs, 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
{ $$ = new ExprSelect(state->alloc, CUR_POS, $1, std::move($3), nullptr); }
{ $$ = state->exprs.add<ExprSelect>(state->exprs.alloc, CUR_POS, $1, std::move($3), nullptr); }
| expr_simple '.' attrpath OR_KW expr_select
{ $$ = new ExprSelect(state->alloc, CUR_POS, $1, std::move($3), $5); $5->warnIfCursedOr(state->symbols, state->positions); }
{ $$ = state->exprs.add<ExprSelect>(state->exprs.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
{ $$ = new ExprCall(CUR_POS, $1, {new ExprVar(CUR_POS, state->s.or_)}, state->positions.add(state->origin, @$.endOffset)); }
{ $$ = state->exprs.add<ExprCall>(CUR_POS, $1, {state->exprs.add<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)
$$ = new ExprPos(CUR_POS);
$$ = state->exprs.add<ExprPos>(CUR_POS);
else
$$ = new ExprVar(CUR_POS, state->symbols.create($1));
$$ = state->exprs.add<ExprVar>(CUR_POS, state->symbols.create($1));
}
| INT_LIT { $$ = new ExprInt($1); }
| FLOAT_LIT { $$ = new ExprFloat($1); }
| INT_LIT { $$ = state->exprs.add<ExprInt>($1); }
| FLOAT_LIT { $$ = state->exprs.add<ExprFloat>($1); }
| '"' string_parts '"' {
std::visit(overloaded{
[&](std::string_view str) { $$ = new ExprString(state->alloc, str); },
[&](std::string_view str) { $$ = state->exprs.add<ExprString>(state->exprs.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});
$$ = new ExprConcatStrings(CUR_POS, false, std::move($2));
$$ = state->exprs.add<ExprConcatStrings>(state->exprs.alloc, CUR_POS, false, std::move($2));
}
| SPATH {
std::string_view path($1.p + 1, $1.l - 2);
$$ = new ExprCall(CUR_POS,
new ExprVar(state->s.findFile),
{new ExprVar(state->s.nixPath),
new ExprString(state->alloc, path)});
$$ = state->exprs.add<ExprCall>(CUR_POS,
state->exprs.add<ExprVar>(state->s.findFile),
{state->exprs.add<ExprVar>(state->s.nixPath),
state->exprs.add<ExprString>(state->exprs.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]
});
$$ = new ExprString(state->alloc, $1);
$$ = state->exprs.add<ExprString>(state->exprs.alloc, $1);
}
| '(' expr ')' { $$ = $2; }
/* Let expressions `let {..., body = ...}' are just desugared
into `(rec {..., body = ...}).body'. */
| LET '{' binds '}'
{ $3->recursive = true; $3->pos = CUR_POS; $$ = new ExprSelect(state->alloc, noPos, $3, state->s.body); }
{ $3->recursive = true; $3->pos = CUR_POS; $$ = state->exprs.add<ExprSelect>(state->exprs.alloc, noPos, $3, state->s.body); }
| REC '{' binds '}'
{ $3->recursive = true; $3->pos = CUR_POS; $$ = $3; }
| '{' binds1 '}'
{ $2->pos = CUR_POS; $$ = $2; }
| '{' '}'
{ $$ = new ExprAttrs(CUR_POS); }
| '[' list ']' { $$ = new ExprList(state->alloc, std::move($2)); }
{ $$ = state->exprs.add<ExprAttrs>(CUR_POS); }
| '[' list ']' { $$ = state->exprs.add<ExprList>(state->exprs.alloc, std::move($2)); }
;
string_parts
: STR { $$ = $1; }
| string_parts_interpolated { $$ = new ExprConcatStrings(CUR_POS, true, std::move($1)); }
| string_parts_interpolated { $$ = state->exprs.add<ExprConcatStrings>(state->exprs.alloc, CUR_POS, true, std::move($1)); }
| { $$ = std::string_view(); }
;
string_parts_interpolated
: string_parts_interpolated STR
{ $$ = std::move($1); $$.emplace_back(state->at(@2), new ExprString(state->alloc, $2)); }
{ $$ = std::move($1); $$.emplace_back(state->at(@2), state->exprs.add<ExprString>(state->exprs.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), new ExprString(state->alloc, $1));
$$.emplace_back(state->at(@1), state->exprs.add<ExprString>(state->exprs.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() == '/'
? new ExprPath(state->alloc, state->rootFS, path)
: new ExprPath(state->alloc, state->basePath.accessor, path);
? state->exprs.add<ExprPath>(state->exprs.alloc, state->rootFS, path)
: state->exprs.add<ExprPath>(state->exprs.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));
$$ = new ExprPath(state->alloc, ref<SourceAccessor>(state->rootFS), path);
$$ = state->exprs.add<ExprPath>(state->exprs.alloc, ref<SourceAccessor>(state->rootFS), path);
}
;
@ -402,7 +402,7 @@ ind_string_parts
binds
: binds1
| { $$ = new ExprAttrs; }
| { $$ = state->exprs.add<ExprAttrs>(); }
;
binds1
@ -417,7 +417,7 @@ binds1
state->dupAttr(i.symbol, iPos, $accum->attrs[i.symbol].pos);
$accum->attrs.emplace(
i.symbol,
ExprAttrs::AttrDef(new ExprVar(iPos, i.symbol), iPos, ExprAttrs::AttrDef::Kind::Inherited));
ExprAttrs::AttrDef(state->exprs.add<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(
new ExprSelect(state->alloc, iPos, from, i.symbol),
state->exprs.add<ExprSelect>(state->exprs.alloc, iPos, from, i.symbol),
iPos,
ExprAttrs::AttrDef::Kind::InheritedFrom));
}
}
| attrpath '=' expr ';'
{ $$ = new ExprAttrs;
{ $$ = state->exprs.add<ExprAttrs>();
state->addAttr($$, std::move($attrpath), @attrpath, $expr, @expr);
}
;
@ -525,7 +525,7 @@ Expr * parseExprFromBuf(
size_t length,
Pos::Origin origin,
const SourcePath & basePath,
std::pmr::polymorphic_allocator<char> & alloc,
Exprs & exprs,
SymbolTable & symbols,
const EvalSettings & settings,
PosTable & positions,
@ -540,7 +540,7 @@ Expr * parseExprFromBuf(
};
ParserState state {
.lexerState = lexerState,
.alloc = alloc,
.exprs = exprs,
.symbols = symbols,
.positions = positions,
.basePath = basePath,

View file

@ -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-boolean)
- [Boolean](@docroot@/language/types.md#type-bool)
- [String](@docroot@/language/types.md#type-string)
- [Path](@docroot@/language/types.md#type-path)
- [List](@docroot@/language/types.md#list)
- [List](@docroot@/language/types.md#type-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#attribute-set) with two attributes:
A search path is represented as a list of [attribute sets](./types.md#type-attrs) 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-paths), 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-path), 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.md#operation---upgrade).
-u`](../command-ref/nix-env/upgrade.md).
)",
.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.md#operation---upgrade).
[`nix-env -u`](../command-ref/nix-env/upgrade.md).
)",
.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:

View file

@ -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-element-constant)
[constant](@docroot@/language/string-context.md#string-context-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-element-constant)
[constant](@docroot@/language/string-context.md#string-context-constant)
string context element is turned into a
[derivation deep](@docroot@/language/string-context.md#string-context-element-derivation-deep)
string context element.

View file

@ -10,6 +10,8 @@
#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 <git2/attr.h>
#include <git2/blob.h>
@ -33,12 +35,14 @@
#include <git2/tag.h>
#include <git2/tree.h>
#include <boost/unordered/concurrent_flat_set.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/unordered_flat_set.hpp>
#include <iostream>
#include <queue>
#include <regex>
#include <span>
#include <ranges>
namespace std {
@ -227,12 +231,16 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
{
/** 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`.
@ -241,6 +249,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
GitRepoImpl(std::filesystem::path _path, bool create, bool bare)
: path(std::move(_path))
, bare(bare)
{
initLibGit2();
@ -317,32 +326,56 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
checkInterrupt();
}
/**
* Return a connection pool for this repo. Useful for
* multithreaded access.
*/
Pool<GitRepoImpl> getPool()
{
// TODO: as an optimization, it would be nice to include `this` in the pool.
return Pool<GitRepoImpl>(std::numeric_limits<size_t>::max(), [this]() -> ref<GitRepoImpl> {
return make_ref<GitRepoImpl>(path, false, bare);
});
}
uint64_t getRevCount(const Hash & rev) override
{
boost::unordered_flat_set<git_oid, std::hash<git_oid>> done;
std::queue<Commit> todo;
boost::concurrent_flat_set<git_oid, std::hash<git_oid>> done;
todo.push(peelObject<Commit>(lookupObject(*this, hashToOID(rev)).get(), GIT_OBJECT_COMMIT));
auto startCommit = peelObject<Commit>(lookupObject(*this, hashToOID(rev)).get(), GIT_OBJECT_COMMIT);
auto startOid = *git_commit_id(startCommit.get());
done.insert(startOid);
while (auto commit = pop(todo)) {
if (!done.insert(*git_commit_id(commit->get())).second)
continue;
auto repoPool(getPool());
for (size_t n = 0; n < git_commit_parentcount(commit->get()); ++n) {
git_commit * parent;
if (git_commit_parent(&parent, commit->get(), n)) {
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) {
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->get()),
*git_commit_id(commit),
git_error_last()->message);
}
todo.push(Commit(parent));
if (done.insert(*parentOid))
pool.enqueue(std::bind(process, *parentOid));
}
}
};
pool.enqueue(std::bind(process, startOid));
pool.process();
return done.size();
}
@ -549,25 +582,15 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
// then use code that was removed in this commit (see blame)
auto dir = this->path;
Strings gitArgs{"-C", dir.string(), "--git-dir", ".", "fetch", "--quiet", "--force"};
Strings gitArgs{"-C", dir.string(), "--git-dir", ".", "fetch", "--progress", "--force"};
if (shallow)
append(gitArgs, {"--depth", "1"});
append(gitArgs, {std::string("--"), url, refspec});
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});
auto status = runProgram(RunOptions{.program = "git", .args = gitArgs, .isInteractive = true}).first;
if (status > 0) {
throw Error("Failed to fetch git repository %s : %s", url, output);
}
if (status > 0)
throw Error("Failed to fetch git repository '%s'", url);
}
void verifyCommit(const Hash & rev, const std::vector<fetchers::PublicKey> & publicKeys) override

View file

@ -2,6 +2,7 @@
///@file
#include "nix/util/types.hh"
#include "nix/util/source-path.hh"
#include "nix/fetchers/fetchers.hh"
namespace nix {
@ -39,7 +40,7 @@ struct Registry
{
}
static std::shared_ptr<Registry> read(const Settings & settings, const Path & path, RegistryType type);
static std::shared_ptr<Registry> read(const Settings & settings, const SourcePath & path, RegistryType type);
void write(const Path & path);

View file

@ -10,18 +10,18 @@
namespace nix::fetchers {
std::shared_ptr<Registry> Registry::read(const Settings & settings, const Path & path, RegistryType type)
std::shared_ptr<Registry> Registry::read(const Settings & settings, const SourcePath & path, RegistryType type)
{
debug("reading registry '%s'", path);
auto registry = std::make_shared<Registry>(settings, type);
if (!pathExists(path))
if (!path.pathExists())
return std::make_shared<Registry>(settings, type);
try {
auto json = nlohmann::json::parse(readFile(path));
auto json = nlohmann::json::parse(path.readFile());
auto version = json.value("version", 0);
@ -97,7 +97,10 @@ static Path getSystemRegistryPath()
static std::shared_ptr<Registry> getSystemRegistry(const Settings & settings)
{
static auto systemRegistry = Registry::read(settings, getSystemRegistryPath(), Registry::System);
static auto systemRegistry = Registry::read(
settings,
SourcePath{getFSSourceAccessor(), CanonPath{getSystemRegistryPath()}}.resolveSymlinks(),
Registry::System);
return systemRegistry;
}
@ -108,13 +111,17 @@ Path getUserRegistryPath()
std::shared_ptr<Registry> getUserRegistry(const Settings & settings)
{
static auto userRegistry = Registry::read(settings, getUserRegistryPath(), Registry::User);
static auto userRegistry = Registry::read(
settings,
SourcePath{getFSSourceAccessor(), CanonPath{getUserRegistryPath()}}.resolveSymlinks(),
Registry::User);
return userRegistry;
}
std::shared_ptr<Registry> getCustomRegistry(const Settings & settings, const Path & p)
{
static auto customRegistry = Registry::read(settings, p, Registry::Custom);
static auto customRegistry =
Registry::read(settings, SourcePath{getFSSourceAccessor(), CanonPath{p}}.resolveSymlinks(), Registry::Custom);
return customRegistry;
}
@ -137,14 +144,19 @@ static std::shared_ptr<Registry> getGlobalRegistry(const Settings & settings, re
return std::make_shared<Registry>(settings, Registry::Global); // empty registry
}
if (!isAbsolute(path)) {
auto storePath = downloadFile(store, settings, path, "flake-registry.json").storePath;
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
store2->addPermRoot(storePath, getCacheDir() + "/flake-registry.json");
path = store->toRealPath(storePath);
}
return Registry::read(settings, path, Registry::Global);
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<LocalFSStore>())
store2->addPermRoot(storePath, getCacheDir() + "/flake-registry.json");
return {store->requireStoreObjectAccessor(storePath)};
} else {
return SourcePath{getFSSourceAccessor(), CanonPath{path}}.resolveSymlinks();
}
}(),
Registry::Global);
}();
return reg;

View file

@ -109,7 +109,8 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
std::smatch match;
auto succeeds = std::regex_match(url, match, pathFlakeRegex);
assert(succeeds);
if (!succeeds)
throw Error("invalid flakeref '%s'", url);
auto path = match[1].str();
auto query = decodeQuery(match[3].str(), /*lenient=*/true);
auto fragment = percentDecode(match[5].str());

View file

@ -7,6 +7,7 @@
#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"
@ -109,7 +110,8 @@ nix_err nix_store_real_path(
if (context)
context->last_err_code = NIX_OK;
try {
auto res = store->ptr->toRealPath(path->path);
auto store2 = store->ptr.dynamic_pointer_cast<nix::LocalFSStore>();
auto res = store2 ? store2->toRealPath(path->path) : store->ptr->printStorePath(path->path);
return call_nix_get_string_callback(res, callback, user_data);
}
NIXC_CATCH_ERRS

View file

@ -0,0 +1,108 @@
#include <gtest/gtest.h>
#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<BuildResult>,
::testing::WithParamInterface<std::pair<std::string_view, BuildResult>>
{};
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

View file

@ -114,13 +114,28 @@ CHARACTERIZATION_TEST(
Realisation{
{
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
.signatures = {"asdf", "qwer"},
},
DrvOutput{
{
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
.outputName = "baz",
},
},
Realisation{
{
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
.signatures = {"asdf", "qwer"},
},
{
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
.outputName = "baz",
},
},
}))
CHARACTERIZATION_TEST(
realisation_with_deps,
"realisation-with-deps",
(std::tuple<Realisation>{
Realisation{
{
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},

View file

@ -0,0 +1,9 @@
{
"errorMsg": "no idea why",
"isNonDeterministic": false,
"startTime": 0,
"status": "NotDeterministic",
"stopTime": 0,
"success": false,
"timesBuilt": 1
}

View file

@ -0,0 +1,9 @@
{
"errorMsg": "no idea why",
"isNonDeterministic": false,
"startTime": 30,
"status": "OutputRejected",
"stopTime": 50,
"success": false,
"timesBuilt": 3
}

View file

@ -0,0 +1,23 @@
{
"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
}

View file

@ -12,8 +12,10 @@
"outputHashMode": "recursive",
"system": "my-system"
},
"inputDrvs": {},
"inputSrcs": [],
"inputs": {
"drvs": {},
"srcs": []
},
"name": "advanced-attributes-defaults",
"outputs": {
"out": {
@ -22,5 +24,5 @@
}
},
"system": "my-system",
"version": 3
"version": 4
}

View file

@ -8,8 +8,10 @@
"dev": "/02qcpld1y6xhs5gz9bchpxaw0xdhmsp5dv88lh25r2ss44kh8dxz",
"out": "/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9"
},
"inputDrvs": {},
"inputSrcs": [],
"inputs": {
"drvs": {},
"srcs": []
},
"name": "advanced-attributes-structured-attrs-defaults",
"outputs": {
"dev": {
@ -33,5 +35,5 @@
"system": "my-system"
},
"system": "my-system",
"version": 3
"version": 4
}

View file

@ -9,25 +9,27 @@
"dev": "/02qcpld1y6xhs5gz9bchpxaw0xdhmsp5dv88lh25r2ss44kh8dxz",
"out": "/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9"
},
"inputDrvs": {
"j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
"inputs": {
"drvs": {
"j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
},
"qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
},
"qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
"srcs": [
"qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv"
]
},
"inputSrcs": [
"qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv"
],
"name": "advanced-attributes-structured-attrs",
"outputs": {
"bin": {
@ -101,5 +103,5 @@
"system": "my-system"
},
"system": "my-system",
"version": 3
"version": 4
}

View file

@ -25,25 +25,27 @@
"requiredSystemFeatures": "rainbow uid-range",
"system": "my-system"
},
"inputDrvs": {
"j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
"inputs": {
"drvs": {
"j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
},
"qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
},
"qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
"srcs": [
"qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv"
]
},
"inputSrcs": [
"qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv"
],
"name": "advanced-attributes",
"outputs": {
"out": {
@ -52,5 +54,5 @@
}
},
"system": "my-system",
"version": 3
"version": 4
}

View file

@ -0,0 +1,46 @@
{
"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": {}
}

View file

@ -10,8 +10,10 @@
"out": "/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9",
"system": "x86_64-linux"
},
"inputDrvs": {},
"inputSrcs": [],
"inputs": {
"drvs": {},
"srcs": []
},
"name": "myname",
"outputs": {
"out": {
@ -20,5 +22,5 @@
}
},
"system": "x86_64-linux",
"version": 3
"version": 4
}

View file

@ -0,0 +1,66 @@
{
"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": {}
}

View file

@ -7,33 +7,35 @@
"env": {
"BIG_BAD": "WOLF"
},
"inputDrvs": {
"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": {
"dynamicOutputs": {
"cat": {
"dynamicOutputs": {},
"outputs": [
"kitten"
]
"inputs": {
"drvs": {
"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": {
"dynamicOutputs": {
"cat": {
"dynamicOutputs": {},
"outputs": [
"kitten"
]
},
"goose": {
"dynamicOutputs": {},
"outputs": [
"gosling"
]
}
},
"goose": {
"dynamicOutputs": {},
"outputs": [
"gosling"
]
}
},
"outputs": [
"cat",
"dog"
]
}
"outputs": [
"cat",
"dog"
]
}
},
"srcs": [
"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"
]
},
"inputSrcs": [
"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"
],
"name": "dyn-dep-derivation",
"outputs": {},
"system": "wasm-sel4",
"version": 3
"version": 4
}

View file

@ -10,8 +10,10 @@
"out": "/nix/store/1qsc7svv43m4dw2prh6mvyf7cai5czji-advanced-attributes-defaults",
"system": "my-system"
},
"inputDrvs": {},
"inputSrcs": [],
"inputs": {
"drvs": {},
"srcs": []
},
"name": "advanced-attributes-defaults",
"outputs": {
"out": {
@ -19,5 +21,5 @@
}
},
"system": "my-system",
"version": 3
"version": 4
}

View file

@ -8,8 +8,10 @@
"dev": "/nix/store/8bazivnbipbyi569623skw5zm91z6kc2-advanced-attributes-structured-attrs-defaults-dev",
"out": "/nix/store/f8f8nvnx32bxvyxyx2ff7akbvwhwd9dw-advanced-attributes-structured-attrs-defaults"
},
"inputDrvs": {},
"inputSrcs": [],
"inputs": {
"drvs": {},
"srcs": []
},
"name": "advanced-attributes-structured-attrs-defaults",
"outputs": {
"dev": {
@ -29,5 +31,5 @@
"system": "my-system"
},
"system": "my-system",
"version": 3
"version": 4
}

View file

@ -9,25 +9,27 @@
"dev": "/nix/store/wyfgwsdi8rs851wmy1xfzdxy7y5vrg5l-advanced-attributes-structured-attrs-dev",
"out": "/nix/store/7cxy4zx1vqc885r4jl2l64pymqbdmhii-advanced-attributes-structured-attrs"
},
"inputDrvs": {
"afc3vbjbzql750v2lp8gxgaxsajphzih-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
"inputs": {
"drvs": {
"afc3vbjbzql750v2lp8gxgaxsajphzih-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
},
"vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
},
"vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
"srcs": [
"vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv"
]
},
"inputSrcs": [
"vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv"
],
"name": "advanced-attributes-structured-attrs",
"outputs": {
"bin": {
@ -96,5 +98,5 @@
"system": "my-system"
},
"system": "my-system",
"version": 3
"version": 4
}

View file

@ -23,25 +23,27 @@
"requiredSystemFeatures": "rainbow uid-range",
"system": "my-system"
},
"inputDrvs": {
"afc3vbjbzql750v2lp8gxgaxsajphzih-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
"inputs": {
"drvs": {
"afc3vbjbzql750v2lp8gxgaxsajphzih-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
},
"vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
},
"vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
"srcs": [
"vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv"
]
},
"inputSrcs": [
"vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv"
],
"name": "advanced-attributes",
"outputs": {
"out": {
@ -49,5 +51,5 @@
}
},
"system": "my-system",
"version": 3
"version": 4
}

View file

@ -0,0 +1,46 @@
{
"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": {}
}

View file

@ -0,0 +1,24 @@
{
"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": {}
}

View file

@ -0,0 +1,66 @@
{
"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": {}
}

View file

@ -0,0 +1,16 @@
{
"additionalSandboxProfile": "",
"allowLocalNetworking": false,
"allowSubstitutes": true,
"exportReferencesGraph": {},
"impureEnvVars": [],
"impureHostDeps": [],
"noChroot": false,
"outputChecks": {
"perOutput": {}
},
"passAsFile": [],
"preferLocalBuild": false,
"requiredSystemFeatures": [],
"unsafeDiscardReferences": {}
}

View file

@ -1,5 +1,8 @@
{
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
"hashAlgo": "sha256",
"hash": {
"algorithm": "sha256",
"format": "base64",
"hash": "iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="
},
"method": "flat"
}

View file

@ -1,5 +1,8 @@
{
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
"hashAlgo": "sha256",
"hash": {
"algorithm": "sha256",
"format": "base64",
"hash": "iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="
},
"method": "nar"
}

View file

@ -1,5 +1,8 @@
{
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
"hashAlgo": "sha256",
"hash": {
"algorithm": "sha256",
"format": "base64",
"hash": "iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="
},
"method": "text"
}

View file

@ -7,20 +7,22 @@
"env": {
"BIG_BAD": "WOLF"
},
"inputDrvs": {
"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": {
"dynamicOutputs": {},
"outputs": [
"cat",
"dog"
]
}
"inputs": {
"drvs": {
"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": {
"dynamicOutputs": {},
"outputs": [
"cat",
"dog"
]
}
},
"srcs": [
"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"
]
},
"inputSrcs": [
"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"
],
"name": "simple-derivation",
"outputs": {},
"system": "wasm-sel4",
"version": 3
"version": 4
}

View file

@ -1,5 +1,12 @@
{
"ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh",
"ca": {
"hash": {
"algorithm": "sha256",
"format": "base64",
"hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM="
},
"method": "nar"
},
"compression": "xz",
"deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
"downloadHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
@ -16,5 +23,6 @@
"qwer"
],
"ultimate": true,
"url": "nar/1w1fff338fvdw53sqgamddn1b2xgds473pv6y13gizdbqjv4i5p3.nar.xz"
"url": "nar/1w1fff338fvdw53sqgamddn1b2xgds473pv6y13gizdbqjv4i5p3.nar.xz",
"version": 2
}

View file

@ -1,9 +1,17 @@
{
"ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh",
"ca": {
"hash": {
"algorithm": "sha256",
"format": "base64",
"hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM="
},
"method": "nar"
},
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
"narSize": 34878,
"references": [
"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
"/nix/store/n5wkd9frr45pa74if5gpz9j7mifg27fh-foo"
]
],
"version": 2
}

View file

@ -6,5 +6,6 @@
"references": [],
"registrationTime": null,
"signatures": [],
"ultimate": false
"ultimate": false,
"version": 2
}

View file

@ -2,5 +2,6 @@
"ca": null,
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
"narSize": 0,
"references": []
"references": [],
"version": 2
}

View file

@ -1,5 +1,12 @@
{
"ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh",
"ca": {
"hash": {
"algorithm": "sha256",
"format": "base64",
"hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM="
},
"method": "nar"
},
"deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
"narSize": 34878,
@ -12,5 +19,6 @@
"asdf",
"qwer"
],
"ultimate": true
"ultimate": true,
"version": 2
}

View file

@ -1,9 +1,17 @@
{
"ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh",
"ca": {
"hash": {
"algorithm": "sha256",
"format": "base64",
"hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM="
},
"method": "nar"
},
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
"narSize": 34878,
"references": [
"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
"/nix/store/n5wkd9frr45pa74if5gpz9j7mifg27fh-foo"
]
],
"version": 2
}

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