Compare commits
1 Commits
master
...
factor-out
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f53a435cb |
11
.github/actions/install-nix-action/action.yaml
vendored
11
.github/actions/install-nix-action/action.yaml
vendored
@@ -24,8 +24,8 @@ inputs:
|
||||
description: "Github token"
|
||||
required: true
|
||||
use_cache:
|
||||
description: "Whether to setup github actions cache (not implemented currently)"
|
||||
default: false
|
||||
description: "Whether to setup magic-nix-cache"
|
||||
default: true
|
||||
required: false
|
||||
runs:
|
||||
using: "composite"
|
||||
@@ -122,3 +122,10 @@ runs:
|
||||
source-url: ${{ inputs.experimental-installer-version != 'latest' && 'https://artifacts.nixos.org/experimental-installer/tag/${{ inputs.experimental-installer-version }}/${{ env.EXPERIMENTAL_INSTALLER_ARTIFACT }}' || '' }}
|
||||
nix-package-url: ${{ inputs.dogfood == 'true' && steps.download-nix-installer.outputs.tarball-path || (inputs.tarball_url || '') }}
|
||||
extra-conf: ${{ inputs.extra_nix_config }}
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@565684385bcd71bad329742eefe8d12f2e765b39 # v13
|
||||
if: ${{ inputs.use_cache == 'true' }}
|
||||
with:
|
||||
diagnostic-endpoint: ''
|
||||
use-flakehub: false
|
||||
use-gha-cache: true
|
||||
source-revision: 92d9581367be2233c2d5714a2640e1339f4087d8 # main
|
||||
|
||||
37
.github/workflows/backport.yml
vendored
Normal file
37
.github/workflows/backport.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Backport
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [closed, labeled]
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
backport:
|
||||
name: Backport Pull Request
|
||||
permissions:
|
||||
# for korthout/backport-action
|
||||
contents: write
|
||||
pull-requests: write
|
||||
if: github.repository_owner == 'NixOS' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name))
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: ${{ vars.CI_APP_ID }}
|
||||
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
# required to find all branches
|
||||
fetch-depth: 0
|
||||
- name: Create backport PRs
|
||||
uses: korthout/backport-action@c656f5d5851037b2b38fb5db2691a03fa229e3b2 # v4.0.1
|
||||
id: backport
|
||||
with:
|
||||
# Config README: https://github.com/korthout/backport-action#backport-action
|
||||
github_token: ${{ steps.generate-token.outputs.token }}
|
||||
github_workspace: ${{ github.workspace }}
|
||||
auto_merge_enabled: true
|
||||
pull_description: |-
|
||||
Automatic backport to `${target_branch}`, triggered by a label in #${pull_number}.
|
||||
252
.github/workflows/ci.yml
vendored
Normal file
252
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
name: "CI"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dogfood:
|
||||
description: 'Use dogfood Nix build'
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
eval:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/install-nix-action
|
||||
with:
|
||||
dogfood: ${{ github.event_name == 'workflow_dispatch' && inputs.dogfood || github.event_name != 'workflow_dispatch' }}
|
||||
extra_nix_config:
|
||||
experimental-features = nix-command flakes
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
use_cache: false
|
||||
- run: nix flake show --all-systems --json
|
||||
|
||||
pre-commit-checks:
|
||||
name: pre-commit checks
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/install-nix-action
|
||||
with:
|
||||
dogfood: ${{ github.event_name == 'workflow_dispatch' && inputs.dogfood || github.event_name != 'workflow_dispatch' }}
|
||||
extra_nix_config: experimental-features = nix-command flakes
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- run: ./ci/gha/tests/pre-commit-checks
|
||||
|
||||
basic-checks:
|
||||
name: aggregate basic checks
|
||||
if: ${{ always() }}
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [pre-commit-checks, eval]
|
||||
steps:
|
||||
- name: Exit with any errors
|
||||
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
|
||||
run: |
|
||||
exit 1
|
||||
|
||||
tests:
|
||||
needs: basic-checks
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- scenario: on ubuntu
|
||||
runs-on: ubuntu-24.04
|
||||
os: linux
|
||||
instrumented: false
|
||||
primary: true
|
||||
stdenv: stdenv
|
||||
- scenario: on macos
|
||||
runs-on: macos-14
|
||||
os: darwin
|
||||
instrumented: false
|
||||
primary: true
|
||||
stdenv: stdenv
|
||||
- scenario: on ubuntu (with sanitizers / coverage)
|
||||
runs-on: ubuntu-24.04
|
||||
os: linux
|
||||
instrumented: true
|
||||
primary: false
|
||||
stdenv: clangStdenv
|
||||
name: tests ${{ matrix.scenario }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/install-nix-action
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
dogfood: ${{ github.event_name == 'workflow_dispatch' && inputs.dogfood || github.event_name != 'workflow_dispatch' }}
|
||||
# The sandbox would otherwise be disabled by default on Darwin
|
||||
extra_nix_config: "sandbox = true"
|
||||
# Since ubuntu 22.30, unprivileged usernamespaces are no longer allowed to map to the root user:
|
||||
# https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces
|
||||
- run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
||||
if: matrix.os == 'linux'
|
||||
- name: Run component tests
|
||||
run: |
|
||||
nix build --file ci/gha/tests/wrapper.nix componentTests -L \
|
||||
--arg withInstrumentation ${{ matrix.instrumented }} \
|
||||
--argstr stdenv "${{ matrix.stdenv }}"
|
||||
- name: Run VM tests
|
||||
run: |
|
||||
nix build --file ci/gha/tests/wrapper.nix vmTests -L \
|
||||
--arg withInstrumentation ${{ matrix.instrumented }} \
|
||||
--argstr stdenv "${{ matrix.stdenv }}"
|
||||
if: ${{ matrix.os == 'linux' }}
|
||||
- name: Run flake checks and prepare the installer tarball
|
||||
run: |
|
||||
ci/gha/tests/build-checks
|
||||
ci/gha/tests/prepare-installer-for-github-actions
|
||||
if: ${{ matrix.primary }}
|
||||
- name: Collect code coverage
|
||||
run: |
|
||||
nix build --file ci/gha/tests/wrapper.nix codeCoverage.coverageReports -L \
|
||||
--arg withInstrumentation ${{ matrix.instrumented }} \
|
||||
--argstr stdenv "${{ matrix.stdenv }}" \
|
||||
--out-link coverage-reports
|
||||
cat coverage-reports/index.txt >> $GITHUB_STEP_SUMMARY
|
||||
if: ${{ matrix.instrumented }}
|
||||
- name: Upload coverage reports
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: coverage-reports
|
||||
path: coverage-reports/
|
||||
if: ${{ matrix.instrumented }}
|
||||
- name: Upload installer tarball
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: installer-${{matrix.os}}
|
||||
path: out/*
|
||||
if: ${{ matrix.primary }}
|
||||
|
||||
installer_test:
|
||||
needs: [tests]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- scenario: on ubuntu
|
||||
runs-on: ubuntu-24.04
|
||||
os: linux
|
||||
experimental-installer: false
|
||||
- scenario: on macos
|
||||
runs-on: macos-14
|
||||
os: darwin
|
||||
experimental-installer: false
|
||||
- scenario: on ubuntu (experimental)
|
||||
runs-on: ubuntu-24.04
|
||||
os: linux
|
||||
experimental-installer: true
|
||||
- scenario: on macos (experimental)
|
||||
runs-on: macos-14
|
||||
os: darwin
|
||||
experimental-installer: true
|
||||
name: installer test ${{ matrix.scenario }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Download installer tarball
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||
with:
|
||||
name: installer-${{matrix.os}}
|
||||
path: out
|
||||
- name: Looking up the installer tarball URL
|
||||
id: installer-tarball-url
|
||||
run: |
|
||||
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@4e002c8ec80594ecd40e759629461e26c8abed15 # v31.9.0
|
||||
if: ${{ !matrix.experimental-installer }}
|
||||
with:
|
||||
install_url: ${{ format('{0}/install', steps.installer-tarball-url.outputs.installer-url) }}
|
||||
install_options: ${{ format('--tarball-url-prefix {0}', steps.installer-tarball-url.outputs.installer-url) }}
|
||||
- uses: ./.github/actions/install-nix-action
|
||||
if: ${{ matrix.experimental-installer }}
|
||||
with:
|
||||
dogfood: false
|
||||
experimental-installer: true
|
||||
tarball_url: ${{ steps.installer-tarball-url.outputs.tarball-path }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- run: sudo apt install fish zsh
|
||||
if: matrix.os == 'linux'
|
||||
- run: brew install fish
|
||||
if: matrix.os == 'darwin'
|
||||
- run: exec bash -c "nix-instantiate -E 'builtins.currentTime' --eval"
|
||||
- run: exec sh -c "nix-instantiate -E 'builtins.currentTime' --eval"
|
||||
- run: exec zsh -c "nix-instantiate -E 'builtins.currentTime' --eval"
|
||||
- run: exec fish -c "nix-instantiate -E 'builtins.currentTime' --eval"
|
||||
- run: exec bash -c "nix-channel --add https://releases.nixos.org/nixos/unstable/nixos-23.05pre466020.60c1d71f2ba nixpkgs"
|
||||
- run: exec bash -c "nix-channel --update && nix-env -iA nixpkgs.hello && hello"
|
||||
|
||||
flake_regressions:
|
||||
needs: tests
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout nix
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout flake-regressions
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: NixOS/flake-regressions
|
||||
path: flake-regressions
|
||||
- name: Checkout flake-regressions-data
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: NixOS/flake-regressions-data
|
||||
path: flake-regressions/tests
|
||||
- name: Download installer tarball
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||
with:
|
||||
name: installer-linux
|
||||
path: out
|
||||
- name: Looking up the installer tarball URL
|
||||
id: installer-tarball-url
|
||||
run: |
|
||||
echo "installer-url=file://$GITHUB_WORKSPACE/out" >> "$GITHUB_OUTPUT"
|
||||
- uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31.9.0
|
||||
with:
|
||||
install_url: ${{ format('{0}/install', steps.installer-tarball-url.outputs.installer-url) }}
|
||||
install_options: ${{ format('--tarball-url-prefix {0}', steps.installer-tarball-url.outputs.installer-url) }}
|
||||
- name: Run flake regressions tests
|
||||
run: MAX_FLAKES=25 flake-regressions/eval-all.sh
|
||||
|
||||
profile_build:
|
||||
needs: tests
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 60
|
||||
if: >-
|
||||
github.event_name == 'push' &&
|
||||
github.ref_name == 'master'
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/install-nix-action
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
dogfood: ${{ github.event_name == 'workflow_dispatch' && inputs.dogfood || github.event_name != 'workflow_dispatch' }}
|
||||
extra_nix_config: |
|
||||
experimental-features = flakes nix-command ca-derivations impure-derivations
|
||||
max-jobs = 1
|
||||
- run: |
|
||||
nix build -L --file ./ci/gha/profile-build buildTimeReport --out-link build-time-report.md
|
||||
cat build-time-report.md >> $GITHUB_STEP_SUMMARY
|
||||
24
.github/workflows/labels.yml
vendored
Normal file
24
.github/workflows/labels.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: "Label PR"
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [edited, opened, synchronize, reopened]
|
||||
|
||||
# WARNING:
|
||||
# When extending this action, be aware that $GITHUB_TOKEN allows some write
|
||||
# access to the GitHub API. This means that it should not evaluate user input in
|
||||
# a way that allows code injection.
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
labels:
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.repository_owner == 'NixOS'
|
||||
steps:
|
||||
- uses: actions/labeler@v6
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
sync-labels: false
|
||||
69
.github/workflows/upload-release.yml
vendored
Normal file
69
.github/workflows/upload-release.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: Upload Release
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
eval_id:
|
||||
description: "Hydra evaluation ID"
|
||||
required: true
|
||||
type: number
|
||||
is_latest:
|
||||
description: "Mark as latest release"
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-24.04
|
||||
environment: releases
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: ./.github/actions/install-nix-action
|
||||
with:
|
||||
dogfood: false # Use stable version
|
||||
use_cache: false # Don't want any cache injection shenanigans
|
||||
extra_nix_config: |
|
||||
experimental-features = nix-command flakes
|
||||
- name: Set NIX_PATH from flake input
|
||||
run: |
|
||||
NIXPKGS_PATH=$(nix build --inputs-from .# nixpkgs#path --print-out-paths --no-link)
|
||||
# Shebangs with perl have issues. Pin nixpkgs this way. nix shell should maybe
|
||||
# get the same uberhack that nix-shell has to support it.
|
||||
echo "NIX_PATH=nixpkgs=$NIXPKGS_PATH" >> "$GITHUB_ENV"
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1
|
||||
with:
|
||||
role-to-assume: "arn:aws:iam::080433136561:role/nix-release"
|
||||
role-session-name: nix-release-oidc-${{ github.run_id }}
|
||||
aws-region: eu-west-1
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload release
|
||||
run: |
|
||||
./maintainers/upload-release.pl \
|
||||
${{ inputs.eval_id }} \
|
||||
--skip-git
|
||||
env:
|
||||
IS_LATEST: ${{ inputs.is_latest && '1' || '' }}
|
||||
- name: Push to GHCR
|
||||
run: |
|
||||
DOCKER_OWNER="ghcr.io/$(echo '${{ github.repository_owner }}' | tr '[A-Z]' '[a-z]')/nix"
|
||||
./maintainers/upload-release.pl \
|
||||
${{ inputs.eval_id }} \
|
||||
--skip-git \
|
||||
--skip-s3 \
|
||||
--docker-owner "$DOCKER_OWNER"
|
||||
env:
|
||||
IS_LATEST: ${{ inputs.is_latest && '1' || '' }}
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,7 +1,5 @@
|
||||
# Default meson build dir
|
||||
/build
|
||||
# Meson creates this file too
|
||||
src/.wraplock
|
||||
|
||||
# /tests/functional/
|
||||
/tests/functional/common/subst-vars.sh
|
||||
@@ -16,10 +14,6 @@ src/.wraplock
|
||||
/tests/functional/lang/*.err
|
||||
/tests/functional/lang/*.ast
|
||||
|
||||
# /tests/functional/cli-characterisation/
|
||||
/tests/functional/cli-characterisation/*.out
|
||||
/tests/functional/cli-characterisation/*.err
|
||||
|
||||
/outputs
|
||||
|
||||
*~
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
nixFlake ? builtins.getFlake ("git+file://" + toString ../../..),
|
||||
system ? builtins.currentSystem,
|
||||
pkgs ? nixFlake.inputs.nixpkgs.legacyPackages.${system},
|
||||
}:
|
||||
|
||||
let
|
||||
packages = nixFlake.packages.${system};
|
||||
|
||||
fixOutput =
|
||||
test:
|
||||
test.overrideAttrs (prev: {
|
||||
nativeBuildInputs = prev.nativeBuildInputs or [ ] ++ [ pkgs.colorized-logs ];
|
||||
env.GTEST_COLOR = "no";
|
||||
# Wine's console emulation wraps every character in ANSI cursor
|
||||
# hide/show sequences, making logs unreadable in GitHub Actions.
|
||||
buildCommand = ''
|
||||
set -o pipefail
|
||||
{
|
||||
${prev.buildCommand}
|
||||
} 2>&1 | ansi2txt
|
||||
'';
|
||||
});
|
||||
in
|
||||
|
||||
{
|
||||
unitTests = {
|
||||
"nix-util-tests" = fixOutput packages."nix-util-tests-x86_64-w64-mingw32".passthru.tests.run;
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
callPackage,
|
||||
mkMesonDerivation,
|
||||
runCommand,
|
||||
@@ -94,11 +93,10 @@ mkMesonDerivation (finalAttrs: {
|
||||
mdbook
|
||||
json-schema-for-humans
|
||||
]
|
||||
++ lib.optionals (!officialRelease && buildHtmlManual && !stdenv.hostPlatform.isi686) [
|
||||
++ lib.optionals (!officialRelease && buildHtmlManual) [
|
||||
# When not an official release, we likely have changelog entries that have
|
||||
# yet to be rendered.
|
||||
# When released, these are rendered into a committed file to save a dependency.
|
||||
# Broken on i686.
|
||||
changelog-d
|
||||
];
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
---
|
||||
synopsis: "Rust nix-installer in beta"
|
||||
prs: []
|
||||
---
|
||||
|
||||
The Rust-based rewrite of the Nix installer is now in beta.
|
||||
We'd love help testing it out!
|
||||
|
||||
To test out the new installer, run:
|
||||
```
|
||||
curl -sSfL https://artifacts.nixos.org/nix-installer | sh -s -- install
|
||||
```
|
||||
|
||||
This installer can be run even when you have an existing, script-based Nix installation without any adjustments.
|
||||
|
||||
This new installer also comes with the ability to uninstall your Nix installation; run:
|
||||
```
|
||||
/nix/nix-installer uninstall
|
||||
```
|
||||
|
||||
This will get rid of your entire Nix installation (even if you installed over an existing, script-based installation).
|
||||
|
||||
This installer is a modified version of the [Determinate Nix Installer](https://github.com/DeterminateSystems/nix-installer) by Determinate Systems.
|
||||
Thanks to Determinate Systems for all the investment they've put into the installer.
|
||||
|
||||
Source for the installer is in https://github.com/NixOS/nix-installer.
|
||||
Report any issues in that repo.
|
||||
|
||||
For CI usage, a GitHub Action to install Nix using this installer is available at https://github.com/NixOS/nix-installer-action.
|
||||
@@ -1,81 +0,0 @@
|
||||
---
|
||||
synopsis: "Content-addressed derivations: realisations keyed by store path instead of hash modulo"
|
||||
issues: [11897]
|
||||
prs: [12464]
|
||||
---
|
||||
|
||||
The experimental content-addressed (CA) derivation feature has undergone a significant change to how build traces (formerly called "realisations") are identified. This affects the **binary cache protocol** and the **wire protocols**.
|
||||
|
||||
### What changed
|
||||
|
||||
Previously, a build trace entry (realisation) was keyed by the **hash modulo** of the derivation.
|
||||
A SHA-256 hash computed via the complex "derivation hash modulo" algorithm.
|
||||
This required implementations to understand ATerm serialisation and the full derivation hashing scheme just to look up or store build results.
|
||||
|
||||
Now, build trace entries are keyed by the **regular derivation store path** plus the output name. For example, instead of:
|
||||
|
||||
```
|
||||
sha256:ba7816bf8f01...!out
|
||||
```
|
||||
|
||||
The key is now:
|
||||
|
||||
```
|
||||
/nix/store/abc...-foo.drv^out
|
||||
```
|
||||
|
||||
This is simpler, more intuitive, and means that third-party tools implementing CA derivation support (e.g., Hydra)
|
||||
no longer need to implement the derivation hash modulo algorithm.
|
||||
|
||||
### Binary cache protocol
|
||||
|
||||
- The directory for build traces moved from `realisations/` to `build-trace-v2/`.
|
||||
- File paths changed from `realisations/<hash>!<output>.doi` to `build-trace-v2/<drvName>/<outputName>.doi`.
|
||||
- The JSON format of build trace entries is now split into `key` and `value` objects:
|
||||
```json
|
||||
{
|
||||
"key": {
|
||||
"drvPath": "abc...-foo.drv",
|
||||
"outputName": "out"
|
||||
},
|
||||
"value": {
|
||||
"outPath": "xyz...-foo",
|
||||
"signatures": [{ "keyName": "cache.example.com-1", "sig": "..." }]
|
||||
}
|
||||
}
|
||||
```
|
||||
Previously, these were flat objects with a string `id` field like `"sha256:...!out"`.
|
||||
- The deprecated `dependentRealisations` field has been removed.
|
||||
|
||||
Existing binary caches will need to be re-populated with the new format for CA derivation build traces.
|
||||
Old build traces at the previous URLs are simply abandoned.
|
||||
Non-CA builds are unaffected.
|
||||
|
||||
### Wire protocols
|
||||
|
||||
- **Worker protocol**:
|
||||
A new feature flag `realisation-with-path-not-hash` is negotiated during the handshake.
|
||||
Clients and daemons that both support this feature use the new binary serialisation for `DrvOutput`, `UnkeyedRealisation`, and related types.
|
||||
Fallback to older protocol versions gracefully degrades (realisations are unavailable).
|
||||
- **Serve protocol**:
|
||||
Bumped from 2.7 to 2.8 with native serialisers for the new types.
|
||||
Fallback to older protocol versions gracefully degrades in the same way.
|
||||
|
||||
Stable code paths do use the realization fields (`BuildResult::Success::builtOutputs`), but only the output name and outpath parts of that.
|
||||
For older protocols, we can fake enough of the realisation format to provide those two parts forthat map, which keeps operations like `--print-output-paths` working.
|
||||
|
||||
### Structured signatures
|
||||
|
||||
[Signatures](@docroot@/protocols/json/signature.md) in JSON formats are now represented as structured objects with `keyName` and `sig` fields, rather than colon-separated strings.
|
||||
`nix path-info --json --json-format 3` opts into the new version for this command.
|
||||
JSON parsing accepts both the old string format and new structured format for backwards compatibility.
|
||||
|
||||
### Impact
|
||||
|
||||
- **Non-CA derivation users**: No impact. This only affects the experimental `ca-derivations` feature.
|
||||
- **Binary cache operators**:
|
||||
Binary caches serving CA derivation build traces will need to be repopulated.
|
||||
Existing NARs and narinfo files are unaffected.
|
||||
- **Tool authors**:
|
||||
Implementations interfacing with the CA derivations protocol are simplified.
|
||||
The derivation hash modulo algorithm is no longer required to form build trace keys.
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
synopsis: "C API: Fix `EvalState` pointer passed to primop callbacks"
|
||||
prs: [15300, 15383]
|
||||
---
|
||||
|
||||
The `EvalState *` passed to C API primop callbacks was incorrectly pointing to
|
||||
the internal `nix::EvalState` rather than the C API wrapper struct. This caused
|
||||
a segfault when the callback used the pointer with C API functions such as
|
||||
`nix_alloc_value()`. The same issue affected `printValueAsJSON` and
|
||||
`printValueAsXML` callbacks on external values.
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
synopsis: GitHub fetcher now validates URL parameters
|
||||
prs: [15331]
|
||||
issues: [15304]
|
||||
---
|
||||
|
||||
The `github:` fetcher now validates URL parameters, and will error if an invalid parameter like `tag` is provided.
|
||||
@@ -125,7 +125,6 @@
|
||||
- [Hash](protocols/json/hash.md)
|
||||
- [Content Address](protocols/json/content-address.md)
|
||||
- [Store Path](protocols/json/store-path.md)
|
||||
- [Signature](protocols/json/signature.md)
|
||||
- [Store Object Info](protocols/json/store-object-info.md)
|
||||
- [Derivation](protocols/json/derivation/index.md)
|
||||
- [Derivation Options](protocols/json/derivation/options.md)
|
||||
@@ -136,9 +135,7 @@
|
||||
- [Serving Tarball Flakes](protocols/tarball-fetcher.md)
|
||||
- [Store Path Specification](protocols/store-path.md)
|
||||
- [Nix Archive (NAR) Format](protocols/nix-archive/index.md)
|
||||
- [Nix Cache Info Format](protocols/nix-cache-info.md)
|
||||
- [Derivation "ATerm" file format](protocols/derivation-aterm.md)
|
||||
- [Nix32 Encoding](protocols/nix32.md)
|
||||
- [C API](c-api.md)
|
||||
- [Glossary](glossary.md)
|
||||
- [Development](development/index.md)
|
||||
@@ -154,7 +151,6 @@
|
||||
- [Contributing](development/contributing.md)
|
||||
- [Releases](release-notes/index.md)
|
||||
{{#include ./SUMMARY-rl-next.md}}
|
||||
- [Release 2.34 (2026-02-27)](release-notes/rl-2.34.md)
|
||||
- [Release 2.33 (2025-12-09)](release-notes/rl-2.33.md)
|
||||
- [Release 2.32 (2025-10-06)](release-notes/rl-2.32.md)
|
||||
- [Release 2.31 (2025-08-21)](release-notes/rl-2.31.md)
|
||||
|
||||
@@ -57,6 +57,11 @@ Most Nix commands interpret the following environment variables:
|
||||
|
||||
Overrides the location of the Nix store (default `prefix/store`).
|
||||
|
||||
- <span id="env-NIX_DATA_DIR">[`NIX_DATA_DIR`](#env-NIX_DATA_DIR)</span>
|
||||
|
||||
Overrides the location of the Nix static data directory (default
|
||||
`prefix/share`).
|
||||
|
||||
- <span id="env-NIX_LOG_DIR">[`NIX_LOG_DIR`](#env-NIX_LOG_DIR)</span>
|
||||
|
||||
Overrides the location of the Nix log directory (default
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
This sandbox by default only allows reading from store objects specified as inputs, and only allows writing to designated [outputs][output] to be [captured as store objects](@docroot@/store/building.md#processing-outputs).
|
||||
|
||||
A derivation is typically specified as a [derivation expression] in the [Nix language], and [instantiated][instantiate] to a [store derivation].
|
||||
There are multiple ways of obtaining store objects from store derivations, collectively called [realisation][realise].
|
||||
There are multiple ways of obtaining store objects from store derivatons, collectively called [realisation][realise].
|
||||
|
||||
[derivation]: #gloss-derivation
|
||||
|
||||
|
||||
@@ -6,23 +6,14 @@ It is broken up into multiple Meson packages, which are optionally combined in a
|
||||
There are no mandatory extra steps to the building process:
|
||||
generic Meson installation instructions like [this](https://mesonbuild.com/Quick-guide.html#using-meson-as-a-distro-packager) should work.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/NixOS/nix.git
|
||||
cd nix
|
||||
meson setup build
|
||||
cd build
|
||||
ninja
|
||||
(sudo) ninja install
|
||||
```
|
||||
|
||||
The installation path can be specified by passing `-Dprefix=prefix`
|
||||
to `meson setup build`. The default installation directory is `/usr/local`. You
|
||||
The installation path can be specified by passing the `-Dprefix=prefix`
|
||||
to `configure`. The default installation directory is `/usr/local`. You
|
||||
can change this to any location you like. You must have write permission
|
||||
to the *prefix* path.
|
||||
|
||||
Nix keeps its *store* (the place where packages are stored) in
|
||||
`/nix/store` by default. This can be changed using
|
||||
`-Dlibstore:store-dir=path`.
|
||||
`-Dstore-dir=path`.
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
|
||||
@@ -16,29 +16,30 @@ If you are on Linux with systemd:
|
||||
sudo systemctl daemon-reload
|
||||
```
|
||||
|
||||
2. Remove files created by Nix:
|
||||
Remove files created by Nix:
|
||||
|
||||
```console
|
||||
sudo rm -rf /etc/nix /etc/profile.d/nix.sh /etc/tmpfiles.d/nix-daemon.conf /nix ~/.local/share/nix ~/.local/state/nix ~/.cache/nix ~/.nix-defexpr ~/.nix-profile ~/.nix-channels ~root/.nix-channels ~root/.nix-defexpr ~root/.nix-profile ~root/.cache/nix
|
||||
```
|
||||
```console
|
||||
sudo rm -rf /etc/nix /etc/profile.d/nix.sh /etc/tmpfiles.d/nix-daemon.conf /nix ~root/.nix-channels ~root/.nix-defexpr ~root/.nix-profile ~root/.cache/nix
|
||||
```
|
||||
|
||||
3. Remove build users and their group:
|
||||
Remove build users and their group:
|
||||
|
||||
```console
|
||||
for i in $(seq 1 32); do
|
||||
sudo userdel nixbld$i
|
||||
done
|
||||
sudo groupdel nixbld
|
||||
```
|
||||
```console
|
||||
for i in $(seq 1 32); do
|
||||
sudo userdel nixbld$i
|
||||
done
|
||||
sudo groupdel nixbld
|
||||
```
|
||||
|
||||
4. There may also be references to Nix in
|
||||
- `/etc/bash.bashrc`
|
||||
- `/etc/bashrc`
|
||||
- `/etc/profile`
|
||||
- `/etc/zsh/zshrc`
|
||||
- `/etc/zshrc`
|
||||
There may also be references to Nix in
|
||||
|
||||
which you may remove.
|
||||
- `/etc/bash.bashrc`
|
||||
- `/etc/bashrc`
|
||||
- `/etc/profile`
|
||||
- `/etc/zsh/zshrc`
|
||||
- `/etc/zshrc`
|
||||
|
||||
which you may remove.
|
||||
|
||||
### FreeBSD
|
||||
|
||||
@@ -53,7 +54,7 @@ If you are on Linux with systemd:
|
||||
2. Remove files created by Nix:
|
||||
|
||||
```console
|
||||
sudo rm -rf /etc/nix /usr/local/etc/profile.d/nix.sh /nix ~/.local/share/nix ~/.local/state/nix ~/.cache/nix ~/.nix-defexpr ~/.nix-profile ~/.nix-channels ~root/.nix-channels ~root/.nix-defexpr ~root/.nix-profile ~root/.cache/nix
|
||||
sudo rm -rf /etc/nix /usr/local/etc/profile.d/nix.sh /nix ~root/.nix-channels ~root/.nix-defexpr ~root/.nix-profile ~root/.cache/nix
|
||||
```
|
||||
|
||||
3. Remove build users and their group:
|
||||
@@ -153,7 +154,7 @@ If you are on Linux with systemd:
|
||||
6. Remove the files Nix added to your system, except for the store:
|
||||
|
||||
```console
|
||||
sudo rm -rf /etc/nix /var/root/.nix-profile /var/root/.nix-defexpr /var/root/.nix-channels ~/.nix-profile ~/.nix-defexpr ~/.nix-channels ~/.local/share/nix ~/.local/state/nix ~/.cache/nix
|
||||
sudo rm -rf /etc/nix /var/root/.nix-profile /var/root/.nix-defexpr /var/root/.nix-channels ~/.nix-profile ~/.nix-defexpr ~/.nix-channels
|
||||
```
|
||||
|
||||
|
||||
@@ -191,6 +192,6 @@ If you are on Linux with systemd:
|
||||
To remove a [single-user installation](./installing-binary.md#single-user-installation) of Nix, run:
|
||||
|
||||
```console
|
||||
rm -rf /nix ~/.nix-channels ~/.nix-defexpr ~/.nix-profile ~/.local/share/nix ~/.local/state/nix ~/.cache/nix
|
||||
rm -rf /nix ~/.nix-channels ~/.nix-defexpr ~/.nix-profile
|
||||
```
|
||||
You might also want to manually remove references to Nix from your `~/.profile`.
|
||||
|
||||
@@ -338,7 +338,7 @@ Here is more information on the `output*` attributes, and what values they may b
|
||||
This will specify the output hash of the single output of a [fixed-output derivation].
|
||||
|
||||
The `outputHash` attribute must be a string containing the hash in either hexadecimal or "nix32" encoding, or following the format for integrity metadata as defined by [SRI](https://www.w3.org/TR/SRI/).
|
||||
The ["nix32" encoding](@docroot@/protocols/nix32.md) is Nix's variant of base-32 encoding.
|
||||
The "nix32" encoding is an adaptation of base-32 encoding.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
|
||||
@@ -19,16 +19,17 @@ whatever port you like:
|
||||
$ nix-serve -p 8080
|
||||
```
|
||||
|
||||
To check whether it works, try fetching the [`nix-cache-info`](@docroot@/protocols/nix-cache-info.md) file on the client:
|
||||
To check whether it works, try the following on the client:
|
||||
|
||||
```console
|
||||
$ curl http://avalon:8080/nix-cache-info
|
||||
StoreDir: /nix/store
|
||||
WantMassQuery: 1
|
||||
Priority: 30
|
||||
```
|
||||
|
||||
When writing to a binary cache (e.g., with [`nix copy`](@docroot@/command-ref/new-cli/nix3-copy.md)), Nix creates [`nix-cache-info`](@docroot@/protocols/nix-cache-info.md) automatically if it doesn't exist.
|
||||
which should print something like:
|
||||
|
||||
StoreDir: /nix/store
|
||||
WantMassQuery: 1
|
||||
Priority: 30
|
||||
|
||||
On the client side, you can tell Nix to use your binary cache using
|
||||
`--substituters`, e.g.:
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
{{#include build-trace-entry-v3-fixed.md}}
|
||||
{{#include build-trace-entry-v2-fixed.md}}
|
||||
|
||||
## Examples
|
||||
|
||||
### Simple build trace entry
|
||||
|
||||
```json
|
||||
{{#include schema/build-trace-entry-v3/simple.json}}
|
||||
{{#include schema/build-trace-entry-v2/simple.json}}
|
||||
```
|
||||
|
||||
### Build trace entry with signature
|
||||
|
||||
```json
|
||||
{{#include schema/build-trace-entry-v3/with-structured-signature.json}}
|
||||
{{#include schema/build-trace-entry-v2/with-signature.json}}
|
||||
```
|
||||
|
||||
<!--
|
||||
## Raw Schema
|
||||
|
||||
[JSON Schema for Build Trace Entry v1](schema/build-trace-entry-v3.json)
|
||||
[JSON Schema for Build Trace Entry v1](schema/build-trace-entry-v2.json)
|
||||
-->
|
||||
|
||||
@@ -13,12 +13,11 @@ schemas = [
|
||||
'hash-v1',
|
||||
'content-address-v1',
|
||||
'store-path-v1',
|
||||
'signature-v2',
|
||||
'store-object-info-v3',
|
||||
'store-object-info-v2',
|
||||
'derivation-v4',
|
||||
'derivation-options-v1',
|
||||
'deriving-path-v1',
|
||||
'build-trace-entry-v3',
|
||||
'build-trace-entry-v2',
|
||||
'build-result-v1',
|
||||
'store-v1',
|
||||
]
|
||||
|
||||
@@ -83,7 +83,7 @@ properties:
|
||||
description: |
|
||||
A mapping from output names to their build trace entries.
|
||||
additionalProperties:
|
||||
"$ref": "build-trace-entry-v3.yaml#/$defs/value"
|
||||
"$ref": "build-trace-entry-v2.yaml"
|
||||
|
||||
failure:
|
||||
type: object
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"$schema": "http://json-schema.org/draft-04/schema"
|
||||
"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/build-trace-entry-v3.json"
|
||||
"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/build-trace-entry-v2.json"
|
||||
title: Build Trace Entry
|
||||
description: |
|
||||
A record of a successful build outcome for a specific derivation output.
|
||||
@@ -12,28 +12,28 @@ description: |
|
||||
> [**experimental**](@docroot@/development/experimental-features.md#xp-feature-ca-derivations)
|
||||
> and subject to change.
|
||||
|
||||
## Version History
|
||||
Verision history:
|
||||
|
||||
- Version 1: Original format
|
||||
|
||||
- Version 2:
|
||||
- Remove `dependentRealisations`
|
||||
|
||||
- Version 3:
|
||||
- Use `drvPath` not `drvHash` to refer to derivation in a more conventional way.
|
||||
- Separate into `key` and `value`
|
||||
- Use 2nd version of signatures format (objects, not strings)
|
||||
- Version 2: Remove `dependentRealisations`
|
||||
|
||||
type: object
|
||||
required:
|
||||
- key
|
||||
- value
|
||||
- id
|
||||
- outPath
|
||||
- signatures
|
||||
allOf:
|
||||
- "$ref": "#/$defs/key"
|
||||
- "$ref": "#/$defs/value"
|
||||
properties:
|
||||
key:
|
||||
"$ref": "#/$defs/key"
|
||||
value:
|
||||
"$ref": "#/$defs/value"
|
||||
additionalProperties: false
|
||||
id: {}
|
||||
outPath: {}
|
||||
signatures: {}
|
||||
additionalProperties:
|
||||
dependentRealisations:
|
||||
description: deprecated field
|
||||
type: object
|
||||
|
||||
"$defs":
|
||||
key:
|
||||
@@ -43,20 +43,23 @@ additionalProperties: false
|
||||
This is the "key" part, refering to a derivation and output.
|
||||
type: object
|
||||
required:
|
||||
- drvPath
|
||||
- outputName
|
||||
- id
|
||||
properties:
|
||||
drvPath:
|
||||
"$ref": "store-path-v1.yaml"
|
||||
title: Derivation Path
|
||||
description: |
|
||||
The store path of the derivation that was built.
|
||||
outputName:
|
||||
id:
|
||||
type: string
|
||||
title: Output Name
|
||||
title: Derivation Output ID
|
||||
pattern: "^sha256:[0-9a-f]{64}![a-zA-Z_][a-zA-Z0-9_-]*$"
|
||||
description: |
|
||||
Name of the specific output (e.g., "out", "dev", "doc")
|
||||
additionalProperties: false
|
||||
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"`
|
||||
|
||||
value:
|
||||
title: Build Trace Value
|
||||
@@ -74,10 +77,19 @@ additionalProperties: false
|
||||
description: |
|
||||
The path to the store object that resulted from building this derivation for the given output name.
|
||||
|
||||
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:
|
||||
"$ref": "signature-v2.yaml"
|
||||
type: string
|
||||
title: Signature
|
||||
description: A single cryptographic signature
|
||||
@@ -1 +1 @@
|
||||
../../../../../../src/libutil-tests/data/hash
|
||||
../../../../../../src/libutil-tests/data/hash/
|
||||
@@ -1 +0,0 @@
|
||||
../../../../../../src/libstore-tests/data/nar-info/json-3
|
||||
@@ -1,33 +0,0 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema"
|
||||
"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/signature-v2.json"
|
||||
title: Signature
|
||||
description: |
|
||||
A cryptographic signature along with the name of the key that produced it.
|
||||
|
||||
This schema describes the JSON representation of signatures as used in various Nix JSON APIs.
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> This JSON format is currently
|
||||
> [**experimental**](@docroot@/development/experimental-features.md#xp-feature-nix-command)
|
||||
> and subject to change.
|
||||
|
||||
## Version History
|
||||
|
||||
- Version 1: Colon-separated string in the format `<key-name>:<signature-in-Base64>`
|
||||
|
||||
- Version 2: Structured object with `keyName` and `sig` fields
|
||||
|
||||
type: object
|
||||
required:
|
||||
- keyName
|
||||
- sig
|
||||
properties:
|
||||
keyName:
|
||||
type: string
|
||||
title: Key Name
|
||||
description: The name of the key used to produce this signature
|
||||
sig:
|
||||
type: string
|
||||
title: Signature Data
|
||||
description: The raw signature bytes, Base64-encoded
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"keyName": "cache.nixos.org-1",
|
||||
"sig": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
}
|
||||
1
doc/manual/source/protocols/json/schema/store-object-info-v2
Symbolic link
1
doc/manual/source/protocols/json/schema/store-object-info-v2
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../../src/libstore-tests/data/path-info/json-2
|
||||
@@ -1,6 +1,6 @@
|
||||
"$schema": "http://json-schema.org/draft-04/schema"
|
||||
"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/store-object-info-v3.json"
|
||||
title: Store Object Info v3
|
||||
"$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).
|
||||
|
||||
@@ -50,10 +50,10 @@ $defs:
|
||||
properties:
|
||||
version:
|
||||
type: integer
|
||||
const: 3
|
||||
title: Format version (must be 3)
|
||||
const: 2
|
||||
title: Format version (must be 2)
|
||||
description: |
|
||||
Must be `3`.
|
||||
Must be `2`.
|
||||
This is a guard that allows us to continue evolving this format.
|
||||
Here is the rough version history:
|
||||
|
||||
@@ -63,8 +63,6 @@ $defs:
|
||||
|
||||
- Version 2: Use structured JSON type for `ca`
|
||||
|
||||
- Version 3: Use structured JSON type for `signatures`
|
||||
|
||||
path:
|
||||
"$ref": "./store-path-v1.yaml"
|
||||
title: Store Path
|
||||
@@ -176,7 +174,7 @@ $defs:
|
||||
|
||||
> This is an "impure" field that may not be included in certain contexts.
|
||||
items:
|
||||
"$ref": "./signature-v2.yaml"
|
||||
type: string
|
||||
|
||||
# Computed closure fields
|
||||
closureSize:
|
||||
@@ -1 +0,0 @@
|
||||
../../../../../../src/libstore-tests/data/path-info/json-3
|
||||
@@ -24,7 +24,7 @@ description: |
|
||||
|
||||
The format follows this pattern: `${digest}-${name}`
|
||||
|
||||
- **hash**: Digest rendered in [Nix32](@docroot@/protocols/nix32.md), a variant of base-32 (20 hash bytes become 32 ASCII characters)
|
||||
- **hash**: Digest rendered in a custom variant of [Base32](https://en.wikipedia.org/wiki/Base32) (20 arbitrary bytes become 32 ASCII characters)
|
||||
- **name**: The package name and optional version/suffix information
|
||||
|
||||
type: string
|
||||
|
||||
@@ -37,7 +37,7 @@ properties:
|
||||
- contents
|
||||
properties:
|
||||
info:
|
||||
"$ref": "./store-object-info-v3.yaml#/$defs/impure"
|
||||
"$ref": "./store-object-info-v2.yaml#/$defs/impure"
|
||||
title: Store Object Info
|
||||
description: |
|
||||
Metadata about the [store object](@docroot@/store/store-object.md) including hash, size, references, etc.
|
||||
@@ -70,7 +70,7 @@ properties:
|
||||
"^[A-Za-z0-9+/]{43}=$":
|
||||
type: object
|
||||
additionalProperties:
|
||||
"$ref": "./build-trace-entry-v3.yaml#/$defs/value"
|
||||
"$ref": "./build-trace-entry-v2.yaml#/$defs/value"
|
||||
additionalProperties: false
|
||||
|
||||
"$defs":
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{{#include signature-v2-fixed.md}}
|
||||
|
||||
## Examples
|
||||
|
||||
### Simple signature
|
||||
|
||||
```json
|
||||
{{#include schema/signature-v2/simple.json}}
|
||||
```
|
||||
@@ -1,45 +1,45 @@
|
||||
{{#include store-object-info-v3-fixed.md}}
|
||||
{{#include store-object-info-v2-fixed.md}}
|
||||
|
||||
## Examples
|
||||
|
||||
### Minimal store object (content-addressed)
|
||||
|
||||
```json
|
||||
{{#include schema/store-object-info-v3/pure.json}}
|
||||
{{#include schema/store-object-info-v2/pure.json}}
|
||||
```
|
||||
|
||||
### Store object with impure fields
|
||||
|
||||
```json
|
||||
{{#include schema/store-object-info-v3/impure.json}}
|
||||
{{#include schema/store-object-info-v2/impure.json}}
|
||||
```
|
||||
|
||||
### Minimal store object (empty)
|
||||
|
||||
```json
|
||||
{{#include schema/store-object-info-v3/empty_pure.json}}
|
||||
{{#include schema/store-object-info-v2/empty_pure.json}}
|
||||
```
|
||||
|
||||
### Store object with all impure fields
|
||||
|
||||
```json
|
||||
{{#include schema/store-object-info-v3/empty_impure.json}}
|
||||
{{#include schema/store-object-info-v2/empty_impure.json}}
|
||||
```
|
||||
|
||||
### NAR info (minimal)
|
||||
|
||||
```json
|
||||
{{#include schema/nar-info-v3/pure.json}}
|
||||
{{#include schema/nar-info-v2/pure.json}}
|
||||
```
|
||||
|
||||
### NAR info (with binary cache fields)
|
||||
|
||||
```json
|
||||
{{#include schema/nar-info-v3/impure.json}}
|
||||
{{#include schema/nar-info-v2/impure.json}}
|
||||
```
|
||||
|
||||
<!-- need to convert YAML to JSON first
|
||||
## Raw Schema
|
||||
|
||||
[JSON Schema for Store Object Info v1](schema/store-object-info-v3.json)
|
||||
[JSON Schema for Store Object Info v1](schema/store-object-info-v2.json)
|
||||
-->
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
# Nix Cache Info Format
|
||||
|
||||
The `nix-cache-info` file is a metadata file at the root of a [binary cache](@docroot@/package-management/binary-cache-substituter.md) (e.g., `https://cache.example.com/nix-cache-info`).
|
||||
|
||||
MIME type: `text/x-nix-cache-info`
|
||||
|
||||
## Format
|
||||
|
||||
Line-based key-value format:
|
||||
|
||||
```
|
||||
Key: value
|
||||
```
|
||||
|
||||
Leading and trailing whitespace is trimmed from values.
|
||||
Lines without a colon are ignored.
|
||||
Unknown keys are silently ignored.
|
||||
|
||||
## Fields
|
||||
|
||||
### `StoreDir`
|
||||
|
||||
The Nix store directory path that this cache was built for (e.g., `/nix/store`).
|
||||
|
||||
If present, Nix verifies that this matches the client's store directory:
|
||||
|
||||
```
|
||||
error: binary cache 'https://example.com' is for Nix stores with prefix '/nix/store', not '/home/user/nix/store'
|
||||
```
|
||||
|
||||
### `WantMassQuery`
|
||||
|
||||
`1` or `0`. Sets the default for [`want-mass-query`](@docroot@/store/types/http-binary-cache-store.md#store-http-binary-cache-store-want-mass-query).
|
||||
|
||||
### `Priority`
|
||||
|
||||
Integer. Sets the default for [`priority`](@docroot@/store/types/http-binary-cache-store.md#store-http-binary-cache-store-priority).
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
StoreDir: /nix/store
|
||||
WantMassQuery: 1
|
||||
Priority: 30
|
||||
```
|
||||
|
||||
## Caching Behavior
|
||||
|
||||
Nix caches `nix-cache-info` in the [cache directory](@docroot@/command-ref/env-common.md#env-NIX_CACHE_HOME) with a 7-day TTL.
|
||||
|
||||
## See Also
|
||||
|
||||
- [HTTP Binary Cache Store](@docroot@/store/types/http-binary-cache-store.md)
|
||||
- [Serving a Nix store via HTTP](@docroot@/package-management/binary-cache-substituter.md)
|
||||
- [`substituters`](@docroot@/command-ref/conf-file.md#conf-substituters)
|
||||
@@ -1,19 +0,0 @@
|
||||
# Nix32 Encoding
|
||||
|
||||
Nix32 is Nix's variant of base-32 encoding, used for [store path digests](@docroot@/protocols/store-path.md), hash output via [`nix hash`](@docroot@/command-ref/new-cli/nix3-hash.md), and the [`outputHash`](@docroot@/language/advanced-attributes.md#adv-attr-outputHash) derivation attribute.
|
||||
|
||||
## Alphabet
|
||||
|
||||
The Nix32 alphabet consists of these 32 characters:
|
||||
|
||||
```
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d f g h i j k l m n p q r s v w x y z
|
||||
```
|
||||
|
||||
The letters `e`, `o`, `u`, and `t` are omitted.
|
||||
|
||||
## Byte Order
|
||||
|
||||
Nix32 encoding processes the hash bytes from the end (last byte first), while base-16 encoding processes from the beginning (first byte first).
|
||||
|
||||
Consequently, the string sort order is determined primarily by the first bytes for base-16, and by the last bytes for Nix32.
|
||||
@@ -20,11 +20,12 @@ where
|
||||
|
||||
- `store-dir` = the [store directory](@docroot@/store/store-path.md#store-directory)
|
||||
|
||||
- `digest` = base-32 representation of the compressed to 160 bits [SHA-256] hash of `fingerprint`.
|
||||
- `digest` = base-32 representation of the compressed to 160 bits [SHA-256] hash of `fingerprint`
|
||||
|
||||
Nix uses a custom base-32 encoding called [Nix32](@docroot@/protocols/nix32.md).
|
||||
|
||||
For the definition of the hash compression algorithm, please refer to section 5.1 of the [Nix thesis](https://edolstra.github.io/pubs/phd-thesis.pdf).
|
||||
For the definition of the hash compression algorithm, please refer to the section 5.1 of
|
||||
the [Nix thesis](https://edolstra.github.io/pubs/phd-thesis.pdf), which also defines the
|
||||
specifics of base-32 encoding. Note that base-32 encoding processes the hash bytestring from
|
||||
the end, while base-16 processes in from the beginning.
|
||||
|
||||
## Fingerprint
|
||||
|
||||
|
||||
@@ -1,352 +0,0 @@
|
||||
# Release 2.34.0 (2026-02-27)
|
||||
|
||||
## Highlights
|
||||
|
||||
- Rust nix-installer in beta
|
||||
|
||||
The Rust-based rewrite of the Nix installer is now in beta.
|
||||
We'd love help testing it out!
|
||||
|
||||
To test out the new installer, run:
|
||||
```
|
||||
curl -sSfL https://artifacts.nixos.org/nix-installer | sh -s -- install
|
||||
```
|
||||
|
||||
This installer can be run even when you have an existing, script-based Nix installation without any adjustments.
|
||||
|
||||
This new installer also comes with the ability to uninstall your Nix installation; run:
|
||||
```
|
||||
/nix/nix-installer uninstall
|
||||
```
|
||||
|
||||
This will get rid of your entire Nix installation (even if you installed over an existing, script-based installation).
|
||||
|
||||
This installer is a modified version of the [Determinate Nix Installer](https://github.com/DeterminateSystems/nix-installer) by Determinate Systems.
|
||||
Thanks to Determinate Systems for all the investment they've put into the installer.
|
||||
|
||||
Source for the installer is in <https://github.com/NixOS/nix-installer>.
|
||||
Report any issues in that repo.
|
||||
|
||||
For CI usage, a GitHub Action to install Nix using this installer is available at <https://github.com/NixOS/nix-installer-action>.
|
||||
|
||||
- Stabilisation of `no-url-literals` experimental feature and new diagnostics infrastructure, with `lint-url-literals`, `lint-short-path-literals`, and `lint-absolute-path-literals` settings [#8738](https://github.com/NixOS/nix/issues/8738) [#10048](https://github.com/NixOS/nix/issues/10048) [#10281](https://github.com/NixOS/nix/issues/10281) [#15326](https://github.com/NixOS/nix/pull/15326)
|
||||
|
||||
Experimental feature `no-url-literals` has been stabilised and is now controlled by the `lint-url-literals` option.
|
||||
New diagnostics infrastructure has been added for linting discouraged language features.
|
||||
|
||||
### New lint infrastructure
|
||||
|
||||
#### [`lint-url-literals`](@docroot@/command-ref/conf-file.md#conf-lint-url-literals)
|
||||
|
||||
The `no-url-literals` experimental feature has been stabilised and replaced with a new [`lint-url-literals`](@docroot@/command-ref/conf-file.md#conf-lint-url-literals) setting.
|
||||
|
||||
To migrate from the experimental feature, replace:
|
||||
```
|
||||
experimental-features = no-url-literals
|
||||
```
|
||||
with:
|
||||
```
|
||||
lint-url-literals = fatal
|
||||
```
|
||||
|
||||
#### [`lint-short-path-literals`](@docroot@/command-ref/conf-file.md#conf-lint-short-path-literals)
|
||||
|
||||
The [`warn-short-path-literals`](@docroot@/command-ref/conf-file.md#conf-warn-short-path-literals) boolean setting has been deprecated and replaced with [`lint-short-path-literals`](@docroot@/command-ref/conf-file.md#conf-lint-short-path-literals).
|
||||
|
||||
To migrate, replace:
|
||||
```
|
||||
warn-short-path-literals = true
|
||||
```
|
||||
with:
|
||||
```
|
||||
lint-short-path-literals = warn
|
||||
```
|
||||
|
||||
#### [`lint-absolute-path-literals`](@docroot@/command-ref/conf-file.md#conf-lint-absolute-path-literals)
|
||||
|
||||
A new [`lint-absolute-path-literals`](@docroot@/command-ref/conf-file.md#conf-lint-absolute-path-literals) setting has been added to control handling of absolute path literals (paths starting with `/`) and home path literals (paths starting with `~/`).
|
||||
|
||||
#### Setting values
|
||||
|
||||
All three settings accept three values:
|
||||
- `ignore`: Allow the feature without emitting any diagnostic (default)
|
||||
- `warn`: Emit a warning when the feature is used
|
||||
- `fatal`: Treat the feature as a parse error
|
||||
|
||||
The defaults may change in future versions.
|
||||
|
||||
- Improved parser error messages [#15092](https://github.com/NixOS/nix/pull/15092)
|
||||
|
||||
Parser error messages now use legible strings for tokens instead of internal names. For example, malformed expression `a ++ ++ b` now produces the following error:
|
||||
```
|
||||
error: syntax error, unexpected '++'
|
||||
at «string»:1:6:
|
||||
1| a ++ ++ b
|
||||
| ^
|
||||
```
|
||||
|
||||
Instead of:
|
||||
```
|
||||
error: syntax error, unexpected CONCAT
|
||||
at «string»:1:6:
|
||||
1| a ++ ++ b
|
||||
| ^
|
||||
```
|
||||
|
||||
## New features
|
||||
|
||||
- `nix repl` now supports `inherit` and multiple bindings [#15082](https://github.com/NixOS/nix/pull/15082)
|
||||
|
||||
The `nix repl` now supports `inherit` statements and multiple bindings per line:
|
||||
|
||||
```
|
||||
nix-repl> a = { x = 1; y = 2; }
|
||||
nix-repl> inherit (a) x y
|
||||
nix-repl> x + y
|
||||
3
|
||||
|
||||
nix-repl> p = 1; q = 2;
|
||||
nix-repl> p + q
|
||||
3
|
||||
|
||||
nix-repl> foo.bar.baz = 1;
|
||||
nix-repl> foo.bar
|
||||
{ baz = 1; }
|
||||
```
|
||||
|
||||
- New command `nix store roots-daemon` for serving GC roots [#15143](https://github.com/NixOS/nix/pull/15143)
|
||||
|
||||
New command [`nix store roots-daemon`](@docroot@/command-ref/new-cli/nix3-store-roots-daemon.md) runs a daemon that serves garbage collector roots over a Unix domain socket.
|
||||
It enables the garbage collector to discover runtime roots when the main Nix daemon doesn't have `CAP_SYS_PTRACE` capability and therefore cannot scan `/proc`.
|
||||
|
||||
The garbage collector can be configured to use this daemon via the [`use-roots-daemon`](@docroot@/store/types/local-store.md#store-experimental-option-use-roots-daemon) store setting.
|
||||
|
||||
This feature requires the [`local-overlay-store` experimental feature](@docroot@/development/experimental-features.md#xp-feature-local-overlay-store).
|
||||
|
||||
- New command `nix-nswrapper` in `libexec` [#15183](https://github.com/NixOS/nix/pull/15183)
|
||||
|
||||
The new command `libexec/nix-nswrapper` is used to run the Nix daemon in an unprivileged user namespace on Linux. In order to use this command, build user UIDs and GIDs must be allocated in `/etc/subuid` and `/etc/subgid`.
|
||||
|
||||
It can be used to run the Nix daemon with full sandboxing without executing as root. Support has been added to Nixpkgs with the new `nix.daemonUser` and `nix.daemonGroup` settings.
|
||||
|
||||
- New setting `ignore-gc-delete-failure` for local stores [#15054](https://github.com/NixOS/nix/pull/15054)
|
||||
|
||||
A new local store setting [`ignore-gc-delete-failure`](@docroot@/store/types/local-store.md#store-local-store-ignore-gc-delete-failure) has been added.
|
||||
When enabled, garbage collection will log warnings instead of failing when it cannot delete store paths.
|
||||
This is useful when running Nix as an unprivileged user that may not have write access to all paths in the store.
|
||||
|
||||
This setting is experimental and requires the [`local-overlay-store`](@docroot@/development/experimental-features.md#xp-feature-local-overlay-store) experimental feature.
|
||||
|
||||
- New setting `narinfo-cache-meta-ttl` [#15287](https://github.com/NixOS/nix/pull/15287)
|
||||
|
||||
The new setting `narinfo-cache-meta-ttl` controls how long binary cache metadata (i.e. `/nix-cache-info`) is cached locally, in seconds. This was previously hard-coded to 7 days, which is still the default. As a result, you can now use `nix store info --refresh` to check whether a binary cache is still valid.
|
||||
|
||||
- Support HTTPS binary caches using mTLS (client certificate) authentication [#13002](https://github.com/NixOS/nix/issues/13002) [#13030](https://github.com/NixOS/nix/pull/13030)
|
||||
|
||||
Added support for `tls-certificate` and `tls-private-key` options in substituter URLs.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
https://substituter.invalid?tls-certificate=/path/to/cert.pem&tls-private-key=/path/to/key.pem
|
||||
```
|
||||
|
||||
When these options are configured, Nix will use this certificate/private key pair to authenticate to the server.
|
||||
|
||||
- `nix store gc --dry-run` and `nix-collect-garbage --dry-run` now report the number of paths that would be freed [#15229](https://github.com/NixOS/nix/pull/15229) [#5704](https://github.com/NixOS/nix/issues/5704)
|
||||
|
||||
## Performance improvements
|
||||
|
||||
- Unpacking tarballs to `~/.cache/nix/tarball-cache-v2` is now multithreaded [#12087](https://github.com/NixOS/nix/pull/12087)
|
||||
|
||||
Content-addressed cache for `builtins.fetchTarball` and tarball-based flake inputs (e.g. `github:NixOS/nixpkgs`, `https://channels.nixos.org/nixos-25.11/nixexprs.tar.xz`) now writes git blobs (files) to the `tarball-cache-v2` repository concurrently, which significantly reduces the wall time for tarball unpacking (up to ~1.8x faster unpacking for `https://channels.nixos.org/nixos-25.11/nixexprs.tar.xz` in our testing).
|
||||
|
||||
Currently, Nix doesn't perform any maintenance on the `~/.cache/nix/tarball-cache-v2` repository, which will be addressed in future versions. Users that wish to reclaim disk space used by the tarball cache may want to run:
|
||||
|
||||
```
|
||||
rm -rf ~/.cache/nix/tarball-cache # Historical tarball-cache, not used by Nix >= 2.33
|
||||
cd ~/.cache/nix/tarball-cache-v2 && git multi-pack-index write && git multi-pack-index repack && git multi-pack-index expire
|
||||
```
|
||||
|
||||
- `nix nar ls` and other NAR listing operations have been optimised further [#15163](https://github.com/NixOS/nix/pull/15163)
|
||||
|
||||
- Evaluator hot-path optimizations [#15270](https://github.com/NixOS/nix/pull/15270) [#15271](https://github.com/NixOS/nix/pull/15271)
|
||||
|
||||
## C API Changes
|
||||
|
||||
- New store API methods [#14766](https://github.com/NixOS/nix/pull/14766) [#14768](https://github.com/NixOS/nix/pull/14768)
|
||||
|
||||
The C API now includes additional methods:
|
||||
|
||||
- `nix_store_query_path_from_hash_part()` - Get the full store path given its hash part
|
||||
- `nix_store_copy_path()` - Copy a single store path between two stores, allows repairs and configuring signature checking
|
||||
|
||||
- Errors returned from your primops are not treated as recoverable by default [#13930](https://github.com/NixOS/nix/pull/13930) [#15286](https://github.com/NixOS/nix/pull/15286)
|
||||
|
||||
Nix 2.34 by default remembers the error in the thunk that triggered it.
|
||||
|
||||
Previously the following sequence of events worked:
|
||||
|
||||
1. Have a thunk that invokes a primop that's defined through the C API
|
||||
2. The primop returns an error
|
||||
3. Force the thunk again
|
||||
4. The primop returns a value
|
||||
5. The thunk evaluated successfully
|
||||
|
||||
**Resolution**
|
||||
|
||||
C API consumers that rely on this must change their recoverable error calls:
|
||||
|
||||
```diff
|
||||
-nix_set_err_msg(context, NIX_ERR_*, msg);
|
||||
+nix_set_err_msg(context, NIX_ERR_RECOVERABLE, msg);
|
||||
```
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Avoid dropping ssh connections with `ssh-ng://` stores for store path copying [#14998](https://github.com/NixOS/nix/pull/14998) [#6950](https://github.com/NixOS/nix/issues/6950)
|
||||
|
||||
Due to a bug in how Nix handled Boost.Coroutine2 suspension and resumption, copying from `ssh-ng://` stores would drop the SSH connection for each copied path. This issue has been fixed, which improves performance by avoiding multiple SSH/Nix Worker Protocol handshakes.
|
||||
|
||||
- S3 binary caches now use virtual-hosted-style addressing by default [#15208](https://github.com/NixOS/nix/issues/15208) [#15216](https://github.com/NixOS/nix/pull/15216)
|
||||
|
||||
S3 binary caches now use virtual-hosted-style URLs
|
||||
(`https://bucket.s3.region.amazonaws.com/key`) instead of path-style URLs
|
||||
(`https://s3.region.amazonaws.com/bucket/key`) when connecting to standard AWS
|
||||
S3 endpoints. This enables HTTP/2 multiplexing and fixes TCP connection
|
||||
exhaustion (TIME_WAIT socket accumulation) under high-concurrency workloads.
|
||||
|
||||
A new `addressing-style` store option controls this behavior:
|
||||
|
||||
- `auto` (default): virtual-hosted-style for standard AWS endpoints, path-style
|
||||
for custom endpoints.
|
||||
- `path`: forces path-style addressing (deprecated by AWS).
|
||||
- `virtual`: forces virtual-hosted-style addressing (bucket names must not
|
||||
contain dots).
|
||||
|
||||
Bucket names containing dots (e.g., `my.bucket.name`) automatically fall back
|
||||
to path-style addressing in `auto` mode, because dotted names create
|
||||
multi-level subdomains that break TLS wildcard certificate validation.
|
||||
|
||||
Example using path-style for backwards compatibility:
|
||||
|
||||
```
|
||||
s3://my-bucket/key?region=us-east-1&addressing-style=path
|
||||
```
|
||||
|
||||
Additionally, TCP keep-alive is now enabled on all HTTP connections, preventing
|
||||
idle connections from being silently dropped by intermediate network devices
|
||||
(NATs, firewalls, load balancers).
|
||||
|
||||
- `nix-prefetch-url --unpack` now properly checks for empty archives [#15242](https://github.com/NixOS/nix/pull/15242)
|
||||
|
||||
Prior versions failed to check for empty archives and would crash with a `nullptr` dereference when unpacking empty archives.
|
||||
This is now fixed.
|
||||
|
||||
- Prevent runaway processes when Nix is killed with `SIGKILL` when building in a local store with build users [#15193](https://github.com/NixOS/nix/pull/15193)
|
||||
|
||||
When run as root, Nix doesn't run builds via the daemon and is a parent of the forked build processes. Prior versions of Nix failed to preserve the `PR_SET_PDEATHSIG` parent-death signal across `setuid` calls. This could lead to build processes being reparented and continue running in the background. This has been fixed.
|
||||
|
||||
- Fix crash when interrupting `--log-format internal-json` [#15335](https://github.com/NixOS/nix/pull/15335)
|
||||
|
||||
Pressing Ctrl-C during `--log-format internal-json` (used by [nix-output-monitor](https://github.com/maralorn/nix-output-monitor)) no longer causes a spurious "Nix crashed. This is a bug." report.
|
||||
|
||||
- Fix percent-encoding in `file://` and `local://` store URIs [#15280](https://github.com/NixOS/nix/pull/15280)
|
||||
|
||||
Store URIs with special characters like `+` in the path (e.g. `file:///tmp/a+b`) no longer incorrectly create percent-encoded directories (e.g. `/tmp/a%2Bb`).
|
||||
|
||||
- Fix crash during tab completion in `nix repl` [#15255](https://github.com/NixOS/nix/pull/15255)
|
||||
|
||||
- Fix "Too many open files" on macOS [#15205](https://github.com/NixOS/nix/pull/15205)
|
||||
|
||||
Nix now raises the open file soft limit to the hard limit at startup, fixing "Too many open files" errors on macOS where the default soft limit is low.
|
||||
|
||||
- `nix develop` no longer fails when `inputs.nixpkgs` has `flake = false` [#15175](https://github.com/NixOS/nix/pull/15175)
|
||||
|
||||
- `builtins.flakeRefToString` no longer fails with "attribute is a thunk" [#15160](https://github.com/NixOS/nix/pull/15160)
|
||||
|
||||
- Fix `QueryPathInfo` throwing on invalid paths in the daemon [#15134](https://github.com/NixOS/nix/pull/15134)
|
||||
|
||||
- `nix-store --generate-binary-cache-key` now fsyncs key files to prevent corruption [#15107](https://github.com/NixOS/nix/pull/15107)
|
||||
|
||||
- Fix `build-hook` setting in `nix.conf` being ignored [#15083](https://github.com/NixOS/nix/pull/15083)
|
||||
|
||||
- Fix empty error messages when builds are cancelled due to a dependency failure [#14972](https://github.com/NixOS/nix/pull/14972)
|
||||
|
||||
When a build fails without `--keep-going`, other in-progress builds are cancelled. Previously, these cancelled builds were incorrectly reported as failed with empty error messages. This affected `buildPathsWithResults` callers such as `nix flake check`.
|
||||
|
||||
## Miscellaneous changes
|
||||
|
||||
- Content-Encoding decompression is now handled by libcurl [#14324](https://github.com/NixOS/nix/issues/14324) [#15336](https://github.com/NixOS/nix/pull/15336)
|
||||
|
||||
Transparent decompression of HTTP downloads specifying `Content-Encoding` header now uses libcurl. This adds support for previously advertised, but not supported `deflate` encoding as well as deprecated `x-gzip` alias.
|
||||
Non-standard `xz`, `bzip2` encodings that were previously advertised are no longer supported, as they do not commonly appear in the wild and should not be sent by compliant servers.
|
||||
|
||||
`br`, `zstd`, `gzip` continue to be supported. Distro packaging should ensure that the `libcurl` dependency is linked against required libraries to support these encodings. By default, the build system now requires libcurl >= 8.17.0, which is not known to have issues around [pausing and decompression](https://github.com/curl/curl/issues/16280).
|
||||
|
||||
- Static builds now support S3 features (`libstore:s3-aws-auth` meson option) [#15076](https://github.com/NixOS/nix/pull/15076)
|
||||
|
||||
- Improved package-related error messages [#15349](https://github.com/NixOS/nix/pull/15349)
|
||||
|
||||
Store path context is now rendered in the user-facing `hash^out` format instead of the internal `!out!hash` format.
|
||||
A misleading error message in `nix-env` that incorrectly blamed content-addressed derivations has been fixed.
|
||||
|
||||
- Improved error message for empty derivation files [#15298](https://github.com/NixOS/nix/pull/15298)
|
||||
|
||||
Parsing an empty `.drv` file (e.g. due to store corruption after an unclean shutdown) now produces a clear error message instead of the cryptic `expected string 'D'`.
|
||||
|
||||
- Relative `file:` paths for tarballs are now rejected with a clear error [#14983](https://github.com/NixOS/nix/pull/14983)
|
||||
|
||||
- Continued progress on the Windows port, including build fixes, CI improvements, and platform abstractions.
|
||||
|
||||
- Nix docker images are now uploaded to [GHCR](https://github.com/NixOS/nix/pkgs/container/nix) as part of the release process
|
||||
|
||||
Historically, only pre-release builds of `amd64` docker images have been uploaded to ghcr.io with the `latest` tag pointing to the last built image from `master` branch. This has been fixed and going forward, <https://github.com/NixOS/nix/pkgs/container/nix> will include the same images as <https://hub.docker.com/r/nixos/nix/> that are built by [Hydra](https://hydra.nixos.org/project/nix) for [arm64](https://hydra.nixos.org/job/nix/maintenance-2.34/dockerImage.aarch64-linux) and [amd64](https://hydra.nixos.org/job/nix/maintenance-2.34/dockerImage.x86_64-linux). Pre-release versions are no longer pushed to the registry.
|
||||
|
||||
## Contributors
|
||||
|
||||
This release was made possible by the following 43 contributors:
|
||||
|
||||
- Taeer Bar-Yam [**(@Radvendii)**](https://github.com/Radvendii)
|
||||
- Sergei Zimmerman [**(@xokdvium)**](https://github.com/xokdvium)
|
||||
- Jörg Thalheim [**(@Mic92)**](https://github.com/Mic92)
|
||||
- Graham Dennis [**(@GrahamDennis)**](https://github.com/GrahamDennis)
|
||||
- Damien Diederen [**(@ztzg)**](https://github.com/ztzg)
|
||||
- koberbe-jh [**(@koberbe-jh)**](https://github.com/koberbe-jh)
|
||||
- Robert Hensing [**(@roberth)**](https://github.com/roberth)
|
||||
- Bouke van der Bijl [**(@bouk)**](https://github.com/bouk)
|
||||
- Lisanna Dettwyler [**(@lisanna-dettwyler)**](https://github.com/lisanna-dettwyler)
|
||||
- kiara [**(@KiaraGrouwstra)**](https://github.com/KiaraGrouwstra)
|
||||
- Side Effect [**(@YawKar)**](https://github.com/YawKar)
|
||||
- dram [**(@dramforever)**](https://github.com/dramforever)
|
||||
- tomf [**(@tomfitzhenry)**](https://github.com/tomfitzhenry)
|
||||
- Kamil Monicz [**(@Zaczero)**](https://github.com/Zaczero)
|
||||
- Cosima Neidahl [**(@OPNA2608)**](https://github.com/OPNA2608)
|
||||
- Siddhant Kumar [**(@siddhantk232)**](https://github.com/siddhantk232)
|
||||
- Jens Petersen [**(@juhp)**](https://github.com/juhp)
|
||||
- Johannes Kirschbauer [**(@hsjobeki)**](https://github.com/hsjobeki)
|
||||
- tomberek [**(@tomberek)**](https://github.com/tomberek)
|
||||
- Eelco Dolstra [**(@edolstra)**](https://github.com/edolstra)
|
||||
- Artemis Tosini [**(@artemist)**](https://github.com/artemist)
|
||||
- David McFarland [**(@corngood)**](https://github.com/corngood)
|
||||
- Tucker Shea [**(@NoRePercussions)**](https://github.com/NoRePercussions)
|
||||
- Connor Baker [**(@ConnorBaker)**](https://github.com/ConnorBaker)
|
||||
- Cole Helbling [**(@cole-h)**](https://github.com/cole-h)
|
||||
- Eveeifyeve [**(@Eveeifyeve)**](https://github.com/Eveeifyeve)
|
||||
- John Ericson [**(@Ericson2314)**](https://github.com/Ericson2314)
|
||||
- Graham Christensen [**(@grahamc)**](https://github.com/grahamc)
|
||||
- Ilja [**(@iljah)**](https://github.com/iljah)
|
||||
- Pol Dellaiera [**(@drupol)**](https://github.com/drupol)
|
||||
- steelman [**(@steelman)**](https://github.com/steelman)
|
||||
- Brian McKenna [**(@puffnfresh)**](https://github.com/puffnfresh)
|
||||
- JustAGuyTryingHisBest [**(@JustAGuyTryingHisBest)**](https://github.com/JustAGuyTryingHisBest)
|
||||
- zowoq [**(@zowoq)**](https://github.com/zowoq)
|
||||
- Agustín Covarrubias [**(@agucova)**](https://github.com/agucova)
|
||||
- Sergei Trofimovich [**(@trofi)**](https://github.com/trofi)
|
||||
- Bernardo Meurer [**(@lovesegfault)**](https://github.com/lovesegfault)
|
||||
- Peter Bynum [**(@pkpbynum)**](https://github.com/pkpbynum)
|
||||
- Amaan Qureshi [**(@amaanq)**](https://github.com/amaanq)
|
||||
- Michael Hoang [**(@Enzime)**](https://github.com/Enzime)
|
||||
- Michael Daniels [**(@mdaniels5757)**](https://github.com/mdaniels5757)
|
||||
- Matthew Kenigsberg [**(@mkenigs)**](https://github.com/mkenigs)
|
||||
- Shea Levy [**(@shlevy)**](https://github.com/shlevy)
|
||||
@@ -31,7 +31,7 @@ A store path is rendered to a file system path as the concatenation of
|
||||
|
||||
- [Store directory](#store-directory) (typically `/nix/store`)
|
||||
- Path separator (`/`)
|
||||
- Digest rendered in [Nix32](@docroot@/protocols/nix32.md), a variant of base-32 (20 hash bytes become 32 ASCII characters)
|
||||
- Digest rendered in a custom variant of [Base32](https://en.wikipedia.org/wiki/Base32) (20 arbitrary bytes become 32 ASCII characters)
|
||||
- Hyphen (`-`)
|
||||
- Name
|
||||
|
||||
|
||||
@@ -358,6 +358,7 @@ dockerTools.buildLayeredImageWithNixDb {
|
||||
|
||||
extraCommands = ''
|
||||
rm -rf nix-support
|
||||
ln -s /nix/var/nix/profiles nix/var/nix/gcroots/profiles
|
||||
'';
|
||||
fakeRootCommands = ''
|
||||
chmod 1777 tmp
|
||||
|
||||
10
flake.lock
generated
10
flake.lock
generated
@@ -63,15 +63,15 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1771903837,
|
||||
"narHash": "sha256-jEA8WggGKtMFeNeCKq3NK8cLEjJmG6/RLUElYYbBZ0E=",
|
||||
"rev": "e764fc9a405871f1f6ca3d1394fb422e0a0c3951",
|
||||
"lastModified": 1763948260,
|
||||
"narHash": "sha256-zZk7fn2ARAqmLwaYTpxBJmj81KIdz11NiWt7ydHHD/M=",
|
||||
"rev": "1c8ba8d3f7634acac4a2094eef7c32ad9106532c",
|
||||
"type": "tarball",
|
||||
"url": "https://releases.nixos.org/nixos/25.11/nixos-25.11.6495.e764fc9a4058/nixexprs.tar.xz"
|
||||
"url": "https://releases.nixos.org/nixos/25.05/nixos-25.05.813095.1c8ba8d3f763/nixexprs.tar.xz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://channels.nixos.org/nixos-25.11/nixexprs.tar.xz"
|
||||
"url": "https://channels.nixos.org/nixos-25.05/nixexprs.tar.xz"
|
||||
}
|
||||
},
|
||||
"nixpkgs-23-11": {
|
||||
|
||||
52
flake.nix
52
flake.nix
@@ -1,7 +1,7 @@
|
||||
{
|
||||
description = "The purely functional package manager";
|
||||
|
||||
inputs.nixpkgs.url = "https://channels.nixos.org/nixos-25.11/nixexprs.tar.xz";
|
||||
inputs.nixpkgs.url = "https://channels.nixos.org/nixos-25.05/nixexprs.tar.xz";
|
||||
|
||||
inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
|
||||
inputs.nixpkgs-23-11.url = "github:NixOS/nixpkgs/a62e6edd6d5e1fa0329b8653c801147986f8d446";
|
||||
@@ -115,9 +115,6 @@
|
||||
}
|
||||
// lib.optionalAttrs (crossSystem == "x86_64-unknown-freebsd13") {
|
||||
useLLVM = true;
|
||||
}
|
||||
// lib.optionalAttrs (crossSystem == "x86_64-w64-mingw32") {
|
||||
emulator = pkgs: "${pkgs.buildPackages.wineWow64Packages.stable_11}/bin/wine";
|
||||
};
|
||||
overlays = [
|
||||
(overlayFor (pkgs: pkgs.${stdenv}))
|
||||
@@ -409,10 +406,6 @@
|
||||
|
||||
"nix-cmd" = { };
|
||||
|
||||
"nix-nswrapper" = {
|
||||
linuxOnly = true;
|
||||
};
|
||||
|
||||
"nix-cli" = { };
|
||||
|
||||
"nix-everything" = { };
|
||||
@@ -433,37 +426,32 @@
|
||||
pkgName:
|
||||
{
|
||||
supportsCross ? true,
|
||||
linuxOnly ? false,
|
||||
}:
|
||||
lib.optionalAttrs (linuxOnly -> nixpkgsFor.${system}.native.stdenv.hostPlatform.isLinux) (
|
||||
{
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}" = nixpkgsFor.${system}.native.nixComponents2.${pkgName};
|
||||
"${pkgName}-static" = nixpkgsFor.${system}.native.pkgsStatic.nixComponents2.${pkgName};
|
||||
"${pkgName}-llvm" = nixpkgsFor.${system}.native.pkgsLLVM.nixComponents2.${pkgName};
|
||||
}
|
||||
// flatMapAttrs (lib.genAttrs stdenvs (_: { })) (
|
||||
stdenvName:
|
||||
{ }:
|
||||
{
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}-${stdenvName}" =
|
||||
nixpkgsFor.${system}.nativeForStdenv.${stdenvName}.nixComponents2.${pkgName};
|
||||
}
|
||||
)
|
||||
)
|
||||
{
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}" = nixpkgsFor.${system}.native.nixComponents2.${pkgName};
|
||||
"${pkgName}-static" = nixpkgsFor.${system}.native.pkgsStatic.nixComponents2.${pkgName};
|
||||
"${pkgName}-llvm" = nixpkgsFor.${system}.native.pkgsLLVM.nixComponents2.${pkgName};
|
||||
}
|
||||
// lib.optionalAttrs supportsCross (
|
||||
flatMapAttrs (lib.genAttrs crossSystems (_: { })) (
|
||||
crossSystem:
|
||||
{ }:
|
||||
lib.optionalAttrs
|
||||
(linuxOnly -> nixpkgsFor.${system}.cross.${crossSystem}.stdenv.hostPlatform.isLinux)
|
||||
{
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}-${crossSystem}" = nixpkgsFor.${system}.cross.${crossSystem}.nixComponents2.${pkgName};
|
||||
}
|
||||
{
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}-${crossSystem}" = nixpkgsFor.${system}.cross.${crossSystem}.nixComponents2.${pkgName};
|
||||
}
|
||||
)
|
||||
)
|
||||
// flatMapAttrs (lib.genAttrs stdenvs (_: { })) (
|
||||
stdenvName:
|
||||
{ }:
|
||||
{
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}-${stdenvName}" =
|
||||
nixpkgsFor.${system}.nativeForStdenv.${stdenvName}.nixComponents2.${pkgName};
|
||||
}
|
||||
)
|
||||
)
|
||||
// lib.optionalAttrs (builtins.elem system linux64BitSystems) {
|
||||
dockerImage =
|
||||
|
||||
@@ -88,28 +88,16 @@
|
||||
''^tests/functional/lang/eval-fail-path-slash\.nix$''
|
||||
''^tests/functional/lang/eval-fail-toJSON-non-utf-8\.nix$''
|
||||
''^tests/functional/lang/eval-fail-set\.nix$''
|
||||
|
||||
# Language tests, don't churn the formatting of strings
|
||||
''^tests/functional/lang/eval-fail-fromTOML-overflow\.nix$''
|
||||
''^tests/functional/lang/eval-fail-fromTOML-underflow\.nix$''
|
||||
''^tests/functional/lang/eval-fail-bad-string-interpolation-3\.nix$''
|
||||
''^tests/functional/lang/eval-fail-bad-string-interpolation-4\.nix$''
|
||||
''^tests/functional/lang/eval-okay-regex-match2\.nix$''
|
||||
|
||||
# URL literal tests - nixfmt converts unquoted URLs to strings
|
||||
''^tests/functional/lang/eval-fail-url-literal\.nix$''
|
||||
''^tests/functional/lang/eval-okay-url-literal-warn\.nix$''
|
||||
''^tests/functional/lang/eval-okay-url-literal-default\.nix$''
|
||||
];
|
||||
};
|
||||
clang-format = {
|
||||
enable = true;
|
||||
# https://github.com/cachix/git-hooks.nix/pull/532
|
||||
package = pkgs.llvmPackages_21.clang-tools;
|
||||
package = pkgs.llvmPackages_latest.clang-tools;
|
||||
excludes = [
|
||||
# We don't want to format test data
|
||||
# ''tests/(?!nixos/).*\.nix''
|
||||
"^src/[^/]*-tests/data/.*$"
|
||||
''^src/[^/]*-tests/data/.*$''
|
||||
|
||||
# Don't format vendored code
|
||||
''^doc/manual/redirects\.js$''
|
||||
|
||||
@@ -24,10 +24,6 @@ subproject('libcmd')
|
||||
# Executables
|
||||
subproject('nix')
|
||||
|
||||
if host_machine.system() == 'linux'
|
||||
subproject('nswrapper')
|
||||
endif
|
||||
|
||||
# Docs
|
||||
if get_option('doc-gen')
|
||||
subproject('internal-api-docs')
|
||||
|
||||
@@ -11,7 +11,7 @@ ExecStart=@@bindir@/nix-daemon nix-daemon --daemon
|
||||
KillMode=process
|
||||
LimitNOFILE=1048576
|
||||
TasksMax=1048576
|
||||
Delegate=
|
||||
Delegate=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Clang gets grumpy about missing libasan symbols if -shared-libasan is not
|
||||
# passed when building shared libs, at least on Linux
|
||||
if cxx.get_id() == 'clang' and ('address' in get_option('b_sanitize') or 'undefined' in get_option(
|
||||
'b_sanitize',
|
||||
'b_sanitize',
|
||||
))
|
||||
add_project_link_arguments('-shared-libasan', language : 'cpp')
|
||||
endif
|
||||
|
||||
@@ -22,8 +22,6 @@ add_project_arguments(
|
||||
'-Werror=undef',
|
||||
'-Werror=unused-result',
|
||||
'-Werror=sign-compare',
|
||||
'-Werror=return-type',
|
||||
'-Werror=non-virtual-dtor',
|
||||
'-Wignored-qualifiers',
|
||||
'-Wimplicit-fallthrough',
|
||||
'-Wno-deprecated-declarations',
|
||||
@@ -33,13 +31,6 @@ add_project_arguments(
|
||||
# GCC doesn't benefit much from precompiled headers.
|
||||
do_pch = cxx.get_id() == 'clang'
|
||||
|
||||
if cxx.get_id() == 'gcc'
|
||||
add_project_arguments(
|
||||
'-Wno-interference-size', # Used for C++ ABI only. We don't provide any guarantees about different march tunings.
|
||||
language : 'cpp',
|
||||
)
|
||||
endif
|
||||
|
||||
# This is a clang-only option for improving build times.
|
||||
# It forces the instantiation of templates in the PCH itself and
|
||||
# not every translation unit it's included in.
|
||||
@@ -49,11 +40,6 @@ endif
|
||||
# instantiations in libutil and libstore.
|
||||
if cxx.get_id() == 'clang'
|
||||
add_project_arguments('-fpch-instantiate-templates', language : 'cpp')
|
||||
# Catch brace elision bugs: when WorkerProto::Version changed from `unsigned int`
|
||||
# to `struct { unsigned int major; uint8_t minor; }`, `.version = 16` silently
|
||||
# became `.version = {16, 0}` instead of failing, breaking protocol compatibility
|
||||
# in a subtle way
|
||||
add_project_arguments('-Werror=c99-designator', language : 'cpp')
|
||||
endif
|
||||
|
||||
# Detect if we're using libstdc++ (GCC's standard library)
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
{
|
||||
runCommand,
|
||||
stdenv,
|
||||
system,
|
||||
buildPackages,
|
||||
cacert,
|
||||
nix,
|
||||
nixComponents2,
|
||||
}:
|
||||
|
||||
let
|
||||
|
||||
inherit (stdenv.hostPlatform) system;
|
||||
|
||||
installerClosureInfo = buildPackages.closureInfo {
|
||||
rootPaths = [
|
||||
nix
|
||||
nixComponents2.nix-manual.man
|
||||
cacert
|
||||
];
|
||||
};
|
||||
@@ -46,7 +42,6 @@ runCommand "nix-binary-tarball-${version}" env ''
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${../scripts/install-multi-user.sh} $TMPDIR/install-multi-user \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by nix-manual ${nixComponents2.nix-manual.man} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
|
||||
if type -p shellcheck; then
|
||||
|
||||
@@ -155,14 +155,12 @@ let
|
||||
];
|
||||
};
|
||||
|
||||
mesonBuildLayer = finalAttrs: prevAttrs: rec {
|
||||
mesonBuildLayer = finalAttrs: prevAttrs: {
|
||||
nativeBuildInputs = prevAttrs.nativeBuildInputs or [ ] ++ [
|
||||
pkg-config
|
||||
];
|
||||
separateDebugInfo = !stdenv.hostPlatform.isStatic;
|
||||
# needed by separateDebugInfo
|
||||
# SEE: https://github.com/NixOS/nixpkgs/pull/394674/commits/a4d355342976e9e9823fb94f133bc43ebec9da5b
|
||||
__structuredAttrs = separateDebugInfo;
|
||||
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
|
||||
};
|
||||
|
||||
mesonLibraryLayer = finalAttrs: prevAttrs: {
|
||||
@@ -418,8 +416,6 @@ in
|
||||
|
||||
nix-cmd = callPackage ../src/libcmd/package.nix { };
|
||||
|
||||
nix-nswrapper = callPackage ../src/nswrapper/package.nix { };
|
||||
|
||||
/**
|
||||
The Nix command line interface. Note that this does not include its tests, whereas `nix-everything` does.
|
||||
*/
|
||||
|
||||
@@ -30,23 +30,33 @@ scope: {
|
||||
NIX_CFLAGS_COMPILE = "-DINITIAL_MARK_STACK_SIZE=1048576";
|
||||
});
|
||||
|
||||
curl =
|
||||
(pkgs.curl.override {
|
||||
http3Support = !pkgs.stdenv.hostPlatform.isWindows;
|
||||
# Make sure we enable all the dependencies for Content-Encoding/Transfer-Encoding decompression.
|
||||
zstdSupport = true;
|
||||
brotliSupport = true;
|
||||
zlibSupport = true;
|
||||
}).overrideAttrs
|
||||
{
|
||||
# TODO: Fix in nixpkgs. Static build with brotli is marked as broken, but it's not the case.
|
||||
# Remove once https://github.com/NixOS/nixpkgs/pull/494111 lands in the 25.11 channel.
|
||||
meta.broken = false;
|
||||
};
|
||||
lowdown = pkgs.lowdown.overrideAttrs (prevAttrs: rec {
|
||||
version = "2.0.2";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://kristaps.bsd.lv/lowdown/snapshots/lowdown-${version}.tar.gz";
|
||||
hash = "sha512-cfzhuF4EnGmLJf5EGSIbWqJItY3npbRSALm+GarZ7SMU7Hr1xw0gtBFMpOdi5PBar4TgtvbnG4oRPh+COINGlA==";
|
||||
};
|
||||
nativeBuildInputs = prevAttrs.nativeBuildInputs ++ [ pkgs.buildPackages.bmake ];
|
||||
postInstall =
|
||||
lib.replaceStrings [ "lowdown.so.1" "lowdown.1.dylib" ] [ "lowdown.so.2" "lowdown.2.dylib" ]
|
||||
(prevAttrs.postInstall or "");
|
||||
patches = [ ];
|
||||
});
|
||||
|
||||
libblake3 = pkgs.libblake3.override {
|
||||
useTBB = !(stdenv.hostPlatform.isWindows || stdenv.hostPlatform.isStatic);
|
||||
};
|
||||
# TODO: Remove this when https://github.com/NixOS/nixpkgs/pull/442682 is included in a stable release
|
||||
toml11 =
|
||||
if lib.versionAtLeast pkgs.toml11.version "4.4.0" then
|
||||
pkgs.toml11
|
||||
else
|
||||
pkgs.toml11.overrideAttrs rec {
|
||||
version = "4.4.0";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "ToruNiina";
|
||||
repo = "toml11";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-sgWKYxNT22nw376ttGsTdg0AMzOwp8QH3E8mx0BZJTQ=";
|
||||
};
|
||||
};
|
||||
|
||||
# TODO Hack until https://github.com/NixOS/nixpkgs/issues/45462 is fixed.
|
||||
boost =
|
||||
|
||||
@@ -131,7 +131,7 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
|
||||
ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags;
|
||||
|
||||
availableComponents = lib.filterAttrs (
|
||||
k: v: lib.meta.availableOn pkgs.stdenv.hostPlatform v
|
||||
k: v: lib.meta.availableOn pkgs.hostPlatform v
|
||||
) allComponents;
|
||||
|
||||
activeComponents = buildInputsClosureCond isInternal (
|
||||
@@ -300,7 +300,7 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
|
||||
lib.filter (x: !isInternal x) (
|
||||
lib.lists.concatMap (
|
||||
# Nix manual has a build-time dependency on nix, but we
|
||||
# don't want to do a native build just to enter the cross
|
||||
# don't want to do a native build just to enter the ross
|
||||
# dev shell.
|
||||
#
|
||||
# TODO: think of a more principled fix for this.
|
||||
@@ -323,7 +323,7 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
|
||||
pkgs.buildPackages.shellcheck
|
||||
pkgs.buildPackages.include-what-you-use
|
||||
]
|
||||
++ lib.optional stdenv.hostPlatform.isUnix pkgs.buildPackages.gdb
|
||||
++ lib.optional pkgs.hostPlatform.isUnix pkgs.buildPackages.gdb
|
||||
++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) (
|
||||
lib.hiPrio pkgs.buildPackages.clang-tools
|
||||
)
|
||||
@@ -341,7 +341,7 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
|
||||
|
||||
buildInputs =
|
||||
# TODO change Nixpkgs to mark gbenchmark as building on Windows
|
||||
lib.optional stdenv.hostPlatform.isUnix pkgs.gbenchmark
|
||||
lib.optional pkgs.hostPlatform.isUnix pkgs.gbenchmark
|
||||
++ dedupByString (v: "${v}") (
|
||||
lib.filter (x: !isInternal x) (lib.lists.concatMap (c: c.buildInputs) activeComponents)
|
||||
)
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
|
||||
nix-cmd,
|
||||
|
||||
nix-nswrapper,
|
||||
|
||||
nix-cli,
|
||||
|
||||
nix-functional-tests,
|
||||
@@ -173,9 +171,6 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
# Forwarded outputs
|
||||
ln -sT ${nix-manual} $doc
|
||||
ln -sT ${nix-manual.man} $man
|
||||
''
|
||||
+ lib.optionalString stdenv.isLinux ''
|
||||
lndir ${nix-nswrapper} $out
|
||||
'';
|
||||
|
||||
passthru = {
|
||||
|
||||
@@ -57,7 +57,6 @@ let
|
||||
"nix-flake"
|
||||
"nix-flake-c"
|
||||
"nix-flake-tests"
|
||||
"nix-nswrapper"
|
||||
"nix-main"
|
||||
"nix-main-c"
|
||||
"nix-cmd"
|
||||
@@ -115,11 +114,7 @@ rec {
|
||||
|
||||
# Binary package for various platforms.
|
||||
build = forAllPackages (
|
||||
pkgName:
|
||||
lib.filterAttrs (
|
||||
system: _do_not_touch:
|
||||
pkgName == "nix-nswrapper" -> nixpkgsFor.${system}.native.stdenv.hostPlatform.isLinux
|
||||
) (forAllSystems (system: nixpkgsFor.${system}.native.nixComponents2.${pkgName}))
|
||||
pkgName: forAllSystems (system: nixpkgsFor.${system}.native.nixComponents2.${pkgName})
|
||||
);
|
||||
|
||||
shellInputs = removeAttrs (forAllSystems (
|
||||
@@ -139,10 +134,6 @@ rec {
|
||||
(
|
||||
if pkgName == "nix-functional-tests" then
|
||||
lib.flip builtins.removeAttrs [ "x86_64-w64-mingw32" ]
|
||||
else if pkgName == "nix-nswrapper" then
|
||||
lib.filterAttrs (
|
||||
crossSystem: _do_not_touch: nixpkgsFor.x86_64-linux.cross.${crossSystem}.stdenv.hostPlatform.isLinux
|
||||
)
|
||||
else
|
||||
lib.id
|
||||
)
|
||||
@@ -179,13 +170,7 @@ rec {
|
||||
)
|
||||
);
|
||||
in
|
||||
forAllPackages (
|
||||
pkgName:
|
||||
lib.filterAttrs (
|
||||
system: _do_not_touch:
|
||||
pkgName == "nix-nswrapper" -> nixpkgsFor.${system}.native.stdenv.hostPlatform.isLinux
|
||||
) (forAllSystems (system: components.${system}.${pkgName}))
|
||||
);
|
||||
forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName}));
|
||||
|
||||
buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents2.nix-cli);
|
||||
|
||||
@@ -205,13 +190,7 @@ rec {
|
||||
)
|
||||
);
|
||||
in
|
||||
forAllPackages (
|
||||
pkgName:
|
||||
lib.filterAttrs (
|
||||
system: _do_not_touch:
|
||||
pkgName == "nix-nswrapper" -> nixpkgsFor.${system}.native.stdenv.hostPlatform.isLinux
|
||||
) (forAllSystems (system: components.${system}.${pkgName}))
|
||||
);
|
||||
forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName}));
|
||||
|
||||
# Perl bindings for various platforms.
|
||||
perlBindings = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents2.nix-perl-bindings);
|
||||
|
||||
@@ -52,7 +52,6 @@ readonly PROFILE_FISH_PREFIXES=(
|
||||
readonly PROFILE_NIX_FILE_FISH="$NIX_ROOT/var/nix/profiles/default/etc/profile.d/nix-daemon.fish"
|
||||
|
||||
readonly NIX_INSTALLED_NIX="@nix@"
|
||||
readonly NIX_INSTALLED_NIX_MAN="@nix-manual@"
|
||||
readonly NIX_INSTALLED_CACERT="@cacert@"
|
||||
#readonly NIX_INSTALLED_NIX="/nix/store/byi37zv50wnfrpp4d81z3spswd5zva37-nix-2.3.6"
|
||||
#readonly NIX_INSTALLED_CACERT="/nix/store/7pi45g541xa8ahwgpbpy7ggsl0xj1jj6-nss-cacert-3.49.2"
|
||||
@@ -970,8 +969,6 @@ setup_default_profile() {
|
||||
task "Setting up the default profile"
|
||||
_sudo "to install a bootstrapping Nix in to the default profile" \
|
||||
HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_NIX"
|
||||
_sudo "to install Nix man pages in to the default profile" \
|
||||
HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_NIX_MAN"
|
||||
|
||||
if [ -z "${NIX_SSL_CERT_FILE:-}" ] || ! [ -f "${NIX_SSL_CERT_FILE:-}" ] || cert_in_store; then
|
||||
_sudo "to install a bootstrapping SSL certificate just for Nix in to the default profile" \
|
||||
|
||||
@@ -38,7 +38,6 @@ escape_systemd_env() {
|
||||
create_systemd_proxy_env() {
|
||||
vars="http_proxy https_proxy ftp_proxy all_proxy no_proxy HTTP_PROXY HTTPS_PROXY FTP_PROXY ALL_PROXY NO_PROXY"
|
||||
for v in $vars; do
|
||||
# shellcheck disable=SC2268
|
||||
if [ "x${!v:-}" != "x" ]; then
|
||||
echo "Environment=${v}=$(escape_systemd_env "${!v}")"
|
||||
fi
|
||||
|
||||
@@ -1 +1 @@
|
||||
../libstore-tests/data/build-result
|
||||
../../src/libstore-tests/data/build-result
|
||||
@@ -1 +1 @@
|
||||
../libstore-tests/data/realisation
|
||||
../../src/libstore-tests/data/realisation
|
||||
@@ -1 +1 @@
|
||||
../libstore-tests/data/content-address
|
||||
../../src/libstore-tests/data/content-address
|
||||
@@ -1 +1 @@
|
||||
../libstore-tests/data/derivation
|
||||
../../src/libstore-tests/data/derivation
|
||||
@@ -1 +1 @@
|
||||
../libstore-tests/data/derived-path
|
||||
../../src/libstore-tests/data/derived-path
|
||||
@@ -1 +1 @@
|
||||
../libutil-tests/data/memory-source-accessor
|
||||
../../src/libutil-tests/data/memory-source-accessor
|
||||
@@ -1 +1 @@
|
||||
../libutil-tests/data/hash
|
||||
../../src/libutil-tests/data/hash
|
||||
@@ -51,13 +51,6 @@ schemas = [
|
||||
'simple.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
'stem' : 'signature',
|
||||
'schema' : schema_dir / 'signature-v2.yaml',
|
||||
'files' : [
|
||||
'simple.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
'stem' : 'deriving-path',
|
||||
'schema' : schema_dir / 'deriving-path-v1.yaml',
|
||||
@@ -69,10 +62,13 @@ schemas = [
|
||||
},
|
||||
{
|
||||
'stem' : 'build-trace-entry',
|
||||
'schema' : schema_dir / 'build-trace-entry-v3.yaml',
|
||||
'schema' : schema_dir / 'build-trace-entry-v2.yaml',
|
||||
'files' : [
|
||||
'simple.json',
|
||||
'with-structured-signature.json',
|
||||
# The field is no longer supported, but we want to show that we
|
||||
# ignore it during parsing.
|
||||
'with-dependent-realisations.json',
|
||||
'with-signature.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -158,20 +154,20 @@ schemas += [
|
||||
# Match overall
|
||||
{
|
||||
'stem' : 'store-object-info',
|
||||
'schema' : schema_dir / 'store-object-info-v3.yaml',
|
||||
'schema' : schema_dir / 'store-object-info-v2.yaml',
|
||||
'files' : [
|
||||
'json-3' / 'pure.json',
|
||||
'json-3' / 'impure.json',
|
||||
'json-3' / 'empty_pure.json',
|
||||
'json-3' / 'empty_impure.json',
|
||||
'json-2' / 'pure.json',
|
||||
'json-2' / 'impure.json',
|
||||
'json-2' / 'empty_pure.json',
|
||||
'json-2' / 'empty_impure.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
'stem' : 'nar-info',
|
||||
'schema' : schema_dir / 'store-object-info-v3.yaml',
|
||||
'schema' : schema_dir / 'store-object-info-v2.yaml',
|
||||
'files' : [
|
||||
'json-3' / 'pure.json',
|
||||
'json-3' / 'impure.json',
|
||||
'json-2' / 'pure.json',
|
||||
'json-2' / 'impure.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -186,32 +182,32 @@ schemas += [
|
||||
# Match exact variant
|
||||
{
|
||||
'stem' : 'store-object-info',
|
||||
'schema' : schema_dir / 'store-object-info-v3.yaml#/$defs/base',
|
||||
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/base',
|
||||
'files' : [
|
||||
'json-3' / 'pure.json',
|
||||
'json-3' / 'empty_pure.json',
|
||||
'json-2' / 'pure.json',
|
||||
'json-2' / 'empty_pure.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
'stem' : 'store-object-info',
|
||||
'schema' : schema_dir / 'store-object-info-v3.yaml#/$defs/impure',
|
||||
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/impure',
|
||||
'files' : [
|
||||
'json-3' / 'impure.json',
|
||||
'json-3' / 'empty_impure.json',
|
||||
'json-2' / 'impure.json',
|
||||
'json-2' / 'empty_impure.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
'stem' : 'nar-info',
|
||||
'schema' : schema_dir / 'store-object-info-v3.yaml#/$defs/base',
|
||||
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/base',
|
||||
'files' : [
|
||||
'json-3' / 'pure.json',
|
||||
'json-2' / 'pure.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
'stem' : 'nar-info',
|
||||
'schema' : schema_dir / 'store-object-info-v3.yaml#/$defs/narInfo',
|
||||
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/narInfo',
|
||||
'files' : [
|
||||
'json-3' / 'impure.json',
|
||||
'json-2' / 'impure.json',
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
@@ -1 +1 @@
|
||||
../libstore-tests/data/nar-info
|
||||
../../src/libstore-tests/data/nar-info
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"keyName": "cache.nixos.org-1",
|
||||
"sig": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
../libstore-tests/data/dummy-store
|
||||
../../src/libstore-tests/data/dummy-store
|
||||
@@ -1 +1 @@
|
||||
../libstore-tests/data/path-info
|
||||
../../src/libstore-tests/data/path-info
|
||||
@@ -1 +1 @@
|
||||
../libstore-tests/data/store-path
|
||||
../../src/libstore-tests/data/store-path
|
||||
@@ -108,16 +108,20 @@ RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const
|
||||
overloaded{
|
||||
[&](const BuiltPath::Opaque & p) { res.insert(p.path); },
|
||||
[&](const BuiltPath::Built & p) {
|
||||
auto drvHashes = staticOutputHashes(store, store.readDerivation(p.drvPath->outPath()));
|
||||
for (auto & [outputName, outputPath] : p.outputs) {
|
||||
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) {
|
||||
DrvOutput key{
|
||||
.drvPath = p.drvPath->outPath(),
|
||||
.outputName = outputName,
|
||||
};
|
||||
auto drvOutput = get(drvHashes, outputName);
|
||||
if (!drvOutput)
|
||||
throw Error(
|
||||
"the derivation '%s' has unrealised output '%s' (derived-path.cc/toRealisedPaths)",
|
||||
store.printStorePath(p.drvPath->outPath()),
|
||||
outputName);
|
||||
DrvOutput key{*drvOutput, outputName};
|
||||
auto thisRealisation = store.queryRealisation(key);
|
||||
// We’ve built it, so we must have the realisation.
|
||||
assert(thisRealisation);
|
||||
res.insert(Realisation{*thisRealisation, key});
|
||||
assert(thisRealisation); // We’ve built it, so we must
|
||||
// have the realisation
|
||||
res.insert(Realisation{*thisRealisation, std::move(key)});
|
||||
} else {
|
||||
res.insert(outputPath);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "nix/cmd/command.hh"
|
||||
#include "nix/cmd/legacy.hh"
|
||||
#include "nix/cmd/markdown.hh"
|
||||
#include "nix/store/globals.hh"
|
||||
#include "nix/store/store-open.hh"
|
||||
#include "nix/store/local-fs-store.hh"
|
||||
#include "nix/store/derivations.hh"
|
||||
@@ -64,25 +63,6 @@ void NixMultiCommand::run()
|
||||
command->second->run();
|
||||
}
|
||||
|
||||
StoreConfigCommand::StoreConfigCommand() {}
|
||||
|
||||
ref<StoreConfig> StoreConfigCommand::getStoreConfig()
|
||||
{
|
||||
if (!_storeConfig)
|
||||
_storeConfig = createStoreConfig();
|
||||
return ref<StoreConfig>(_storeConfig);
|
||||
}
|
||||
|
||||
ref<StoreConfig> StoreConfigCommand::createStoreConfig()
|
||||
{
|
||||
return resolveStoreConfig(StoreReference{settings.storeUri.get()});
|
||||
}
|
||||
|
||||
void StoreConfigCommand::run()
|
||||
{
|
||||
run(getStoreConfig());
|
||||
}
|
||||
|
||||
StoreCommand::StoreCommand() {}
|
||||
|
||||
ref<Store> StoreCommand::getStore()
|
||||
@@ -94,20 +74,12 @@ ref<Store> StoreCommand::getStore()
|
||||
|
||||
ref<Store> StoreCommand::createStore()
|
||||
{
|
||||
auto store = getStoreConfig()->openStore();
|
||||
store->init();
|
||||
return store;
|
||||
return openStore();
|
||||
}
|
||||
|
||||
void StoreCommand::run(ref<StoreConfig> storeConfig)
|
||||
void StoreCommand::run()
|
||||
{
|
||||
// We can either efficiently implement getStore/createStore with memoization,
|
||||
// or use the StoreConfig passed in run.
|
||||
// It's more efficient to memoize, especially since there are some direct users
|
||||
// of getStore. The StoreConfig in both cases should be the same, though.
|
||||
auto store = getStore();
|
||||
assert(&*storeConfig == &store->config);
|
||||
run(std::move(store));
|
||||
run(getStore());
|
||||
}
|
||||
|
||||
CopyCommand::CopyCommand()
|
||||
@@ -116,28 +88,28 @@ CopyCommand::CopyCommand()
|
||||
.longName = "from",
|
||||
.description = "URL of the source Nix store.",
|
||||
.labels = {"store-uri"},
|
||||
.handler = {[this](std::string s) { srcUri = StoreReference::parse(s); }},
|
||||
.handler = {&srcUri},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "to",
|
||||
.description = "URL of the destination Nix store.",
|
||||
.labels = {"store-uri"},
|
||||
.handler = {[this](std::string s) { dstUri = StoreReference::parse(s); }},
|
||||
.handler = {&dstUri},
|
||||
});
|
||||
}
|
||||
|
||||
ref<StoreConfig> CopyCommand::createStoreConfig()
|
||||
ref<Store> CopyCommand::createStore()
|
||||
{
|
||||
return !srcUri ? StoreCommand::createStoreConfig() : resolveStoreConfig(StoreReference{*srcUri});
|
||||
return srcUri.empty() ? StoreCommand::createStore() : openStore(srcUri);
|
||||
}
|
||||
|
||||
ref<Store> CopyCommand::getDstStore()
|
||||
{
|
||||
if (!srcUri && !dstUri)
|
||||
if (srcUri.empty() && dstUri.empty())
|
||||
throw UsageError("you must pass '--from' and/or '--to'");
|
||||
|
||||
return !dstUri ? openStore() : openStore(StoreReference{*dstUri});
|
||||
return dstUri.empty() ? openStore() : openStore(dstUri);
|
||||
}
|
||||
|
||||
EvalCommand::EvalCommand()
|
||||
@@ -159,7 +131,7 @@ EvalCommand::~EvalCommand()
|
||||
ref<Store> EvalCommand::getEvalStore()
|
||||
{
|
||||
if (!evalStore)
|
||||
evalStore = evalStoreUrl ? openStore(StoreReference{*evalStoreUrl}) : getStore();
|
||||
evalStore = evalStoreUrl ? openStore(*evalStoreUrl) : getStore();
|
||||
return ref<Store>(evalStore);
|
||||
}
|
||||
|
||||
@@ -285,18 +257,18 @@ MixProfile::MixProfile()
|
||||
});
|
||||
}
|
||||
|
||||
void MixProfile::updateProfile(Store & store_, const StorePath & storePath)
|
||||
void MixProfile::updateProfile(const StorePath & storePath)
|
||||
{
|
||||
if (!profile)
|
||||
return;
|
||||
auto * store = dynamic_cast<LocalFSStore *>(&store_);
|
||||
auto store = getDstStore().dynamic_pointer_cast<LocalFSStore>();
|
||||
if (!store)
|
||||
throw Error("'--profile' is not supported for this Nix store");
|
||||
auto profile2 = absPath(*profile);
|
||||
switchLink(profile2, createGeneration(*store, profile2, storePath));
|
||||
}
|
||||
|
||||
void MixProfile::updateProfile(Store & store, const BuiltPaths & buildables)
|
||||
void MixProfile::updateProfile(const BuiltPaths & buildables)
|
||||
{
|
||||
if (!profile)
|
||||
return;
|
||||
@@ -320,16 +292,14 @@ void MixProfile::updateProfile(Store & store, const BuiltPaths & buildables)
|
||||
throw UsageError(
|
||||
"'--profile' requires that the arguments produce a single store path, but there are %d", result.size());
|
||||
|
||||
updateProfile(store, result[0]);
|
||||
updateProfile(result[0]);
|
||||
}
|
||||
|
||||
MixDefaultProfile::MixDefaultProfile()
|
||||
{
|
||||
profile = getDefaultProfile(settings.getProfileDirsOptions()).string();
|
||||
profile = getDefaultProfile().string();
|
||||
}
|
||||
|
||||
static constexpr auto environmentVariablesCategory = "Options that change environment variables";
|
||||
|
||||
MixEnvironment::MixEnvironment()
|
||||
: ignoreEnvironment(false)
|
||||
{
|
||||
|
||||
@@ -148,7 +148,7 @@ MixEvalArgs::MixEvalArgs()
|
||||
)",
|
||||
.category = category,
|
||||
.labels = {"store-url"},
|
||||
.handler = {[this](std::string s) { evalStoreUrl = StoreReference::parse(s); }},
|
||||
.handler = {&evalStoreUrl},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#include "nix/cmd/get-build-log.hh"
|
||||
#include "nix/store/log-store.hh"
|
||||
#include "nix/store/store-open.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
std::string fetchBuildLog(ref<Store> store, const StorePath & path, std::string_view what)
|
||||
{
|
||||
auto subs = getDefaultSubstituters();
|
||||
|
||||
subs.push_front(store);
|
||||
|
||||
for (auto & sub : subs) {
|
||||
auto * logSubP = dynamic_cast<LogStore *>(&*sub);
|
||||
if (!logSubP) {
|
||||
printInfo("Skipped '%s' which does not support retrieving build logs", sub->config.getHumanReadableURI());
|
||||
continue;
|
||||
}
|
||||
auto & logSub = *logSubP;
|
||||
|
||||
auto log = logSub.getBuildLog(path);
|
||||
if (!log)
|
||||
continue;
|
||||
printInfo("got build log for '%s' from '%s'", what, logSub.config.getHumanReadableURI());
|
||||
return *log;
|
||||
}
|
||||
|
||||
throw Error("build log of '%s' is not available", what);
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "nix/util/args.hh"
|
||||
#include "nix/cmd/common-eval-args.hh"
|
||||
#include "nix/store/path.hh"
|
||||
#include "nix/store/store-reference.hh"
|
||||
#include "nix/flake/lockfile.hh"
|
||||
|
||||
#include <optional>
|
||||
@@ -41,43 +40,28 @@ struct NixMultiCommand : MultiCommand, virtual Command
|
||||
// For the overloaded run methods
|
||||
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
|
||||
|
||||
/**
|
||||
* A command that requires a \ref StoreConfig store configuration.
|
||||
*/
|
||||
struct StoreConfigCommand : virtual Command
|
||||
{
|
||||
StoreConfigCommand();
|
||||
void run() override;
|
||||
|
||||
/**
|
||||
* Return the default Nix store configuration.
|
||||
*/
|
||||
ref<StoreConfig> getStoreConfig();
|
||||
|
||||
virtual ref<StoreConfig> createStoreConfig();
|
||||
/**
|
||||
* Main entry point, with a `StoreConfig` provided
|
||||
*/
|
||||
virtual void run(ref<StoreConfig>) = 0;
|
||||
|
||||
private:
|
||||
std::shared_ptr<StoreConfig> _storeConfig;
|
||||
};
|
||||
|
||||
/**
|
||||
* A command that requires a \ref Store "Nix store".
|
||||
*/
|
||||
struct StoreCommand : virtual StoreConfigCommand
|
||||
struct StoreCommand : virtual Command
|
||||
{
|
||||
StoreCommand();
|
||||
void run(ref<StoreConfig>) override;
|
||||
void run() override;
|
||||
|
||||
/**
|
||||
* Return the default Nix store.
|
||||
*/
|
||||
ref<Store> getStore();
|
||||
|
||||
ref<Store> createStore();
|
||||
/**
|
||||
* Return the destination Nix store.
|
||||
*/
|
||||
virtual ref<Store> getDstStore()
|
||||
{
|
||||
return getStore();
|
||||
}
|
||||
|
||||
virtual ref<Store> createStore();
|
||||
/**
|
||||
* Main entry point, with a `Store` provided
|
||||
*/
|
||||
@@ -93,13 +77,13 @@ private:
|
||||
*/
|
||||
struct CopyCommand : virtual StoreCommand
|
||||
{
|
||||
std::optional<StoreReference> srcUri, dstUri;
|
||||
std::string srcUri, dstUri;
|
||||
|
||||
CopyCommand();
|
||||
|
||||
ref<StoreConfig> createStoreConfig() override;
|
||||
ref<Store> createStore() override;
|
||||
|
||||
ref<Store> getDstStore();
|
||||
ref<Store> getDstStore() override;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -300,11 +284,11 @@ struct StorePathCommand : public StorePathsCommand
|
||||
*/
|
||||
struct RegisterCommand
|
||||
{
|
||||
typedef std::map<std::vector<std::string>, fun<ref<Command>()>> Commands;
|
||||
typedef std::map<std::vector<std::string>, std::function<ref<Command>()>> Commands;
|
||||
|
||||
static Commands & commands();
|
||||
|
||||
RegisterCommand(std::vector<std::string> && name, fun<ref<Command>()> command)
|
||||
RegisterCommand(std::vector<std::string> && name, std::function<ref<Command>()> command)
|
||||
{
|
||||
commands().emplace(name, command);
|
||||
}
|
||||
@@ -331,11 +315,11 @@ struct MixProfile : virtual StoreCommand
|
||||
MixProfile();
|
||||
|
||||
/* If 'profile' is set, make it point at 'storePath'. */
|
||||
void updateProfile(Store & store, const StorePath & storePath);
|
||||
void updateProfile(const StorePath & storePath);
|
||||
|
||||
/* If 'profile' is set, make it point at the store path produced
|
||||
by 'buildables'. */
|
||||
void updateProfile(Store & store, const BuiltPaths & buildables);
|
||||
void updateProfile(const BuiltPaths & buildables);
|
||||
};
|
||||
|
||||
struct MixDefaultProfile : MixProfile
|
||||
@@ -407,7 +391,7 @@ void createOutLinks(const std::filesystem::path & outLink, const BuiltPaths & bu
|
||||
struct MixOutLinkBase : virtual Args
|
||||
{
|
||||
/** Prefix for any output symlinks. Empty means do not write an output symlink. */
|
||||
std::filesystem::path outLink;
|
||||
Path outLink;
|
||||
|
||||
MixOutLinkBase(const std::string & defaultOutLink)
|
||||
: outLink(defaultOutLink)
|
||||
@@ -435,7 +419,7 @@ struct MixOutLinkByDefault : MixOutLinkBase, virtual Args
|
||||
addFlag({
|
||||
.longName = "no-link",
|
||||
.description = "Do not create symlinks to the build results.",
|
||||
.handler = {&outLink, std::filesystem::path{}},
|
||||
.handler = {&outLink, Path("")},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "nix/main/common-args.hh"
|
||||
#include "nix/expr/search-path.hh"
|
||||
#include "nix/expr/eval-settings.hh"
|
||||
#include "nix/store/store-reference.hh"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
@@ -56,7 +55,7 @@ struct MixEvalArgs : virtual Args, virtual MixRepair
|
||||
|
||||
LookupPath lookupPath;
|
||||
|
||||
std::optional<StoreReference> evalStoreUrl;
|
||||
std::optional<std::string> evalStoreUrl;
|
||||
|
||||
private:
|
||||
struct AutoArgExpr
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "nix/store/store-api.hh"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace nix {
|
||||
|
||||
/**
|
||||
* Fetch the build log for a store path, searching the store and its
|
||||
* substituters.
|
||||
*
|
||||
* @param store The store to search (and its substituters).
|
||||
* @param path The store path to get the build log for.
|
||||
* @param what A description of what we're fetching the log for (used in messages).
|
||||
* @return The build log content.
|
||||
* @throws Error if the build log is not available.
|
||||
*/
|
||||
std::string fetchBuildLog(ref<Store> store, const StorePath & path, std::string_view what);
|
||||
|
||||
} // namespace nix
|
||||
@@ -1,14 +1,13 @@
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "nix/util/fun.hh"
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace nix {
|
||||
|
||||
typedef fun<void(int, char **)> MainFunction;
|
||||
typedef std::function<void(int, char **)> MainFunction;
|
||||
|
||||
struct RegisterLegacyCommand
|
||||
{
|
||||
@@ -16,9 +15,9 @@ struct RegisterLegacyCommand
|
||||
|
||||
static Commands & commands();
|
||||
|
||||
RegisterLegacyCommand(const std::string & name, MainFunction command)
|
||||
RegisterLegacyCommand(const std::string & name, MainFunction fun)
|
||||
{
|
||||
commands().insert_or_assign(name, command);
|
||||
commands()[name] = fun;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ headers = files(
|
||||
'common-eval-args.hh',
|
||||
'compatibility-settings.hh',
|
||||
'editor-for.hh',
|
||||
'get-build-log.hh',
|
||||
'installable-attr-path.hh',
|
||||
'installable-derived-path.hh',
|
||||
'installable-flake.hh',
|
||||
@@ -21,5 +20,4 @@ headers = files(
|
||||
'network-proxy.hh',
|
||||
'repl-interacter.hh',
|
||||
'repl.hh',
|
||||
'unix-socket-server.hh',
|
||||
)
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
/// @file
|
||||
|
||||
#include "nix/util/finally.hh"
|
||||
#include "nix/util/fun.hh"
|
||||
#include "nix/util/types.hh"
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
@@ -16,7 +14,6 @@ namespace detail {
|
||||
struct ReplCompleterMixin
|
||||
{
|
||||
virtual StringSet completePrefix(const std::string & prefix) = 0;
|
||||
virtual ~ReplCompleterMixin() = default;
|
||||
};
|
||||
}; // namespace detail
|
||||
|
||||
@@ -28,7 +25,7 @@ enum class ReplPromptType {
|
||||
class ReplInteracter
|
||||
{
|
||||
public:
|
||||
using Guard = Finally<fun<void()>>;
|
||||
using Guard = Finally<std::function<void()>>;
|
||||
|
||||
virtual Guard init(detail::ReplCompleterMixin * repl) = 0;
|
||||
/** Returns a boolean of whether the interacter got EOF */
|
||||
@@ -38,10 +35,10 @@ public:
|
||||
|
||||
class ReadlineLikeInteracter : public virtual ReplInteracter
|
||||
{
|
||||
std::filesystem::path historyFile;
|
||||
std::string historyFile;
|
||||
public:
|
||||
ReadlineLikeInteracter(std::filesystem::path historyFile)
|
||||
: historyFile(std::move(historyFile))
|
||||
ReadlineLikeInteracter(std::string historyFile)
|
||||
: historyFile(historyFile)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
///@file
|
||||
|
||||
#include "nix/expr/eval.hh"
|
||||
#include "nix/util/os-string.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
@@ -26,9 +25,10 @@ struct AbstractNixRepl
|
||||
* @todo this is a layer violation
|
||||
*
|
||||
* @param programName Name of the command, e.g. `nix` or `nix-env`.
|
||||
* @param args arguments to the command.
|
||||
* @param args aguments to the command.
|
||||
*/
|
||||
using RunNix = void(const std::string & programName, OsStrings args, const std::optional<std::string> & input);
|
||||
using RunNix =
|
||||
void(const std::string & programName, const Strings & args, const std::optional<std::string> & input);
|
||||
|
||||
/**
|
||||
* @param runNix Function to run the nix CLI to support various
|
||||
@@ -37,8 +37,9 @@ struct AbstractNixRepl
|
||||
*/
|
||||
static std::unique_ptr<AbstractNixRepl> create(
|
||||
const LookupPath & lookupPath,
|
||||
nix::ref<Store> store,
|
||||
ref<EvalState> state,
|
||||
fun<AnnotatedValues()> getValues,
|
||||
std::function<AnnotatedValues()> getValues,
|
||||
RunNix * runNix = nullptr);
|
||||
|
||||
static ReplExitStatus runSimple(ref<EvalState> evalState, const ValMap & extraEnv);
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "nix/util/file-descriptor.hh"
|
||||
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace nix::unix {
|
||||
|
||||
/**
|
||||
* Information about the identity of the peer on a Unix domain socket connection.
|
||||
*/
|
||||
struct PeerInfo
|
||||
{
|
||||
std::optional<pid_t> pid;
|
||||
std::optional<uid_t> uid;
|
||||
std::optional<gid_t> gid;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the identity of the caller, if possible.
|
||||
*/
|
||||
PeerInfo getPeerInfo(Descriptor remote);
|
||||
|
||||
/**
|
||||
* Callback type for handling new connections.
|
||||
*
|
||||
* The callback receives ownership of the connection and is responsible
|
||||
* for handling it (e.g., forking a child process, spawning a thread, etc.).
|
||||
*
|
||||
* @param socket The accepted connection file descriptor.
|
||||
* @param closeListeners A callback to close the listening sockets.
|
||||
* Useful in forked child processes to release the bound sockets.
|
||||
*/
|
||||
using UnixSocketHandler = fun<void(AutoCloseFD socket, std::function<void()> closeListeners)>;
|
||||
|
||||
/**
|
||||
* Options for the serve loop.
|
||||
*
|
||||
* Only used if no systemd socket activation is detected.
|
||||
*/
|
||||
struct ServeUnixSocketOptions
|
||||
{
|
||||
/**
|
||||
* The Unix domain socket path to create and listen on.
|
||||
*/
|
||||
std::filesystem::path socketPath;
|
||||
|
||||
/**
|
||||
* Mode for the created socket file.
|
||||
*/
|
||||
mode_t socketMode = 0666;
|
||||
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* Additional file descriptor to poll. Useful for doing a self-pipe trick
|
||||
* https://cr.yp.to/docs/selfpipe.html.
|
||||
*/
|
||||
Descriptor auxiliaryFd = INVALID_DESCRIPTOR;
|
||||
|
||||
/**
|
||||
* Optional callback invoked on POLLIN event for auxiliaryFd.
|
||||
*/
|
||||
std::function<void()> onAuxiliaryFdPollin = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a server loop that accepts connections and calls the handler for each.
|
||||
*
|
||||
* This function handles:
|
||||
* - systemd socket activation (via LISTEN_FDS environment variable)
|
||||
* - Creating and binding a Unix domain socket if no activation is detected
|
||||
* - Polling for incoming connections
|
||||
* - Accepting connections
|
||||
*
|
||||
* For each accepted connection, the handler is called with the connection
|
||||
* file descriptor. The handler takes ownership of the file descriptor and
|
||||
* is responsible for closing it when done.
|
||||
*
|
||||
* This function never returns normally. It runs until interrupted
|
||||
* (e.g., via SIGINT), at which point it throws `Interrupted`.
|
||||
*
|
||||
* @param options Configuration for the server.
|
||||
* @param handler Callback invoked for each accepted connection.
|
||||
*/
|
||||
[[noreturn]] void serveUnixSocket(const ServeUnixSocketOptions & options, UnixSocketHandler handler);
|
||||
|
||||
} // namespace nix::unix
|
||||
@@ -203,10 +203,8 @@ FlakeRef InstallableFlake::nixpkgsFlakeRef() const
|
||||
|
||||
if (auto nixpkgsInput = lockedFlake->lockFile.findInput({"nixpkgs"})) {
|
||||
if (auto lockedNode = std::dynamic_pointer_cast<const flake::LockedNode>(nixpkgsInput)) {
|
||||
if (lockedNode->isFlake) {
|
||||
debug("using nixpkgs flake '%s'", lockedNode->lockedRef);
|
||||
return std::move(lockedNode->lockedRef);
|
||||
}
|
||||
debug("using nixpkgs flake '%s'", lockedNode->lockedRef);
|
||||
return std::move(lockedNode->lockedRef);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ MixFlakeOptions::MixFlakeOptions()
|
||||
.category = category,
|
||||
.labels = {"flake-lock-path"},
|
||||
.handler = {[&](std::string lockFilePath) {
|
||||
lockFlags.referenceLockFilePath = {getFSSourceAccessor(), CanonPath(absPath(lockFilePath).string())};
|
||||
lockFlags.referenceLockFilePath = {getFSSourceAccessor(), CanonPath(absPath(lockFilePath))};
|
||||
}},
|
||||
.completer = completePath,
|
||||
});
|
||||
@@ -400,7 +400,7 @@ void completeFlakeRefWithFragment(
|
||||
}
|
||||
}
|
||||
} catch (Error & e) {
|
||||
logWarning(e.info());
|
||||
warn(e.msg());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,12 +583,16 @@ static void throwBuildErrors(std::vector<KeyedBuildResult> & buildResults, const
|
||||
auto failedResult = failed.begin();
|
||||
if (failedResult != failed.end()) {
|
||||
if (failed.size() == 1) {
|
||||
throw *failedResult->second;
|
||||
failedResult->second->rethrow();
|
||||
} else {
|
||||
StringSet failedPaths;
|
||||
for (; failedResult != failed.end(); failedResult++) {
|
||||
if (!failedResult->second->message().empty()) {
|
||||
logError(failedResult->second->info());
|
||||
if (!failedResult->second->errorMsg.empty()) {
|
||||
logError(
|
||||
ErrorInfo{
|
||||
.level = lvlError,
|
||||
.msg = failedResult->second->errorMsg,
|
||||
});
|
||||
}
|
||||
failedPaths.insert(failedResult->first->path.to_string(store));
|
||||
}
|
||||
|
||||
@@ -74,7 +74,6 @@ sources = files(
|
||||
'command.cc',
|
||||
'common-eval-args.cc',
|
||||
'editor-for.cc',
|
||||
'get-build-log.cc',
|
||||
'installable-attr-path.cc',
|
||||
'installable-derived-path.cc',
|
||||
'installable-flake.cc',
|
||||
@@ -87,12 +86,6 @@ sources = files(
|
||||
'repl.cc',
|
||||
)
|
||||
|
||||
if host_machine.system() != 'windows'
|
||||
sources += files(
|
||||
'unix/unix-socket-server.cc',
|
||||
)
|
||||
endif
|
||||
|
||||
subdir('include/nix/cmd')
|
||||
|
||||
subdir('nix-meson-build-support/export-all-symbols')
|
||||
|
||||
@@ -40,8 +40,8 @@ void sigintHandler(int signo)
|
||||
static detail::ReplCompleterMixin * curRepl; // ugly
|
||||
|
||||
#if !USE_READLINE
|
||||
static char * completionCallback(char * s, int * match) noexcept
|
||||
try {
|
||||
static char * completionCallback(char * s, int * match)
|
||||
{
|
||||
auto possible = curRepl->completePrefix(s);
|
||||
if (possible.size() == 1) {
|
||||
*match = 1;
|
||||
@@ -73,12 +73,10 @@ try {
|
||||
|
||||
*match = 0;
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static int listPossibleCallback(char * s, char *** avp) noexcept
|
||||
try {
|
||||
static int listPossibleCallback(char * s, char *** avp)
|
||||
{
|
||||
auto possible = curRepl->completePrefix(s);
|
||||
|
||||
if (possible.size() > (std::numeric_limits<int>::max() / sizeof(char *)))
|
||||
@@ -107,9 +105,6 @@ try {
|
||||
*avp = vp;
|
||||
|
||||
return ac;
|
||||
} catch (...) {
|
||||
*avp = nullptr;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -118,14 +113,14 @@ ReadlineLikeInteracter::Guard ReadlineLikeInteracter::init(detail::ReplCompleter
|
||||
// Allow nix-repl specific settings in .inputrc
|
||||
rl_readline_name = "nix-repl";
|
||||
try {
|
||||
createDirs(historyFile.parent_path());
|
||||
createDirs(dirOf(historyFile));
|
||||
} catch (SystemError & e) {
|
||||
logWarning(e.info());
|
||||
}
|
||||
#if !USE_READLINE
|
||||
el_hist_size = 1000;
|
||||
#endif
|
||||
read_history(historyFile.string().c_str());
|
||||
read_history(historyFile.c_str());
|
||||
auto oldRepl = curRepl;
|
||||
curRepl = repl;
|
||||
Guard restoreRepl([oldRepl] { curRepl = oldRepl; });
|
||||
@@ -208,7 +203,7 @@ bool ReadlineLikeInteracter::getLine(std::string & input, ReplPromptType promptT
|
||||
|
||||
ReadlineLikeInteracter::~ReadlineLikeInteracter()
|
||||
{
|
||||
write_history(historyFile.string().c_str());
|
||||
write_history(historyFile.c_str());
|
||||
}
|
||||
|
||||
}; // namespace nix
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include "nix/util/error.hh"
|
||||
#include "nix/cmd/repl-interacter.hh"
|
||||
@@ -13,8 +12,9 @@
|
||||
#include "nix/expr/eval-settings.hh"
|
||||
#include "nix/expr/attr-path.hh"
|
||||
#include "nix/util/signals.hh"
|
||||
#include "nix/store/store-open.hh"
|
||||
#include "nix/store/log-store.hh"
|
||||
#include "nix/cmd/common-eval-args.hh"
|
||||
#include "nix/cmd/get-build-log.hh"
|
||||
#include "nix/expr/get-drvs.hh"
|
||||
#include "nix/store/derivations.hh"
|
||||
#include "nix/store/globals.hh"
|
||||
@@ -29,8 +29,6 @@
|
||||
#include "nix/util/ref.hh"
|
||||
#include "nix/expr/value.hh"
|
||||
|
||||
#include "nix/util/os-string.hh"
|
||||
#include "nix/util/processes.hh"
|
||||
#include "nix/util/strings.hh"
|
||||
|
||||
namespace nix {
|
||||
@@ -63,22 +61,27 @@ struct NixRepl : AbstractNixRepl, detail::ReplCompleterMixin, gc
|
||||
std::list<std::filesystem::path> loadedFiles;
|
||||
// Arguments passed to :load-flake, saved so they can be reloaded with :reload
|
||||
Strings loadedFlakes;
|
||||
fun<AnnotatedValues()> getValues;
|
||||
std::function<AnnotatedValues()> getValues;
|
||||
|
||||
const static int envSize = 32768;
|
||||
std::shared_ptr<StaticEnv> staticEnv;
|
||||
std::optional<Value> lastLoaded;
|
||||
Value lastLoaded;
|
||||
Env * env;
|
||||
int displ;
|
||||
StringSet varNames;
|
||||
|
||||
RunNix * runNixPtr;
|
||||
|
||||
void runNix(const std::string & program, OsStrings args, const std::optional<std::string> & input = {});
|
||||
void runNix(const std::string & program, const Strings & args, const std::optional<std::string> & input = {});
|
||||
|
||||
std::unique_ptr<ReplInteracter> interacter;
|
||||
|
||||
NixRepl(const LookupPath & lookupPath, ref<EvalState> state, fun<AnnotatedValues()> getValues, RunNix * runNix);
|
||||
NixRepl(
|
||||
const LookupPath & lookupPath,
|
||||
nix::ref<Store> store,
|
||||
ref<EvalState> state,
|
||||
std::function<AnnotatedValues()> getValues,
|
||||
RunNix * runNix);
|
||||
virtual ~NixRepl() = default;
|
||||
|
||||
ReplExitStatus mainLoop() override;
|
||||
@@ -97,7 +100,6 @@ struct NixRepl : AbstractNixRepl, detail::ReplCompleterMixin, gc
|
||||
void addAttrsToScope(Value & attrs);
|
||||
void addVarToScope(const Symbol name, Value & v);
|
||||
Expr * parseString(std::string s);
|
||||
ExprAttrs * parseReplBindings(std::string s);
|
||||
void evalString(std::string s, Value & v);
|
||||
void loadDebugTraceEnv(DebugTrace & dt);
|
||||
|
||||
@@ -130,13 +132,17 @@ std::string removeWhitespace(std::string s)
|
||||
}
|
||||
|
||||
NixRepl::NixRepl(
|
||||
const LookupPath & lookupPath, ref<EvalState> state, fun<NixRepl::AnnotatedValues()> getValues, RunNix * runNix)
|
||||
const LookupPath & lookupPath,
|
||||
nix::ref<Store> store,
|
||||
ref<EvalState> state,
|
||||
std::function<NixRepl::AnnotatedValues()> getValues,
|
||||
RunNix * runNix)
|
||||
: AbstractNixRepl(state)
|
||||
, debugTraceIndex(0)
|
||||
, getValues(getValues)
|
||||
, staticEnv(new StaticEnv(nullptr, state->staticBaseEnv))
|
||||
, runNixPtr{runNix}
|
||||
, interacter(std::make_unique<ReadlineLikeInteracter>(getDataDir() / "repl-history"))
|
||||
, interacter(make_unique<ReadlineLikeInteracter>((getDataDir() / "repl-history").string()))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -303,6 +309,21 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
|
||||
return completions;
|
||||
}
|
||||
|
||||
// FIXME: DRY and match or use the parser
|
||||
static bool isVarName(std::string_view s)
|
||||
{
|
||||
if (s.size() == 0)
|
||||
return false;
|
||||
char c = s[0];
|
||||
if ((c >= '0' && c <= '9') || c == '-' || c == '\'')
|
||||
return false;
|
||||
for (auto & i : s)
|
||||
if (!((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || (i >= '0' && i <= '9') || i == '_' || i == '-'
|
||||
|| i == '\''))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
StorePath NixRepl::getDerivationPath(Value & v)
|
||||
{
|
||||
auto packageInfo = getDerivation(*state, v, false);
|
||||
@@ -490,12 +511,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
|
||||
// runProgram redirects stdout to a StringSink,
|
||||
// using runProgram2 to allow editors to display their UI
|
||||
runProgram2({
|
||||
.program = editor,
|
||||
.lookupPath = true,
|
||||
.args = toOsStrings(std::move(args)),
|
||||
.isInteractive = true,
|
||||
});
|
||||
runProgram2(RunOptions{.program = editor, .lookupPath = true, .args = args, .isInteractive = true});
|
||||
|
||||
// Reload right after exiting the editor
|
||||
state->resetFileCache();
|
||||
@@ -515,7 +531,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
state->callFunction(f, v, result, PosIdx());
|
||||
|
||||
StorePath drvPath = getDerivationPath(result);
|
||||
runNix("nix-shell", toOsStrings({state->store->printStorePath(drvPath)}));
|
||||
runNix("nix-shell", {state->store->printStorePath(drvPath)});
|
||||
}
|
||||
|
||||
else if (command == ":b" || command == ":bl" || command == ":i" || command == ":sh" || command == ":log") {
|
||||
@@ -546,15 +562,37 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
}
|
||||
}
|
||||
} else if (command == ":i") {
|
||||
runNix("nix-env", toOsStrings({"-i", drvPathRaw}));
|
||||
runNix("nix-env", {"-i", drvPathRaw});
|
||||
} else if (command == ":log") {
|
||||
settings.readOnlyMode = true;
|
||||
Finally roModeReset([&]() { settings.readOnlyMode = false; });
|
||||
auto subs = getDefaultSubstituters();
|
||||
|
||||
subs.push_front(state->store);
|
||||
|
||||
bool foundLog = false;
|
||||
RunPager pager;
|
||||
auto log = fetchBuildLog(state->store, drvPath, drvPathRaw);
|
||||
logger->writeToStdout(log);
|
||||
for (auto & sub : subs) {
|
||||
auto * logSubP = dynamic_cast<LogStore *>(&*sub);
|
||||
if (!logSubP) {
|
||||
printInfo(
|
||||
"Skipped '%s' which does not support retrieving build logs", sub->config.getHumanReadableURI());
|
||||
continue;
|
||||
}
|
||||
auto & logSub = *logSubP;
|
||||
|
||||
auto log = logSub.getBuildLog(drvPath);
|
||||
if (log) {
|
||||
printInfo("got build log for '%s' from '%s'", drvPathRaw, logSub.config.getHumanReadableURI());
|
||||
logger->writeToStdout(*log);
|
||||
foundLog = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundLog)
|
||||
throw Error("build log of '%s' is not available", drvPathRaw);
|
||||
} else {
|
||||
runNix("nix-shell", toOsStrings({drvPathRaw}));
|
||||
runNix("nix-shell", {drvPathRaw});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,22 +693,15 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
throw Error("unknown command '%1%'", command);
|
||||
|
||||
else {
|
||||
// Try parsing as bindings first (handles `x = 1`, `inherit ...`, etc.)
|
||||
ExprAttrs * bindings = nullptr;
|
||||
try {
|
||||
bindings = parseReplBindings(line);
|
||||
} catch (ParseError &) {
|
||||
}
|
||||
|
||||
if (bindings) {
|
||||
Env * inheritEnv = bindings->inheritFromExprs ? bindings->buildInheritFromEnv(*state, *env) : nullptr;
|
||||
for (auto & [symbol, def] : *bindings->attrs) {
|
||||
Value & v(*state->allocValue());
|
||||
v.mkThunk(def.chooseByKind(env, env, inheritEnv), def.e);
|
||||
addVarToScope(symbol, v);
|
||||
}
|
||||
size_t p = line.find('=');
|
||||
std::string name;
|
||||
if (p != std::string::npos && p < line.size() && line[p + 1] != '='
|
||||
&& isVarName(name = removeWhitespace(line.substr(0, p)))) {
|
||||
Expr * e = parseString(line.substr(p + 1));
|
||||
Value & v(*state->allocValue());
|
||||
v.mkThunk(env, e);
|
||||
addVarToScope(state->symbols.create(name), v);
|
||||
} else {
|
||||
// Otherwise evaluate as expression
|
||||
Value v;
|
||||
evalString(line, v);
|
||||
auto suspension = logger->suspend();
|
||||
@@ -704,7 +735,7 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
|
||||
try {
|
||||
cwd = std::filesystem::current_path();
|
||||
} catch (std::filesystem::filesystem_error & e) {
|
||||
throw SystemError(e.code(), "cannot determine current working directory");
|
||||
throw SysError("cannot determine current working directory");
|
||||
}
|
||||
|
||||
auto flakeRef = parseFlakeRef(fetchSettings, flakeRefS, cwd.string(), true);
|
||||
@@ -742,19 +773,11 @@ void NixRepl::initEnv()
|
||||
|
||||
void NixRepl::showLastLoaded()
|
||||
{
|
||||
if (!lastLoaded)
|
||||
throw Error("nothing has been loaded yet");
|
||||
|
||||
RunPager pager;
|
||||
try {
|
||||
for (auto & i : *lastLoaded->attrs()) {
|
||||
std::string_view name = state->symbols[i.name];
|
||||
logger->cout(name);
|
||||
}
|
||||
} catch (SystemError & e) {
|
||||
/* Ignore broken pipes when the pager gets interrupted. */
|
||||
if (!e.is(std::errc::broken_pipe))
|
||||
throw;
|
||||
|
||||
for (auto & i : *lastLoaded.attrs()) {
|
||||
std::string_view name = state->symbols[i.name];
|
||||
logger->cout(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -772,7 +795,7 @@ void NixRepl::loadFiles()
|
||||
loadedFiles.clear();
|
||||
|
||||
for (auto & i : old) {
|
||||
notice("Loading %1%...", PathFmt(i));
|
||||
notice("Loading '%1%'...", i);
|
||||
loadFile(i);
|
||||
}
|
||||
|
||||
@@ -859,28 +882,6 @@ Expr * NixRepl::parseString(std::string s)
|
||||
}
|
||||
}
|
||||
|
||||
ExprAttrs * NixRepl::parseReplBindings(std::string s)
|
||||
{
|
||||
auto basePath = state->rootPath(".");
|
||||
|
||||
// Try parsing as bindings
|
||||
std::exception_ptr bindingsError;
|
||||
try {
|
||||
return state->parseReplBindings(s, basePath, staticEnv);
|
||||
} catch (ParseError &) {
|
||||
bindingsError = std::current_exception();
|
||||
}
|
||||
|
||||
// Try with semicolon appended (for `inherit foo` shorthand)
|
||||
// Use original source (s) for error messages, not s + ";"
|
||||
try {
|
||||
return state->parseReplBindings(s + ";", s, basePath, staticEnv);
|
||||
} catch (ParseError &) {
|
||||
// Semicolon retry failed; rethrow the original bindings error
|
||||
std::rethrow_exception(bindingsError);
|
||||
}
|
||||
}
|
||||
|
||||
void NixRepl::evalString(std::string s, Value & v)
|
||||
{
|
||||
Expr * e = parseString(s);
|
||||
@@ -888,10 +889,10 @@ void NixRepl::evalString(std::string s, Value & v)
|
||||
state->forceValue(v, v.determinePos(noPos));
|
||||
}
|
||||
|
||||
void NixRepl::runNix(const std::string & program, OsStrings args, const std::optional<std::string> & input)
|
||||
void NixRepl::runNix(const std::string & program, const Strings & args, const std::optional<std::string> & input)
|
||||
{
|
||||
if (runNixPtr)
|
||||
(*runNixPtr)(program, std::move(args), input);
|
||||
(*runNixPtr)(program, args, input);
|
||||
else
|
||||
throw Error(
|
||||
"Cannot run '%s' because no method of calling the Nix CLI was provided. This is a configuration problem pertaining to how this program was built. See Nix 2.25 release notes",
|
||||
@@ -899,9 +900,13 @@ void NixRepl::runNix(const std::string & program, OsStrings args, const std::opt
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractNixRepl> AbstractNixRepl::create(
|
||||
const LookupPath & lookupPath, ref<EvalState> state, fun<AnnotatedValues()> getValues, RunNix * runNix)
|
||||
const LookupPath & lookupPath,
|
||||
nix::ref<Store> store,
|
||||
ref<EvalState> state,
|
||||
std::function<AnnotatedValues()> getValues,
|
||||
RunNix * runNix)
|
||||
{
|
||||
return std::make_unique<NixRepl>(lookupPath, state, getValues, runNix);
|
||||
return std::make_unique<NixRepl>(lookupPath, std::move(store), state, getValues, runNix);
|
||||
}
|
||||
|
||||
ReplExitStatus AbstractNixRepl::runSimple(ref<EvalState> evalState, const ValMap & extraEnv)
|
||||
@@ -914,6 +919,7 @@ ReplExitStatus AbstractNixRepl::runSimple(ref<EvalState> evalState, const ValMap
|
||||
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDelete)
|
||||
auto repl = std::make_unique<NixRepl>(
|
||||
lookupPath,
|
||||
openStore(),
|
||||
evalState,
|
||||
getValues,
|
||||
/*runNix=*/nullptr);
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
///@file
|
||||
|
||||
#include "nix/cmd/unix-socket-server.hh"
|
||||
#include "nix/util/environment-variables.hh"
|
||||
#include "nix/util/file-system.hh"
|
||||
#include "nix/util/logging.hh"
|
||||
#include "nix/util/signals.hh"
|
||||
#include "nix/util/strings.hh"
|
||||
#include "nix/util/unix-domain-socket.hh"
|
||||
#include "nix/util/util.hh"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <poll.h>
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
# include <sys/ucred.h>
|
||||
#endif
|
||||
|
||||
namespace nix::unix {
|
||||
|
||||
PeerInfo getPeerInfo(Descriptor remote)
|
||||
{
|
||||
PeerInfo peer;
|
||||
|
||||
#if defined(SO_PEERCRED)
|
||||
|
||||
# if defined(__OpenBSD__)
|
||||
struct sockpeercred cred;
|
||||
# else
|
||||
ucred cred;
|
||||
# endif
|
||||
socklen_t credLen = sizeof(cred);
|
||||
if (getsockopt(remote, SOL_SOCKET, SO_PEERCRED, &cred, &credLen) == 0) {
|
||||
peer.pid = cred.pid;
|
||||
peer.uid = cred.uid;
|
||||
peer.gid = cred.gid;
|
||||
}
|
||||
|
||||
#elif defined(LOCAL_PEERCRED)
|
||||
|
||||
# if !defined(SOL_LOCAL)
|
||||
# define SOL_LOCAL 0
|
||||
# endif
|
||||
|
||||
xucred cred;
|
||||
socklen_t credLen = sizeof(cred);
|
||||
if (getsockopt(remote, SOL_LOCAL, LOCAL_PEERCRED, &cred, &credLen) == 0)
|
||||
peer.uid = cred.cr_uid;
|
||||
|
||||
#endif
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
[[noreturn]] void serveUnixSocket(const ServeUnixSocketOptions & options, UnixSocketHandler handler)
|
||||
{
|
||||
std::vector<AutoCloseFD> listeningSockets;
|
||||
|
||||
static constexpr int SD_LISTEN_FDS_START = 3;
|
||||
|
||||
// Handle socket-based activation by systemd.
|
||||
auto listenFds = getEnv("LISTEN_FDS");
|
||||
if (listenFds) {
|
||||
if (getEnv("LISTEN_PID") != std::to_string(getpid()))
|
||||
throw Error("unexpected systemd environment variables");
|
||||
auto count = string2Int<unsigned int>(*listenFds);
|
||||
assert(count);
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
AutoCloseFD fdSocket(SD_LISTEN_FDS_START + i);
|
||||
closeOnExec(fdSocket.get());
|
||||
listeningSockets.push_back(std::move(fdSocket));
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, create and bind to a Unix domain socket.
|
||||
else {
|
||||
createDirs(options.socketPath.parent_path());
|
||||
listeningSockets.push_back(createUnixDomainSocket(options.socketPath.string(), options.socketMode));
|
||||
}
|
||||
|
||||
std::vector<struct pollfd> fds;
|
||||
for (auto & i : listeningSockets)
|
||||
fds.push_back({.fd = i.get(), .events = POLLIN});
|
||||
|
||||
if (options.auxiliaryFd != INVALID_DESCRIPTOR)
|
||||
fds.push_back({.fd = options.auxiliaryFd, .events = POLLIN});
|
||||
|
||||
// Loop accepting connections.
|
||||
while (1) {
|
||||
try {
|
||||
checkInterrupt();
|
||||
|
||||
auto count = poll(fds.data(), fds.size(), -1);
|
||||
if (count == -1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
throw SysError("polling for incoming connections");
|
||||
}
|
||||
|
||||
if (options.auxiliaryFd != INVALID_DESCRIPTOR && options.onAuxiliaryFdPollin && fds.back().revents & POLLIN)
|
||||
/* Useful for reaping children. */
|
||||
options.onAuxiliaryFdPollin();
|
||||
|
||||
for (auto & fd : std::views::take(fds, listeningSockets.size())) {
|
||||
if (!fd.revents)
|
||||
continue;
|
||||
|
||||
// Accept a connection.
|
||||
struct sockaddr_un remoteAddr;
|
||||
socklen_t remoteAddrLen = sizeof(remoteAddr);
|
||||
|
||||
AutoCloseFD remote = accept(fd.fd, (struct sockaddr *) &remoteAddr, &remoteAddrLen);
|
||||
checkInterrupt();
|
||||
if (!remote) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
throw SysError("accepting connection");
|
||||
}
|
||||
|
||||
handler(std::move(remote), [&]() { listeningSockets.clear(); });
|
||||
}
|
||||
|
||||
} catch (Error & error) {
|
||||
auto ei = error.info();
|
||||
// FIXME: add to trace?
|
||||
ei.msg = HintFmt("while processing connection: %1%", ei.msg.str());
|
||||
logError(ei);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nix::unix
|
||||
@@ -181,13 +181,13 @@ EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto fetchSettings = std::make_unique<nix::fetchers::Settings>(std::move(builder->fetchSettings));
|
||||
auto settings = std::make_unique<nix::EvalSettings>(std::move(builder->settings));
|
||||
auto ownedState =
|
||||
std::make_shared<nix::EvalState>(builder->lookupPath, builder->store, *fetchSettings, *settings);
|
||||
auto & stateRef = *ownedState;
|
||||
void * p = ::operator new(sizeof(EvalState), static_cast<std::align_val_t>(alignof(EvalState)));
|
||||
return new (p) EvalState{stateRef, std::move(fetchSettings), std::move(settings), std::move(ownedState)};
|
||||
return unsafe_new_with_self<EvalState>([&](auto * self) {
|
||||
return EvalState{
|
||||
.fetchSettings = std::move(builder->fetchSettings),
|
||||
.settings = std::move(builder->settings),
|
||||
.state = nix::EvalState(builder->lookupPath, builder->store, self->fetchSettings, self->settings),
|
||||
};
|
||||
});
|
||||
}
|
||||
NIXC_CATCH_ERRS_NULL
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#ifndef NIX_API_EXPR_INTERNAL_H
|
||||
#define NIX_API_EXPR_INTERNAL_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "nix/fetchers/fetch-settings.hh"
|
||||
#include "nix/expr/eval.hh"
|
||||
#include "nix/expr/eval-settings.hh"
|
||||
@@ -24,11 +22,9 @@ struct nix_eval_state_builder
|
||||
|
||||
struct EvalState
|
||||
{
|
||||
nix::EvalState & state;
|
||||
// Owned resources; null for temporary wrappers created in C API callbacks.
|
||||
std::unique_ptr<nix::fetchers::Settings> ownedFetchSettings;
|
||||
std::unique_ptr<nix::EvalSettings> ownedSettings;
|
||||
std::shared_ptr<nix::EvalState> ownedState;
|
||||
nix::fetchers::Settings fetchSettings;
|
||||
nix::EvalSettings settings;
|
||||
nix::EvalState state;
|
||||
};
|
||||
|
||||
struct BindingsBuilder
|
||||
|
||||
@@ -137,8 +137,7 @@ public:
|
||||
}
|
||||
nix_string_context ctx{context};
|
||||
nix_string_return res{""};
|
||||
EvalState wrapper{state};
|
||||
desc.printValueAsJSON(v, &wrapper, strict, &ctx, copyToStore, &res);
|
||||
desc.printValueAsJSON(v, (EvalState *) &state, strict, &ctx, copyToStore, &res);
|
||||
if (res.str.empty()) {
|
||||
return nix::ExternalValueBase::printValueAsJSON(state, strict, context, copyToStore);
|
||||
}
|
||||
@@ -154,16 +153,22 @@ public:
|
||||
bool location,
|
||||
nix::XMLWriter & doc,
|
||||
nix::NixStringContext & context,
|
||||
nix::StringSet & drvsSeen,
|
||||
nix::PathSet & drvsSeen,
|
||||
const nix::PosIdx pos) const override
|
||||
{
|
||||
if (!desc.printValueAsXML) {
|
||||
return nix::ExternalValueBase::printValueAsXML(state, strict, location, doc, context, drvsSeen, pos);
|
||||
}
|
||||
nix_string_context ctx{context};
|
||||
EvalState wrapper{state};
|
||||
desc.printValueAsXML(
|
||||
v, &wrapper, strict, location, &doc, &ctx, &drvsSeen, *reinterpret_cast<const uint32_t *>(&pos));
|
||||
v,
|
||||
(EvalState *) &state,
|
||||
strict,
|
||||
location,
|
||||
&doc,
|
||||
&ctx,
|
||||
&drvsSeen,
|
||||
*reinterpret_cast<const uint32_t *>(&pos));
|
||||
}
|
||||
|
||||
virtual ~NixCExternalValue() override {};
|
||||
|
||||
@@ -145,7 +145,6 @@ typedef struct NixCExternalValueDesc
|
||||
* Optional, the default is to throw an error
|
||||
* @todo The mechanisms for this call are incomplete. There are no C
|
||||
* bindings to work with XML, pathsets and positions.
|
||||
* This callback also has no test coverage.
|
||||
* @param[in] self the void* passed to nix_create_external_value
|
||||
* @param[in] state The evaluator state
|
||||
* @param[in] strict boolean Whether to force the value before printing
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "nix/expr/attr-set.hh"
|
||||
#include "nix/expr/eval-error.hh"
|
||||
#include "nix/util/configuration.hh"
|
||||
#include "nix/expr/eval.hh"
|
||||
#include "nix/store/globals.hh"
|
||||
@@ -105,17 +104,11 @@ static void nix_c_primop_wrapper(
|
||||
nix_value * external_arg = new_nix_value(args[i], state.mem);
|
||||
external_args.push_back(external_arg);
|
||||
}
|
||||
EvalState wrapper{state};
|
||||
f(userdata, &ctx, &wrapper, external_args.data(), vTmpPtr);
|
||||
f(userdata, &ctx, (EvalState *) &state, external_args.data(), vTmpPtr);
|
||||
|
||||
if (ctx.last_err_code != NIX_OK) {
|
||||
if (ctx.last_err_code == NIX_ERR_RECOVERABLE) {
|
||||
state.error<nix::RecoverableEvalError>("Recoverable error from custom function: %s", *ctx.last_err)
|
||||
.atPos(pos)
|
||||
.debugThrow();
|
||||
} else {
|
||||
state.error<nix::EvalError>("Error from custom function: %s", *ctx.last_err).atPos(pos).debugThrow();
|
||||
}
|
||||
/* TODO: Throw different errors depending on the error code */
|
||||
state.error<nix::EvalError>("Error from custom function: %s", *ctx.last_err).atPos(pos).debugThrow();
|
||||
}
|
||||
|
||||
if (!vTmp.isValid()) {
|
||||
@@ -160,7 +153,7 @@ PrimOp * nix_alloc_primop(
|
||||
.args = {},
|
||||
.arity = (size_t) arity,
|
||||
.doc = doc,
|
||||
.impl = std::bind(nix_c_primop_wrapper, fun, user_data, arity, _1, _2, _3, _4)};
|
||||
.fun = std::bind(nix_c_primop_wrapper, fun, user_data, arity, _1, _2, _3, _4)};
|
||||
if (args)
|
||||
for (size_t i = 0; args[i]; i++)
|
||||
p->args.emplace_back(*args);
|
||||
@@ -201,8 +194,6 @@ ValueType nix_get_type(nix_c_context * context, const nix_value * value)
|
||||
switch (v.type()) {
|
||||
case nThunk:
|
||||
return NIX_TYPE_THUNK;
|
||||
case nFailed:
|
||||
return NIX_TYPE_FAILED;
|
||||
case nInt:
|
||||
return NIX_TYPE_INT;
|
||||
case nFloat:
|
||||
|
||||
@@ -100,8 +100,7 @@ typedef enum {
|
||||
/** @brief External value from C++ plugins or C API
|
||||
* @see Externals
|
||||
*/
|
||||
NIX_TYPE_EXTERNAL,
|
||||
NIX_TYPE_FAILED,
|
||||
NIX_TYPE_EXTERNAL
|
||||
} ValueType;
|
||||
|
||||
// forward declarations
|
||||
|
||||
@@ -12,22 +12,21 @@ class nix_api_expr_test : public nix_api_store_test
|
||||
{
|
||||
protected:
|
||||
|
||||
void SetUp() override
|
||||
nix_api_expr_test()
|
||||
{
|
||||
nix_api_store_test::SetUp();
|
||||
nix_libexpr_init(ctx);
|
||||
state = nix_state_create(nullptr, nullptr, store);
|
||||
value = nix_alloc_value(nullptr, state);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
~nix_api_expr_test()
|
||||
{
|
||||
nix_gc_decref(nullptr, value);
|
||||
nix_state_free(state);
|
||||
}
|
||||
|
||||
EvalState * state = nullptr;
|
||||
nix_value * value = nullptr;
|
||||
EvalState * state;
|
||||
nix_value * value;
|
||||
};
|
||||
|
||||
} // namespace nixC
|
||||
|
||||
@@ -37,8 +37,7 @@ static void BM_EvalDynamicAttrs(benchmark::State & state)
|
||||
EvalSettings evalSettings{readOnlyMode};
|
||||
evalSettings.nixPath = {};
|
||||
|
||||
auto stPtr = std::make_shared<EvalState>(LookupPath{}, store, fetchSettings, evalSettings, nullptr);
|
||||
auto & st = *stPtr;
|
||||
EvalState st({}, store, fetchSettings, evalSettings, nullptr);
|
||||
Expr * expr = st.parseExprFromString(exprStr, st.rootPath(CanonPath::root));
|
||||
|
||||
Value v;
|
||||
|
||||
@@ -16,8 +16,7 @@ struct GetDerivationsEnv
|
||||
fetchers::Settings fetchSettings{};
|
||||
bool readOnlyMode = true;
|
||||
EvalSettings evalSettings{readOnlyMode};
|
||||
std::shared_ptr<EvalState> statePtr;
|
||||
EvalState & state;
|
||||
EvalState state;
|
||||
|
||||
Bindings * autoArgs = nullptr;
|
||||
Value attrsValue;
|
||||
@@ -28,8 +27,7 @@ struct GetDerivationsEnv
|
||||
settings.nixPath = {};
|
||||
return settings;
|
||||
}())
|
||||
, statePtr(std::make_shared<EvalState>(LookupPath{}, store, fetchSettings, evalSettings, nullptr))
|
||||
, state(*statePtr)
|
||||
, state({}, store, fetchSettings, evalSettings, nullptr)
|
||||
{
|
||||
autoArgs = state.buildBindings(0).finish();
|
||||
|
||||
|
||||
@@ -84,8 +84,6 @@ test(
|
||||
this_exe,
|
||||
env : {
|
||||
'_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data',
|
||||
'HOME' : meson.current_build_dir() / 'test-home',
|
||||
'NIX_STORE' : '',
|
||||
},
|
||||
protocol : 'gtest',
|
||||
)
|
||||
|
||||
@@ -476,52 +476,6 @@ TEST_F(nix_api_expr_test, nix_expr_primop_nix_err_key_conversion)
|
||||
nix_gc_decref(ctx, result);
|
||||
}
|
||||
|
||||
static void
|
||||
primop_alloc_value(void * user_data, nix_c_context * context, EvalState * state, nix_value ** args, nix_value * ret)
|
||||
{
|
||||
assert(context);
|
||||
assert(state);
|
||||
|
||||
// Regression test: nix_c_primop_wrapper previously cast the inner
|
||||
// nix::EvalState* directly to EvalState* (C wrapper). C API functions
|
||||
// like nix_alloc_value() then accessed state->state at the wrong offset,
|
||||
// causing a segfault.
|
||||
nix_value * v = nix_alloc_value(context, state);
|
||||
assert(v != nullptr);
|
||||
nix_init_int(context, v, 42);
|
||||
nix_copy_value(context, ret, v);
|
||||
nix_gc_decref(nullptr, v);
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_primop_can_use_state_in_callback)
|
||||
{
|
||||
PrimOp * primop =
|
||||
nix_alloc_primop(ctx, primop_alloc_value, 1, "allocValue", nullptr, "test alloc_value in callback", nullptr);
|
||||
assert_ctx_ok();
|
||||
nix_value * primopValue = nix_alloc_value(ctx, state);
|
||||
assert_ctx_ok();
|
||||
nix_init_primop(ctx, primopValue, primop);
|
||||
assert_ctx_ok();
|
||||
|
||||
nix_value * dummy = nix_alloc_value(ctx, state);
|
||||
assert_ctx_ok();
|
||||
nix_init_int(ctx, dummy, 0);
|
||||
assert_ctx_ok();
|
||||
|
||||
nix_value * result = nix_alloc_value(ctx, state);
|
||||
assert_ctx_ok();
|
||||
nix_value_call(ctx, state, primopValue, dummy, result);
|
||||
assert_ctx_ok();
|
||||
|
||||
auto r = nix_get_int(ctx, result);
|
||||
ASSERT_EQ(42, r);
|
||||
|
||||
nix_gc_decref(ctx, dummy);
|
||||
nix_gc_decref(ctx, result);
|
||||
nix_gc_decref(ctx, primopValue);
|
||||
nix_gc_decref(ctx, primop);
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_call_multi_no_args)
|
||||
{
|
||||
nix_value * n = nix_alloc_value(ctx, state);
|
||||
@@ -563,106 +517,4 @@ TEST_F(nix_api_expr_test, nix_expr_attrset_update)
|
||||
assert_ctx_ok();
|
||||
}
|
||||
|
||||
// The following is a test case for retryable thunks. This is a requirement
|
||||
// for the current way in which NixOps4 evaluates its deployment expressions.
|
||||
// An alternative strategy could be implemented, but unwinding the stack may
|
||||
// be a more efficient way to deal with many suspensions/resumptions, compared
|
||||
// to e.g. using a thread or coroutine stack for each suspended dependency.
|
||||
// This test models the essential bits of a deployment tool that uses such
|
||||
// a strategy.
|
||||
|
||||
// State for the retryable primop - simulates deployment resource availability
|
||||
struct DeploymentResourceState
|
||||
{
|
||||
bool vm_created = false;
|
||||
};
|
||||
|
||||
static void primop_load_resource_input(
|
||||
void * user_data, nix_c_context * context, EvalState * state, nix_value ** args, nix_value * ret)
|
||||
{
|
||||
assert(context);
|
||||
assert(state);
|
||||
auto * resource_state = static_cast<DeploymentResourceState *>(user_data);
|
||||
|
||||
// Get the resource input name argument
|
||||
std::string input_name;
|
||||
if (nix_get_string(context, args[0], OBSERVE_STRING(input_name)) != NIX_OK)
|
||||
return;
|
||||
|
||||
// Only handle "vm_id" input - throw for anything else
|
||||
if (input_name != "vm_id") {
|
||||
std::string error_msg = "unknown resource input: " + input_name;
|
||||
nix_set_err_msg(context, NIX_ERR_NIX_ERROR, error_msg.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (resource_state->vm_created) {
|
||||
// VM has been created, return the ID
|
||||
nix_init_string(context, ret, "vm-12345");
|
||||
} else {
|
||||
// VM not created yet, fail with dependency error
|
||||
nix_set_err_msg(context, NIX_ERR_RECOVERABLE, "VM not yet created");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_expr_thunk_re_evaluation_after_deployment)
|
||||
{
|
||||
// This test demonstrates NixOps4's requirement: a thunk calling a primop should be
|
||||
// re-evaluable when deployment resources become available that were not available initially.
|
||||
|
||||
DeploymentResourceState resource_state;
|
||||
|
||||
PrimOp * primop = nix_alloc_primop(
|
||||
ctx,
|
||||
primop_load_resource_input,
|
||||
1,
|
||||
"loadResourceInput",
|
||||
nullptr,
|
||||
"load a deployment resource input",
|
||||
&resource_state);
|
||||
assert_ctx_ok();
|
||||
|
||||
nix_value * primopValue = nix_alloc_value(ctx, state);
|
||||
assert_ctx_ok();
|
||||
nix_init_primop(ctx, primopValue, primop);
|
||||
assert_ctx_ok();
|
||||
|
||||
nix_value * inputName = nix_alloc_value(ctx, state);
|
||||
assert_ctx_ok();
|
||||
nix_init_string(ctx, inputName, "vm_id");
|
||||
assert_ctx_ok();
|
||||
|
||||
// Create a single thunk by using nix_init_apply instead of nix_value_call
|
||||
// This creates a lazy application that can be forced multiple times
|
||||
nix_value * thunk = nix_alloc_value(ctx, state);
|
||||
assert_ctx_ok();
|
||||
nix_init_apply(ctx, thunk, primopValue, inputName);
|
||||
assert_ctx_ok();
|
||||
|
||||
// First force: VM not created yet, should fail
|
||||
nix_value_force(ctx, state, thunk);
|
||||
ASSERT_EQ(NIX_ERR_NIX_ERROR, nix_err_code(ctx));
|
||||
ASSERT_THAT(nix_err_msg(nullptr, ctx, nullptr), testing::HasSubstr("VM not yet created"));
|
||||
|
||||
// Clear the error context for the next attempt
|
||||
nix_c_context_free(ctx);
|
||||
ctx = nix_c_context_create();
|
||||
|
||||
// Simulate deployment process: VM gets created
|
||||
resource_state.vm_created = true;
|
||||
|
||||
// Second force of the SAME thunk: this is where the "failed" value issue appears
|
||||
// With failed value caching, this should fail because the thunk is marked as permanently failed
|
||||
// Without failed value caching (or with retryable failures), this should succeed
|
||||
nix_value_force(ctx, state, thunk);
|
||||
|
||||
// If we get here without error, the thunk was successfully re-evaluated
|
||||
assert_ctx_ok();
|
||||
|
||||
std::string result;
|
||||
nix_get_string(ctx, thunk, OBSERVE_STRING(result));
|
||||
assert_ctx_ok();
|
||||
ASSERT_STREQ("vm-12345", result.c_str());
|
||||
}
|
||||
|
||||
} // namespace nixC
|
||||
|
||||
@@ -66,44 +66,4 @@ TEST_F(nix_api_expr_test, nix_expr_eval_external)
|
||||
nix_state_free(stateFn);
|
||||
}
|
||||
|
||||
static void print_value_as_json_using_state(
|
||||
void * self, EvalState * state, bool strict, nix_string_context * c, bool copyToStore, nix_string_return * res)
|
||||
{
|
||||
// Regression test: same cast bug as in nix_c_primop_wrapper (see primop_alloc_value).
|
||||
nix_value * v = nix_alloc_value(nullptr, state);
|
||||
assert(v != nullptr);
|
||||
nix_gc_decref(nullptr, v);
|
||||
|
||||
nix_set_string_return(res, "42");
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_external_printValueAsJSON_can_use_state)
|
||||
{
|
||||
NixCExternalValueDesc desc{};
|
||||
desc.print = [](void *, nix_printer *) {};
|
||||
desc.showType = [](void *, nix_string_return *) {};
|
||||
desc.typeOf = [](void *, nix_string_return *) {};
|
||||
desc.printValueAsJSON = print_value_as_json_using_state;
|
||||
|
||||
ExternalValue * val = nix_create_external_value(ctx, &desc, nullptr);
|
||||
assert_ctx_ok();
|
||||
nix_init_external(ctx, value, val);
|
||||
assert_ctx_ok();
|
||||
|
||||
nix_value * toJsonFn = nix_alloc_value(ctx, state);
|
||||
nix_expr_eval_from_string(ctx, state, "builtins.toJSON", ".", toJsonFn);
|
||||
assert_ctx_ok();
|
||||
|
||||
nix_value * result = nix_alloc_value(ctx, state);
|
||||
nix_value_call(ctx, state, toJsonFn, value, result);
|
||||
assert_ctx_ok();
|
||||
|
||||
std::string json_str;
|
||||
nix_get_string(ctx, result, OBSERVE_STRING(json_str));
|
||||
ASSERT_EQ("42", json_str);
|
||||
|
||||
nix_gc_decref(ctx, result);
|
||||
nix_gc_decref(ctx, toJsonFn);
|
||||
}
|
||||
|
||||
} // namespace nixC
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user