mirror of
https://github.com/NixOS/nix
synced 2025-07-04 19:41:48 +02:00
Merge remote-tracking branch 'origin/master' into relative-flakes
This commit is contained in:
commit
8534c4222c
263 changed files with 2129 additions and 805 deletions
155
.github/workflows/ci.yml
vendored
155
.github/workflows/ci.yml
vendored
|
@ -7,9 +7,16 @@ on:
|
||||||
permissions: read-all
|
permissions: read-all
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
eval:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- uses: cachix/install-nix-action@v30
|
||||||
|
- run: nix --experimental-features 'nix-command flakes' flake show --all-systems --json
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
needs: [check_secrets]
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
@ -23,87 +30,24 @@ jobs:
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
# The sandbox would otherwise be disabled by default on Darwin
|
# The sandbox would otherwise be disabled by default on Darwin
|
||||||
extra_nix_config: "sandbox = true"
|
extra_nix_config: |
|
||||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
sandbox = true
|
||||||
- uses: cachix/cachix-action@v15
|
max-jobs = 1
|
||||||
if: needs.check_secrets.outputs.cachix == 'true'
|
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||||
|
# 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 == 'ubuntu-latest'
|
||||||
|
- run: scripts/build-checks
|
||||||
|
- run: scripts/prepare-installer-for-github-actions
|
||||||
|
- name: Upload installer tarball
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: '${{ env.CACHIX_NAME }}'
|
name: installer-${{matrix.os}}
|
||||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
path: out/*
|
||||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
|
||||||
- if: matrix.os == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
free -h
|
|
||||||
swapon --show
|
|
||||||
swap=$(swapon --show --noheadings | head -n 1 | awk '{print $1}')
|
|
||||||
echo "Found swap: $swap"
|
|
||||||
sudo swapoff $swap
|
|
||||||
# resize it (fallocate)
|
|
||||||
sudo fallocate -l 10G $swap
|
|
||||||
sudo mkswap $swap
|
|
||||||
sudo swapon $swap
|
|
||||||
free -h
|
|
||||||
(
|
|
||||||
while sleep 60; do
|
|
||||||
free -h
|
|
||||||
done
|
|
||||||
) &
|
|
||||||
- run: nix --experimental-features 'nix-command flakes' flake check -L
|
|
||||||
- run: nix --experimental-features 'nix-command flakes' flake show --all-systems --json
|
|
||||||
|
|
||||||
# Steps to test CI automation in your own fork.
|
|
||||||
# Cachix:
|
|
||||||
# 1. Sign-up for https://www.cachix.org/
|
|
||||||
# 2. Create a cache for $githubuser-nix-install-tests
|
|
||||||
# 3. Create a cachix auth token and save it in https://github.com/$githubuser/nix/settings/secrets/actions in "Repository secrets" as CACHIX_AUTH_TOKEN
|
|
||||||
# Dockerhub:
|
|
||||||
# 1. Sign-up for https://hub.docker.com/
|
|
||||||
# 2. Store your dockerhub username as DOCKERHUB_USERNAME in "Repository secrets" of your fork repository settings (https://github.com/$githubuser/nix/settings/secrets/actions)
|
|
||||||
# 3. Create an access token in https://hub.docker.com/settings/security and store it as DOCKERHUB_TOKEN in "Repository secrets" of your fork
|
|
||||||
check_secrets:
|
|
||||||
permissions:
|
|
||||||
contents: none
|
|
||||||
name: Check Cachix and Docker secrets present for installer tests
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cachix: ${{ steps.secret.outputs.cachix }}
|
|
||||||
docker: ${{ steps.secret.outputs.docker }}
|
|
||||||
steps:
|
|
||||||
- name: Check for secrets
|
|
||||||
id: secret
|
|
||||||
env:
|
|
||||||
_CACHIX_SECRETS: ${{ secrets.CACHIX_SIGNING_KEY }}${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
_DOCKER_SECRETS: ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=cachix::${{ env._CACHIX_SECRETS != '' }}"
|
|
||||||
echo "::set-output name=docker::${{ env._DOCKER_SECRETS != '' }}"
|
|
||||||
|
|
||||||
installer:
|
|
||||||
needs: [tests, check_secrets]
|
|
||||||
if: github.event_name == 'push' && needs.check_secrets.outputs.cachix == 'true'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
installerURL: ${{ steps.prepare-installer.outputs.installerURL }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
install_url: https://releases.nixos.org/nix/nix-2.20.3/install
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: '${{ env.CACHIX_NAME }}'
|
|
||||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
|
||||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
|
||||||
cachixArgs: '-v'
|
|
||||||
- id: prepare-installer
|
|
||||||
run: scripts/prepare-installer-for-github-actions
|
|
||||||
|
|
||||||
installer_test:
|
installer_test:
|
||||||
needs: [installer, check_secrets]
|
needs: [tests]
|
||||||
if: github.event_name == 'push' && needs.check_secrets.outputs.cachix == 'true'
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
@ -111,11 +55,18 @@ jobs:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
- name: Download installer tarball
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: installer-${{matrix.os}}
|
||||||
|
path: out
|
||||||
|
- name: Serving installer
|
||||||
|
id: serving_installer
|
||||||
|
run: ./scripts/serve-installer-for-github-actions
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
install_url: '${{needs.installer.outputs.installerURL}}'
|
install_url: 'http://localhost:8126/install'
|
||||||
install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve"
|
install_options: "--tarball-url-prefix http://localhost:8126/"
|
||||||
- run: sudo apt install fish zsh
|
- run: sudo apt install fish zsh
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
- run: brew install fish
|
- run: brew install fish
|
||||||
|
@ -127,32 +78,50 @@ jobs:
|
||||||
- run: exec bash -c "nix-channel --add https://releases.nixos.org/nixos/unstable/nixos-23.05pre466020.60c1d71f2ba nixpkgs"
|
- 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"
|
- run: exec bash -c "nix-channel --update && nix-env -iA nixpkgs.hello && hello"
|
||||||
|
|
||||||
|
# Steps to test CI automation in your own fork.
|
||||||
|
# 1. Sign-up for https://hub.docker.com/
|
||||||
|
# 2. Store your dockerhub username as DOCKERHUB_USERNAME in "Repository secrets" of your fork repository settings (https://github.com/$githubuser/nix/settings/secrets/actions)
|
||||||
|
# 3. Create an access token in https://hub.docker.com/settings/security and store it as DOCKERHUB_TOKEN in "Repository secrets" of your fork
|
||||||
|
check_secrets:
|
||||||
|
permissions:
|
||||||
|
contents: none
|
||||||
|
name: Check Docker secrets present for installer tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
docker: ${{ steps.secret.outputs.docker }}
|
||||||
|
steps:
|
||||||
|
- name: Check for secrets
|
||||||
|
id: secret
|
||||||
|
env:
|
||||||
|
_DOCKER_SECRETS: ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
echo "::set-output name=docker::${{ env._DOCKER_SECRETS != '' }}"
|
||||||
|
|
||||||
docker_push_image:
|
docker_push_image:
|
||||||
needs: [check_secrets, tests, vm_tests]
|
needs: [tests, vm_tests, check_secrets]
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
if: >-
|
if: >-
|
||||||
|
needs.check_secrets.outputs.docker == 'true' &&
|
||||||
github.event_name == 'push' &&
|
github.event_name == 'push' &&
|
||||||
github.ref_name == 'master' &&
|
github.ref_name == 'master'
|
||||||
needs.check_secrets.outputs.cachix == 'true' &&
|
|
||||||
needs.check_secrets.outputs.docker == 'true'
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
- name: Check for secrets
|
||||||
|
id: secret
|
||||||
|
env:
|
||||||
|
_DOCKER_SECRETS: ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
echo "::set-output name=docker::${{ env._DOCKER_SECRETS != '' }}"
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
install_url: https://releases.nixos.org/nix/nix-2.20.3/install
|
install_url: https://releases.nixos.org/nix/nix-2.20.3/install
|
||||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||||
- run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#nix.version | tr -d \")" >> $GITHUB_ENV
|
- run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#nix.version | tr -d \")" >> $GITHUB_ENV
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
if: needs.check_secrets.outputs.cachix == 'true'
|
|
||||||
with:
|
|
||||||
name: '${{ env.CACHIX_NAME }}'
|
|
||||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
|
||||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
|
||||||
- run: nix --experimental-features 'nix-command flakes' build .#dockerImage -L
|
- run: nix --experimental-features 'nix-command flakes' build .#dockerImage -L
|
||||||
- run: docker load -i ./result/image.tar.gz
|
- run: docker load -i ./result/image.tar.gz
|
||||||
- run: docker tag nix:$NIX_VERSION ${{ secrets.DOCKERHUB_USERNAME }}/nix:$NIX_VERSION
|
- run: docker tag nix:$NIX_VERSION ${{ secrets.DOCKERHUB_USERNAME }}/nix:$NIX_VERSION
|
||||||
|
|
122
.gitignore
vendored
122
.gitignore
vendored
|
@ -1,110 +1,12 @@
|
||||||
Makefile.config
|
|
||||||
perl/Makefile.config
|
|
||||||
|
|
||||||
# /
|
|
||||||
/aclocal.m4
|
|
||||||
/autom4te.cache
|
|
||||||
/precompiled-headers.h.gch
|
|
||||||
/config.*
|
|
||||||
/configure
|
|
||||||
/stamp-h1
|
|
||||||
/svn-revision
|
|
||||||
/libtool
|
|
||||||
/config/config.*
|
|
||||||
# Default meson build dir
|
# Default meson build dir
|
||||||
/build
|
/build
|
||||||
|
|
||||||
# /doc/manual/
|
|
||||||
/doc/manual/*.1
|
|
||||||
/doc/manual/*.5
|
|
||||||
/doc/manual/*.8
|
|
||||||
/doc/manual/generated/*
|
|
||||||
/doc/manual/nix.json
|
|
||||||
/doc/manual/conf-file.json
|
|
||||||
/doc/manual/language.json
|
|
||||||
/doc/manual/xp-features.json
|
|
||||||
/doc/manual/source/SUMMARY.md
|
|
||||||
/doc/manual/source/SUMMARY-rl-next.md
|
|
||||||
/doc/manual/source/store/types/*
|
|
||||||
!/doc/manual/source/store/types/index.md.in
|
|
||||||
/doc/manual/source/command-ref/new-cli
|
|
||||||
/doc/manual/source/command-ref/conf-file.md
|
|
||||||
/doc/manual/source/command-ref/experimental-features-shortlist.md
|
|
||||||
/doc/manual/source/contributing/experimental-feature-descriptions.md
|
|
||||||
/doc/manual/source/language/builtins.md
|
|
||||||
/doc/manual/source/language/builtin-constants.md
|
|
||||||
/doc/manual/source/release-notes/rl-next.md
|
|
||||||
|
|
||||||
# /scripts/
|
|
||||||
/scripts/nix-profile.sh
|
|
||||||
/scripts/nix-profile-daemon.sh
|
|
||||||
/scripts/nix-profile.fish
|
|
||||||
/scripts/nix-profile-daemon.fish
|
|
||||||
|
|
||||||
# /src/libexpr/
|
|
||||||
/src/libexpr/lexer-tab.cc
|
|
||||||
/src/libexpr/lexer-tab.hh
|
|
||||||
/src/libexpr/parser-tab.cc
|
|
||||||
/src/libexpr/parser-tab.hh
|
|
||||||
/src/libexpr/parser-tab.output
|
|
||||||
/src/libexpr/nix.tbl
|
|
||||||
/src/libexpr/tests
|
|
||||||
/src/libexpr-tests/libnixexpr-tests
|
|
||||||
|
|
||||||
# /src/libfetchers
|
|
||||||
/src/libfetchers-tests/libnixfetchers-tests
|
|
||||||
|
|
||||||
# /src/libflake
|
|
||||||
/src/libflake-tests/libnixflake-tests
|
|
||||||
|
|
||||||
# /src/libstore/
|
|
||||||
*.gen.*
|
|
||||||
/src/libstore/tests
|
|
||||||
/src/libstore-tests/libnixstore-tests
|
|
||||||
|
|
||||||
# /src/libutil/
|
|
||||||
/src/libutil/tests
|
|
||||||
/src/libutil-tests/libnixutil-tests
|
|
||||||
|
|
||||||
/src/nix/nix
|
|
||||||
|
|
||||||
/src/nix/generated-doc
|
|
||||||
|
|
||||||
# /src/nix-env/
|
|
||||||
/src/nix-env/nix-env
|
|
||||||
|
|
||||||
# /src/nix-instantiate/
|
|
||||||
/src/nix-instantiate/nix-instantiate
|
|
||||||
|
|
||||||
# /src/nix-store/
|
|
||||||
/src/nix-store/nix-store
|
|
||||||
|
|
||||||
/src/nix-prefetch-url/nix-prefetch-url
|
|
||||||
|
|
||||||
/src/nix-collect-garbage/nix-collect-garbage
|
|
||||||
|
|
||||||
# /src/nix-channel/
|
|
||||||
/src/nix-channel/nix-channel
|
|
||||||
|
|
||||||
# /src/nix-build/
|
|
||||||
/src/nix-build/nix-build
|
|
||||||
|
|
||||||
/src/nix-copy-closure/nix-copy-closure
|
|
||||||
|
|
||||||
/src/error-demo/error-demo
|
|
||||||
|
|
||||||
/src/build-remote/build-remote
|
|
||||||
|
|
||||||
# /tests/functional/
|
# /tests/functional/
|
||||||
/tests/functional/test-tmp
|
|
||||||
/tests/functional/common/subst-vars.sh
|
/tests/functional/common/subst-vars.sh
|
||||||
/tests/functional/result*
|
|
||||||
/tests/functional/restricted-innocent
|
/tests/functional/restricted-innocent
|
||||||
/tests/functional/shell
|
|
||||||
/tests/functional/shell.drv
|
|
||||||
/tests/functional/repl-result-out
|
|
||||||
/tests/functional/debugger-test-out
|
/tests/functional/debugger-test-out
|
||||||
/tests/functional/test-libstoreconsumer/test-libstoreconsumer
|
/tests/functional/test-libstoreconsumer/test-libstoreconsumer
|
||||||
|
/tests/functional/nix-shell
|
||||||
|
|
||||||
# /tests/functional/lang/
|
# /tests/functional/lang/
|
||||||
/tests/functional/lang/*.out
|
/tests/functional/lang/*.out
|
||||||
|
@ -112,27 +14,9 @@ perl/Makefile.config
|
||||||
/tests/functional/lang/*.err
|
/tests/functional/lang/*.err
|
||||||
/tests/functional/lang/*.ast
|
/tests/functional/lang/*.ast
|
||||||
|
|
||||||
/perl/lib/Nix/Config.pm
|
|
||||||
/perl/lib/Nix/Store.cc
|
|
||||||
|
|
||||||
/misc/systemd/nix-daemon.service
|
|
||||||
/misc/systemd/nix-daemon.socket
|
|
||||||
/misc/systemd/nix-daemon.conf
|
|
||||||
/misc/upstart/nix-daemon.conf
|
|
||||||
|
|
||||||
outputs/
|
outputs/
|
||||||
|
|
||||||
*.a
|
|
||||||
*.o
|
|
||||||
*.o.tmp
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
*.dll
|
|
||||||
*.exe
|
|
||||||
*.dep
|
|
||||||
*~
|
*~
|
||||||
*.pc
|
|
||||||
*.plist
|
|
||||||
|
|
||||||
# GNU Global
|
# GNU Global
|
||||||
GPATH
|
GPATH
|
||||||
|
@ -147,8 +31,6 @@ GTAGS
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
*.compile_commands.json
|
*.compile_commands.json
|
||||||
|
|
||||||
nix-rust/target
|
|
||||||
|
|
||||||
result
|
result
|
||||||
result-*
|
result-*
|
||||||
|
|
||||||
|
@ -163,3 +45,5 @@ result-*
|
||||||
|
|
||||||
# Mac OS
|
# Mac OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
flake-regressions
|
||||||
|
|
16
.mergify.yml
16
.mergify.yml
|
@ -2,13 +2,11 @@ queue_rules:
|
||||||
- name: default
|
- name: default
|
||||||
# all required tests need to go here
|
# all required tests need to go here
|
||||||
merge_conditions:
|
merge_conditions:
|
||||||
- check-success=installer
|
|
||||||
- check-success=installer_test (macos-latest)
|
|
||||||
- check-success=installer_test (ubuntu-latest)
|
|
||||||
- check-success=tests (macos-latest)
|
- check-success=tests (macos-latest)
|
||||||
- check-success=tests (ubuntu-latest)
|
- check-success=tests (ubuntu-latest)
|
||||||
|
- check-success=installer_test (macos-latest)
|
||||||
|
- check-success=installer_test (ubuntu-latest)
|
||||||
- check-success=vm_tests
|
- check-success=vm_tests
|
||||||
merge_method: rebase
|
|
||||||
batch_size: 5
|
batch_size: 5
|
||||||
|
|
||||||
pull_request_rules:
|
pull_request_rules:
|
||||||
|
@ -90,3 +88,13 @@ pull_request_rules:
|
||||||
- "2.24-maintenance"
|
- "2.24-maintenance"
|
||||||
labels:
|
labels:
|
||||||
- merge-queue
|
- merge-queue
|
||||||
|
|
||||||
|
- name: backport patches to 2.25
|
||||||
|
conditions:
|
||||||
|
- label=backport 2.25-maintenance
|
||||||
|
actions:
|
||||||
|
backport:
|
||||||
|
branches:
|
||||||
|
- "2.25-maintenance"
|
||||||
|
labels:
|
||||||
|
- merge-queue
|
||||||
|
|
|
@ -199,6 +199,7 @@ nix3_manpages = [
|
||||||
'nix3-build',
|
'nix3-build',
|
||||||
'nix3-bundle',
|
'nix3-bundle',
|
||||||
'nix3-config',
|
'nix3-config',
|
||||||
|
'nix3-config-check',
|
||||||
'nix3-config-show',
|
'nix3-config-show',
|
||||||
'nix3-copy',
|
'nix3-copy',
|
||||||
'nix3-daemon',
|
'nix3-daemon',
|
||||||
|
@ -206,8 +207,8 @@ nix3_manpages = [
|
||||||
'nix3-derivation',
|
'nix3-derivation',
|
||||||
'nix3-derivation-show',
|
'nix3-derivation-show',
|
||||||
'nix3-develop',
|
'nix3-develop',
|
||||||
#'nix3-doctor',
|
|
||||||
'nix3-edit',
|
'nix3-edit',
|
||||||
|
'nix3-env-shell',
|
||||||
'nix3-eval',
|
'nix3-eval',
|
||||||
'nix3-flake-archive',
|
'nix3-flake-archive',
|
||||||
'nix3-flake-check',
|
'nix3-flake-check',
|
||||||
|
@ -224,6 +225,7 @@ nix3_manpages = [
|
||||||
'nix3-fmt',
|
'nix3-fmt',
|
||||||
'nix3-hash-file',
|
'nix3-hash-file',
|
||||||
'nix3-hash',
|
'nix3-hash',
|
||||||
|
'nix3-hash-convert',
|
||||||
'nix3-hash-path',
|
'nix3-hash-path',
|
||||||
'nix3-hash-to-base16',
|
'nix3-hash-to-base16',
|
||||||
'nix3-hash-to-base32',
|
'nix3-hash-to-base32',
|
||||||
|
@ -238,6 +240,7 @@ nix3_manpages = [
|
||||||
'nix3-nar-cat',
|
'nix3-nar-cat',
|
||||||
'nix3-nar-dump-path',
|
'nix3-nar-dump-path',
|
||||||
'nix3-nar-ls',
|
'nix3-nar-ls',
|
||||||
|
'nix3-nar-pack',
|
||||||
'nix3-nar',
|
'nix3-nar',
|
||||||
'nix3-path-info',
|
'nix3-path-info',
|
||||||
'nix3-print-dev-env',
|
'nix3-print-dev-env',
|
||||||
|
@ -260,7 +263,7 @@ nix3_manpages = [
|
||||||
'nix3-repl',
|
'nix3-repl',
|
||||||
'nix3-run',
|
'nix3-run',
|
||||||
'nix3-search',
|
'nix3-search',
|
||||||
#'nix3-shell',
|
'nix3-store-add',
|
||||||
'nix3-store-add-file',
|
'nix3-store-add-file',
|
||||||
'nix3-store-add-path',
|
'nix3-store-add-path',
|
||||||
'nix3-store-cat',
|
'nix3-store-cat',
|
||||||
|
@ -270,6 +273,7 @@ nix3_manpages = [
|
||||||
'nix3-store-diff-closures',
|
'nix3-store-diff-closures',
|
||||||
'nix3-store-dump-path',
|
'nix3-store-dump-path',
|
||||||
'nix3-store-gc',
|
'nix3-store-gc',
|
||||||
|
'nix3-store-info',
|
||||||
'nix3-store-ls',
|
'nix3-store-ls',
|
||||||
'nix3-store-make-content-addressed',
|
'nix3-store-make-content-addressed',
|
||||||
'nix3-store',
|
'nix3-store',
|
||||||
|
|
22
doc/manual/rl-next/ignore-local-registries.md
Normal file
22
doc/manual/rl-next/ignore-local-registries.md
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
synopsis: "Flake lock file generation now ignores local registries"
|
||||||
|
prs: [12019]
|
||||||
|
---
|
||||||
|
|
||||||
|
When resolving indirect flake references like `nixpkgs` in `flake.nix` files, Nix will no longer use the system and user flake registries. It will only use the global flake registry and overrides given on the command line via `--override-flake`.
|
||||||
|
|
||||||
|
This avoids accidents where users have local registry overrides that map `nixpkgs` to a `path:` flake in the local file system, which then end up in committed lock files pushed to other users.
|
||||||
|
|
||||||
|
In the future, we may remove the use of the registry during lock file generation altogether. It's better to explicitly specify the URL of a flake input. For example, instead of
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
outputs = { self, nixpkgs }: { ... };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
write
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
|
||||||
|
outputs = { self, nixpkgs }: { ... };
|
||||||
|
}
|
||||||
|
```
|
21
doc/manual/rl-next/nix-sshopts-parsing.md
Normal file
21
doc/manual/rl-next/nix-sshopts-parsing.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
synopsis: "Improved `NIX_SSHOPTS` parsing for better SSH option handling"
|
||||||
|
issues: [5181]
|
||||||
|
prs: [12020]
|
||||||
|
---
|
||||||
|
|
||||||
|
The parsing of the `NIX_SSHOPTS` environment variable has been improved to handle spaces and quotes correctly.
|
||||||
|
Previously, incorrectly split SSH options could cause failures in CLIs like `nix-copy-closure`,
|
||||||
|
especially when using complex ssh invocations such as `-o ProxyCommand="ssh -W %h:%p ..."`.
|
||||||
|
|
||||||
|
This change introduces a `shellSplitString` function to ensure
|
||||||
|
that `NIX_SSHOPTS` is parsed in a manner consistent with shell
|
||||||
|
behavior, addressing common parsing errors.
|
||||||
|
|
||||||
|
For example, the following now works as expected:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export NIX_SSHOPTS='-o ProxyCommand="ssh -W %h:%p ..."'
|
||||||
|
```
|
||||||
|
|
||||||
|
This update improves the reliability of SSH-related operations using `NIX_SSHOPTS` across Nix CLIs.
|
|
@ -258,14 +258,14 @@ let
|
||||||
mkdir -p $out/nix/var/nix/profiles/per-user/${uname}
|
mkdir -p $out/nix/var/nix/profiles/per-user/${uname}
|
||||||
|
|
||||||
ln -s ${profile} $out/nix/var/nix/profiles/default-1-link
|
ln -s ${profile} $out/nix/var/nix/profiles/default-1-link
|
||||||
ln -s $out/nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default
|
ln -s /nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default
|
||||||
ln -s /nix/var/nix/profiles/default $out${userHome}/.nix-profile
|
ln -s /nix/var/nix/profiles/default $out${userHome}/.nix-profile
|
||||||
|
|
||||||
ln -s ${channel} $out/nix/var/nix/profiles/per-user/${uname}/channels-1-link
|
ln -s ${channel} $out/nix/var/nix/profiles/per-user/${uname}/channels-1-link
|
||||||
ln -s $out/nix/var/nix/profiles/per-user/${uname}/channels-1-link $out/nix/var/nix/profiles/per-user/${uname}/channels
|
ln -s /nix/var/nix/profiles/per-user/${uname}/channels-1-link $out/nix/var/nix/profiles/per-user/${uname}/channels
|
||||||
|
|
||||||
mkdir -p $out${userHome}/.nix-defexpr
|
mkdir -p $out${userHome}/.nix-defexpr
|
||||||
ln -s $out/nix/var/nix/profiles/per-user/${uname}/channels $out${userHome}/.nix-defexpr/channels
|
ln -s /nix/var/nix/profiles/per-user/${uname}/channels $out${userHome}/.nix-defexpr/channels
|
||||||
echo "${channelURL} ${channelName}" > $out${userHome}/.nix-channels
|
echo "${channelURL} ${channelName}" > $out${userHome}/.nix-channels
|
||||||
|
|
||||||
mkdir -p $out/bin $out/usr/bin
|
mkdir -p $out/bin $out/usr/bin
|
||||||
|
|
46
flake.nix
46
flake.nix
|
@ -124,18 +124,36 @@
|
||||||
# without "polluting" the top level "`pkgs`" attrset.
|
# without "polluting" the top level "`pkgs`" attrset.
|
||||||
# This also has the benefit of providing us with a distinct set of packages
|
# This also has the benefit of providing us with a distinct set of packages
|
||||||
# we can iterate over.
|
# we can iterate over.
|
||||||
nixComponents = lib.makeScope final.nixDependencies.newScope (import ./packaging/components.nix {
|
nixComponents =
|
||||||
inherit (final) lib;
|
lib.makeScopeWithSplicing'
|
||||||
inherit officialRelease;
|
{
|
||||||
src = self;
|
inherit (final) splicePackages;
|
||||||
});
|
inherit (final.nixDependencies) newScope;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
otherSplices = final.generateSplicesForMkScope "nixComponents";
|
||||||
|
f = import ./packaging/components.nix {
|
||||||
|
inherit (final) lib;
|
||||||
|
inherit officialRelease;
|
||||||
|
src = self;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# The dependencies are in their own scope, so that they don't have to be
|
# The dependencies are in their own scope, so that they don't have to be
|
||||||
# in Nixpkgs top level `pkgs` or `nixComponents`.
|
# in Nixpkgs top level `pkgs` or `nixComponents`.
|
||||||
nixDependencies = lib.makeScope final.newScope (import ./packaging/dependencies.nix {
|
nixDependencies =
|
||||||
inherit inputs stdenv;
|
lib.makeScopeWithSplicing'
|
||||||
pkgs = final;
|
{
|
||||||
});
|
inherit (final) splicePackages;
|
||||||
|
inherit (final) newScope; # layered directly on pkgs, unlike nixComponents above
|
||||||
|
}
|
||||||
|
{
|
||||||
|
otherSplices = final.generateSplicesForMkScope "nixDependencies";
|
||||||
|
f = import ./packaging/dependencies.nix {
|
||||||
|
inherit inputs stdenv;
|
||||||
|
pkgs = final;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
nix = final.nixComponents.nix-cli;
|
nix = final.nixComponents.nix-cli;
|
||||||
|
|
||||||
|
@ -168,7 +186,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
checks = forAllSystems (system: {
|
checks = forAllSystems (system: {
|
||||||
binaryTarball = self.hydraJobs.binaryTarball.${system};
|
installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system};
|
||||||
installTests = self.hydraJobs.installTests.${system};
|
installTests = self.hydraJobs.installTests.${system};
|
||||||
nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system};
|
nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system};
|
||||||
rl-next =
|
rl-next =
|
||||||
|
@ -183,11 +201,7 @@
|
||||||
# Some perl dependencies are broken on i686-linux.
|
# Some perl dependencies are broken on i686-linux.
|
||||||
# Since the support is only best-effort there, disable the perl
|
# Since the support is only best-effort there, disable the perl
|
||||||
# bindings
|
# bindings
|
||||||
|
perlBindings = self.hydraJobs.perlBindings.${system};
|
||||||
# Temporarily disabled because GitHub Actions OOM issues. Once
|
|
||||||
# the old build system is gone and we are back to one build
|
|
||||||
# system, we should reenable this.
|
|
||||||
#perlBindings = self.hydraJobs.perlBindings.${system};
|
|
||||||
}
|
}
|
||||||
# Add "passthru" tests
|
# Add "passthru" tests
|
||||||
// flatMapAttrs ({
|
// flatMapAttrs ({
|
||||||
|
@ -219,6 +233,8 @@
|
||||||
inherit (nixpkgsFor.${system}.native)
|
inherit (nixpkgsFor.${system}.native)
|
||||||
changelog-d;
|
changelog-d;
|
||||||
default = self.packages.${system}.nix;
|
default = self.packages.${system}.nix;
|
||||||
|
installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system};
|
||||||
|
binaryTarball = self.hydraJobs.binaryTarball.${system};
|
||||||
# TODO probably should be `nix-cli`
|
# TODO probably should be `nix-cli`
|
||||||
nix = self.packages.${system}.nix-everything;
|
nix = self.packages.${system}.nix-everything;
|
||||||
nix-manual = nixpkgsFor.${system}.native.nixComponents.nix-manual;
|
nix-manual = nixpkgsFor.${system}.native.nixComponents.nix-manual;
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
hooks = {
|
hooks = {
|
||||||
clang-format = {
|
clang-format = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
# https://github.com/cachix/git-hooks.nix/pull/532
|
||||||
|
package = pkgs.llvmPackages_latest.clang-tools;
|
||||||
excludes = [
|
excludes = [
|
||||||
# We don't want to format test data
|
# We don't want to format test data
|
||||||
# ''tests/(?!nixos/).*\.nix''
|
# ''tests/(?!nixos/).*\.nix''
|
||||||
|
@ -496,7 +498,6 @@
|
||||||
''^scripts/create-darwin-volume\.sh$''
|
''^scripts/create-darwin-volume\.sh$''
|
||||||
''^scripts/install-darwin-multi-user\.sh$''
|
''^scripts/install-darwin-multi-user\.sh$''
|
||||||
''^scripts/install-multi-user\.sh$''
|
''^scripts/install-multi-user\.sh$''
|
||||||
''^scripts/install-nix-from-closure\.sh$''
|
|
||||||
''^scripts/install-systemd-multi-user\.sh$''
|
''^scripts/install-systemd-multi-user\.sh$''
|
||||||
''^src/nix/get-env\.sh$''
|
''^src/nix/get-env\.sh$''
|
||||||
''^tests/functional/ca/build-dry\.sh$''
|
''^tests/functional/ca/build-dry\.sh$''
|
||||||
|
|
|
@ -34,6 +34,7 @@ endif
|
||||||
subproject('libutil-c')
|
subproject('libutil-c')
|
||||||
subproject('libstore-c')
|
subproject('libstore-c')
|
||||||
subproject('libexpr-c')
|
subproject('libexpr-c')
|
||||||
|
subproject('libflake-c')
|
||||||
subproject('libmain-c')
|
subproject('libmain-c')
|
||||||
|
|
||||||
# Language Bindings
|
# Language Bindings
|
||||||
|
|
13
misc/launchd/meson.build
Normal file
13
misc/launchd/meson.build
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
configure_file(
|
||||||
|
input : 'org.nixos.nix-daemon.plist.in',
|
||||||
|
output : 'org.nixos.nix-daemon.plist',
|
||||||
|
install : true,
|
||||||
|
install_dir : get_option('prefix') / 'Library/LaunchDaemons',
|
||||||
|
install_mode : 'rw-r--r--',
|
||||||
|
configuration : {
|
||||||
|
# TODO: unhardcode paths with something like:
|
||||||
|
# 'storedir' : store_dir,
|
||||||
|
# 'localstatedir' : localstatedir,
|
||||||
|
# 'bindir' : bindir,
|
||||||
|
},
|
||||||
|
)
|
|
@ -2,4 +2,10 @@ subdir('bash')
|
||||||
subdir('fish')
|
subdir('fish')
|
||||||
subdir('zsh')
|
subdir('zsh')
|
||||||
|
|
||||||
subdir('systemd')
|
if host_machine.system() == 'linux'
|
||||||
|
subdir('systemd')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if host_machine.system() == 'darwin'
|
||||||
|
subdir('launchd')
|
||||||
|
endif
|
||||||
|
|
|
@ -44,6 +44,7 @@ in
|
||||||
nix-expr-tests = callPackage ../src/libexpr-tests/package.nix { };
|
nix-expr-tests = callPackage ../src/libexpr-tests/package.nix { };
|
||||||
|
|
||||||
nix-flake = callPackage ../src/libflake/package.nix { };
|
nix-flake = callPackage ../src/libflake/package.nix { };
|
||||||
|
nix-flake-c = callPackage ../src/libflake-c/package.nix { };
|
||||||
nix-flake-tests = callPackage ../src/libflake-tests/package.nix { };
|
nix-flake-tests = callPackage ../src/libflake-tests/package.nix { };
|
||||||
|
|
||||||
nix-main = callPackage ../src/libmain/package.nix { };
|
nix-main = callPackage ../src/libmain/package.nix { };
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
nix-expr-tests,
|
nix-expr-tests,
|
||||||
|
|
||||||
nix-flake,
|
nix-flake,
|
||||||
|
nix-flake-c,
|
||||||
nix-flake-tests,
|
nix-flake-tests,
|
||||||
|
|
||||||
nix-main,
|
nix-main,
|
||||||
|
@ -53,6 +54,7 @@ let
|
||||||
nix-expr-c
|
nix-expr-c
|
||||||
nix-fetchers
|
nix-fetchers
|
||||||
nix-flake
|
nix-flake
|
||||||
|
nix-flake-c
|
||||||
nix-main
|
nix-main
|
||||||
nix-main-c
|
nix-main-c
|
||||||
nix-store
|
nix-store
|
||||||
|
@ -86,6 +88,7 @@ let
|
||||||
"nix-expr-c"
|
"nix-expr-c"
|
||||||
"nix-fetchers"
|
"nix-fetchers"
|
||||||
"nix-flake"
|
"nix-flake"
|
||||||
|
"nix-flake-c"
|
||||||
"nix-main"
|
"nix-main"
|
||||||
"nix-main-c"
|
"nix-main-c"
|
||||||
"nix-store"
|
"nix-store"
|
||||||
|
@ -169,6 +172,7 @@ in
|
||||||
nix-expr
|
nix-expr
|
||||||
nix-expr-c
|
nix-expr-c
|
||||||
nix-flake
|
nix-flake
|
||||||
|
nix-flake-c
|
||||||
nix-main
|
nix-main
|
||||||
nix-main-c
|
nix-main-c
|
||||||
;
|
;
|
||||||
|
|
|
@ -18,12 +18,8 @@ let
|
||||||
|
|
||||||
testNixVersions = pkgs: daemon:
|
testNixVersions = pkgs: daemon:
|
||||||
pkgs.nixComponents.nix-functional-tests.override {
|
pkgs.nixComponents.nix-functional-tests.override {
|
||||||
pname =
|
pname = "nix-daemon-compat-tests";
|
||||||
"nix-tests"
|
version = "${pkgs.nix.version}-with-daemon-${daemon.version}";
|
||||||
+ lib.optionalString
|
|
||||||
(lib.versionAtLeast daemon.version "2.4pre20211005" &&
|
|
||||||
lib.versionAtLeast pkgs.nix.version "2.4pre20211005")
|
|
||||||
"-${pkgs.nix.version}-against-${daemon.version}";
|
|
||||||
|
|
||||||
test-daemon = daemon;
|
test-daemon = daemon;
|
||||||
};
|
};
|
||||||
|
@ -127,15 +123,10 @@ in
|
||||||
self.hydraJobs.binaryTarballCross."x86_64-linux"."armv7l-unknown-linux-gnueabihf"
|
self.hydraJobs.binaryTarballCross."x86_64-linux"."armv7l-unknown-linux-gnueabihf"
|
||||||
self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu"
|
self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu"
|
||||||
];
|
];
|
||||||
installerScriptForGHA = installScriptFor [
|
|
||||||
# Native
|
installerScriptForGHA = forAllSystems (system: nixpkgsFor.${system}.native.callPackage ../scripts/installer.nix {
|
||||||
self.hydraJobs.binaryTarball."x86_64-linux"
|
tarballs = [ self.hydraJobs.binaryTarball.${system} ];
|
||||||
self.hydraJobs.binaryTarball."aarch64-darwin"
|
});
|
||||||
# Cross
|
|
||||||
self.hydraJobs.binaryTarballCross."x86_64-linux"."armv6l-unknown-linux-gnueabihf"
|
|
||||||
self.hydraJobs.binaryTarballCross."x86_64-linux"."armv7l-unknown-linux-gnueabihf"
|
|
||||||
self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu"
|
|
||||||
];
|
|
||||||
|
|
||||||
# docker image with Nix inside
|
# docker image with Nix inside
|
||||||
dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage);
|
dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage);
|
||||||
|
|
|
@ -23,7 +23,7 @@ in
|
||||||
runCommand "nix-binary-tarball-${version}" env ''
|
runCommand "nix-binary-tarball-${version}" env ''
|
||||||
cp ${installerClosureInfo}/registration $TMPDIR/reginfo
|
cp ${installerClosureInfo}/registration $TMPDIR/reginfo
|
||||||
cp ${./create-darwin-volume.sh} $TMPDIR/create-darwin-volume.sh
|
cp ${./create-darwin-volume.sh} $TMPDIR/create-darwin-volume.sh
|
||||||
substitute ${./install-nix-from-closure.sh} $TMPDIR/install \
|
substitute ${./install-nix-from-tarball.sh} $TMPDIR/install \
|
||||||
--subst-var-by nix ${nix} \
|
--subst-var-by nix ${nix} \
|
||||||
--subst-var-by cacert ${cacert}
|
--subst-var-by cacert ${cacert}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ runCommand "nix-binary-tarball-${version}" env ''
|
||||||
fn=$out/$dir.tar.xz
|
fn=$out/$dir.tar.xz
|
||||||
mkdir -p $out/nix-support
|
mkdir -p $out/nix-support
|
||||||
echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products
|
echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products
|
||||||
tar cvfJ $fn \
|
tar cfJ $fn \
|
||||||
--owner=0 --group=0 --mode=u+rw,uga+r \
|
--owner=0 --group=0 --mode=u+rw,uga+r \
|
||||||
--mtime='1970-01-01' \
|
--mtime='1970-01-01' \
|
||||||
--absolute-names \
|
--absolute-names \
|
||||||
|
|
6
scripts/build-checks
Executable file
6
scripts/build-checks
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
system=$(nix eval --raw --impure --expr builtins.currentSystem)
|
||||||
|
nix eval --json ".#checks.$system" --apply builtins.attrNames | \
|
||||||
|
jq -r '.[]' | \
|
||||||
|
xargs -P0 -I '{}' sh -c "nix build -L .#checks.$system.{} || { echo 'FAILED: \033[0;31mnix build -L .#checks.$system.{}\\033[0m'; kill 0; }"
|
|
@ -463,7 +463,7 @@ EOF
|
||||||
|
|
||||||
EDITOR="$SCRATCH/ex_cleanroom_wrapper" _sudo "to add nix to fstab" "$@" <<EOF
|
EDITOR="$SCRATCH/ex_cleanroom_wrapper" _sudo "to add nix to fstab" "$@" <<EOF
|
||||||
:a
|
:a
|
||||||
UUID=$uuid $escaped_mountpoint apfs rw,noauto,nobrowse,suid,owners
|
UUID=$uuid $escaped_mountpoint apfs rw,noauto,nobrowse,nosuid,noatime,owners
|
||||||
.
|
.
|
||||||
:x
|
:x
|
||||||
EOF
|
EOF
|
||||||
|
|
|
@ -56,6 +56,9 @@ readonly NIX_INSTALLED_CACERT="@cacert@"
|
||||||
#readonly NIX_INSTALLED_CACERT="/nix/store/7dxhzymvy330i28ii676fl1pqwcahv2f-nss-cacert-3.49.2"
|
#readonly NIX_INSTALLED_CACERT="/nix/store/7dxhzymvy330i28ii676fl1pqwcahv2f-nss-cacert-3.49.2"
|
||||||
readonly EXTRACTED_NIX_PATH="$(dirname "$0")"
|
readonly EXTRACTED_NIX_PATH="$(dirname "$0")"
|
||||||
|
|
||||||
|
# allow to override identity change command
|
||||||
|
readonly NIX_BECOME=${NIX_BECOME:-sudo}
|
||||||
|
|
||||||
readonly ROOT_HOME=~root
|
readonly ROOT_HOME=~root
|
||||||
|
|
||||||
if [ -t 0 ] && [ -z "${NIX_INSTALLER_YES:-}" ]; then
|
if [ -t 0 ] && [ -z "${NIX_INSTALLER_YES:-}" ]; then
|
||||||
|
@ -123,7 +126,7 @@ uninstall_directions() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
$step. Restore $profile_target$PROFILE_BACKUP_SUFFIX back to $profile_target
|
$step. Restore $profile_target$PROFILE_BACKUP_SUFFIX back to $profile_target
|
||||||
|
|
||||||
sudo mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
|
$NIX_BECOME mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
|
||||||
|
|
||||||
(after this one, you may need to re-open any terminals that were
|
(after this one, you may need to re-open any terminals that were
|
||||||
opened while it existed.)
|
opened while it existed.)
|
||||||
|
@ -136,7 +139,7 @@ EOF
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
$step. Delete the files Nix added to your system:
|
$step. Delete the files Nix added to your system:
|
||||||
|
|
||||||
sudo rm -rf "/etc/nix" "$NIX_ROOT" "$ROOT_HOME/.nix-profile" "$ROOT_HOME/.nix-defexpr" "$ROOT_HOME/.nix-channels" "$ROOT_HOME/.local/state/nix" "$ROOT_HOME/.cache/nix" "$HOME/.nix-profile" "$HOME/.nix-defexpr" "$HOME/.nix-channels" "$HOME/.local/state/nix" "$HOME/.cache/nix"
|
$NIX_BECOME rm -rf "/etc/nix" "$NIX_ROOT" "$ROOT_HOME/.nix-profile" "$ROOT_HOME/.nix-defexpr" "$ROOT_HOME/.nix-channels" "$ROOT_HOME/.local/state/nix" "$ROOT_HOME/.cache/nix" "$HOME/.nix-profile" "$HOME/.nix-defexpr" "$HOME/.nix-channels" "$HOME/.local/state/nix" "$HOME/.cache/nix"
|
||||||
|
|
||||||
and that is it.
|
and that is it.
|
||||||
|
|
||||||
|
@ -343,7 +346,7 @@ __sudo() {
|
||||||
|
|
||||||
echo "I am executing:"
|
echo "I am executing:"
|
||||||
echo ""
|
echo ""
|
||||||
printf " $ sudo %s\\n" "$cmd"
|
printf " $ $NIX_BECOME %s\\n" "$cmd"
|
||||||
echo ""
|
echo ""
|
||||||
echo "$expl"
|
echo "$expl"
|
||||||
echo ""
|
echo ""
|
||||||
|
@ -361,7 +364,9 @@ _sudo() {
|
||||||
if is_root; then
|
if is_root; then
|
||||||
env "$@"
|
env "$@"
|
||||||
else
|
else
|
||||||
sudo "$@"
|
# env sets environment variables for sudo alternatives
|
||||||
|
# that don't support "VAR=value command" syntax
|
||||||
|
$NIX_BECOME env "$@"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,7 +695,7 @@ place_channel_configuration() {
|
||||||
if [ -z "${NIX_INSTALLER_NO_CHANNEL_ADD:-}" ]; then
|
if [ -z "${NIX_INSTALLER_NO_CHANNEL_ADD:-}" ]; then
|
||||||
echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > "$SCRATCH/.nix-channels"
|
echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > "$SCRATCH/.nix-channels"
|
||||||
_sudo "to set up the default system channel (part 1)" \
|
_sudo "to set up the default system channel (part 1)" \
|
||||||
install -m 0664 "$SCRATCH/.nix-channels" "$ROOT_HOME/.nix-channels"
|
install -m 0644 "$SCRATCH/.nix-channels" "$ROOT_HOME/.nix-channels"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -964,7 +969,7 @@ $NIX_EXTRA_CONF
|
||||||
build-users-group = $NIX_BUILD_GROUP_NAME
|
build-users-group = $NIX_BUILD_GROUP_NAME
|
||||||
EOF
|
EOF
|
||||||
_sudo "to place the default nix daemon configuration (part 2)" \
|
_sudo "to place the default nix daemon configuration (part 2)" \
|
||||||
install -m 0664 "$SCRATCH/nix.conf" /etc/nix/nix.conf
|
install -m 0644 "$SCRATCH/nix.conf" /etc/nix/nix.conf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ self="$(dirname "$0")"
|
||||||
nix="@nix@"
|
nix="@nix@"
|
||||||
cacert="@cacert@"
|
cacert="@cacert@"
|
||||||
|
|
||||||
|
# allow to override identity change command
|
||||||
|
readonly NIX_BECOME="${NIX_BECOME:-sudo}"
|
||||||
|
|
||||||
if ! [ -e "$self/.reginfo" ]; then
|
if ! [ -e "$self/.reginfo" ]; then
|
||||||
echo "$0: incomplete installer (.reginfo is missing)" >&2
|
echo "$0: incomplete installer (.reginfo is missing)" >&2
|
||||||
|
@ -48,15 +50,14 @@ case "$(uname -s)" in
|
||||||
INSTALL_MODE=no-daemon;;
|
INSTALL_MODE=no-daemon;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# space-separated string
|
ACTION=
|
||||||
ACTIONS=
|
|
||||||
|
|
||||||
# handle the command line flags
|
# handle the command line flags
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case $1 in
|
case $1 in
|
||||||
--daemon)
|
--daemon)
|
||||||
INSTALL_MODE=daemon
|
INSTALL_MODE=daemon
|
||||||
ACTIONS="${ACTIONS}install "
|
ACTION=install
|
||||||
;;
|
;;
|
||||||
--no-daemon)
|
--no-daemon)
|
||||||
if [ "$(uname -s)" = "Darwin" ]; then
|
if [ "$(uname -s)" = "Darwin" ]; then
|
||||||
|
@ -64,19 +65,14 @@ while [ $# -gt 0 ]; do
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
INSTALL_MODE=no-daemon
|
INSTALL_MODE=no-daemon
|
||||||
# intentional tail space
|
ACTION=install
|
||||||
ACTIONS="${ACTIONS}install "
|
|
||||||
;;
|
;;
|
||||||
# --uninstall)
|
|
||||||
# # intentional tail space
|
|
||||||
# ACTIONS="${ACTIONS}uninstall "
|
|
||||||
# ;;
|
|
||||||
--yes)
|
--yes)
|
||||||
export NIX_INSTALLER_YES=1;;
|
export NIX_INSTALLER_YES=1;;
|
||||||
--no-channel-add)
|
--no-channel-add)
|
||||||
export NIX_INSTALLER_NO_CHANNEL_ADD=1;;
|
export NIX_INSTALLER_NO_CHANNEL_ADD=1;;
|
||||||
--daemon-user-count)
|
--daemon-user-count)
|
||||||
export NIX_USER_COUNT=$2
|
export NIX_USER_COUNT="$2"
|
||||||
shift;;
|
shift;;
|
||||||
--no-modify-profile)
|
--no-modify-profile)
|
||||||
NIX_INSTALLER_NO_MODIFY_PROFILE=1;;
|
NIX_INSTALLER_NO_MODIFY_PROFILE=1;;
|
||||||
|
@ -128,7 +124,7 @@ done
|
||||||
|
|
||||||
if [ "$INSTALL_MODE" = "daemon" ]; then
|
if [ "$INSTALL_MODE" = "daemon" ]; then
|
||||||
printf '\e[1;31mSwitching to the Multi-user Installer\e[0m\n'
|
printf '\e[1;31mSwitching to the Multi-user Installer\e[0m\n'
|
||||||
exec "$self/install-multi-user" $ACTIONS # let ACTIONS split
|
exec "$self/install-multi-user" $ACTION
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -140,8 +136,8 @@ echo "performing a single-user installation of Nix..." >&2
|
||||||
|
|
||||||
if ! [ -e "$dest" ]; then
|
if ! [ -e "$dest" ]; then
|
||||||
cmd="mkdir -m 0755 $dest && chown $USER $dest"
|
cmd="mkdir -m 0755 $dest && chown $USER $dest"
|
||||||
echo "directory $dest does not exist; creating it by running '$cmd' using sudo" >&2
|
echo "directory $dest does not exist; creating it by running '$cmd' using $NIX_BECOME" >&2
|
||||||
if ! sudo sh -c "$cmd"; then
|
if ! $NIX_BECOME sh -c "$cmd"; then
|
||||||
echo "$0: please manually run '$cmd' as root to create $dest" >&2
|
echo "$0: please manually run '$cmd' as root to create $dest" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
|
@ -1,10 +1,11 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
set -e
|
set -euo pipefail
|
||||||
|
|
||||||
script=$(nix-build -A outputs.hydraJobs.installerScriptForGHA --no-out-link)
|
nix build -L ".#installerScriptForGHA" ".#binaryTarball"
|
||||||
installerHash=$(echo "$script" | cut -b12-43 -)
|
|
||||||
|
|
||||||
installerURL=https://$CACHIX_NAME.cachix.org/serve/$installerHash/install
|
mkdir -p out
|
||||||
|
cp ./result/install "out/install"
|
||||||
echo "::set-output name=installerURL::$installerURL"
|
name="$(basename "$(realpath ./result-1)")"
|
||||||
|
# everything before the first dash
|
||||||
|
cp -r ./result-1 "out/${name%%-*}"
|
||||||
|
|
22
scripts/serve-installer-for-github-actions
Executable file
22
scripts/serve-installer-for-github-actions
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
if [[ ! -d out ]]; then
|
||||||
|
echo "run prepare-installer-for-github-actions first"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cd out
|
||||||
|
PORT=${PORT:-8126}
|
||||||
|
nohup python -m http.server "$PORT" >/dev/null 2>&1 &
|
||||||
|
pid=$!
|
||||||
|
|
||||||
|
while ! curl -s "http://localhost:$PORT"; do
|
||||||
|
sleep 1
|
||||||
|
if ! kill -0 $pid; then
|
||||||
|
echo "Failed to start http server"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo 'To install nix, run the following command:'
|
||||||
|
echo "sh <(curl http://localhost:$PORT/install) --tarball-url-prefix http://localhost:$PORT"
|
|
@ -40,6 +40,7 @@ GENERATE_LATEX = NO
|
||||||
INPUT = \
|
INPUT = \
|
||||||
@src@/src/libutil-c \
|
@src@/src/libutil-c \
|
||||||
@src@/src/libexpr-c \
|
@src@/src/libexpr-c \
|
||||||
|
@src@/src/libflake-c \
|
||||||
@src@/src/libstore-c \
|
@src@/src/libstore-c \
|
||||||
@src@/src/external-api-docs/README.md
|
@src@/src/external-api-docs/README.md
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ mkMesonDerivation (finalAttrs: {
|
||||||
# Source is not compiled, but still must be available for Doxygen
|
# Source is not compiled, but still must be available for Doxygen
|
||||||
# to gather comments.
|
# to gather comments.
|
||||||
(cpp ../libexpr-c)
|
(cpp ../libexpr-c)
|
||||||
|
(cpp ../libflake-c)
|
||||||
(cpp ../libstore-c)
|
(cpp ../libstore-c)
|
||||||
(cpp ../libutil-c)
|
(cpp ../libutil-c)
|
||||||
];
|
];
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../../build-utils-meson
|
|
|
@ -858,7 +858,7 @@ std::vector<FlakeRef> RawInstallablesCommand::getFlakeRefsForCompletion()
|
||||||
applyDefaultInstallables(rawInstallables);
|
applyDefaultInstallables(rawInstallables);
|
||||||
std::vector<FlakeRef> res;
|
std::vector<FlakeRef> res;
|
||||||
res.reserve(rawInstallables.size());
|
res.reserve(rawInstallables.size());
|
||||||
for (auto i : rawInstallables)
|
for (const auto & i : rawInstallables)
|
||||||
res.push_back(parseFlakeRefWithFragment(
|
res.push_back(parseFlakeRefWithFragment(
|
||||||
fetchSettings,
|
fetchSettings,
|
||||||
expandTilde(i),
|
expandTilde(i),
|
||||||
|
|
|
@ -14,7 +14,7 @@ project('nix-cmd', 'cpp',
|
||||||
|
|
||||||
cxx = meson.get_compiler('cpp')
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
subdir('build-utils-meson/deps-lists')
|
subdir('nix-meson-build-support/deps-lists')
|
||||||
|
|
||||||
configdata = configuration_data()
|
configdata = configuration_data()
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ deps_public_maybe_subproject = [
|
||||||
dependency('nix-flake'),
|
dependency('nix-flake'),
|
||||||
dependency('nix-main'),
|
dependency('nix-main'),
|
||||||
]
|
]
|
||||||
subdir('build-utils-meson/subprojects')
|
subdir('nix-meson-build-support/subprojects')
|
||||||
|
|
||||||
nlohmann_json = dependency('nlohmann_json', version : '>= 3.9')
|
nlohmann_json = dependency('nlohmann_json', version : '>= 3.9')
|
||||||
deps_public += nlohmann_json
|
deps_public += nlohmann_json
|
||||||
|
@ -70,7 +70,7 @@ add_project_arguments(
|
||||||
language : 'cpp',
|
language : 'cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('build-utils-meson/common')
|
subdir('nix-meson-build-support/common')
|
||||||
|
|
||||||
sources = files(
|
sources = files(
|
||||||
'built-path.cc',
|
'built-path.cc',
|
||||||
|
@ -125,4 +125,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
|
||||||
|
|
||||||
libraries_private = []
|
libraries_private = []
|
||||||
|
|
||||||
subdir('build-utils-meson/export')
|
subdir('nix-meson-build-support/export')
|
||||||
|
|
1
src/libcmd/nix-meson-build-support
Symbolic link
1
src/libcmd/nix-meson-build-support
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../nix-meson-build-support
|
|
@ -39,8 +39,8 @@ mkMesonLibrary (finalAttrs: {
|
||||||
|
|
||||||
workDir = ./.;
|
workDir = ./.;
|
||||||
fileset = fileset.unions [
|
fileset = fileset.unions [
|
||||||
../../build-utils-meson
|
../../nix-meson-build-support
|
||||||
./build-utils-meson
|
./nix-meson-build-support
|
||||||
../../.version
|
../../.version
|
||||||
./.version
|
./.version
|
||||||
./meson.build
|
./meson.build
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../../build-utils-meson
|
|
|
@ -14,7 +14,7 @@ project('nix-expr-c', 'cpp',
|
||||||
|
|
||||||
cxx = meson.get_compiler('cpp')
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
subdir('build-utils-meson/deps-lists')
|
subdir('nix-meson-build-support/deps-lists')
|
||||||
|
|
||||||
configdata = configuration_data()
|
configdata = configuration_data()
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ deps_public_maybe_subproject = [
|
||||||
dependency('nix-util-c'),
|
dependency('nix-util-c'),
|
||||||
dependency('nix-store-c'),
|
dependency('nix-store-c'),
|
||||||
]
|
]
|
||||||
subdir('build-utils-meson/subprojects')
|
subdir('nix-meson-build-support/subprojects')
|
||||||
|
|
||||||
# TODO rename, because it will conflict with downstream projects
|
# TODO rename, because it will conflict with downstream projects
|
||||||
configdata.set_quoted('PACKAGE_VERSION', meson.project_version())
|
configdata.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||||
|
@ -53,7 +53,7 @@ add_project_arguments(
|
||||||
language : 'cpp',
|
language : 'cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('build-utils-meson/common')
|
subdir('nix-meson-build-support/common')
|
||||||
|
|
||||||
sources = files(
|
sources = files(
|
||||||
'nix_api_expr.cc',
|
'nix_api_expr.cc',
|
||||||
|
@ -72,8 +72,8 @@ headers = [config_h] + files(
|
||||||
# TODO move this header to libexpr, maybe don't use it in tests?
|
# TODO move this header to libexpr, maybe don't use it in tests?
|
||||||
headers += files('nix_api_expr_internal.h')
|
headers += files('nix_api_expr_internal.h')
|
||||||
|
|
||||||
subdir('build-utils-meson/export-all-symbols')
|
subdir('nix-meson-build-support/export-all-symbols')
|
||||||
subdir('build-utils-meson/windows-version')
|
subdir('nix-meson-build-support/windows-version')
|
||||||
|
|
||||||
this_library = library(
|
this_library = library(
|
||||||
'nixexprc',
|
'nixexprc',
|
||||||
|
@ -89,4 +89,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
|
||||||
|
|
||||||
libraries_private = []
|
libraries_private = []
|
||||||
|
|
||||||
subdir('build-utils-meson/export')
|
subdir('nix-meson-build-support/export')
|
||||||
|
|
1
src/libexpr-c/nix-meson-build-support
Symbolic link
1
src/libexpr-c/nix-meson-build-support
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../nix-meson-build-support
|
|
@ -6,6 +6,7 @@
|
||||||
#include "eval-gc.hh"
|
#include "eval-gc.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "eval-settings.hh"
|
#include "eval-settings.hh"
|
||||||
|
#include "ref.hh"
|
||||||
|
|
||||||
#include "nix_api_expr.h"
|
#include "nix_api_expr.h"
|
||||||
#include "nix_api_expr_internal.h"
|
#include "nix_api_expr_internal.h"
|
||||||
|
@ -18,6 +19,29 @@
|
||||||
# include <mutex>
|
# include <mutex>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate and initialize using self-reference
|
||||||
|
*
|
||||||
|
* This allows a brace initializer to reference the object being constructed.
|
||||||
|
*
|
||||||
|
* @warning Use with care, as the pointer points to an object that is not fully constructed yet.
|
||||||
|
*
|
||||||
|
* @tparam T Type to allocate
|
||||||
|
* @tparam F A function type for `init`, taking a T* and returning the initializer for T
|
||||||
|
* @param init Function that takes a T* and returns the initializer for T
|
||||||
|
* @return Pointer to allocated and initialized object
|
||||||
|
*/
|
||||||
|
template <typename T, typename F>
|
||||||
|
static T * unsafe_new_with_self(F && init)
|
||||||
|
{
|
||||||
|
// Allocate
|
||||||
|
void * p = ::operator new(
|
||||||
|
sizeof(T),
|
||||||
|
static_cast<std::align_val_t>(alignof(T)));
|
||||||
|
// Initialize with placement new
|
||||||
|
return new (p) T(init(static_cast<T *>(p)));
|
||||||
|
}
|
||||||
|
|
||||||
nix_err nix_libexpr_init(nix_c_context * context)
|
nix_err nix_libexpr_init(nix_c_context * context)
|
||||||
{
|
{
|
||||||
if (context)
|
if (context)
|
||||||
|
@ -93,7 +117,42 @@ nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_val
|
||||||
NIXC_CATCH_ERRS
|
NIXC_CATCH_ERRS
|
||||||
}
|
}
|
||||||
|
|
||||||
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c, Store * store)
|
nix_eval_state_builder * nix_eval_state_builder_new(nix_c_context * context, Store * store)
|
||||||
|
{
|
||||||
|
if (context)
|
||||||
|
context->last_err_code = NIX_OK;
|
||||||
|
try {
|
||||||
|
return unsafe_new_with_self<nix_eval_state_builder>([&](auto * self) {
|
||||||
|
return nix_eval_state_builder{
|
||||||
|
.store = nix::ref<nix::Store>(store->ptr),
|
||||||
|
.settings = nix::EvalSettings{/* &bool */ self->readOnlyMode},
|
||||||
|
.fetchSettings = nix::fetchers::Settings{},
|
||||||
|
.readOnlyMode = true,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
NIXC_CATCH_ERRS_NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
void nix_eval_state_builder_free(nix_eval_state_builder * builder)
|
||||||
|
{
|
||||||
|
delete builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
nix_err nix_eval_state_builder_load(nix_c_context * context, nix_eval_state_builder * builder)
|
||||||
|
{
|
||||||
|
if (context)
|
||||||
|
context->last_err_code = NIX_OK;
|
||||||
|
try {
|
||||||
|
// TODO: load in one go?
|
||||||
|
builder->settings.readOnlyMode = nix::settings.readOnlyMode;
|
||||||
|
loadConfFile(builder->settings);
|
||||||
|
loadConfFile(builder->fetchSettings);
|
||||||
|
}
|
||||||
|
NIXC_CATCH_ERRS
|
||||||
|
}
|
||||||
|
|
||||||
|
nix_err nix_eval_state_builder_set_lookup_path(nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath_c)
|
||||||
{
|
{
|
||||||
if (context)
|
if (context)
|
||||||
context->last_err_code = NIX_OK;
|
context->last_err_code = NIX_OK;
|
||||||
|
@ -102,28 +161,47 @@ EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c
|
||||||
if (lookupPath_c != nullptr)
|
if (lookupPath_c != nullptr)
|
||||||
for (size_t i = 0; lookupPath_c[i] != nullptr; i++)
|
for (size_t i = 0; lookupPath_c[i] != nullptr; i++)
|
||||||
lookupPath.push_back(lookupPath_c[i]);
|
lookupPath.push_back(lookupPath_c[i]);
|
||||||
|
builder->lookupPath = nix::LookupPath::parse(lookupPath);
|
||||||
|
}
|
||||||
|
NIXC_CATCH_ERRS
|
||||||
|
}
|
||||||
|
|
||||||
void * p = ::operator new(
|
EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder * builder)
|
||||||
sizeof(EvalState),
|
{
|
||||||
static_cast<std::align_val_t>(alignof(EvalState)));
|
if (context)
|
||||||
auto * p2 = static_cast<EvalState *>(p);
|
context->last_err_code = NIX_OK;
|
||||||
new (p) EvalState {
|
try {
|
||||||
.fetchSettings = nix::fetchers::Settings{},
|
return unsafe_new_with_self<EvalState>([&](auto * self) {
|
||||||
.settings = nix::EvalSettings{
|
return EvalState{
|
||||||
nix::settings.readOnlyMode,
|
.fetchSettings = std::move(builder->fetchSettings),
|
||||||
},
|
.settings = std::move(builder->settings),
|
||||||
.state = nix::EvalState(
|
.state = nix::EvalState(
|
||||||
nix::LookupPath::parse(lookupPath),
|
builder->lookupPath,
|
||||||
store->ptr,
|
builder->store,
|
||||||
p2->fetchSettings,
|
self->fetchSettings,
|
||||||
p2->settings),
|
self->settings),
|
||||||
};
|
};
|
||||||
loadConfFile(p2->settings);
|
});
|
||||||
return p2;
|
|
||||||
}
|
}
|
||||||
NIXC_CATCH_ERRS_NULL
|
NIXC_CATCH_ERRS_NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c, Store * store)
|
||||||
|
{
|
||||||
|
auto builder = nix_eval_state_builder_new(context, store);
|
||||||
|
if (builder == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (nix_eval_state_builder_load(context, builder) != NIX_OK)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (nix_eval_state_builder_set_lookup_path(context, builder, lookupPath_c)
|
||||||
|
!= NIX_OK)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return nix_eval_state_build(context, builder);
|
||||||
|
}
|
||||||
|
|
||||||
void nix_state_free(EvalState * state)
|
void nix_state_free(EvalState * state)
|
||||||
{
|
{
|
||||||
delete state;
|
delete state;
|
||||||
|
|
|
@ -30,6 +30,11 @@ extern "C" {
|
||||||
// cffi start
|
// cffi start
|
||||||
|
|
||||||
// Type definitions
|
// Type definitions
|
||||||
|
/**
|
||||||
|
* @brief Builder for EvalState
|
||||||
|
*/
|
||||||
|
typedef struct nix_eval_state_builder nix_eval_state_builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Represents a state of the Nix language evaluator.
|
* @brief Represents a state of the Nix language evaluator.
|
||||||
*
|
*
|
||||||
|
@ -174,12 +179,70 @@ nix_err nix_value_force(nix_c_context * context, EvalState * state, nix_value *
|
||||||
nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_value * value);
|
nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_value * value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a new Nix language evaluator state.
|
* @brief Create a new nix_eval_state_builder
|
||||||
|
*
|
||||||
|
* The settings are initialized to their default value.
|
||||||
|
* Values can be sourced elsewhere with nix_eval_state_builder_load.
|
||||||
|
*
|
||||||
|
* @param[out] context Optional, stores error information
|
||||||
|
* @param[in] store The Nix store to use.
|
||||||
|
* @return A new nix_eval_state_builder or NULL on failure.
|
||||||
|
*/
|
||||||
|
nix_eval_state_builder * nix_eval_state_builder_new(nix_c_context * context, Store * store);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read settings from the ambient environment
|
||||||
|
*
|
||||||
|
* Settings are sourced from environment variables and configuration files,
|
||||||
|
* as documented in the Nix manual.
|
||||||
|
*
|
||||||
|
* @param[out] context Optional, stores error information
|
||||||
|
* @param[out] builder The builder to modify.
|
||||||
|
* @return NIX_OK if successful, an error code otherwise.
|
||||||
|
*/
|
||||||
|
nix_err nix_eval_state_builder_load(nix_c_context * context, nix_eval_state_builder * builder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the lookup path for `<...>` expressions
|
||||||
|
*
|
||||||
|
* @param[in] context Optional, stores error information
|
||||||
|
* @param[in] builder The builder to modify.
|
||||||
|
* @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH.
|
||||||
|
*/
|
||||||
|
nix_err nix_eval_state_builder_set_lookup_path(
|
||||||
|
nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new Nix language evaluator state
|
||||||
|
*
|
||||||
|
* Remember to nix_eval_state_builder_free after building the state.
|
||||||
|
*
|
||||||
|
* @param[out] context Optional, stores error information
|
||||||
|
* @param[in] builder The builder to use and free
|
||||||
|
* @return A new Nix state or NULL on failure.
|
||||||
|
* @see nix_eval_state_builder_new, nix_eval_state_builder_free
|
||||||
|
*/
|
||||||
|
EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder * builder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free a nix_eval_state_builder
|
||||||
|
*
|
||||||
|
* Does not fail.
|
||||||
|
*
|
||||||
|
* @param[in] builder The builder to free.
|
||||||
|
*/
|
||||||
|
void nix_eval_state_builder_free(nix_eval_state_builder * builder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new Nix language evaluator state
|
||||||
|
*
|
||||||
|
* For more control, use nix_eval_state_builder
|
||||||
*
|
*
|
||||||
* @param[out] context Optional, stores error information
|
* @param[out] context Optional, stores error information
|
||||||
* @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH.
|
* @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH.
|
||||||
* @param[in] store The Nix store to use.
|
* @param[in] store The Nix store to use.
|
||||||
* @return A new Nix state or NULL on failure.
|
* @return A new Nix state or NULL on failure.
|
||||||
|
* @see nix_state_builder_new
|
||||||
*/
|
*/
|
||||||
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath, Store * store);
|
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath, Store * store);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,17 @@
|
||||||
#include "eval-settings.hh"
|
#include "eval-settings.hh"
|
||||||
#include "attr-set.hh"
|
#include "attr-set.hh"
|
||||||
#include "nix_api_value.h"
|
#include "nix_api_value.h"
|
||||||
|
#include "search-path.hh"
|
||||||
|
|
||||||
|
struct nix_eval_state_builder
|
||||||
|
{
|
||||||
|
nix::ref<nix::Store> store;
|
||||||
|
nix::EvalSettings settings;
|
||||||
|
nix::fetchers::Settings fetchSettings;
|
||||||
|
nix::LookupPath lookupPath;
|
||||||
|
// TODO: make an EvalSettings setting own this instead?
|
||||||
|
bool readOnlyMode;
|
||||||
|
};
|
||||||
|
|
||||||
struct EvalState
|
struct EvalState
|
||||||
{
|
{
|
||||||
|
|
|
@ -213,7 +213,7 @@ nix_get_string(nix_c_context * context, const nix_value * value, nix_get_string_
|
||||||
/** @brief Get path as string
|
/** @brief Get path as string
|
||||||
* @param[out] context Optional, stores error information
|
* @param[out] context Optional, stores error information
|
||||||
* @param[in] value Nix value to inspect
|
* @param[in] value Nix value to inspect
|
||||||
* @return string
|
* @return string, if the type is NIX_TYPE_PATH
|
||||||
* @return NULL in case of error.
|
* @return NULL in case of error.
|
||||||
*/
|
*/
|
||||||
const char * nix_get_path_string(nix_c_context * context, const nix_value * value);
|
const char * nix_get_path_string(nix_c_context * context, const nix_value * value);
|
||||||
|
|
|
@ -20,8 +20,8 @@ mkMesonLibrary (finalAttrs: {
|
||||||
|
|
||||||
workDir = ./.;
|
workDir = ./.;
|
||||||
fileset = fileset.unions [
|
fileset = fileset.unions [
|
||||||
../../build-utils-meson
|
../../nix-meson-build-support
|
||||||
./build-utils-meson
|
./nix-meson-build-support
|
||||||
../../.version
|
../../.version
|
||||||
./.version
|
./.version
|
||||||
./meson.build
|
./meson.build
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../../build-utils-meson
|
|
|
@ -14,7 +14,7 @@ project('nix-expr-test-support', 'cpp',
|
||||||
|
|
||||||
cxx = meson.get_compiler('cpp')
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
subdir('build-utils-meson/deps-lists')
|
subdir('nix-meson-build-support/deps-lists')
|
||||||
|
|
||||||
deps_private_maybe_subproject = [
|
deps_private_maybe_subproject = [
|
||||||
]
|
]
|
||||||
|
@ -24,8 +24,9 @@ deps_public_maybe_subproject = [
|
||||||
dependency('nix-store'),
|
dependency('nix-store'),
|
||||||
dependency('nix-store-test-support'),
|
dependency('nix-store-test-support'),
|
||||||
dependency('nix-expr'),
|
dependency('nix-expr'),
|
||||||
|
dependency('nix-expr-c'),
|
||||||
]
|
]
|
||||||
subdir('build-utils-meson/subprojects')
|
subdir('nix-meson-build-support/subprojects')
|
||||||
|
|
||||||
rapidcheck = dependency('rapidcheck')
|
rapidcheck = dependency('rapidcheck')
|
||||||
deps_public += rapidcheck
|
deps_public += rapidcheck
|
||||||
|
@ -39,7 +40,7 @@ add_project_arguments(
|
||||||
language : 'cpp',
|
language : 'cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('build-utils-meson/common')
|
subdir('nix-meson-build-support/common')
|
||||||
|
|
||||||
sources = files(
|
sources = files(
|
||||||
'tests/value/context.cc',
|
'tests/value/context.cc',
|
||||||
|
@ -53,8 +54,8 @@ headers = files(
|
||||||
'tests/value/context.hh',
|
'tests/value/context.hh',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('build-utils-meson/export-all-symbols')
|
subdir('nix-meson-build-support/export-all-symbols')
|
||||||
subdir('build-utils-meson/windows-version')
|
subdir('nix-meson-build-support/windows-version')
|
||||||
|
|
||||||
this_library = library(
|
this_library = library(
|
||||||
'nix-expr-test-support',
|
'nix-expr-test-support',
|
||||||
|
@ -72,4 +73,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
|
||||||
|
|
||||||
libraries_private = []
|
libraries_private = []
|
||||||
|
|
||||||
subdir('build-utils-meson/export')
|
subdir('nix-meson-build-support/export')
|
||||||
|
|
1
src/libexpr-test-support/nix-meson-build-support
Symbolic link
1
src/libexpr-test-support/nix-meson-build-support
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../nix-meson-build-support
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
, nix-store-test-support
|
, nix-store-test-support
|
||||||
, nix-expr
|
, nix-expr
|
||||||
|
, nix-expr-c
|
||||||
|
|
||||||
, rapidcheck
|
, rapidcheck
|
||||||
|
|
||||||
|
@ -22,8 +23,8 @@ mkMesonLibrary (finalAttrs: {
|
||||||
|
|
||||||
workDir = ./.;
|
workDir = ./.;
|
||||||
fileset = fileset.unions [
|
fileset = fileset.unions [
|
||||||
../../build-utils-meson
|
../../nix-meson-build-support
|
||||||
./build-utils-meson
|
./nix-meson-build-support
|
||||||
../../.version
|
../../.version
|
||||||
./.version
|
./.version
|
||||||
./meson.build
|
./meson.build
|
||||||
|
@ -35,6 +36,7 @@ mkMesonLibrary (finalAttrs: {
|
||||||
propagatedBuildInputs = [
|
propagatedBuildInputs = [
|
||||||
nix-store-test-support
|
nix-store-test-support
|
||||||
nix-expr
|
nix-expr
|
||||||
|
nix-expr-c
|
||||||
rapidcheck
|
rapidcheck
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../../build-utils-meson
|
|
|
@ -691,15 +691,15 @@ namespace nix {
|
||||||
ASSERT_TRACE2("elemAt \"foo\" (-1)",
|
ASSERT_TRACE2("elemAt \"foo\" (-1)",
|
||||||
TypeError,
|
TypeError,
|
||||||
HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)),
|
HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)),
|
||||||
HintFmt("while evaluating the first argument passed to builtins.elemAt"));
|
HintFmt("while evaluating the first argument passed to 'builtins.elemAt'"));
|
||||||
|
|
||||||
ASSERT_TRACE1("elemAt [] (-1)",
|
ASSERT_TRACE1("elemAt [] (-1)",
|
||||||
Error,
|
Error,
|
||||||
HintFmt("list index %d is out of bounds", -1));
|
HintFmt("'builtins.elemAt' called with index %d on a list of size %d", -1, 0));
|
||||||
|
|
||||||
ASSERT_TRACE1("elemAt [\"foo\"] 3",
|
ASSERT_TRACE1("elemAt [\"foo\"] 3",
|
||||||
Error,
|
Error,
|
||||||
HintFmt("list index %d is out of bounds", 3));
|
HintFmt("'builtins.elemAt' called with index %d on a list of size %d", 3, 1));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,11 +708,11 @@ namespace nix {
|
||||||
ASSERT_TRACE2("head 1",
|
ASSERT_TRACE2("head 1",
|
||||||
TypeError,
|
TypeError,
|
||||||
HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)),
|
HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)),
|
||||||
HintFmt("while evaluating the first argument passed to builtins.elemAt"));
|
HintFmt("while evaluating the first argument passed to 'builtins.head'"));
|
||||||
|
|
||||||
ASSERT_TRACE1("head []",
|
ASSERT_TRACE1("head []",
|
||||||
Error,
|
Error,
|
||||||
HintFmt("list index %d is out of bounds", 0));
|
HintFmt("'builtins.head' called on an empty list"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,11 +721,11 @@ namespace nix {
|
||||||
ASSERT_TRACE2("tail 1",
|
ASSERT_TRACE2("tail 1",
|
||||||
TypeError,
|
TypeError,
|
||||||
HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)),
|
HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)),
|
||||||
HintFmt("while evaluating the first argument passed to builtins.tail"));
|
HintFmt("while evaluating the first argument passed to 'builtins.tail'"));
|
||||||
|
|
||||||
ASSERT_TRACE1("tail []",
|
ASSERT_TRACE1("tail []",
|
||||||
Error,
|
Error,
|
||||||
HintFmt("'tail' called on an empty list"));
|
HintFmt("'builtins.tail' called on an empty list"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ project('nix-expr-tests', 'cpp',
|
||||||
|
|
||||||
cxx = meson.get_compiler('cpp')
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
subdir('build-utils-meson/deps-lists')
|
subdir('nix-meson-build-support/deps-lists')
|
||||||
|
|
||||||
deps_private_maybe_subproject = [
|
deps_private_maybe_subproject = [
|
||||||
dependency('nix-expr'),
|
dependency('nix-expr'),
|
||||||
|
@ -23,10 +23,10 @@ deps_private_maybe_subproject = [
|
||||||
]
|
]
|
||||||
deps_public_maybe_subproject = [
|
deps_public_maybe_subproject = [
|
||||||
]
|
]
|
||||||
subdir('build-utils-meson/subprojects')
|
subdir('nix-meson-build-support/subprojects')
|
||||||
|
|
||||||
subdir('build-utils-meson/export-all-symbols')
|
subdir('nix-meson-build-support/export-all-symbols')
|
||||||
subdir('build-utils-meson/windows-version')
|
subdir('nix-meson-build-support/windows-version')
|
||||||
|
|
||||||
rapidcheck = dependency('rapidcheck')
|
rapidcheck = dependency('rapidcheck')
|
||||||
deps_private += rapidcheck
|
deps_private += rapidcheck
|
||||||
|
@ -49,7 +49,7 @@ add_project_arguments(
|
||||||
language : 'cpp',
|
language : 'cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('build-utils-meson/common')
|
subdir('nix-meson-build-support/common')
|
||||||
|
|
||||||
sources = files(
|
sources = files(
|
||||||
'derived-path.cc',
|
'derived-path.cc',
|
||||||
|
|
1
src/libexpr-tests/nix-meson-build-support
Symbolic link
1
src/libexpr-tests/nix-meson-build-support
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../nix-meson-build-support
|
|
@ -7,12 +7,49 @@
|
||||||
|
|
||||||
#include "tests/nix_api_expr.hh"
|
#include "tests/nix_api_expr.hh"
|
||||||
#include "tests/string_callback.hh"
|
#include "tests/string_callback.hh"
|
||||||
|
#include "file-system.hh"
|
||||||
|
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
namespace nixC {
|
namespace nixC {
|
||||||
|
|
||||||
|
TEST_F(nix_api_store_test, nix_eval_state_lookup_path)
|
||||||
|
{
|
||||||
|
auto tmpDir = nix::createTempDir();
|
||||||
|
auto delTmpDir = std::make_unique<nix::AutoDelete>(tmpDir, true);
|
||||||
|
auto nixpkgs = tmpDir + "/pkgs";
|
||||||
|
auto nixos = tmpDir + "/cfg";
|
||||||
|
std::filesystem::create_directories(nixpkgs);
|
||||||
|
std::filesystem::create_directories(nixos);
|
||||||
|
|
||||||
|
std::string nixpkgsEntry = "nixpkgs=" + nixpkgs;
|
||||||
|
std::string nixosEntry = "nixos-config=" + nixos;
|
||||||
|
const char * lookupPath[] = {nixpkgsEntry.c_str(), nixosEntry.c_str(), nullptr};
|
||||||
|
|
||||||
|
auto builder = nix_eval_state_builder_new(ctx, store);
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
ASSERT_EQ(NIX_OK, nix_eval_state_builder_set_lookup_path(ctx, builder, lookupPath));
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
auto state = nix_eval_state_build(ctx, builder);
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
nix_eval_state_builder_free(builder);
|
||||||
|
|
||||||
|
Value * value = nix_alloc_value(ctx, state);
|
||||||
|
nix_expr_eval_from_string(ctx, state, "builtins.seq <nixos-config> <nixpkgs>", ".", value);
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
ASSERT_EQ(nix_get_type(ctx, value), NIX_TYPE_PATH);
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
auto pathStr = nix_get_path_string(ctx, value);
|
||||||
|
assert_ctx_ok();
|
||||||
|
ASSERT_EQ(0, strcmp(pathStr, nixpkgs.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(nix_api_expr_test, nix_expr_eval_from_string)
|
TEST_F(nix_api_expr_test, nix_expr_eval_from_string)
|
||||||
{
|
{
|
||||||
nix_expr_eval_from_string(nullptr, state, "builtins.nixVersion", ".", value);
|
nix_expr_eval_from_string(nullptr, state, "builtins.nixVersion", ".", value);
|
||||||
|
|
|
@ -27,8 +27,8 @@ mkMesonExecutable (finalAttrs: {
|
||||||
|
|
||||||
workDir = ./.;
|
workDir = ./.;
|
||||||
fileset = fileset.unions [
|
fileset = fileset.unions [
|
||||||
../../build-utils-meson
|
../../nix-meson-build-support
|
||||||
./build-utils-meson
|
./nix-meson-build-support
|
||||||
../../.version
|
../../.version
|
||||||
./.version
|
./.version
|
||||||
./meson.build
|
./meson.build
|
||||||
|
|
|
@ -177,6 +177,57 @@ namespace nix {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// The following macros ultimately define 48 tests (16 variations on three
|
||||||
|
// templates). Each template tests an expression that can be written in 2^4
|
||||||
|
// different ways, by making four choices about whether to write a particular
|
||||||
|
// attribute path segment as `x.y = ...;` (collapsed) or `x = { y = ...; };`
|
||||||
|
// (expanded).
|
||||||
|
//
|
||||||
|
// The nestedAttrsetMergeXXXX tests check that the expression
|
||||||
|
// `{ a.b.c = 1; a.b.d = 2; }` has the same value regardless of how it is
|
||||||
|
// expanded. (That exact expression is exercised in test
|
||||||
|
// nestedAttrsetMerge0000, because it is fully collapsed. The test
|
||||||
|
// nestedAttrsetMerge1001 would instead examine
|
||||||
|
// `{ a = { b.c = 1; }; a.b = { d = 2; }; }`.)
|
||||||
|
//
|
||||||
|
// The nestedAttrsetMergeDupXXXX tests check that the expression
|
||||||
|
// `{ a.b.c = 1; a.b.c = 2; }` throws a duplicate attribute error, again
|
||||||
|
// regardless of how it is expanded.
|
||||||
|
//
|
||||||
|
// The nestedAttrsetMergeLetXXXX tests check that the expression
|
||||||
|
// `let a.b.c = 1; a.b.d = 2; in a` has the same value regardless of how it is
|
||||||
|
// expanded.
|
||||||
|
#define X_EXPAND_IF0(k, v) k "." v
|
||||||
|
#define X_EXPAND_IF1(k, v) k " = { " v " };"
|
||||||
|
#define X4(w, x, y, z) \
|
||||||
|
TEST_F(TrivialExpressionTest, nestedAttrsetMerge##w##x##y##z) { \
|
||||||
|
auto v = eval("{ a.b = { c = 1; d = 2; }; } == { " \
|
||||||
|
X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \
|
||||||
|
X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " }"); \
|
||||||
|
ASSERT_THAT(v, IsTrue()); \
|
||||||
|
}; \
|
||||||
|
TEST_F(TrivialExpressionTest, nestedAttrsetMergeDup##w##x##y##z) { \
|
||||||
|
ASSERT_THROW(eval("{ " \
|
||||||
|
X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \
|
||||||
|
X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "c = 2;")) " }"), Error); \
|
||||||
|
}; \
|
||||||
|
TEST_F(TrivialExpressionTest, nestedAttrsetMergeLet##w##x##y##z) { \
|
||||||
|
auto v = eval("{ b = { c = 1; d = 2; }; } == (let " \
|
||||||
|
X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \
|
||||||
|
X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " in a)"); \
|
||||||
|
ASSERT_THAT(v, IsTrue()); \
|
||||||
|
};
|
||||||
|
#define X3(...) X4(__VA_ARGS__, 0) X4(__VA_ARGS__, 1)
|
||||||
|
#define X2(...) X3(__VA_ARGS__, 0) X3(__VA_ARGS__, 1)
|
||||||
|
#define X1(...) X2(__VA_ARGS__, 0) X2(__VA_ARGS__, 1)
|
||||||
|
X1(0) X1(1)
|
||||||
|
#undef X_EXPAND_IF0
|
||||||
|
#undef X_EXPAND_IF1
|
||||||
|
#undef X1
|
||||||
|
#undef X2
|
||||||
|
#undef X3
|
||||||
|
#undef X4
|
||||||
|
|
||||||
TEST_F(TrivialExpressionTest, functor) {
|
TEST_F(TrivialExpressionTest, functor) {
|
||||||
auto v = eval("{ __functor = self: arg: self.v + arg; v = 10; } 5");
|
auto v = eval("{ __functor = self: arg: self.v + arg; v = 10; } 5");
|
||||||
ASSERT_THAT(v, IsIntEq(15));
|
ASSERT_THAT(v, IsIntEq(15));
|
||||||
|
|
|
@ -129,7 +129,6 @@ std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v
|
||||||
try {
|
try {
|
||||||
auto colon = fn.rfind(':');
|
auto colon = fn.rfind(':');
|
||||||
if (colon == std::string::npos) fail();
|
if (colon == std::string::npos) fail();
|
||||||
std::string filename(fn, 0, colon);
|
|
||||||
auto lineno = std::stoi(std::string(fn, colon + 1, std::string::npos));
|
auto lineno = std::stoi(std::string(fn, colon + 1, std::string::npos));
|
||||||
return {SourcePath{path.accessor, CanonPath(fn.substr(0, colon))}, lineno};
|
return {SourcePath{path.accessor, CanonPath(fn.substr(0, colon))}, lineno};
|
||||||
} catch (std::invalid_argument & e) {
|
} catch (std::invalid_argument & e) {
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../../build-utils-meson
|
|
|
@ -347,6 +347,16 @@ void EvalState::allowPath(const StorePath & storePath)
|
||||||
rootFS2->allowPrefix(CanonPath(store->toRealPath(storePath)));
|
rootFS2->allowPrefix(CanonPath(store->toRealPath(storePath)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EvalState::allowClosure(const StorePath & storePath)
|
||||||
|
{
|
||||||
|
if (!rootFS.dynamic_pointer_cast<AllowListSourceAccessor>()) return;
|
||||||
|
|
||||||
|
StorePathSet closure;
|
||||||
|
store->computeFSClosure(storePath, closure);
|
||||||
|
for (auto & p : closure)
|
||||||
|
allowPath(p);
|
||||||
|
}
|
||||||
|
|
||||||
void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value & v)
|
void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value & v)
|
||||||
{
|
{
|
||||||
allowPath(storePath);
|
allowPath(storePath);
|
||||||
|
@ -3099,10 +3109,7 @@ std::optional<SourcePath> EvalState::resolveLookupPathPath(const LookupPath::Pat
|
||||||
allowPath(path.path.abs());
|
allowPath(path.path.abs());
|
||||||
if (store->isInStore(path.path.abs())) {
|
if (store->isInStore(path.path.abs())) {
|
||||||
try {
|
try {
|
||||||
StorePathSet closure;
|
allowClosure(store->toStorePath(path.path.abs()).first);
|
||||||
store->computeFSClosure(store->toStorePath(path.path.abs()).first, closure);
|
|
||||||
for (auto & p : closure)
|
|
||||||
allowPath(p);
|
|
||||||
} catch (InvalidPath &) { }
|
} catch (InvalidPath &) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3178,5 +3185,14 @@ std::ostream & operator << (std::ostream & str, const ExternalValueBase & v) {
|
||||||
return v.print(str);
|
return v.print(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void forceNoNullByte(std::string_view s)
|
||||||
|
{
|
||||||
|
if (s.find('\0') != s.npos) {
|
||||||
|
using namespace std::string_view_literals;
|
||||||
|
auto str = replaceStrings(std::string(s), "\0"sv, "␀"sv);
|
||||||
|
throw Error("input string '%s' cannot be represented as Nix string because it contains null bytes", str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -400,6 +400,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void allowPath(const StorePath & storePath);
|
void allowPath(const StorePath & storePath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow access to the closure of a store path.
|
||||||
|
*/
|
||||||
|
void allowClosure(const StorePath & storePath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allow access to a store path and return it as a string.
|
* Allow access to a store path and return it as a string.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -50,6 +50,7 @@ class JSONSax : nlohmann::json_sax<json> {
|
||||||
public:
|
public:
|
||||||
void key(string_t & name, EvalState & state)
|
void key(string_t & name, EvalState & state)
|
||||||
{
|
{
|
||||||
|
forceNoNullByte(name);
|
||||||
attrs.insert_or_assign(state.symbols.create(name), &value(state));
|
attrs.insert_or_assign(state.symbols.create(name), &value(state));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -122,6 +123,7 @@ public:
|
||||||
|
|
||||||
bool string(string_t & val) override
|
bool string(string_t & val) override
|
||||||
{
|
{
|
||||||
|
forceNoNullByte(val);
|
||||||
rs->value(state).mkString(val);
|
rs->value(state).mkString(val);
|
||||||
rs->add();
|
rs->add();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
// inluding the generated headers twice leads to errors
|
||||||
|
#ifndef BISON_HEADER
|
||||||
|
# include "lexer-tab.hh"
|
||||||
|
# include "parser-tab.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace nix::lexer::internal {
|
namespace nix::lexer::internal {
|
||||||
|
|
||||||
void initLoc(YYLTYPE * loc);
|
void initLoc(YYLTYPE * loc);
|
||||||
|
|
|
@ -14,7 +14,7 @@ project('nix-expr', 'cpp',
|
||||||
|
|
||||||
cxx = meson.get_compiler('cpp')
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
subdir('build-utils-meson/deps-lists')
|
subdir('nix-meson-build-support/deps-lists')
|
||||||
|
|
||||||
configdata = configuration_data()
|
configdata = configuration_data()
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ deps_public_maybe_subproject = [
|
||||||
dependency('nix-store'),
|
dependency('nix-store'),
|
||||||
dependency('nix-fetchers'),
|
dependency('nix-fetchers'),
|
||||||
]
|
]
|
||||||
subdir('build-utils-meson/subprojects')
|
subdir('nix-meson-build-support/subprojects')
|
||||||
|
|
||||||
boost = dependency(
|
boost = dependency(
|
||||||
'boost',
|
'boost',
|
||||||
|
@ -77,7 +77,7 @@ add_project_arguments(
|
||||||
language : 'cpp',
|
language : 'cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('build-utils-meson/common')
|
subdir('nix-meson-build-support/common')
|
||||||
|
|
||||||
parser_tab = custom_target(
|
parser_tab = custom_target(
|
||||||
input : 'parser.y',
|
input : 'parser.y',
|
||||||
|
@ -121,7 +121,7 @@ lexer_tab = custom_target(
|
||||||
install_dir : get_option('includedir') / 'nix',
|
install_dir : get_option('includedir') / 'nix',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('build-utils-meson/generate-header')
|
subdir('nix-meson-build-support/generate-header')
|
||||||
|
|
||||||
generated_headers = []
|
generated_headers = []
|
||||||
foreach header : [
|
foreach header : [
|
||||||
|
@ -205,4 +205,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
|
||||||
|
|
||||||
libraries_private = []
|
libraries_private = []
|
||||||
|
|
||||||
subdir('build-utils-meson/export')
|
subdir('nix-meson-build-support/export')
|
||||||
|
|
1
src/libexpr/nix-meson-build-support
Symbolic link
1
src/libexpr/nix-meson-build-support
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../nix-meson-build-support
|
|
@ -168,7 +168,7 @@ struct ExprVar : Expr
|
||||||
the set stored in the environment that is `level` levels up
|
the set stored in the environment that is `level` levels up
|
||||||
from the current one.*/
|
from the current one.*/
|
||||||
Level level;
|
Level level;
|
||||||
Displacement displ;
|
Displacement displ = 0;
|
||||||
|
|
||||||
ExprVar(Symbol name) : name(name) { };
|
ExprVar(Symbol name) : name(name) { };
|
||||||
ExprVar(const PosIdx & pos, Symbol name) : pos(pos), name(name) { };
|
ExprVar(const PosIdx & pos, Symbol name) : pos(pos), name(name) { };
|
||||||
|
@ -242,7 +242,7 @@ struct ExprAttrs : Expr
|
||||||
Kind kind;
|
Kind kind;
|
||||||
Expr * e;
|
Expr * e;
|
||||||
PosIdx pos;
|
PosIdx pos;
|
||||||
Displacement displ; // displacement
|
Displacement displ = 0; // displacement
|
||||||
AttrDef(Expr * e, const PosIdx & pos, Kind kind = Kind::Plain)
|
AttrDef(Expr * e, const PosIdx & pos, Kind kind = Kind::Plain)
|
||||||
: kind(kind), e(e), pos(pos) { };
|
: kind(kind), e(e), pos(pos) { };
|
||||||
AttrDef() { };
|
AttrDef() { };
|
||||||
|
|
|
@ -40,8 +40,8 @@ mkMesonLibrary (finalAttrs: {
|
||||||
|
|
||||||
workDir = ./.;
|
workDir = ./.;
|
||||||
fileset = fileset.unions [
|
fileset = fileset.unions [
|
||||||
../../build-utils-meson
|
../../nix-meson-build-support
|
||||||
./build-utils-meson
|
./nix-meson-build-support
|
||||||
../../.version
|
../../.version
|
||||||
./.version
|
./.version
|
||||||
./meson.build
|
./meson.build
|
||||||
|
|
|
@ -88,6 +88,7 @@ struct ParserState
|
||||||
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
|
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
|
||||||
void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos);
|
void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos);
|
||||||
void addAttr(ExprAttrs * attrs, AttrPath && attrPath, const ParserLocation & loc, Expr * e, const ParserLocation & exprLoc);
|
void addAttr(ExprAttrs * attrs, AttrPath && attrPath, const ParserLocation & loc, Expr * e, const ParserLocation & exprLoc);
|
||||||
|
void addAttr(ExprAttrs * attrs, AttrPath & attrPath, const Symbol & symbol, ExprAttrs::AttrDef && def);
|
||||||
Formals * validateFormals(Formals * formals, PosIdx pos = noPos, Symbol arg = {});
|
Formals * validateFormals(Formals * formals, PosIdx pos = noPos, Symbol arg = {});
|
||||||
Expr * stripIndentation(const PosIdx pos,
|
Expr * stripIndentation(const PosIdx pos,
|
||||||
std::vector<std::pair<PosIdx, std::variant<Expr *, StringToken>>> && es);
|
std::vector<std::pair<PosIdx, std::variant<Expr *, StringToken>>> && es);
|
||||||
|
@ -120,64 +121,29 @@ inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, const
|
||||||
// Checking attrPath validity.
|
// Checking attrPath validity.
|
||||||
// ===========================
|
// ===========================
|
||||||
for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
|
for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
|
||||||
|
ExprAttrs * nested;
|
||||||
if (i->symbol) {
|
if (i->symbol) {
|
||||||
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
|
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
|
||||||
if (j != attrs->attrs.end()) {
|
if (j != attrs->attrs.end()) {
|
||||||
if (j->second.kind != ExprAttrs::AttrDef::Kind::Inherited) {
|
nested = dynamic_cast<ExprAttrs *>(j->second.e);
|
||||||
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e);
|
if (!nested) {
|
||||||
if (!attrs2) dupAttr(attrPath, pos, j->second.pos);
|
attrPath.erase(i + 1, attrPath.end());
|
||||||
attrs = attrs2;
|
|
||||||
} else
|
|
||||||
dupAttr(attrPath, pos, j->second.pos);
|
dupAttr(attrPath, pos, j->second.pos);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ExprAttrs * nested = new ExprAttrs;
|
nested = new ExprAttrs;
|
||||||
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
|
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
|
||||||
attrs = nested;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ExprAttrs *nested = new ExprAttrs;
|
nested = new ExprAttrs;
|
||||||
attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, nested, pos));
|
attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, nested, pos));
|
||||||
attrs = nested;
|
|
||||||
}
|
}
|
||||||
|
attrs = nested;
|
||||||
}
|
}
|
||||||
// Expr insertion.
|
// Expr insertion.
|
||||||
// ==========================
|
// ==========================
|
||||||
if (i->symbol) {
|
if (i->symbol) {
|
||||||
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
|
addAttr(attrs, attrPath, i->symbol, ExprAttrs::AttrDef(e, pos));
|
||||||
if (j != attrs->attrs.end()) {
|
|
||||||
// This attr path is already defined. However, if both
|
|
||||||
// e and the expr pointed by the attr path are two attribute sets,
|
|
||||||
// we want to merge them.
|
|
||||||
// Otherwise, throw an error.
|
|
||||||
auto ae = dynamic_cast<ExprAttrs *>(e);
|
|
||||||
auto jAttrs = dynamic_cast<ExprAttrs *>(j->second.e);
|
|
||||||
if (jAttrs && ae) {
|
|
||||||
if (ae->inheritFromExprs && !jAttrs->inheritFromExprs)
|
|
||||||
jAttrs->inheritFromExprs = std::make_unique<std::vector<Expr *>>();
|
|
||||||
for (auto & ad : ae->attrs) {
|
|
||||||
auto j2 = jAttrs->attrs.find(ad.first);
|
|
||||||
if (j2 != jAttrs->attrs.end()) // Attr already defined in iAttrs, error.
|
|
||||||
dupAttr(ad.first, j2->second.pos, ad.second.pos);
|
|
||||||
jAttrs->attrs.emplace(ad.first, ad.second);
|
|
||||||
if (ad.second.kind == ExprAttrs::AttrDef::Kind::InheritedFrom) {
|
|
||||||
auto & sel = dynamic_cast<ExprSelect &>(*ad.second.e);
|
|
||||||
auto & from = dynamic_cast<ExprInheritFrom &>(*sel.e);
|
|
||||||
from.displ += jAttrs->inheritFromExprs->size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jAttrs->dynamicAttrs.insert(jAttrs->dynamicAttrs.end(), ae->dynamicAttrs.begin(), ae->dynamicAttrs.end());
|
|
||||||
if (ae->inheritFromExprs) {
|
|
||||||
jAttrs->inheritFromExprs->insert(jAttrs->inheritFromExprs->end(),
|
|
||||||
ae->inheritFromExprs->begin(), ae->inheritFromExprs->end());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dupAttr(attrPath, pos, j->second.pos);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// This attr path is not defined. Let's create it.
|
|
||||||
attrs->attrs.emplace(i->symbol, ExprAttrs::AttrDef(e, pos));
|
|
||||||
e->setName(i->symbol);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, e, pos));
|
attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, e, pos));
|
||||||
}
|
}
|
||||||
|
@ -189,6 +155,60 @@ inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Precondition: attrPath is used for error messages and should already contain
|
||||||
|
* symbol as its last element.
|
||||||
|
*/
|
||||||
|
inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath & attrPath, const Symbol & symbol, ExprAttrs::AttrDef && def)
|
||||||
|
{
|
||||||
|
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(symbol);
|
||||||
|
if (j != attrs->attrs.end()) {
|
||||||
|
// This attr path is already defined. However, if both
|
||||||
|
// e and the expr pointed by the attr path are two attribute sets,
|
||||||
|
// we want to merge them.
|
||||||
|
// Otherwise, throw an error.
|
||||||
|
auto ae = dynamic_cast<ExprAttrs *>(def.e);
|
||||||
|
auto jAttrs = dynamic_cast<ExprAttrs *>(j->second.e);
|
||||||
|
|
||||||
|
// N.B. In a world in which we are less bound by our past mistakes, we
|
||||||
|
// would also test that jAttrs and ae are not recursive. The effect of
|
||||||
|
// not doing so is that any `rec` marker on ae is discarded, and any
|
||||||
|
// `rec` marker on jAttrs will apply to the attributes in ae.
|
||||||
|
// See https://github.com/NixOS/nix/issues/9020.
|
||||||
|
if (jAttrs && ae) {
|
||||||
|
if (ae->inheritFromExprs && !jAttrs->inheritFromExprs)
|
||||||
|
jAttrs->inheritFromExprs = std::make_unique<std::vector<Expr *>>();
|
||||||
|
for (auto & ad : ae->attrs) {
|
||||||
|
if (ad.second.kind == ExprAttrs::AttrDef::Kind::InheritedFrom) {
|
||||||
|
auto & sel = dynamic_cast<ExprSelect &>(*ad.second.e);
|
||||||
|
auto & from = dynamic_cast<ExprInheritFrom &>(*sel.e);
|
||||||
|
from.displ += jAttrs->inheritFromExprs->size();
|
||||||
|
}
|
||||||
|
attrPath.emplace_back(AttrName(ad.first));
|
||||||
|
addAttr(jAttrs, attrPath, ad.first, std::move(ad.second));
|
||||||
|
attrPath.pop_back();
|
||||||
|
}
|
||||||
|
ae->attrs.clear();
|
||||||
|
jAttrs->dynamicAttrs.insert(jAttrs->dynamicAttrs.end(),
|
||||||
|
std::make_move_iterator(ae->dynamicAttrs.begin()),
|
||||||
|
std::make_move_iterator(ae->dynamicAttrs.end()));
|
||||||
|
ae->dynamicAttrs.clear();
|
||||||
|
if (ae->inheritFromExprs) {
|
||||||
|
jAttrs->inheritFromExprs->insert(jAttrs->inheritFromExprs->end(),
|
||||||
|
std::make_move_iterator(ae->inheritFromExprs->begin()),
|
||||||
|
std::make_move_iterator(ae->inheritFromExprs->end()));
|
||||||
|
ae->inheritFromExprs = nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dupAttr(attrPath, def.pos, j->second.pos);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This attr path is not defined. Let's create it.
|
||||||
|
attrs->attrs.emplace(symbol, def);
|
||||||
|
def.e->setName(symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline Formals * ParserState::validateFormals(Formals * formals, PosIdx pos, Symbol arg)
|
inline Formals * ParserState::validateFormals(Formals * formals, PosIdx pos, Symbol arg)
|
||||||
{
|
{
|
||||||
std::sort(formals->formals.begin(), formals->formals.end(),
|
std::sort(formals->formals.begin(), formals->formals.end(),
|
||||||
|
|
|
@ -66,14 +66,12 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS
|
||||||
ensureValid(b.drvPath->getBaseStorePath());
|
ensureValid(b.drvPath->getBaseStorePath());
|
||||||
},
|
},
|
||||||
[&](const NixStringContextElem::Opaque & o) {
|
[&](const NixStringContextElem::Opaque & o) {
|
||||||
auto ctxS = store->printStorePath(o.path);
|
|
||||||
ensureValid(o.path);
|
ensureValid(o.path);
|
||||||
if (maybePathsOut)
|
if (maybePathsOut)
|
||||||
maybePathsOut->emplace(o.path);
|
maybePathsOut->emplace(o.path);
|
||||||
},
|
},
|
||||||
[&](const NixStringContextElem::DrvDeep & d) {
|
[&](const NixStringContextElem::DrvDeep & d) {
|
||||||
/* Treat same as Opaque */
|
/* Treat same as Opaque */
|
||||||
auto ctxS = store->printStorePath(d.drvPath);
|
|
||||||
ensureValid(d.drvPath);
|
ensureValid(d.drvPath);
|
||||||
if (maybePathsOut)
|
if (maybePathsOut)
|
||||||
maybePathsOut->emplace(d.drvPath);
|
maybePathsOut->emplace(d.drvPath);
|
||||||
|
@ -121,11 +119,9 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS
|
||||||
if (store != buildStore) copyClosure(*buildStore, *store, outputsToCopyAndAllow);
|
if (store != buildStore) copyClosure(*buildStore, *store, outputsToCopyAndAllow);
|
||||||
|
|
||||||
if (isIFD) {
|
if (isIFD) {
|
||||||
for (auto & outputPath : outputsToCopyAndAllow) {
|
/* Allow access to the output closures of this derivation. */
|
||||||
/* Add the output of this derivations to the allowed
|
for (auto & outputPath : outputsToCopyAndAllow)
|
||||||
paths. */
|
allowClosure(outputPath);
|
||||||
allowPath(outputPath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -1102,7 +1098,7 @@ static RegisterPrimOp primop_warn({
|
||||||
.name = "__warn",
|
.name = "__warn",
|
||||||
.args = {"e1", "e2"},
|
.args = {"e1", "e2"},
|
||||||
.doc = R"(
|
.doc = R"(
|
||||||
Evaluate *e1*, which must be a string and print iton standard error as a warning.
|
Evaluate *e1*, which must be a string, and print it on standard error as a warning.
|
||||||
Then return *e2*.
|
Then return *e2*.
|
||||||
This function is useful for non-critical situations where attention is advisable.
|
This function is useful for non-critical situations where attention is advisable.
|
||||||
|
|
||||||
|
@ -3261,23 +3257,19 @@ static RegisterPrimOp primop_isList({
|
||||||
.fun = prim_isList,
|
.fun = prim_isList,
|
||||||
});
|
});
|
||||||
|
|
||||||
static void elemAt(EvalState & state, const PosIdx pos, Value & list, int n, Value & v)
|
|
||||||
{
|
|
||||||
state.forceList(list, pos, "while evaluating the first argument passed to builtins.elemAt");
|
|
||||||
if (n < 0 || (unsigned int) n >= list.listSize())
|
|
||||||
state.error<EvalError>(
|
|
||||||
"list index %1% is out of bounds",
|
|
||||||
n
|
|
||||||
).atPos(pos).debugThrow();
|
|
||||||
state.forceValue(*list.listElems()[n], pos);
|
|
||||||
v = *list.listElems()[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the n-1'th element of a list. */
|
/* Return the n-1'th element of a list. */
|
||||||
static void prim_elemAt(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_elemAt(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
NixInt::Inner elem = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.elemAt").value;
|
NixInt::Inner n = state.forceInt(*args[1], pos, "while evaluating the second argument passed to 'builtins.elemAt'").value;
|
||||||
elemAt(state, pos, *args[0], elem, v);
|
state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.elemAt'");
|
||||||
|
if (n < 0 || (unsigned int) n >= args[0]->listSize())
|
||||||
|
state.error<EvalError>(
|
||||||
|
"'builtins.elemAt' called with index %d on a list of size %d",
|
||||||
|
n,
|
||||||
|
args[0]->listSize()
|
||||||
|
).atPos(pos).debugThrow();
|
||||||
|
state.forceValue(*args[0]->listElems()[n], pos);
|
||||||
|
v = *args[0]->listElems()[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_elemAt({
|
static RegisterPrimOp primop_elemAt({
|
||||||
|
@ -3293,7 +3285,13 @@ static RegisterPrimOp primop_elemAt({
|
||||||
/* Return the first element of a list. */
|
/* Return the first element of a list. */
|
||||||
static void prim_head(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_head(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
elemAt(state, pos, *args[0], 0, v);
|
state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.head'");
|
||||||
|
if (args[0]->listSize() == 0)
|
||||||
|
state.error<EvalError>(
|
||||||
|
"'builtins.head' called on an empty list"
|
||||||
|
).atPos(pos).debugThrow();
|
||||||
|
state.forceValue(*args[0]->listElems()[0], pos);
|
||||||
|
v = *args[0]->listElems()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_head({
|
static RegisterPrimOp primop_head({
|
||||||
|
@ -3312,9 +3310,9 @@ static RegisterPrimOp primop_head({
|
||||||
don't want to use it! */
|
don't want to use it! */
|
||||||
static void prim_tail(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_tail(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.tail");
|
state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.tail'");
|
||||||
if (args[0]->listSize() == 0)
|
if (args[0]->listSize() == 0)
|
||||||
state.error<EvalError>("'tail' called on an empty list").atPos(pos).debugThrow();
|
state.error<EvalError>("'builtins.tail' called on an empty list").atPos(pos).debugThrow();
|
||||||
|
|
||||||
auto list = state.buildList(args[0]->listSize() - 1);
|
auto list = state.buildList(args[0]->listSize() - 1);
|
||||||
for (const auto & [n, v] : enumerate(list))
|
for (const auto & [n, v] : enumerate(list))
|
||||||
|
@ -4385,7 +4383,7 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
|
|
||||||
for (auto i = begin; i != end; ++i) {
|
for (auto i = begin; i != end; ++i) {
|
||||||
assert(idx <= 2 * len + 1 - 3);
|
assert(idx <= 2 * len + 1 - 3);
|
||||||
auto match = *i;
|
const auto & match = *i;
|
||||||
|
|
||||||
// Add a string for non-matched characters.
|
// Add a string for non-matched characters.
|
||||||
list[idx++] = mkString(state, match.prefix());
|
list[idx++] = mkString(state, match.prefix());
|
||||||
|
|
|
@ -132,6 +132,8 @@ static void prim_addDrvOutputDependencies(EvalState & state, const PosIdx pos, V
|
||||||
},
|
},
|
||||||
[&](const NixStringContextElem::DrvDeep & c) -> NixStringContextElem::DrvDeep {
|
[&](const NixStringContextElem::DrvDeep & c) -> NixStringContextElem::DrvDeep {
|
||||||
/* Reuse original item because we want this to be idempotent. */
|
/* Reuse original item because we want this to be idempotent. */
|
||||||
|
/* FIXME: Suspicious move out of const. This is actually a copy, so the comment
|
||||||
|
above does not make much sense. */
|
||||||
return std::move(c);
|
return std::move(c);
|
||||||
},
|
},
|
||||||
}, context.begin()->raw) }),
|
}, context.begin()->raw) }),
|
||||||
|
|
|
@ -40,7 +40,7 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto toPath = *toPathMaybe;
|
const auto & toPath = *toPathMaybe;
|
||||||
|
|
||||||
// check and return
|
// check and return
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,10 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V
|
||||||
|
|
||||||
auto attrs = state.buildBindings(size);
|
auto attrs = state.buildBindings(size);
|
||||||
|
|
||||||
for(auto & elem : table)
|
for(auto & elem : table) {
|
||||||
|
forceNoNullByte(elem.first);
|
||||||
visit(attrs.alloc(elem.first), elem.second);
|
visit(attrs.alloc(elem.first), elem.second);
|
||||||
|
}
|
||||||
|
|
||||||
v.mkAttrs(attrs);
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
@ -54,7 +56,11 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V
|
||||||
v.mkFloat(toml::get<NixFloat>(t));
|
v.mkFloat(toml::get<NixFloat>(t));
|
||||||
break;;
|
break;;
|
||||||
case toml::value_t::string:
|
case toml::value_t::string:
|
||||||
v.mkString(toml::get<std::string>(t));
|
{
|
||||||
|
auto s = toml::get<std::string_view>(t);
|
||||||
|
forceNoNullByte(s);
|
||||||
|
v.mkString(s);
|
||||||
|
}
|
||||||
break;;
|
break;;
|
||||||
case toml::value_t::local_datetime:
|
case toml::value_t::local_datetime:
|
||||||
case toml::value_t::offset_datetime:
|
case toml::value_t::offset_datetime:
|
||||||
|
@ -66,7 +72,9 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V
|
||||||
attrs.alloc("_type").mkString("timestamp");
|
attrs.alloc("_type").mkString("timestamp");
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << t;
|
s << t;
|
||||||
attrs.alloc("value").mkString(toView(s));
|
auto str = toView(s);
|
||||||
|
forceNoNullByte(str);
|
||||||
|
attrs.alloc("value").mkString(str);
|
||||||
v.mkAttrs(attrs);
|
v.mkAttrs(attrs);
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Dates and times are not supported");
|
throw std::runtime_error("Dates and times are not supported");
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
|
@ -510,4 +510,6 @@ typedef std::shared_ptr<Value *> RootValue;
|
||||||
|
|
||||||
RootValue allocRootValue(Value * v);
|
RootValue allocRootValue(Value * v);
|
||||||
|
|
||||||
|
void forceNoNullByte(std::string_view s);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../../build-utils-meson
|
|
|
@ -14,7 +14,7 @@ project('nix-fetchers-tests', 'cpp',
|
||||||
|
|
||||||
cxx = meson.get_compiler('cpp')
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
subdir('build-utils-meson/deps-lists')
|
subdir('nix-meson-build-support/deps-lists')
|
||||||
|
|
||||||
deps_private_maybe_subproject = [
|
deps_private_maybe_subproject = [
|
||||||
dependency('nix-store-test-support'),
|
dependency('nix-store-test-support'),
|
||||||
|
@ -22,10 +22,10 @@ deps_private_maybe_subproject = [
|
||||||
]
|
]
|
||||||
deps_public_maybe_subproject = [
|
deps_public_maybe_subproject = [
|
||||||
]
|
]
|
||||||
subdir('build-utils-meson/subprojects')
|
subdir('nix-meson-build-support/subprojects')
|
||||||
|
|
||||||
subdir('build-utils-meson/export-all-symbols')
|
subdir('nix-meson-build-support/export-all-symbols')
|
||||||
subdir('build-utils-meson/windows-version')
|
subdir('nix-meson-build-support/windows-version')
|
||||||
|
|
||||||
rapidcheck = dependency('rapidcheck')
|
rapidcheck = dependency('rapidcheck')
|
||||||
deps_private += rapidcheck
|
deps_private += rapidcheck
|
||||||
|
@ -42,7 +42,7 @@ add_project_arguments(
|
||||||
language : 'cpp',
|
language : 'cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('build-utils-meson/common')
|
subdir('nix-meson-build-support/common')
|
||||||
|
|
||||||
sources = files(
|
sources = files(
|
||||||
'public-key.cc',
|
'public-key.cc',
|
||||||
|
|
1
src/libfetchers-tests/nix-meson-build-support
Symbolic link
1
src/libfetchers-tests/nix-meson-build-support
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../nix-meson-build-support
|
|
@ -26,8 +26,8 @@ mkMesonExecutable (finalAttrs: {
|
||||||
|
|
||||||
workDir = ./.;
|
workDir = ./.;
|
||||||
fileset = fileset.unions [
|
fileset = fileset.unions [
|
||||||
../../build-utils-meson
|
../../nix-meson-build-support
|
||||||
./build-utils-meson
|
./nix-meson-build-support
|
||||||
../../.version
|
../../.version
|
||||||
./.version
|
./.version
|
||||||
./meson.build
|
./meson.build
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../../build-utils-meson
|
|
|
@ -113,7 +113,15 @@ Input Input::fromAttrs(const Settings & settings, Attrs && attrs)
|
||||||
|
|
||||||
std::optional<std::string> Input::getFingerprint(ref<Store> store) const
|
std::optional<std::string> Input::getFingerprint(ref<Store> store) const
|
||||||
{
|
{
|
||||||
return scheme ? scheme->getFingerprint(store, *this) : std::nullopt;
|
if (!scheme) return std::nullopt;
|
||||||
|
|
||||||
|
if (cachedFingerprint) return *cachedFingerprint;
|
||||||
|
|
||||||
|
auto fingerprint = scheme->getFingerprint(store, *this);
|
||||||
|
|
||||||
|
cachedFingerprint = fingerprint;
|
||||||
|
|
||||||
|
return fingerprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParsedURL Input::toURL() const
|
ParsedURL Input::toURL() const
|
||||||
|
@ -313,7 +321,7 @@ std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(ref<Store> sto
|
||||||
|
|
||||||
auto accessor = makeStorePathAccessor(store, storePath);
|
auto accessor = makeStorePathAccessor(store, storePath);
|
||||||
|
|
||||||
accessor->fingerprint = scheme->getFingerprint(store, *this);
|
accessor->fingerprint = getFingerprint(store);
|
||||||
|
|
||||||
return {accessor, *this};
|
return {accessor, *this};
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
|
@ -324,7 +332,7 @@ std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(ref<Store> sto
|
||||||
auto [accessor, result] = scheme->getAccessor(store, *this);
|
auto [accessor, result] = scheme->getAccessor(store, *this);
|
||||||
|
|
||||||
assert(!accessor->fingerprint);
|
assert(!accessor->fingerprint);
|
||||||
accessor->fingerprint = scheme->getFingerprint(store, result);
|
accessor->fingerprint = result.getFingerprint(store);
|
||||||
|
|
||||||
return {accessor, std::move(result)};
|
return {accessor, std::move(result)};
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,11 @@ struct Input
|
||||||
std::shared_ptr<InputScheme> scheme; // note: can be null
|
std::shared_ptr<InputScheme> scheme; // note: can be null
|
||||||
Attrs attrs;
|
Attrs attrs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached result of getFingerprint().
|
||||||
|
*/
|
||||||
|
mutable std::optional<std::optional<std::string>> cachedFingerprint;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Create an `Input` from a URL.
|
* Create an `Input` from a URL.
|
||||||
|
@ -105,6 +110,11 @@ public:
|
||||||
|
|
||||||
bool operator ==(const Input & other) const noexcept;
|
bool operator ==(const Input & other) const noexcept;
|
||||||
|
|
||||||
|
bool operator <(const Input & other) const
|
||||||
|
{
|
||||||
|
return attrs < other.attrs;
|
||||||
|
}
|
||||||
|
|
||||||
bool contains(const Input & other) const;
|
bool contains(const Input & other) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "signals.hh"
|
#include "signals.hh"
|
||||||
#include "users.hh"
|
#include "users.hh"
|
||||||
#include "fs-sink.hh"
|
#include "fs-sink.hh"
|
||||||
|
#include "sync.hh"
|
||||||
|
|
||||||
#include <git2/attr.h>
|
#include <git2/attr.h>
|
||||||
#include <git2/blob.h>
|
#include <git2/blob.h>
|
||||||
|
@ -437,7 +438,12 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
||||||
{
|
{
|
||||||
if (!(statusFlags & GIT_STATUS_INDEX_DELETED) &&
|
if (!(statusFlags & GIT_STATUS_INDEX_DELETED) &&
|
||||||
!(statusFlags & GIT_STATUS_WT_DELETED))
|
!(statusFlags & GIT_STATUS_WT_DELETED))
|
||||||
|
{
|
||||||
info.files.insert(CanonPath(path));
|
info.files.insert(CanonPath(path));
|
||||||
|
if (statusFlags != GIT_STATUS_CURRENT)
|
||||||
|
info.dirtyFiles.insert(CanonPath(path));
|
||||||
|
} else
|
||||||
|
info.deletedFiles.insert(CanonPath(path));
|
||||||
if (statusFlags != GIT_STATUS_CURRENT)
|
if (statusFlags != GIT_STATUS_CURRENT)
|
||||||
info.isDirty = true;
|
info.isDirty = true;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1262,4 +1268,17 @@ ref<GitRepo> getTarballCache()
|
||||||
return GitRepo::openRepo(repoDir, true, true);
|
return GitRepo::openRepo(repoDir, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GitRepo::WorkdirInfo GitRepo::getCachedWorkdirInfo(const std::filesystem::path & path)
|
||||||
|
{
|
||||||
|
static Sync<std::map<std::filesystem::path, WorkdirInfo>> _cache;
|
||||||
|
{
|
||||||
|
auto cache(_cache.lock());
|
||||||
|
auto i = cache->find(path);
|
||||||
|
if (i != cache->end()) return i->second;
|
||||||
|
}
|
||||||
|
auto workdirInfo = GitRepo::openRepo(path)->getWorkdirInfo();
|
||||||
|
_cache.lock()->emplace(path, workdirInfo);
|
||||||
|
return workdirInfo;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,12 +59,20 @@ struct GitRepo
|
||||||
modified or added, but excluding deleted files. */
|
modified or added, but excluding deleted files. */
|
||||||
std::set<CanonPath> files;
|
std::set<CanonPath> files;
|
||||||
|
|
||||||
|
/* All modified or added files. */
|
||||||
|
std::set<CanonPath> dirtyFiles;
|
||||||
|
|
||||||
|
/* The deleted files. */
|
||||||
|
std::set<CanonPath> deletedFiles;
|
||||||
|
|
||||||
/* The submodules listed in .gitmodules of this workdir. */
|
/* The submodules listed in .gitmodules of this workdir. */
|
||||||
std::vector<Submodule> submodules;
|
std::vector<Submodule> submodules;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual WorkdirInfo getWorkdirInfo() = 0;
|
virtual WorkdirInfo getWorkdirInfo() = 0;
|
||||||
|
|
||||||
|
static WorkdirInfo getCachedWorkdirInfo(const std::filesystem::path & path);
|
||||||
|
|
||||||
/* Get the ref that HEAD points to. */
|
/* Get the ref that HEAD points to. */
|
||||||
virtual std::optional<std::string> getWorkdirRef() = 0;
|
virtual std::optional<std::string> getWorkdirRef() = 0;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "finally.hh"
|
#include "finally.hh"
|
||||||
#include "fetch-settings.hh"
|
#include "fetch-settings.hh"
|
||||||
#include "json-utils.hh"
|
#include "json-utils.hh"
|
||||||
|
#include "archive.hh"
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -430,7 +431,7 @@ struct GitInputScheme : InputScheme
|
||||||
// If this is a local directory and no ref or revision is
|
// If this is a local directory and no ref or revision is
|
||||||
// given, then allow the use of an unclean working tree.
|
// given, then allow the use of an unclean working tree.
|
||||||
if (!input.getRef() && !input.getRev() && repoInfo.isLocal)
|
if (!input.getRef() && !input.getRev() && repoInfo.isLocal)
|
||||||
repoInfo.workdirInfo = GitRepo::openRepo(repoInfo.url)->getWorkdirInfo();
|
repoInfo.workdirInfo = GitRepo::getCachedWorkdirInfo(repoInfo.url);
|
||||||
|
|
||||||
return repoInfo;
|
return repoInfo;
|
||||||
}
|
}
|
||||||
|
@ -514,8 +515,6 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
auto origRev = input.getRev();
|
auto origRev = input.getRev();
|
||||||
|
|
||||||
std::string name = input.getName();
|
|
||||||
|
|
||||||
auto originalRef = input.getRef();
|
auto originalRef = input.getRef();
|
||||||
auto ref = originalRef ? *originalRef : getDefaultRef(repoInfo);
|
auto ref = originalRef ? *originalRef : getDefaultRef(repoInfo);
|
||||||
input.attrs.insert_or_assign("ref", ref);
|
input.attrs.insert_or_assign("ref", ref);
|
||||||
|
@ -795,10 +794,33 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
std::optional<std::string> getFingerprint(ref<Store> store, const Input & input) const override
|
std::optional<std::string> getFingerprint(ref<Store> store, const Input & input) const override
|
||||||
{
|
{
|
||||||
|
auto makeFingerprint = [&](const Hash & rev)
|
||||||
|
{
|
||||||
|
return rev.gitRev() + (getSubmodulesAttr(input) ? ";s" : "") + (getExportIgnoreAttr(input) ? ";e" : "");
|
||||||
|
};
|
||||||
|
|
||||||
if (auto rev = input.getRev())
|
if (auto rev = input.getRev())
|
||||||
return rev->gitRev() + (getSubmodulesAttr(input) ? ";s" : "") + (getExportIgnoreAttr(input) ? ";e" : "");
|
return makeFingerprint(*rev);
|
||||||
else
|
else {
|
||||||
|
auto repoInfo = getRepoInfo(input);
|
||||||
|
if (repoInfo.isLocal && repoInfo.workdirInfo.headRev && repoInfo.workdirInfo.submodules.empty()) {
|
||||||
|
/* Calculate a fingerprint that takes into account the
|
||||||
|
deleted and modified/added files. */
|
||||||
|
HashSink hashSink{HashAlgorithm::SHA512};
|
||||||
|
for (auto & file : repoInfo.workdirInfo.dirtyFiles) {
|
||||||
|
writeString("modified:", hashSink);
|
||||||
|
writeString(file.abs(), hashSink);
|
||||||
|
dumpPath(repoInfo.url + "/" + file.abs(), hashSink);
|
||||||
|
}
|
||||||
|
for (auto & file : repoInfo.workdirInfo.deletedFiles) {
|
||||||
|
writeString("deleted:", hashSink);
|
||||||
|
writeString(file.abs(), hashSink);
|
||||||
|
}
|
||||||
|
return makeFingerprint(*repoInfo.workdirInfo.headRev)
|
||||||
|
+ ";d=" + hashSink.finish().first.to_string(HashFormat::Base16, false);
|
||||||
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isLocked(const Input & input) const override
|
bool isLocked(const Input & input) const override
|
||||||
|
|
|
@ -14,7 +14,7 @@ project('nix-fetchers', 'cpp',
|
||||||
|
|
||||||
cxx = meson.get_compiler('cpp')
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
subdir('build-utils-meson/deps-lists')
|
subdir('nix-meson-build-support/deps-lists')
|
||||||
|
|
||||||
configdata = configuration_data()
|
configdata = configuration_data()
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ deps_public_maybe_subproject = [
|
||||||
dependency('nix-util'),
|
dependency('nix-util'),
|
||||||
dependency('nix-store'),
|
dependency('nix-store'),
|
||||||
]
|
]
|
||||||
subdir('build-utils-meson/subprojects')
|
subdir('nix-meson-build-support/subprojects')
|
||||||
|
|
||||||
nlohmann_json = dependency('nlohmann_json', version : '>= 3.9')
|
nlohmann_json = dependency('nlohmann_json', version : '>= 3.9')
|
||||||
deps_public += nlohmann_json
|
deps_public += nlohmann_json
|
||||||
|
@ -41,7 +41,7 @@ add_project_arguments(
|
||||||
language : 'cpp',
|
language : 'cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('build-utils-meson/common')
|
subdir('nix-meson-build-support/common')
|
||||||
|
|
||||||
sources = files(
|
sources = files(
|
||||||
'attrs.cc',
|
'attrs.cc',
|
||||||
|
@ -90,4 +90,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
|
||||||
|
|
||||||
libraries_private = []
|
libraries_private = []
|
||||||
|
|
||||||
subdir('build-utils-meson/export')
|
subdir('nix-meson-build-support/export')
|
||||||
|
|
1
src/libfetchers/nix-meson-build-support
Symbolic link
1
src/libfetchers/nix-meson-build-support
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../nix-meson-build-support
|
|
@ -22,8 +22,8 @@ mkMesonLibrary (finalAttrs: {
|
||||||
|
|
||||||
workDir = ./.;
|
workDir = ./.;
|
||||||
fileset = fileset.unions [
|
fileset = fileset.unions [
|
||||||
../../build-utils-meson
|
../../nix-meson-build-support
|
||||||
./build-utils-meson
|
./nix-meson-build-support
|
||||||
../../.version
|
../../.version
|
||||||
./.version
|
./.version
|
||||||
./meson.build
|
./meson.build
|
||||||
|
|
|
@ -94,12 +94,9 @@ void Registry::add(
|
||||||
|
|
||||||
void Registry::remove(const Input & input)
|
void Registry::remove(const Input & input)
|
||||||
{
|
{
|
||||||
// FIXME: use C++20 std::erase.
|
entries.erase(
|
||||||
for (auto i = entries.begin(); i != entries.end(); )
|
std::remove_if(entries.begin(), entries.end(), [&](const Entry & entry) { return entry.from == input; }),
|
||||||
if (i->from == input)
|
entries.end());
|
||||||
i = entries.erase(i);
|
|
||||||
else
|
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Path getSystemRegistryPath()
|
static Path getSystemRegistryPath()
|
||||||
|
@ -181,7 +178,8 @@ Registries getRegistries(const Settings & settings, ref<Store> store)
|
||||||
|
|
||||||
std::pair<Input, Attrs> lookupInRegistries(
|
std::pair<Input, Attrs> lookupInRegistries(
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
const Input & _input)
|
const Input & _input,
|
||||||
|
const RegistryFilter & filter)
|
||||||
{
|
{
|
||||||
Attrs extraAttrs;
|
Attrs extraAttrs;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
@ -193,6 +191,7 @@ std::pair<Input, Attrs> lookupInRegistries(
|
||||||
if (n > 100) throw Error("cycle detected in flake registry for '%s'", input.to_string());
|
if (n > 100) throw Error("cycle detected in flake registry for '%s'", input.to_string());
|
||||||
|
|
||||||
for (auto & registry : getRegistries(*input.settings, store)) {
|
for (auto & registry : getRegistries(*input.settings, store)) {
|
||||||
|
if (filter && !filter(registry->type)) continue;
|
||||||
// FIXME: O(n)
|
// FIXME: O(n)
|
||||||
for (auto & entry : registry->entries) {
|
for (auto & entry : registry->entries) {
|
||||||
if (entry.exact) {
|
if (entry.exact) {
|
||||||
|
|
|
@ -65,8 +65,15 @@ void overrideRegistry(
|
||||||
const Input & to,
|
const Input & to,
|
||||||
const Attrs & extraAttrs);
|
const Attrs & extraAttrs);
|
||||||
|
|
||||||
|
using RegistryFilter = std::function<bool(Registry::RegistryType)>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rewrite a flakeref using the registries. If `filter` is set, only
|
||||||
|
* use the registries for which the filter function returns true.
|
||||||
|
*/
|
||||||
std::pair<Input, Attrs> lookupInRegistries(
|
std::pair<Input, Attrs> lookupInRegistries(
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
const Input & input);
|
const Input & input,
|
||||||
|
const RegistryFilter & filter = {});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
1
src/libflake-c/.version
Symbolic link
1
src/libflake-c/.version
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../.version
|
93
src/libflake-c/meson.build
Normal file
93
src/libflake-c/meson.build
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
project('nix-flake-c', 'cpp',
|
||||||
|
version : files('.version'),
|
||||||
|
default_options : [
|
||||||
|
'cpp_std=c++2a',
|
||||||
|
# TODO(Qyriad): increase the warning level
|
||||||
|
'warning_level=1',
|
||||||
|
'debug=true',
|
||||||
|
'optimization=2',
|
||||||
|
'errorlogs=true', # Please print logs for tests that fail
|
||||||
|
],
|
||||||
|
meson_version : '>= 1.1',
|
||||||
|
license : 'LGPL-2.1-or-later',
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
|
subdir('nix-meson-build-support/deps-lists')
|
||||||
|
|
||||||
|
configdata = configuration_data()
|
||||||
|
|
||||||
|
deps_private_maybe_subproject = [
|
||||||
|
dependency('nix-util'),
|
||||||
|
dependency('nix-store'),
|
||||||
|
dependency('nix-expr'),
|
||||||
|
dependency('nix-flake'),
|
||||||
|
]
|
||||||
|
deps_public_maybe_subproject = [
|
||||||
|
dependency('nix-util-c'),
|
||||||
|
dependency('nix-store-c'),
|
||||||
|
dependency('nix-expr-c'),
|
||||||
|
]
|
||||||
|
subdir('nix-meson-build-support/subprojects')
|
||||||
|
|
||||||
|
# TODO rename, because it will conflict with downstream projects
|
||||||
|
configdata.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||||
|
|
||||||
|
config_h = configure_file(
|
||||||
|
configuration : configdata,
|
||||||
|
output : 'config-flake.h',
|
||||||
|
)
|
||||||
|
|
||||||
|
add_project_arguments(
|
||||||
|
# TODO(Qyriad): Yes this is how the autoconf+Make system did it.
|
||||||
|
# It would be nice for our headers to be idempotent instead.
|
||||||
|
|
||||||
|
# From C++ libraries, only for internals
|
||||||
|
'-include', 'config-util.hh',
|
||||||
|
'-include', 'config-store.hh',
|
||||||
|
'-include', 'config-expr.hh',
|
||||||
|
# not generated (yet?)
|
||||||
|
# '-include', 'config-flake.hh',
|
||||||
|
|
||||||
|
# From C libraries, for our public, installed headers too
|
||||||
|
'-include', 'config-util.h',
|
||||||
|
'-include', 'config-store.h',
|
||||||
|
'-include', 'config-expr.h',
|
||||||
|
'-include', 'config-flake.h',
|
||||||
|
language : 'cpp',
|
||||||
|
)
|
||||||
|
|
||||||
|
subdir('nix-meson-build-support/common')
|
||||||
|
|
||||||
|
sources = files(
|
||||||
|
'nix_api_flake.cc',
|
||||||
|
)
|
||||||
|
|
||||||
|
include_dirs = [include_directories('.')]
|
||||||
|
|
||||||
|
headers = [config_h] + files(
|
||||||
|
'nix_api_flake.h',
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO move this header to libexpr, maybe don't use it in tests?
|
||||||
|
headers += files('nix_api_flake.h')
|
||||||
|
|
||||||
|
subdir('nix-meson-build-support/export-all-symbols')
|
||||||
|
subdir('nix-meson-build-support/windows-version')
|
||||||
|
|
||||||
|
this_library = library(
|
||||||
|
'nixflakec',
|
||||||
|
sources,
|
||||||
|
dependencies : deps_public + deps_private + deps_other,
|
||||||
|
include_directories : include_dirs,
|
||||||
|
link_args: linker_export_flags,
|
||||||
|
prelink : true, # For C++ static initializers
|
||||||
|
install : true,
|
||||||
|
)
|
||||||
|
|
||||||
|
install_headers(headers, subdir : 'nix', preserve_path : true)
|
||||||
|
|
||||||
|
libraries_private = []
|
||||||
|
|
||||||
|
subdir('nix-meson-build-support/export')
|
1
src/libflake-c/nix-meson-build-support
Symbolic link
1
src/libflake-c/nix-meson-build-support
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../nix-meson-build-support
|
32
src/libflake-c/nix_api_flake.cc
Normal file
32
src/libflake-c/nix_api_flake.cc
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#include "nix_api_flake.h"
|
||||||
|
#include "nix_api_flake_internal.hh"
|
||||||
|
#include "nix_api_util_internal.h"
|
||||||
|
|
||||||
|
#include "flake/flake.hh"
|
||||||
|
|
||||||
|
nix_flake_settings * nix_flake_settings_new(nix_c_context * context)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
auto settings = nix::make_ref<nix::flake::Settings>();
|
||||||
|
return new nix_flake_settings{settings};
|
||||||
|
}
|
||||||
|
NIXC_CATCH_ERRS_NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
void nix_flake_settings_free(nix_flake_settings * settings)
|
||||||
|
{
|
||||||
|
delete settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
nix_err nix_flake_init_global(nix_c_context * context, nix_flake_settings * settings)
|
||||||
|
{
|
||||||
|
static std::shared_ptr<nix::flake::Settings> registeredSettings;
|
||||||
|
try {
|
||||||
|
if (registeredSettings)
|
||||||
|
throw nix::Error("nix_flake_init_global already initialized");
|
||||||
|
|
||||||
|
registeredSettings = settings->settings;
|
||||||
|
nix::flake::initLib(*registeredSettings);
|
||||||
|
}
|
||||||
|
NIXC_CATCH_ERRS
|
||||||
|
}
|
46
src/libflake-c/nix_api_flake.h
Normal file
46
src/libflake-c/nix_api_flake.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#ifndef NIX_API_FLAKE_H
|
||||||
|
#define NIX_API_FLAKE_H
|
||||||
|
/** @defgroup libflake libflake
|
||||||
|
* @brief Bindings to the Nix Flakes library
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/** @file
|
||||||
|
* @brief Main entry for the libflake C bindings
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nix_api_store.h"
|
||||||
|
#include "nix_api_util.h"
|
||||||
|
#include "nix_api_expr.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
// cffi start
|
||||||
|
|
||||||
|
typedef struct nix_flake_settings nix_flake_settings;
|
||||||
|
|
||||||
|
// Function prototypes
|
||||||
|
/**
|
||||||
|
* Create a nix_flake_settings initialized with default values.
|
||||||
|
* @param[out] context Optional, stores error information
|
||||||
|
* @return A new nix_flake_settings or NULL on failure.
|
||||||
|
* @see nix_flake_settings_free
|
||||||
|
*/
|
||||||
|
nix_flake_settings * nix_flake_settings_new(nix_c_context * context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release the resources associated with a nix_flake_settings.
|
||||||
|
*/
|
||||||
|
void nix_flake_settings_free(nix_flake_settings * settings);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register Flakes support process-wide.
|
||||||
|
*/
|
||||||
|
nix_err nix_flake_init_global(nix_c_context * context, nix_flake_settings * settings);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
9
src/libflake-c/nix_api_flake_internal.hh
Normal file
9
src/libflake-c/nix_api_flake_internal.hh
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ref.hh"
|
||||||
|
#include "flake/settings.hh"
|
||||||
|
|
||||||
|
struct nix_flake_settings
|
||||||
|
{
|
||||||
|
nix::ref<nix::flake::Settings> settings;
|
||||||
|
};
|
60
src/libflake-c/package.nix
Normal file
60
src/libflake-c/package.nix
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, mkMesonLibrary
|
||||||
|
|
||||||
|
, nix-store-c
|
||||||
|
, nix-expr-c
|
||||||
|
, nix-flake
|
||||||
|
|
||||||
|
# Configuration Options
|
||||||
|
|
||||||
|
, version
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) fileset;
|
||||||
|
in
|
||||||
|
|
||||||
|
mkMesonLibrary (finalAttrs: {
|
||||||
|
pname = "nix-flake-c";
|
||||||
|
inherit version;
|
||||||
|
|
||||||
|
workDir = ./.;
|
||||||
|
fileset = fileset.unions [
|
||||||
|
../../nix-meson-build-support
|
||||||
|
./nix-meson-build-support
|
||||||
|
../../.version
|
||||||
|
./.version
|
||||||
|
./meson.build
|
||||||
|
# ./meson.options
|
||||||
|
(fileset.fileFilter (file: file.hasExt "cc") ./.)
|
||||||
|
(fileset.fileFilter (file: file.hasExt "hh") ./.)
|
||||||
|
(fileset.fileFilter (file: file.hasExt "h") ./.)
|
||||||
|
];
|
||||||
|
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
nix-expr-c
|
||||||
|
nix-store-c
|
||||||
|
nix-flake
|
||||||
|
];
|
||||||
|
|
||||||
|
preConfigure =
|
||||||
|
# "Inline" .version so it's not a symlink, and includes the suffix.
|
||||||
|
# Do the meson utils, without modification.
|
||||||
|
''
|
||||||
|
chmod u+w ./.version
|
||||||
|
echo ${version} > ../../.version
|
||||||
|
'';
|
||||||
|
|
||||||
|
mesonFlags = [
|
||||||
|
];
|
||||||
|
|
||||||
|
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
|
||||||
|
LDFLAGS = "-fuse-ld=gold";
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
platforms = lib.platforms.unix ++ lib.platforms.windows;
|
||||||
|
};
|
||||||
|
|
||||||
|
})
|
|
@ -1 +0,0 @@
|
||||||
../../build-utils-meson
|
|
|
@ -14,18 +14,19 @@ project('nix-flake-tests', 'cpp',
|
||||||
|
|
||||||
cxx = meson.get_compiler('cpp')
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
subdir('build-utils-meson/deps-lists')
|
subdir('nix-meson-build-support/deps-lists')
|
||||||
|
|
||||||
deps_private_maybe_subproject = [
|
deps_private_maybe_subproject = [
|
||||||
dependency('nix-expr-test-support'),
|
dependency('nix-expr-test-support'),
|
||||||
dependency('nix-flake'),
|
dependency('nix-flake'),
|
||||||
|
dependency('nix-flake-c'),
|
||||||
]
|
]
|
||||||
deps_public_maybe_subproject = [
|
deps_public_maybe_subproject = [
|
||||||
]
|
]
|
||||||
subdir('build-utils-meson/subprojects')
|
subdir('nix-meson-build-support/subprojects')
|
||||||
|
|
||||||
subdir('build-utils-meson/export-all-symbols')
|
subdir('nix-meson-build-support/export-all-symbols')
|
||||||
subdir('build-utils-meson/windows-version')
|
subdir('nix-meson-build-support/windows-version')
|
||||||
|
|
||||||
rapidcheck = dependency('rapidcheck')
|
rapidcheck = dependency('rapidcheck')
|
||||||
deps_private += rapidcheck
|
deps_private += rapidcheck
|
||||||
|
@ -42,10 +43,11 @@ add_project_arguments(
|
||||||
language : 'cpp',
|
language : 'cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('build-utils-meson/common')
|
subdir('nix-meson-build-support/common')
|
||||||
|
|
||||||
sources = files(
|
sources = files(
|
||||||
'flakeref.cc',
|
'flakeref.cc',
|
||||||
|
'nix_api_flake.cc',
|
||||||
'url-name.cc',
|
'url-name.cc',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -68,6 +70,7 @@ test(
|
||||||
this_exe,
|
this_exe,
|
||||||
env : {
|
env : {
|
||||||
'_NIX_TEST_UNIT_DATA': meson.current_source_dir() / 'data',
|
'_NIX_TEST_UNIT_DATA': meson.current_source_dir() / 'data',
|
||||||
|
'NIX_CONFIG': 'extra-experimental-features = flakes',
|
||||||
},
|
},
|
||||||
protocol : 'gtest',
|
protocol : 'gtest',
|
||||||
)
|
)
|
||||||
|
|
1
src/libflake-tests/nix-meson-build-support
Symbolic link
1
src/libflake-tests/nix-meson-build-support
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../nix-meson-build-support
|
51
src/libflake-tests/nix_api_flake.cc
Normal file
51
src/libflake-tests/nix_api_flake.cc
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#include "nix_api_store.h"
|
||||||
|
#include "nix_api_store_internal.h"
|
||||||
|
#include "nix_api_util.h"
|
||||||
|
#include "nix_api_util_internal.h"
|
||||||
|
#include "nix_api_expr.h"
|
||||||
|
#include "nix_api_value.h"
|
||||||
|
#include "nix_api_flake.h"
|
||||||
|
|
||||||
|
#include "tests/nix_api_expr.hh"
|
||||||
|
#include "tests/string_callback.hh"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace nixC {
|
||||||
|
|
||||||
|
TEST_F(nix_api_store_test, nix_api_init_global_getFlake_exists)
|
||||||
|
{
|
||||||
|
nix_libstore_init(ctx);
|
||||||
|
assert_ctx_ok();
|
||||||
|
nix_libexpr_init(ctx);
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
auto settings = nix_flake_settings_new(ctx);
|
||||||
|
assert_ctx_ok();
|
||||||
|
ASSERT_NE(nullptr, settings);
|
||||||
|
|
||||||
|
nix_flake_init_global(ctx, settings);
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
nix_eval_state_builder * builder = nix_eval_state_builder_new(ctx, store);
|
||||||
|
ASSERT_NE(nullptr, builder);
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
auto state = nix_eval_state_build(ctx, builder);
|
||||||
|
assert_ctx_ok();
|
||||||
|
ASSERT_NE(nullptr, state);
|
||||||
|
|
||||||
|
nix_eval_state_builder_free(builder);
|
||||||
|
|
||||||
|
auto value = nix_alloc_value(ctx, state);
|
||||||
|
assert_ctx_ok();
|
||||||
|
ASSERT_NE(nullptr, value);
|
||||||
|
|
||||||
|
nix_err err = nix_expr_eval_from_string(ctx, state, "builtins.getFlake", ".", value);
|
||||||
|
assert_ctx_ok();
|
||||||
|
ASSERT_EQ(NIX_OK, err);
|
||||||
|
ASSERT_EQ(NIX_TYPE_FUNCTION, nix_get_type(ctx, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nixC
|
|
@ -4,6 +4,7 @@
|
||||||
, mkMesonExecutable
|
, mkMesonExecutable
|
||||||
|
|
||||||
, nix-flake
|
, nix-flake
|
||||||
|
, nix-flake-c
|
||||||
, nix-expr-test-support
|
, nix-expr-test-support
|
||||||
|
|
||||||
, rapidcheck
|
, rapidcheck
|
||||||
|
@ -26,8 +27,8 @@ mkMesonExecutable (finalAttrs: {
|
||||||
|
|
||||||
workDir = ./.;
|
workDir = ./.;
|
||||||
fileset = fileset.unions [
|
fileset = fileset.unions [
|
||||||
../../build-utils-meson
|
../../nix-meson-build-support
|
||||||
./build-utils-meson
|
./nix-meson-build-support
|
||||||
../../.version
|
../../.version
|
||||||
./.version
|
./.version
|
||||||
./meson.build
|
./meson.build
|
||||||
|
@ -38,6 +39,7 @@ mkMesonExecutable (finalAttrs: {
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
nix-flake
|
nix-flake
|
||||||
|
nix-flake-c
|
||||||
nix-expr-test-support
|
nix-expr-test-support
|
||||||
rapidcheck
|
rapidcheck
|
||||||
gtest
|
gtest
|
||||||
|
@ -67,6 +69,7 @@ mkMesonExecutable (finalAttrs: {
|
||||||
mkdir -p "$HOME"
|
mkdir -p "$HOME"
|
||||||
'' + ''
|
'' + ''
|
||||||
export _NIX_TEST_UNIT_DATA=${resolvePath ./data}
|
export _NIX_TEST_UNIT_DATA=${resolvePath ./data}
|
||||||
|
export NIX_CONFIG="extra-experimental-features = flakes"
|
||||||
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}
|
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}
|
||||||
touch $out
|
touch $out
|
||||||
'');
|
'');
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue