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

Compare commits

...

27 commits

Author SHA1 Message Date
John Ericson
d70f72412d WIP moving around the derivations options docs 2025-11-06 13:46:15 -05: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
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
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
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
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
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
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
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
61 changed files with 545 additions and 143 deletions

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

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

@ -15,6 +15,7 @@ schemas = [
'store-object-info-v1',
'derivation-v3',
'deriving-path-v1',
'build-trace-entry-v1',
]
schema_files = files()

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

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

@ -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,119 @@ 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])
## Output Checks
Additional checks for each output can also be mandated by the derivation,
supplementing the core required output specification above additional properties that must hold on the produced outputs for the derivation build to be considered successful.
**TODO No nix lang**
### Reference checks
The main checks assert properties about the [references][reference] of an output.
These checks vary on two different axes, yielding 4 possible checks.
The first axis is *direct* (references proper) vs *transitive* ([requisites]).
The first axis is *allowal* vs *disallowal*.
[reference]: @docroot@/glossary.md#gloss-reference
[requisites]: @docroot@/store/store-object.md#requisites
- [*allowed references*]{#allowed-references}: Set (store path or output name)
The outputs references must be a subset of this set.
Not every store path in the set must be a reference of the output,
but every reference of the output must be in this set.
For example, the empty set enforces that the output of a derivation cannot have any runtime dependencies on its inputs.
> **Usage note**
>
> This is used in NixOS to check that generated files such as initial ramdisks for booting Linux dont have accidental dependencies on other paths in the Nix store.
- [`allowedRequisites`]{#adv-attr-allowedRequisites}: Set (store paths or outputs name)
like
This attribute is similar to `allowedReferences`, but it specifies
the legal requisites of the whole closure, so all the dependencies
recursively. For example,
```nix
allowedRequisites = [ foobar ];
```
enforces that the output of a derivation cannot have any other
runtime dependency than `foobar`, and in addition it enforces that
`foobar` itself doesn't introduce any other dependency itself.
- [`disallowedReferences`]{#adv-attr-disallowedReferences}\
The optional attribute `disallowedReferences` specifies a list of
illegal references (dependencies) of the output of the builder. For
example,
```nix
disallowedReferences = [ foo ];
```
enforces that the output of a derivation cannot have a direct
runtime dependencies on the derivation `foo`.
https://en.wikipedia.org/wiki/Blacklist_(computing)
- [`disallowedRequisites`]{#adv-attr-disallowedRequisites}\
This attribute is similar to `disallowedReferences`, but it
specifies illegal requisites for the whole closure, so all the
dependencies recursively. For example,
```nix
disallowedRequisites = [ foobar ];
```
enforces that the output of a derivation cannot have any runtime
dependency on `foobar` or any other derivation depending recursively
on `foobar`.
The final references of the store object are always store paths.
However, if all elements of the sets above had to be store paths, it would be hard-to-impossible to write down the reference from outputs *to other outputs*, because in general we don't know outputs' store paths until they are built.
For this reason, it is also acceptable to use an output specification name (of the current derivation) instead of a store path.
To allow an output to have a runtime
dependency on itself, use `"out"` as a list item.
- [`outputChecks`]{#adv-attr-outputChecks}\
When using [structured attributes](#adv-attr-structuredAttrs), the `outputChecks`
attribute allows defining checks per-output.
In addition to
[`allowedReferences`](#adv-attr-allowedReferences), [`allowedRequisites`](#adv-attr-allowedRequisites),
[`disallowedReferences`](#adv-attr-disallowedReferences) and [`disallowedRequisites`](#adv-attr-disallowedRequisites),
the following attributes are available:
- `maxSize` defines the maximum size of the resulting [store object](@docroot@/store/store-object.md).
- `maxClosureSize` defines the maximum size of the output's closure.
- `ignoreSelfRefs` controls whether self-references should be considered when
checking for allowed references/requisites.
Example:
```nix
__structuredAttrs = true;
outputChecks.out = {
# The closure of 'out' must not be larger than 256 MiB.
maxClosureSize = 256 * 1024 * 1024;
# It must not refer to the C compiler or to the 'dev' output.
disallowedRequisites = [ stdenv.cc "dev" ];
};
outputChecks.dev = {
# The 'dev' output must not be larger than 128 KiB.
maxSize = 128 * 1024;
};
```
## 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/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

View file

@ -23,6 +23,7 @@ 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

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

@ -813,7 +813,7 @@ public:
[[gnu::always_inline]]
C * add(auto &&... args)
{
return new C(std::forward<decltype(args)>(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
@ -822,7 +822,7 @@ public:
C * add(const PosIdx & pos, Expr * fun, std::vector<Expr *> && args)
requires(std::same_as<C, ExprCall>)
{
return new C(pos, fun, std::move(args));
return alloc.new_object<C>(pos, fun, std::move(args));
}
template<class C>
@ -830,7 +830,7 @@ public:
C * add(const PosIdx & pos, Expr * fun, std::vector<Expr *> && args, PosIdx && cursedOrEndPos)
requires(std::same_as<C, ExprCall>)
{
return new C(pos, fun, std::move(args), std::move(cursedOrEndPos));
return alloc.new_object<C>(pos, fun, std::move(args), std::move(cursedOrEndPos));
}
template<class C>

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

@ -582,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
}
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");
path = store->toRealPath(storePath);
return {store->requireStoreObjectAccessor(storePath)};
} else {
return SourcePath{getFSSourceAccessor(), CanonPath{path}}.resolveSymlinks();
}
return Registry::read(settings, path, Registry::Global);
}(),
Registry::Global);
}();
return reg;

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

@ -286,7 +286,7 @@ Goal::Co DerivationBuildingGoal::tryToBuild()
PathSet lockFiles;
/* FIXME: Should lock something like the drv itself so we don't build same
CA drv concurrently */
if (dynamic_cast<LocalStore *>(&worker.store)) {
if (auto * localStore = dynamic_cast<LocalStore *>(&worker.store)) {
/* If we aren't a local store, we might need to use the local store as
a build remote, but that would cause a deadlock. */
/* FIXME: Make it so we can use ourselves as a build remote even if we
@ -296,9 +296,9 @@ Goal::Co DerivationBuildingGoal::tryToBuild()
*/
for (auto & i : drv->outputsAndOptPaths(worker.store)) {
if (i.second.second)
lockFiles.insert(worker.store.Store::toRealPath(*i.second.second));
lockFiles.insert(localStore->toRealPath(*i.second.second));
else
lockFiles.insert(worker.store.Store::toRealPath(drvPath) + "." + i.first);
lockFiles.insert(localStore->toRealPath(drvPath) + "." + i.first);
}
}
@ -331,12 +331,14 @@ Goal::Co DerivationBuildingGoal::tryToBuild()
/* If any of the outputs already exist but are not valid, delete
them. */
if (auto * localStore = dynamic_cast<LocalFSStore *>(&worker.store)) {
for (auto & [_, status] : initialOutputs) {
if (!status.known || status.known->isValid())
continue;
auto storePath = status.known->path;
debug("removing invalid path '%s'", worker.store.printStorePath(status.known->path));
deletePath(worker.store.Store::toRealPath(storePath));
deletePath(localStore->toRealPath(storePath));
}
}
/* Don't do a remote build if the derivation has the attribute

View file

@ -896,7 +896,7 @@ static void performOp(
auto path = WorkerProto::Serialise<StorePath>::read(*store, rconn);
logger->startWork();
logger->stopWork();
dumpPath(store->toRealPath(path), conn.to);
store->narFromPath(path, conn.to);
break;
}

View file

@ -189,7 +189,7 @@ public:
0,
"cores",
R"(
Sets the value of the `NIX_BUILD_CORES` environment variable in the [invocation of the `builder` executable](@docroot@/language/derivations.md#builder-execution) of a derivation.
Sets the value of the `NIX_BUILD_CORES` environment variable in the [invocation of the `builder` executable](@docroot@/store/building.md#builder-execution) of a derivation.
The `builder` executable can use this variable to control its own maximum amount of parallelism.
<!--

View file

@ -102,7 +102,12 @@ struct LocalFSStore : virtual Store, virtual GcStore, virtual LogStore
return config.realStoreDir;
}
Path toRealPath(const Path & storePath) override
Path toRealPath(const StorePath & storePath)
{
return toRealPath(printStorePath(storePath));
}
Path toRealPath(const Path & storePath)
{
assert(isInStore(storePath));
return getRealStoreDir() + "/" + std::string(storePath, storeDir.size() + 1);

View file

@ -54,7 +54,7 @@ private:
This is also the location where [`--keep-failed`](@docroot@/command-ref/opt-common.md#opt-keep-failed) leaves its files.
If Nix runs without sandbox, or if the platform does not support sandboxing with bind mounts (e.g. macOS), then the [`builder`](@docroot@/language/derivations.md#attr-builder)'s environment will contain this directory, instead of the virtual location [`sandbox-build-dir`](#conf-sandbox-build-dir).
If Nix runs without sandbox, or if the platform does not support sandboxing with bind mounts (e.g. macOS), then the [`builder`](@docroot@/language/derivations.md#attr-builder)'s environment will contain this directory, instead of the virtual location [`sandbox-build-dir`](@docroot@/command-ref/conf-file.md#conf-sandbox-build-dir).
> **Warning**
>

View file

@ -895,16 +895,6 @@ public:
*/
virtual std::optional<TrustedFlag> isTrustedClient() = 0;
virtual Path toRealPath(const Path & storePath)
{
return storePath;
}
Path toRealPath(const StorePath & storePath)
{
return toRealPath(printStorePath(storePath));
}
/**
* Synchronises the options of the client with those of the daemon
* (a no-op when theres no daemon)

View file

@ -246,7 +246,7 @@ void LocalOverlayStore::optimiseStore()
if (lowerStore->isValidPath(path)) {
uint64_t bytesFreed = 0;
// Deduplicate store path
deleteStorePath(Store::toRealPath(path), bytesFreed);
deleteStorePath(toRealPath(path), bytesFreed);
}
done++;
act.progress(done, paths.size());

View file

@ -1063,7 +1063,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, RepairF
PathLocks outputLock;
auto realPath = Store::toRealPath(info.path);
auto realPath = toRealPath(info.path);
/* Lock the output path. But don't lock if we're being called
from a build hook (whose parent process already acquired a
@ -1262,7 +1262,7 @@ StorePath LocalStore::addToStoreFromDump(
/* The first check above is an optimisation to prevent
unnecessary lock acquisition. */
auto realPath = Store::toRealPath(dstPath);
auto realPath = toRealPath(dstPath);
PathLocks outputLock({realPath});
@ -1413,7 +1413,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
auto hashSink = HashSink(info->narHash.algo);
dumpPath(Store::toRealPath(i), hashSink);
dumpPath(toRealPath(i), hashSink);
auto current = hashSink.finish();
if (info->narHash != nullHash && info->narHash != current.hash) {

View file

@ -58,7 +58,7 @@ struct ChrootDerivationBuilder : virtual DerivationBuilderImpl
environment using bind-mounts. We put it in the Nix store
so that the build outputs can be moved efficiently from the
chroot to their final location. */
auto chrootParentDir = store.Store::toRealPath(drvPath) + ".chroot";
auto chrootParentDir = store.toRealPath(drvPath) + ".chroot";
deletePath(chrootParentDir);
/* Clean up the chroot directory automatically. */
@ -171,7 +171,7 @@ struct ChrootDerivationBuilder : virtual DerivationBuilderImpl
continue;
if (buildMode != bmCheck && status.known->isValid())
continue;
auto p = store.Store::toRealPath(status.known->path);
auto p = store.toRealPath(status.known->path);
if (pathExists(chrootRootDir + p))
std::filesystem::rename((chrootRootDir + p), p);
}
@ -185,7 +185,7 @@ struct ChrootDerivationBuilder : virtual DerivationBuilderImpl
debug("materialising '%s' in the sandbox", store.printStorePath(path));
Path source = store.Store::toRealPath(path);
Path source = store.toRealPath(path);
Path target = chrootRootDir + store.printStorePath(path);
if (pathExists(target)) {

View file

@ -3,11 +3,33 @@
# include <spawn.h>
# include <sys/sysctl.h>
# include <sandbox.h>
# include <sys/ipc.h>
# include <sys/shm.h>
# include <sys/msg.h>
# include <sys/sem.h>
/* This definition is undocumented but depended upon by all major browsers. */
extern "C" int
sandbox_init_with_parameters(const char * profile, uint64_t flags, const char * const parameters[], char ** errorbuf);
/* Darwin IPC structures and constants */
# define IPCS_MAGIC 0x00000001
# define IPCS_SHM_ITER 0x00000002
# define IPCS_SEM_ITER 0x00000020
# define IPCS_MSG_ITER 0x00000200
# define IPCS_SHM_SYSCTL "kern.sysv.ipcs.shm"
# define IPCS_MSG_SYSCTL "kern.sysv.ipcs.msg"
# define IPCS_SEM_SYSCTL "kern.sysv.ipcs.sem"
struct IpcsCommand
{
uint32_t ipcs_magic;
uint32_t ipcs_op;
uint32_t ipcs_cursor;
uint32_t ipcs_datalen;
void * ipcs_data;
};
namespace nix {
struct DarwinDerivationBuilder : DerivationBuilderImpl
@ -204,6 +226,119 @@ struct DarwinDerivationBuilder : DerivationBuilderImpl
posix_spawn(
NULL, drv.builder.c_str(), NULL, &attrp, stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data());
}
/**
* Cleans up all System V IPC objects owned by the specified user.
*
* On Darwin, IPC objects (shared memory segments, message queues, and semaphore)
* can persist after the build user's processes are killed, since there are no IPC namespaces
* like on Linux. This can exhaust kernel IPC limits over time.
*
* Uses sysctl to enumerate and remove all IPC objects owned by the given UID.
*/
void cleanupSysVIPCForUser(uid_t uid)
{
struct IpcsCommand ic;
size_t ic_size = sizeof(ic);
// IPC ids to cleanup
std::vector<int> shm_ids, msg_ids, sem_ids;
{
struct shmid_ds shm_ds;
ic.ipcs_magic = IPCS_MAGIC;
ic.ipcs_op = IPCS_SHM_ITER;
ic.ipcs_cursor = 0;
ic.ipcs_data = &shm_ds;
ic.ipcs_datalen = sizeof(shm_ds);
while (true) {
memset(&shm_ds, 0, sizeof(shm_ds));
if (sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size) != 0) {
break;
}
if (shm_ds.shm_perm.uid == uid) {
int shmid = shmget(shm_ds.shm_perm._key, 0, 0);
if (shmid != -1) {
shm_ids.push_back(shmid);
}
}
}
}
for (auto id : shm_ids) {
if (shmctl(id, IPC_RMID, NULL) == 0)
debug("removed shared memory segment with shmid %d", id);
}
{
struct msqid_ds msg_ds;
ic.ipcs_magic = IPCS_MAGIC;
ic.ipcs_op = IPCS_MSG_ITER;
ic.ipcs_cursor = 0;
ic.ipcs_data = &msg_ds;
ic.ipcs_datalen = sizeof(msg_ds);
while (true) {
memset(&msg_ds, 0, sizeof(msg_ds));
if (sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size) != 0) {
break;
}
if (msg_ds.msg_perm.uid == uid) {
int msgid = msgget(msg_ds.msg_perm._key, 0);
if (msgid != -1) {
msg_ids.push_back(msgid);
}
}
}
}
for (auto id : msg_ids) {
if (msgctl(id, IPC_RMID, NULL) == 0)
debug("removed message queue with msgid %d", id);
}
{
struct semid_ds sem_ds;
ic.ipcs_magic = IPCS_MAGIC;
ic.ipcs_op = IPCS_SEM_ITER;
ic.ipcs_cursor = 0;
ic.ipcs_data = &sem_ds;
ic.ipcs_datalen = sizeof(sem_ds);
while (true) {
memset(&sem_ds, 0, sizeof(sem_ds));
if (sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size) != 0) {
break;
}
if (sem_ds.sem_perm.uid == uid) {
int semid = semget(sem_ds.sem_perm._key, 0, 0);
if (semid != -1) {
sem_ids.push_back(semid);
}
}
}
}
for (auto id : sem_ids) {
if (semctl(id, 0, IPC_RMID) == 0)
debug("removed semaphore with semid %d", id);
}
}
void killSandbox(bool getStats) override
{
DerivationBuilderImpl::killSandbox(getStats);
if (buildUser) {
auto uid = buildUser->getUID();
cleanupSysVIPCForUser(uid);
}
}
};
} // namespace nix

View file

@ -1887,7 +1887,7 @@ void DerivationBuilderImpl::cleanupBuild(bool force)
if (force) {
/* Delete unused redirected outputs (when doing hash rewriting). */
for (auto & i : redirectedOutputs)
deletePath(store.Store::toRealPath(i.second));
deletePath(store.toRealPath(i.second));
}
if (topTmpDir != "") {

View file

@ -269,7 +269,7 @@ constexpr std::array<ExperimentalFeatureDetails, numXpFeatures> xpFeatureDetails
.tag = Xp::LocalOverlayStore,
.name = "local-overlay-store",
.description = R"(
Allow the use of [local overlay store](@docroot@/command-ref/new-cli/nix3-help-stores.md#local-overlay-store).
Allow the use of [local overlay store](@docroot@/command-ref/new-cli/nix3-help-stores.md#experimental-local-overlay-store).
)",
.trackingUrl = "https://github.com/NixOS/nix/milestone/50",
},

View file

@ -793,8 +793,6 @@ struct CmdFlakeCheck : FlakeCommand
// via substitution, as `nix flake check` only needs to verify buildability,
// not actually produce the outputs.
auto missing = store->queryMissing(drvPaths);
// Only occurs if `drvPaths` contains a `DerivedPath::Opaque`, which should never happen
assert(missing.unknown.empty());
std::vector<DerivedPath> toBuild;
for (auto & path : missing.willBuild) {
@ -811,6 +809,8 @@ struct CmdFlakeCheck : FlakeCommand
if (hasErrors)
throw Error("some errors were encountered during the evaluation");
logger->log(lvlInfo, ANSI_GREEN "all checks passed!" ANSI_NORMAL);
if (!omittedSystems.empty()) {
// TODO: empty system is not visible; render all as nix strings?
warn(

View file

@ -187,7 +187,7 @@ Currently the `type` attribute can be one of the following:
* `nixpkgs/nixos-unstable/a3a3dda3bacf61e8a39258a0ed9c924eeca8e293`
* `sub/dir` (if a flake named `sub` is in the registry)
* <a name="path-fetcher"></a>`path`: arbitrary local directories. The required attribute `path`
* <a id="path-fetcher"></a>`path`: arbitrary local directories. The required attribute `path`
specifies the path of the flake. The URL form is
```

View file

@ -122,37 +122,33 @@ static void update(const StringSet & channelNames)
// got redirected in the process, so that we can grab the various parts of a nix channel
// definition from a consistent location if the redirect changes mid-download.
auto result = fetchers::downloadFile(store, fetchSettings, url, std::string(baseNameOf(url)));
auto filename = store->toRealPath(result.storePath);
url = result.effectiveUrl;
bool unpacked = false;
if (std::regex_search(filename, std::regex("\\.tar\\.(gz|bz2|xz)$"))) {
if (std::regex_search(std::string{result.storePath.to_string()}, std::regex("\\.tar\\.(gz|bz2|xz)$"))) {
runProgram(
getNixBin("nix-build").string(),
false,
{"--no-out-link",
"--expr",
"import " + unpackChannelPath + "{ name = \"" + cname + "\"; channelName = \"" + name
+ "\"; src = builtins.storePath \"" + filename + "\"; }"});
+ "\"; src = builtins.storePath \"" + store->printStorePath(result.storePath) + "\"; }"});
unpacked = true;
}
if (!unpacked) {
// Download the channel tarball.
try {
filename = store->toRealPath(
fetchers::downloadFile(store, fetchSettings, url + "/nixexprs.tar.xz", "nixexprs.tar.xz")
.storePath);
result = fetchers::downloadFile(store, fetchSettings, url + "/nixexprs.tar.xz", "nixexprs.tar.xz");
} catch (FileTransferError & e) {
filename = store->toRealPath(
fetchers::downloadFile(store, fetchSettings, url + "/nixexprs.tar.bz2", "nixexprs.tar.bz2")
.storePath);
result =
fetchers::downloadFile(store, fetchSettings, url + "/nixexprs.tar.bz2", "nixexprs.tar.bz2");
}
}
// Regardless of where it came from, add the expression representing this channel to accumulated expression
exprs.push_back(
"f: f { name = \"" + cname + "\"; channelName = \"" + name + "\"; src = builtins.storePath \""
+ filename + "\"; " + extraAttrs + " }");
+ store->printStorePath(result.storePath) + "\"; " + extraAttrs + " }");
}
}