Compare commits
349 Commits
2.33-maint
...
2.24-maint
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c55a7e1423 | ||
|
|
ae47fd6886 | ||
|
|
b78b79349e | ||
|
|
79b932277a | ||
|
|
d52210fae3 | ||
|
|
c2914c0d58 | ||
|
|
148585470c | ||
|
|
ed56b2741d | ||
|
|
bcffa0ce59 | ||
|
|
b0fab9f90b | ||
|
|
7d15dbf9d5 | ||
|
|
fa2a3c6de8 | ||
|
|
3e2c0680b6 | ||
|
|
28c2c78716 | ||
|
|
72bf563191 | ||
|
|
57190f9a39 | ||
|
|
89ea1a8758 | ||
|
|
142f94b7e1 | ||
|
|
0c6a207916 | ||
|
|
a568447137 | ||
|
|
bc88d09a08 | ||
|
|
ccea5cce42 | ||
|
|
e949cdbc05 | ||
|
|
de18f5ac2d | ||
|
|
adbf23e818 | ||
|
|
2a4e2ecd89 | ||
|
|
b47bd02a6a | ||
|
|
8abb67b842 | ||
|
|
97f9f8e909 | ||
|
|
7ef04ba6dd | ||
|
|
bc6e78402c | ||
|
|
4687dc99f7 | ||
|
|
8d99b6578a | ||
|
|
e1dad7daa5 | ||
|
|
d92b509bda | ||
|
|
8adc1f3011 | ||
|
|
076fa01a84 | ||
|
|
61f8fd3e9c | ||
|
|
5ce8d922fd | ||
|
|
333479e6be | ||
|
|
71ab003a0c | ||
|
|
3fccc71492 | ||
|
|
729d18fd4c | ||
|
|
699f27c4ea | ||
|
|
2d792a1867 | ||
|
|
da213e8ee5 | ||
|
|
787a14b173 | ||
|
|
01aace706a | ||
|
|
74a0ab3eea | ||
|
|
589da451e4 | ||
|
|
56e113d67a | ||
|
|
aaf86cc0d5 | ||
|
|
6faf66d2f7 | ||
|
|
3ab83f507c | ||
|
|
0033cf4270 | ||
|
|
79828c12e0 | ||
|
|
2a795bb793 | ||
|
|
9238c892d3 | ||
|
|
5862686ce2 | ||
|
|
feadb3178d | ||
|
|
be35515ef7 | ||
|
|
71f93012fd | ||
|
|
b706642133 | ||
|
|
658392e029 | ||
|
|
d3a52c2ef4 | ||
|
|
3d6a9c7410 | ||
|
|
0f5f24223d | ||
|
|
fcea626e49 | ||
|
|
c6e09073ea | ||
|
|
b9e6e00fe1 | ||
|
|
5fb6551217 | ||
|
|
0f19bfe811 | ||
|
|
865239c732 | ||
|
|
9c5482167f | ||
|
|
a28791a91e | ||
|
|
ae0bb7d71c | ||
|
|
2f1b70a529 | ||
|
|
42b22fe3de | ||
|
|
62e7144ba7 | ||
|
|
a106e33bab | ||
|
|
7616bae342 | ||
|
|
1a402db046 | ||
|
|
4511c47ab7 | ||
|
|
532092a812 | ||
|
|
f22359ba1a | ||
|
|
f366beaa78 | ||
|
|
011084b127 | ||
|
|
d8872fce2c | ||
|
|
12c90a0ec0 | ||
|
|
296769742b | ||
|
|
d31be32c4b | ||
|
|
a1b4bc7292 | ||
|
|
ff91a777a6 | ||
|
|
b4418c5c1d | ||
|
|
876d724061 | ||
|
|
f27e263f89 | ||
|
|
d944cb7f58 | ||
|
|
b2acf4ab97 | ||
|
|
d4f0e8f4e3 | ||
|
|
84e3f4ad79 | ||
|
|
6e44bc2a89 | ||
|
|
2009cc137a | ||
|
|
0cefe354c8 | ||
|
|
c6f504d827 | ||
|
|
6e718c7c5c | ||
|
|
f68cdf1801 | ||
|
|
1422832f7c | ||
|
|
7012e1ff8c | ||
|
|
e81be91738 | ||
|
|
9cc5786201 | ||
|
|
acd43b2239 | ||
|
|
3cd8c1e53d | ||
|
|
10438e6cfd | ||
|
|
c803fe0785 | ||
|
|
9a85784be2 | ||
|
|
a69d32d194 | ||
|
|
e0e50fb01f | ||
|
|
6ae5aa7fa0 | ||
|
|
cd169f14f0 | ||
|
|
e3715053b1 | ||
|
|
ada649ad7f | ||
|
|
e1e219a299 | ||
|
|
a658bafce7 | ||
|
|
e76757083a | ||
|
|
c9dd4a7c28 | ||
|
|
01cb05a265 | ||
|
|
9328fc7529 | ||
|
|
92e5f64068 | ||
|
|
283249a972 | ||
|
|
4d2cc07b48 | ||
|
|
5c0f2b744a | ||
|
|
0e95d8b467 | ||
|
|
53bc8b543c | ||
|
|
86da8bbbf3 | ||
|
|
fcdca4f8d1 | ||
|
|
f393260a5d | ||
|
|
d3cb938e07 | ||
|
|
51e41edbef | ||
|
|
daf526f19d | ||
|
|
d6217bc691 | ||
|
|
22c24a87a1 | ||
|
|
f2bb7e043b | ||
|
|
9a7196ce62 | ||
|
|
7a2b1cbd71 | ||
|
|
534473e90b | ||
|
|
ce5c0c64af | ||
|
|
931eb85f50 | ||
|
|
a9020404cf | ||
|
|
77a71c518f | ||
|
|
36f3fb72e9 | ||
|
|
5099768970 | ||
|
|
6f5684f6d1 | ||
|
|
d6488efeae | ||
|
|
bc8611a29b | ||
|
|
1a21eb43af | ||
|
|
bcf34e89c0 | ||
|
|
0060a4ba5b | ||
|
|
24e63b14e5 | ||
|
|
93e8e5b347 | ||
|
|
792099081c | ||
|
|
971748ace9 | ||
|
|
0e421e7a35 | ||
|
|
9ee4a85a99 | ||
|
|
24542a7b96 | ||
|
|
6304fa5cd1 | ||
|
|
9c54fac5ff | ||
|
|
e863e6ab83 | ||
|
|
dea80c4fec | ||
|
|
26866eef0c | ||
|
|
56332fda1c | ||
|
|
4a7c7f12f5 | ||
|
|
fed54f3550 | ||
|
|
6c1dfab347 | ||
|
|
4b4b6377b2 | ||
|
|
9936cb21ab | ||
|
|
7c8276b799 | ||
|
|
e0c8b0fc4f | ||
|
|
55dc2a9c9a | ||
|
|
112d0a7d85 | ||
|
|
b59b317e47 | ||
|
|
1eda38420f | ||
|
|
caeec0404e | ||
|
|
f145dde10b | ||
|
|
73dd3db039 | ||
|
|
e31d071793 | ||
|
|
42104d650a | ||
|
|
129f8aaab2 | ||
|
|
b9c30a9c87 | ||
|
|
fa3fd41063 | ||
|
|
e79d66ceef | ||
|
|
e144f61ec0 | ||
|
|
2c89c38fa1 | ||
|
|
1a710e54dc | ||
|
|
365e0a9ab1 | ||
|
|
b3ea1e9b19 | ||
|
|
c78b818a0c | ||
|
|
3109250faf | ||
|
|
2fbd0a943c | ||
|
|
bda59dee55 | ||
|
|
000db53f8f | ||
|
|
e40d0352b2 | ||
|
|
c530b13321 | ||
|
|
a924db7d0b | ||
|
|
f986f7e89b | ||
|
|
6a791e946f | ||
|
|
aa22f98b25 | ||
|
|
b3dc855569 | ||
|
|
7bafbfd50e | ||
|
|
578f185daf | ||
|
|
628961d136 | ||
|
|
a4f978bd9b | ||
|
|
180031fb5a | ||
|
|
29d91db99c | ||
|
|
6b2722fc84 | ||
|
|
c951bb0689 | ||
|
|
60eadfac7f | ||
|
|
9fed865d1d | ||
|
|
3cd4e9de1e | ||
|
|
0f8fef49c3 | ||
|
|
bd1b11ec66 | ||
|
|
6a8e9736e0 | ||
|
|
dd79a490bf | ||
|
|
00d0e63c61 | ||
|
|
fc11659148 | ||
|
|
bf67741ff1 | ||
|
|
403f388fdb | ||
|
|
8e8a572d37 | ||
|
|
3bfc35ba74 | ||
|
|
aaeaa4e133 | ||
|
|
22e1613814 | ||
|
|
ef21dfa221 | ||
|
|
c556c205a9 | ||
|
|
6e095ddef9 | ||
|
|
c3e2419e73 | ||
|
|
960c288fa0 | ||
|
|
d14b46f9ba | ||
|
|
c9325fe343 | ||
|
|
2a2d484986 | ||
|
|
9728a4ac94 | ||
|
|
75b00e52ac | ||
|
|
6044907c13 | ||
|
|
597fcc98e1 | ||
|
|
82abed901f | ||
|
|
f9180f12c4 | ||
|
|
baa7565710 | ||
|
|
7e6e75fd48 | ||
|
|
803943fce4 | ||
|
|
0ae90918db | ||
|
|
d6ece7e94a | ||
|
|
50f83e4bbd | ||
|
|
047ee50db2 | ||
|
|
ae7a2ea741 | ||
|
|
f8a1a149c7 | ||
|
|
170242cf0c | ||
|
|
7718688f52 | ||
|
|
0e9b04a66e | ||
|
|
411ec33db3 | ||
|
|
31df105f45 | ||
|
|
57ace600af | ||
|
|
9da1300617 | ||
|
|
1294442c6c | ||
|
|
339236d32e | ||
|
|
4912a9e7fd | ||
|
|
d80bf54e3b | ||
|
|
f1dc3b7d55 | ||
|
|
5f1b132187 | ||
|
|
742eb0f815 | ||
|
|
13e200df45 | ||
|
|
a1d841bf2c | ||
|
|
048cfe51c9 | ||
|
|
15a2b49115 | ||
|
|
34fd00accc | ||
|
|
b23812a59c | ||
|
|
618a0cc987 | ||
|
|
ba81598017 | ||
|
|
e87be60055 | ||
|
|
345a264a39 | ||
|
|
ee6a5faf4b | ||
|
|
d4824c8ff7 | ||
|
|
b4fcd27590 | ||
|
|
082f6bb35d | ||
|
|
1e03ea386b | ||
|
|
b523e4de34 | ||
|
|
563dedcf64 | ||
|
|
a7fdef6858 | ||
|
|
b5154deba3 | ||
|
|
ecd83dc155 | ||
|
|
5b5e1920eb | ||
|
|
fc1d6b2f03 | ||
|
|
9941f620c4 | ||
|
|
5b2a8c223e | ||
|
|
1b076b4f84 | ||
|
|
d9ef3dd012 | ||
|
|
f9714bac34 | ||
|
|
684a690480 | ||
|
|
4354d90384 | ||
|
|
60001b1936 | ||
|
|
c84fc0120f | ||
|
|
cd97688bce | ||
|
|
07909de6ed | ||
|
|
751907dc8a | ||
|
|
d9dd6c62d6 | ||
|
|
97c5ac5752 | ||
|
|
40461a8e0e | ||
|
|
0f825b38f4 | ||
|
|
eb11c14998 | ||
|
|
a6ad5565ef | ||
|
|
2e1cb495c1 | ||
|
|
e25410c788 | ||
|
|
25510ba66f | ||
|
|
d9b60b3902 | ||
|
|
a041688133 | ||
|
|
1288970496 | ||
|
|
0cfc9bf133 | ||
|
|
f160d3ac68 | ||
|
|
6187ee468f | ||
|
|
12fa019ae5 | ||
|
|
f0cffa7300 | ||
|
|
ae486b2910 | ||
|
|
437f7a0042 | ||
|
|
b53b07b30b | ||
|
|
8d0414d682 | ||
|
|
c5a0e624d9 | ||
|
|
0679505d8c | ||
|
|
ea7abb58b5 | ||
|
|
f1ab41b2bc | ||
|
|
c21f664e82 | ||
|
|
0c25bea7cc | ||
|
|
9d8669b14a | ||
|
|
cb0439f0c2 | ||
|
|
30a57328d2 | ||
|
|
79a43160ca | ||
|
|
7befd60c01 | ||
|
|
90fb4e8890 | ||
|
|
3ac5d736e2 | ||
|
|
4e707b8e57 | ||
|
|
20cae372f4 | ||
|
|
d550139191 | ||
|
|
5b62a1dbd6 | ||
|
|
450252c92c | ||
|
|
4036c3aafb | ||
|
|
935bf1157d | ||
|
|
b1941c9f8a | ||
|
|
40832b0a95 | ||
|
|
fa78d7f72f | ||
|
|
2382a52c84 | ||
|
|
fe6a7c805c | ||
|
|
0a167ffd1f | ||
|
|
206e32e2d7 |
32
.github/workflows/backport.yml
vendored
32
.github/workflows/backport.yml
vendored
@@ -1,32 +0,0 @@
|
||||
name: Backport
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [closed, labeled]
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
backport:
|
||||
name: Backport Pull Request
|
||||
permissions:
|
||||
# for zeebe-io/backport-action
|
||||
contents: write
|
||||
pull-requests: write
|
||||
if: github.repository_owner == 'NixOS' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name))
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
# required to find all branches
|
||||
fetch-depth: 0
|
||||
- name: Create backport PRs
|
||||
# should be kept in sync with `version`
|
||||
uses: zeebe-io/backport-action@v3.0.2
|
||||
with:
|
||||
# Config README: https://github.com/zeebe-io/backport-action#backport-action
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
github_workspace: ${{ github.workspace }}
|
||||
pull_description: |-
|
||||
Automatic backport to `${target_branch}`, triggered by a label in #${pull_number}.
|
||||
# should be kept in sync with `uses`
|
||||
version: v0.0.5
|
||||
190
.github/workflows/ci.yml
vendored
190
.github/workflows/ci.yml
vendored
@@ -7,14 +7,28 @@ on:
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
eval:
|
||||
runs-on: ubuntu-24.04
|
||||
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:
|
||||
needs: [check_secrets]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
include:
|
||||
- scenario: on ubuntu
|
||||
runs-on: ubuntu-24.04
|
||||
os: linux
|
||||
- scenario: on macos
|
||||
runs-on: macos-14
|
||||
os: darwin
|
||||
name: tests ${{ matrix.scenario }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -23,102 +37,54 @@ jobs:
|
||||
- uses: cachix/install-nix-action@V27
|
||||
with:
|
||||
# The sandbox would otherwise be disabled by default on Darwin
|
||||
extra_nix_config: "sandbox = true"
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- uses: cachix/cachix-action@v15
|
||||
if: needs.check_secrets.outputs.cachix == 'true'
|
||||
extra_nix_config: |
|
||||
sandbox = true
|
||||
max-jobs = 1
|
||||
- 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 == 'linux'
|
||||
- run: scripts/build-checks
|
||||
- run: scripts/prepare-installer-for-github-actions
|
||||
- name: Upload installer tarball
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: '${{ env.CACHIX_NAME }}'
|
||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
||||
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
|
||||
|
||||
# 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@V27
|
||||
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
|
||||
name: installer-${{matrix.os}}
|
||||
path: out/*
|
||||
|
||||
installer_test:
|
||||
needs: [installer, check_secrets]
|
||||
if: github.event_name == 'push' && needs.check_secrets.outputs.cachix == 'true'
|
||||
needs: [tests]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
include:
|
||||
- scenario: on ubuntu
|
||||
runs-on: ubuntu-24.04
|
||||
os: linux
|
||||
- scenario: on macos
|
||||
runs-on: macos-14
|
||||
os: darwin
|
||||
name: installer test ${{ matrix.scenario }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- uses: cachix/install-nix-action@V27
|
||||
- name: Download installer tarball
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
install_url: '${{needs.installer.outputs.installerURL}}'
|
||||
install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve"
|
||||
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
|
||||
with:
|
||||
install_url: 'http://localhost:8126/install'
|
||||
install_options: "--tarball-url-prefix http://localhost:8126/"
|
||||
- run: sudo apt install fish zsh
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
if: matrix.os == 'linux'
|
||||
- run: brew install fish
|
||||
if: matrix.os == 'macos-latest'
|
||||
if: matrix.os == 'darwin'
|
||||
- run: exec bash -c "nix-instantiate -E 'builtins.currentTime' --eval"
|
||||
- run: exec sh -c "nix-instantiate -E 'builtins.currentTime' --eval"
|
||||
- run: exec zsh -c "nix-instantiate -E 'builtins.currentTime' --eval"
|
||||
@@ -126,32 +92,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 --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-24.04
|
||||
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:
|
||||
needs: [check_secrets, tests]
|
||||
needs: [tests, vm_tests, check_secrets]
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
if: >-
|
||||
needs.check_secrets.outputs.docker == 'true' &&
|
||||
github.event_name == 'push' &&
|
||||
github.ref_name == 'master' &&
|
||||
needs.check_secrets.outputs.cachix == 'true' &&
|
||||
needs.check_secrets.outputs.docker == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
github.ref_name == 'master'
|
||||
runs-on: ubuntu-24.04
|
||||
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
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: cachix/install-nix-action@V27
|
||||
with:
|
||||
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
|
||||
- run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#default.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 }}'
|
||||
- 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: nix --experimental-features 'nix-command flakes' build .#dockerImage -L
|
||||
- run: docker load -i ./result/image.tar.gz
|
||||
- run: docker tag nix:$NIX_VERSION ${{ secrets.DOCKERHUB_USERNAME }}/nix:$NIX_VERSION
|
||||
@@ -188,7 +172,7 @@ jobs:
|
||||
docker push $IMAGE_ID:master
|
||||
|
||||
vm_tests:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
@@ -211,7 +195,7 @@ jobs:
|
||||
|
||||
flake_regressions:
|
||||
needs: vm_tests
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout nix
|
||||
uses: actions/checkout@v4
|
||||
|
||||
2
.github/workflows/labels.yml
vendored
2
.github/workflows/labels.yml
vendored
@@ -15,7 +15,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
labels:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.repository_owner == 'NixOS'
|
||||
steps:
|
||||
- uses: actions/labeler@v5
|
||||
|
||||
94
.mergify.yml
Normal file
94
.mergify.yml
Normal file
@@ -0,0 +1,94 @@
|
||||
queue_rules:
|
||||
- name: default
|
||||
# all required tests need to go here
|
||||
merge_conditions:
|
||||
- check-success=installer
|
||||
- check-success=installer_test (macos-latest)
|
||||
- check-success=installer_test (ubuntu-latest)
|
||||
- check-success=tests on macos
|
||||
- check-success=tests on ubuntu
|
||||
- check-success=installer test on macos
|
||||
- check-success=installer test on ubuntu
|
||||
- check-success=vm_tests
|
||||
merge_method: rebase
|
||||
batch_size: 5
|
||||
|
||||
pull_request_rules:
|
||||
- name: merge using the merge queue
|
||||
conditions:
|
||||
- base=master
|
||||
- label~=merge-queue|dependencies
|
||||
actions:
|
||||
queue: {}
|
||||
|
||||
# The rules below will first create backport pull requests and put those in a merge queue.
|
||||
|
||||
- name: backport patches to 2.18
|
||||
conditions:
|
||||
- label=backport 2.18-maintenance
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- 2.18-maintenance
|
||||
labels:
|
||||
- merge-queue
|
||||
|
||||
- name: backport patches to 2.19
|
||||
conditions:
|
||||
- label=backport 2.19-maintenance
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- 2.19-maintenance
|
||||
labels:
|
||||
- merge-queue
|
||||
|
||||
- name: backport patches to 2.20
|
||||
conditions:
|
||||
- label=backport 2.20-maintenance
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- 2.20-maintenance
|
||||
labels:
|
||||
- merge-queue
|
||||
|
||||
- name: backport patches to 2.21
|
||||
conditions:
|
||||
- label=backport 2.21-maintenance
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- 2.21-maintenance
|
||||
labels:
|
||||
- merge-queue
|
||||
|
||||
- name: backport patches to 2.22
|
||||
conditions:
|
||||
- label=backport 2.22-maintenance
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- 2.22-maintenance
|
||||
labels:
|
||||
- merge-queue
|
||||
|
||||
- name: backport patches to 2.23
|
||||
conditions:
|
||||
- label=backport 2.23-maintenance
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- 2.23-maintenance
|
||||
labels:
|
||||
- merge-queue
|
||||
|
||||
- name: backport patches to 2.24
|
||||
conditions:
|
||||
- label=backport 2.24-maintenance
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- "2.24-maintenance"
|
||||
labels:
|
||||
- merge-queue
|
||||
17
configure.ac
17
configure.ac
@@ -62,12 +62,16 @@ AC_CHECK_TOOL([AR], [ar])
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
|
||||
# Solaris-specific stuff.
|
||||
# OS-specific stuff.
|
||||
case "$host_os" in
|
||||
solaris*)
|
||||
# Solaris requires -lsocket -lnsl for network functions
|
||||
LDFLAGS="-lsocket -lnsl $LDFLAGS"
|
||||
;;
|
||||
darwin*)
|
||||
# Need to link to libsandbox.
|
||||
LDFLAGS="-lsandbox $LDFLAGS"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
@@ -89,9 +93,10 @@ AC_LANG_POP(C++)
|
||||
AC_CHECK_FUNCS([statvfs pipe2])
|
||||
|
||||
|
||||
# Check for lutimes, optionally used for changing the mtime of
|
||||
# symlinks.
|
||||
AC_CHECK_FUNCS([lutimes])
|
||||
# Check for lutimes and utimensat, optionally used for changing the
|
||||
# mtime of symlinks.
|
||||
AC_CHECK_DECLS([AT_SYMLINK_NOFOLLOW], [], [], [[#include <fcntl.h>]])
|
||||
AC_CHECK_FUNCS([lutimes utimensat])
|
||||
|
||||
|
||||
# Check whether the store optimiser can optimise symlinks.
|
||||
@@ -170,6 +175,10 @@ AS_IF(
|
||||
[test "$ENABLE_FUNCTIONAL_TESTS" == "yes" || test "$ENABLE_DOC_GEN" == "yes"],
|
||||
[NEED_PROG(jq, jq)])
|
||||
|
||||
AS_IF(
|
||||
[test "$ENABLE_DOC_GEN" == "yes"],
|
||||
[NEED_PROG(man, man)])
|
||||
|
||||
AS_IF([test "$ENABLE_BUILD" == "yes"],[
|
||||
|
||||
# Look for boost, a required dependency.
|
||||
|
||||
19
default.nix
19
default.nix
@@ -1,10 +1,9 @@
|
||||
(import
|
||||
(
|
||||
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
|
||||
fetchTarball {
|
||||
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
||||
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||
}
|
||||
)
|
||||
{ src = ./.; }
|
||||
).defaultNix
|
||||
(import (
|
||||
let
|
||||
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
|
||||
in
|
||||
fetchTarball {
|
||||
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
||||
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||
}
|
||||
) { src = ./.; }).defaultNix
|
||||
|
||||
@@ -5,7 +5,15 @@ in
|
||||
|
||||
builtinsInfo:
|
||||
let
|
||||
showBuiltin = name: { doc, type ? null, args ? [ ], experimental-feature ? null, impure-only ? false }:
|
||||
showBuiltin =
|
||||
name:
|
||||
{
|
||||
doc,
|
||||
type ? null,
|
||||
args ? [ ],
|
||||
experimental-feature ? null,
|
||||
impure-only ? false,
|
||||
}:
|
||||
let
|
||||
type' = optionalString (type != null) " (${type})";
|
||||
|
||||
|
||||
@@ -32,7 +32,13 @@ let
|
||||
|
||||
commandInfo = fromJSON commandDump;
|
||||
|
||||
showCommand = { command, details, filename, toplevel }:
|
||||
showCommand =
|
||||
{
|
||||
command,
|
||||
details,
|
||||
filename,
|
||||
toplevel,
|
||||
}:
|
||||
let
|
||||
|
||||
result = ''
|
||||
@@ -56,26 +62,27 @@ let
|
||||
${maybeOptions}
|
||||
'';
|
||||
|
||||
showSynopsis = command: args:
|
||||
showSynopsis =
|
||||
command: args:
|
||||
let
|
||||
showArgument = arg: "*${arg.label}*" + optionalString (! arg ? arity) "...";
|
||||
showArgument = arg: "*${arg.label}*" + optionalString (!arg ? arity) "...";
|
||||
arguments = concatStringsSep " " (map showArgument args);
|
||||
in ''
|
||||
in
|
||||
''
|
||||
`${command}` [*option*...] ${arguments}
|
||||
'';
|
||||
|
||||
maybeSubcommands = optionalString (details ? commands && details.commands != {})
|
||||
''
|
||||
where *subcommand* is one of the following:
|
||||
maybeSubcommands = optionalString (details ? commands && details.commands != { }) ''
|
||||
where *subcommand* is one of the following:
|
||||
|
||||
${subcommands}
|
||||
'';
|
||||
${subcommands}
|
||||
'';
|
||||
|
||||
subcommands = if length categories > 1
|
||||
then listCategories
|
||||
else listSubcommands details.commands;
|
||||
subcommands = if length categories > 1 then listCategories else listSubcommands details.commands;
|
||||
|
||||
categories = sort (x: y: x.id < y.id) (unique (map (cmd: cmd.category) (attrValues details.commands)));
|
||||
categories = sort (x: y: x.id < y.id) (
|
||||
unique (map (cmd: cmd.category) (attrValues details.commands))
|
||||
);
|
||||
|
||||
listCategories = concatStrings (map showCategory categories);
|
||||
|
||||
@@ -99,38 +106,39 @@ let
|
||||
|
||||
${allStores}
|
||||
'';
|
||||
index = replaceStrings
|
||||
[ "@store-types@" "./local-store.md" "./local-daemon-store.md" ]
|
||||
[ storesOverview "#local-store" "#local-daemon-store" ]
|
||||
details.doc;
|
||||
index =
|
||||
replaceStrings
|
||||
[ "@store-types@" "./local-store.md" "./local-daemon-store.md" ]
|
||||
[ storesOverview "#local-store" "#local-daemon-store" ]
|
||||
details.doc;
|
||||
storesOverview =
|
||||
let
|
||||
showEntry = store:
|
||||
"- [${store.name}](#${store.slug})";
|
||||
showEntry = store: "- [${store.name}](#${store.slug})";
|
||||
in
|
||||
concatStringsSep "\n" (map showEntry storesList) + "\n";
|
||||
allStores = concatStringsSep "\n" (attrValues storePages);
|
||||
storePages = listToAttrs
|
||||
(map (s: { name = s.filename; value = s.page; }) storesList);
|
||||
storePages = listToAttrs (
|
||||
map (s: {
|
||||
name = s.filename;
|
||||
value = s.page;
|
||||
}) storesList
|
||||
);
|
||||
storesList = showStoreDocs {
|
||||
storeInfo = commandInfo.stores;
|
||||
inherit inlineHTML;
|
||||
};
|
||||
hasInfix = infix: content:
|
||||
hasInfix =
|
||||
infix: content:
|
||||
builtins.stringLength content != builtins.stringLength (replaceStrings [ infix ] [ "" ] content);
|
||||
in
|
||||
optionalString (details ? doc) (
|
||||
# An alternate implementation with builtins.match stack overflowed on some systems.
|
||||
if hasInfix "@store-types@" details.doc
|
||||
then help-stores
|
||||
else details.doc
|
||||
if hasInfix "@store-types@" details.doc then help-stores else details.doc
|
||||
);
|
||||
|
||||
maybeOptions =
|
||||
let
|
||||
allVisibleOptions = filterAttrs
|
||||
(_: o: ! o.hiddenCategory)
|
||||
(details.flags // toplevel.flags);
|
||||
allVisibleOptions = filterAttrs (_: o: !o.hiddenCategory) (details.flags // toplevel.flags);
|
||||
in
|
||||
optionalString (allVisibleOptions != { }) ''
|
||||
# Options
|
||||
@@ -142,55 +150,73 @@ let
|
||||
> See [`man nix.conf`](@docroot@/command-ref/conf-file.md#command-line-flags) for overriding configuration settings with command line flags.
|
||||
'';
|
||||
|
||||
showOptions = inlineHTML: allOptions:
|
||||
showOptions =
|
||||
inlineHTML: allOptions:
|
||||
let
|
||||
showCategory = cat: opts: ''
|
||||
${optionalString (cat != "") "## ${cat}"}
|
||||
|
||||
${concatStringsSep "\n" (attrValues (mapAttrs showOption opts))}
|
||||
'';
|
||||
showOption = name: option:
|
||||
showOption =
|
||||
name: option:
|
||||
let
|
||||
result = trim ''
|
||||
- ${item}
|
||||
|
||||
${option.description}
|
||||
'';
|
||||
item = if inlineHTML
|
||||
then ''<span id="opt-${name}">[`--${name}`](#opt-${name})</span> ${shortName} ${labels}''
|
||||
else "`--${name}` ${shortName} ${labels}";
|
||||
shortName = optionalString
|
||||
(option ? shortName)
|
||||
("/ `-${option.shortName}`");
|
||||
labels = optionalString
|
||||
(option ? labels)
|
||||
(concatStringsSep " " (map (s: "*${s}*") option.labels));
|
||||
in result;
|
||||
categories = mapAttrs
|
||||
# Convert each group from a list of key-value pairs back to an attrset
|
||||
(_: listToAttrs)
|
||||
(groupBy
|
||||
(cmd: cmd.value.category)
|
||||
(attrsToList allOptions));
|
||||
in concatStrings (attrValues (mapAttrs showCategory categories));
|
||||
in squash result;
|
||||
item =
|
||||
if inlineHTML then
|
||||
''<span id="opt-${name}">[`--${name}`](#opt-${name})</span> ${shortName} ${labels}''
|
||||
else
|
||||
"`--${name}` ${shortName} ${labels}";
|
||||
shortName = optionalString (option ? shortName) ("/ `-${option.shortName}`");
|
||||
labels = optionalString (option ? labels) (concatStringsSep " " (map (s: "*${s}*") option.labels));
|
||||
in
|
||||
result;
|
||||
categories =
|
||||
mapAttrs
|
||||
# Convert each group from a list of key-value pairs back to an attrset
|
||||
(_: listToAttrs)
|
||||
(groupBy (cmd: cmd.value.category) (attrsToList allOptions));
|
||||
in
|
||||
concatStrings (attrValues (mapAttrs showCategory categories));
|
||||
in
|
||||
squash result;
|
||||
|
||||
appendName = filename: name: (if filename == "nix" then "nix3" else filename) + "-" + name;
|
||||
|
||||
processCommand = { command, details, filename, toplevel }:
|
||||
processCommand =
|
||||
{
|
||||
command,
|
||||
details,
|
||||
filename,
|
||||
toplevel,
|
||||
}:
|
||||
let
|
||||
cmd = {
|
||||
inherit command;
|
||||
name = filename + ".md";
|
||||
value = showCommand { inherit command details filename toplevel; };
|
||||
value = showCommand {
|
||||
inherit
|
||||
command
|
||||
details
|
||||
filename
|
||||
toplevel
|
||||
;
|
||||
};
|
||||
};
|
||||
subcommand = subCmd: processCommand {
|
||||
command = command + " " + subCmd;
|
||||
details = details.commands.${subCmd};
|
||||
filename = appendName filename subCmd;
|
||||
inherit toplevel;
|
||||
};
|
||||
in [ cmd ] ++ concatMap subcommand (attrNames details.commands or {});
|
||||
subcommand =
|
||||
subCmd:
|
||||
processCommand {
|
||||
command = command + " " + subCmd;
|
||||
details = details.commands.${subCmd};
|
||||
filename = appendName filename subCmd;
|
||||
inherit toplevel;
|
||||
};
|
||||
in
|
||||
[ cmd ] ++ concatMap subcommand (attrNames details.commands or { });
|
||||
|
||||
manpages = processCommand {
|
||||
command = "nix";
|
||||
@@ -199,9 +225,11 @@ let
|
||||
toplevel = commandInfo.args;
|
||||
};
|
||||
|
||||
tableOfContents = let
|
||||
showEntry = page:
|
||||
" - [${page.command}](command-ref/new-cli/${page.name})";
|
||||
in concatStringsSep "\n" (map showEntry manpages) + "\n";
|
||||
tableOfContents =
|
||||
let
|
||||
showEntry = page: " - [${page.command}](command-ref/new-cli/${page.name})";
|
||||
in
|
||||
concatStringsSep "\n" (map showEntry manpages) + "\n";
|
||||
|
||||
in (listToAttrs manpages) // { "SUMMARY.md" = tableOfContents; }
|
||||
in
|
||||
(listToAttrs manpages) // { "SUMMARY.md" = tableOfContents; }
|
||||
|
||||
@@ -1,67 +1,99 @@
|
||||
let
|
||||
inherit (builtins) attrValues concatStringsSep isAttrs isBool mapAttrs;
|
||||
inherit (import <nix/utils.nix>) concatStrings indent optionalString squash;
|
||||
inherit (builtins)
|
||||
attrValues
|
||||
concatStringsSep
|
||||
isAttrs
|
||||
isBool
|
||||
mapAttrs
|
||||
;
|
||||
inherit (import <nix/utils.nix>)
|
||||
concatStrings
|
||||
indent
|
||||
optionalString
|
||||
squash
|
||||
;
|
||||
in
|
||||
|
||||
# `inlineHTML` is a hack to accommodate inconsistent output from `lowdown`
|
||||
{ prefix, inlineHTML ? true }: settingsInfo:
|
||||
{
|
||||
prefix,
|
||||
inlineHTML ? true,
|
||||
}:
|
||||
settingsInfo:
|
||||
|
||||
let
|
||||
|
||||
showSetting = prefix: setting: { description, documentDefault, defaultValue, aliases, value, experimentalFeature }:
|
||||
showSetting =
|
||||
prefix: setting:
|
||||
{
|
||||
description,
|
||||
documentDefault,
|
||||
defaultValue,
|
||||
aliases,
|
||||
value,
|
||||
experimentalFeature,
|
||||
}:
|
||||
let
|
||||
result = squash ''
|
||||
- ${item}
|
||||
- ${item}
|
||||
|
||||
${indent " " body}
|
||||
'';
|
||||
item = if inlineHTML
|
||||
then ''<span id="${prefix}-${setting}">[`${setting}`](#${prefix}-${setting})</span>''
|
||||
else "`${setting}`";
|
||||
${indent " " body}
|
||||
'';
|
||||
item =
|
||||
if inlineHTML then
|
||||
''<span id="${prefix}-${setting}">[`${setting}`](#${prefix}-${setting})</span>''
|
||||
else
|
||||
"`${setting}`";
|
||||
# separate body to cleanly handle indentation
|
||||
body = ''
|
||||
${experimentalFeatureNote}
|
||||
${experimentalFeatureNote}
|
||||
|
||||
${description}
|
||||
${description}
|
||||
|
||||
**Default:** ${showDefault documentDefault defaultValue}
|
||||
**Default:** ${showDefault documentDefault defaultValue}
|
||||
|
||||
${showAliases aliases}
|
||||
'';
|
||||
${showAliases aliases}
|
||||
'';
|
||||
|
||||
experimentalFeatureNote = optionalString (experimentalFeature != null) ''
|
||||
> **Warning**
|
||||
>
|
||||
> This setting is part of an
|
||||
> [experimental feature](@docroot@/development/experimental-features.md).
|
||||
>
|
||||
> To change this setting, make sure the
|
||||
> [`${experimentalFeature}` experimental feature](@docroot@/development/experimental-features.md#xp-feature-${experimentalFeature})
|
||||
> is enabled.
|
||||
> For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md):
|
||||
>
|
||||
> ```
|
||||
> extra-experimental-features = ${experimentalFeature}
|
||||
> ${setting} = ...
|
||||
> ```
|
||||
'';
|
||||
> **Warning**
|
||||
>
|
||||
> This setting is part of an
|
||||
> [experimental feature](@docroot@/development/experimental-features.md).
|
||||
>
|
||||
> To change this setting, make sure the
|
||||
> [`${experimentalFeature}` experimental feature](@docroot@/development/experimental-features.md#xp-feature-${experimentalFeature})
|
||||
> is enabled.
|
||||
> For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md):
|
||||
>
|
||||
> ```
|
||||
> extra-experimental-features = ${experimentalFeature}
|
||||
> ${setting} = ...
|
||||
> ```
|
||||
'';
|
||||
|
||||
showDefault = documentDefault: defaultValue:
|
||||
showDefault =
|
||||
documentDefault: defaultValue:
|
||||
if documentDefault then
|
||||
# a StringMap value type is specified as a string, but
|
||||
# this shows the value type. The empty stringmap is `null` in
|
||||
# JSON, but that converts to `{ }` here.
|
||||
if defaultValue == "" || defaultValue == [] || isAttrs defaultValue
|
||||
then "*empty*"
|
||||
else if isBool defaultValue then
|
||||
if defaultValue then "`true`" else "`false`"
|
||||
else "`${toString defaultValue}`"
|
||||
else "*machine-specific*";
|
||||
if defaultValue == "" || defaultValue == [ ] || isAttrs defaultValue then
|
||||
"*empty*"
|
||||
else if isBool defaultValue then
|
||||
if defaultValue then "`true`" else "`false`"
|
||||
else
|
||||
"`${toString defaultValue}`"
|
||||
else
|
||||
"*machine-specific*";
|
||||
|
||||
showAliases = aliases:
|
||||
optionalString (aliases != [])
|
||||
"**Deprecated alias:** ${(concatStringsSep ", " (map (s: "`${s}`") aliases))}";
|
||||
showAliases =
|
||||
aliases:
|
||||
optionalString (aliases != [ ])
|
||||
"**Deprecated alias:** ${(concatStringsSep ", " (map (s: "`${s}`") aliases))}";
|
||||
|
||||
in result;
|
||||
in
|
||||
result;
|
||||
|
||||
in concatStrings (attrValues (mapAttrs (showSetting prefix) settingsInfo))
|
||||
in
|
||||
concatStrings (attrValues (mapAttrs (showSetting prefix) settingsInfo))
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
let
|
||||
inherit (builtins) attrNames listToAttrs concatStringsSep readFile replaceStrings;
|
||||
inherit (import <nix/utils.nix>) optionalString filterAttrs trim squash toLower unique indent;
|
||||
inherit (builtins)
|
||||
attrNames
|
||||
listToAttrs
|
||||
concatStringsSep
|
||||
readFile
|
||||
replaceStrings
|
||||
;
|
||||
inherit (import <nix/utils.nix>)
|
||||
optionalString
|
||||
filterAttrs
|
||||
trim
|
||||
squash
|
||||
toLower
|
||||
unique
|
||||
indent
|
||||
;
|
||||
showSettings = import <nix/generate-settings.nix>;
|
||||
in
|
||||
|
||||
@@ -14,7 +28,13 @@ in
|
||||
|
||||
let
|
||||
|
||||
showStore = { name, slug }: { settings, doc, experimentalFeature }:
|
||||
showStore =
|
||||
{ name, slug }:
|
||||
{
|
||||
settings,
|
||||
doc,
|
||||
experimentalFeature,
|
||||
}:
|
||||
let
|
||||
result = squash ''
|
||||
# ${name}
|
||||
@@ -25,7 +45,10 @@ let
|
||||
|
||||
## Settings
|
||||
|
||||
${showSettings { prefix = "store-${slug}"; inherit inlineHTML; } settings}
|
||||
${showSettings {
|
||||
prefix = "store-${slug}";
|
||||
inherit inlineHTML;
|
||||
} settings}
|
||||
'';
|
||||
|
||||
experimentalFeatureNote = optionalString (experimentalFeature != null) ''
|
||||
@@ -43,15 +66,15 @@ let
|
||||
> extra-experimental-features = ${experimentalFeature}
|
||||
> ```
|
||||
'';
|
||||
in result;
|
||||
in
|
||||
result;
|
||||
|
||||
storesList = map
|
||||
(name: rec {
|
||||
inherit name;
|
||||
slug = replaceStrings [ " " ] [ "-" ] (toLower name);
|
||||
filename = "${slug}.md";
|
||||
page = showStore { inherit name slug; } storeInfo.${name};
|
||||
})
|
||||
(attrNames storeInfo);
|
||||
storesList = map (name: rec {
|
||||
inherit name;
|
||||
slug = replaceStrings [ " " ] [ "-" ] (toLower name);
|
||||
filename = "${slug}.md";
|
||||
page = showStore { inherit name slug; } storeInfo.${name};
|
||||
}) (attrNames storeInfo);
|
||||
|
||||
in storesList
|
||||
in
|
||||
storesList
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
let
|
||||
inherit (builtins) attrNames listToAttrs concatStringsSep readFile replaceStrings;
|
||||
inherit (builtins)
|
||||
attrNames
|
||||
listToAttrs
|
||||
concatStringsSep
|
||||
readFile
|
||||
replaceStrings
|
||||
;
|
||||
showSettings = import <nix/generate-settings.nix>;
|
||||
showStoreDocs = import <nix/generate-store-info.nix>;
|
||||
in
|
||||
@@ -14,26 +20,26 @@ let
|
||||
|
||||
index =
|
||||
let
|
||||
showEntry = store:
|
||||
"- [${store.name}](./${store.filename})";
|
||||
showEntry = store: "- [${store.name}](./${store.filename})";
|
||||
in
|
||||
concatStringsSep "\n" (map showEntry storesList);
|
||||
|
||||
"index.md" = replaceStrings
|
||||
[ "@store-types@" ] [ index ]
|
||||
(readFile ./src/store/types/index.md.in);
|
||||
"index.md" = replaceStrings [ "@store-types@" ] [ index ] (readFile ./src/store/types/index.md.in);
|
||||
|
||||
tableOfContents =
|
||||
let
|
||||
showEntry = store:
|
||||
" - [${store.name}](store/types/${store.filename})";
|
||||
showEntry = store: " - [${store.name}](store/types/${store.filename})";
|
||||
in
|
||||
concatStringsSep "\n" (map showEntry storesList) + "\n";
|
||||
|
||||
"SUMMARY.md" = tableOfContents;
|
||||
|
||||
storePages = listToAttrs
|
||||
(map (s: { name = s.filename; value = s.page; }) storesList);
|
||||
storePages = listToAttrs (
|
||||
map (s: {
|
||||
name = s.filename;
|
||||
value = s.page;
|
||||
}) storesList
|
||||
);
|
||||
|
||||
in
|
||||
storePages // { inherit "index.md" "SUMMARY.md"; }
|
||||
|
||||
@@ -2,8 +2,8 @@ with builtins;
|
||||
with import <nix/utils.nix>;
|
||||
|
||||
let
|
||||
showExperimentalFeature = name: doc:
|
||||
''
|
||||
- [`${name}`](@docroot@/development/experimental-features.md#xp-feature-${name})
|
||||
'';
|
||||
in xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps)))
|
||||
showExperimentalFeature = name: doc: ''
|
||||
- [`${name}`](@docroot@/development/experimental-features.md#xp-feature-${name})
|
||||
'';
|
||||
in
|
||||
xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps)))
|
||||
|
||||
@@ -2,7 +2,8 @@ with builtins;
|
||||
with import <nix/utils.nix>;
|
||||
|
||||
let
|
||||
showExperimentalFeature = name: doc:
|
||||
showExperimentalFeature =
|
||||
name: doc:
|
||||
squash ''
|
||||
## [`${name}`]{#xp-feature-${name}}
|
||||
|
||||
|
||||
10
doc/manual/rl-next/curl-cloexec.md
Normal file
10
doc/manual/rl-next/curl-cloexec.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
synopsis: Set FD_CLOEXEC on sockets created by curl
|
||||
issues: []
|
||||
prs: [12439]
|
||||
---
|
||||
|
||||
|
||||
Curl creates sockets without setting FD_CLOEXEC/SOCK_CLOEXEC, this can cause connections to remain open forever when using commands like `nix shell`
|
||||
|
||||
This change sets the FD_CLOEXEC flag using a CURLOPT_SOCKOPTFUNCTION callback.
|
||||
205
doc/manual/source/language/string-literals.md
Normal file
205
doc/manual/source/language/string-literals.md
Normal file
@@ -0,0 +1,205 @@
|
||||
# String literals
|
||||
|
||||
A *string literal* represents a [string](types.md#type-string) value.
|
||||
|
||||
> **Syntax**
|
||||
>
|
||||
> *expression* → *string*
|
||||
>
|
||||
> *string* → `"` ( *string_char*\* [*interpolation_element*][string interpolation] )* *string_char*\* `"`
|
||||
>
|
||||
> *string* → `''` ( *indented_string_char*\* [*interpolation_element*][string interpolation] )* *indented_string_char*\* `''`
|
||||
>
|
||||
> *string* → *uri*
|
||||
>
|
||||
> *string_char* ~ `[^"$\\]|\$(?!\{)|\\.`
|
||||
>
|
||||
> *indented_string_char* ~ `[^$']|\$\$|\$(?!\{)|''[$']|''\\.|'(?!')`
|
||||
>
|
||||
> *uri* ~ `[A-Za-z][+\-.0-9A-Za-z]*:[!$%&'*+,\-./0-9:=?@A-Z_a-z~]+`
|
||||
|
||||
Strings can be written in three ways.
|
||||
|
||||
The most common way is to enclose the string between double quotes, e.g., `"foo bar"`.
|
||||
Strings can span multiple lines.
|
||||
The results of other expressions can be included into a string by enclosing them in `${ }`, a feature known as [string interpolation].
|
||||
|
||||
[string interpolation]: ./string-interpolation.md
|
||||
|
||||
The following must be escaped to represent them within a string, by prefixing with a backslash (`\`):
|
||||
|
||||
- Double quote (`"`)
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> "\""
|
||||
> ```
|
||||
>
|
||||
> "\""
|
||||
|
||||
- Backslash (`\`)
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> "\\"
|
||||
> ```
|
||||
>
|
||||
> "\\"
|
||||
|
||||
- Dollar sign followed by an opening curly bracket (`${`) – "dollar-curly"
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> "\${"
|
||||
> ```
|
||||
>
|
||||
> "\${"
|
||||
|
||||
The newline, carriage return, and tab characters can be written as `\n`, `\r` and `\t`, respectively.
|
||||
|
||||
A "double-dollar-curly" (`$${`) can be written literally.
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> "$${"
|
||||
> ```
|
||||
>
|
||||
> "$\${"
|
||||
|
||||
String values are output on the terminal with Nix-specific escaping.
|
||||
Strings written to files will contain the characters encoded by the escaping.
|
||||
|
||||
The second way to write string literals is as an *indented string*, which is enclosed between pairs of *double single-quotes* (`''`), like so:
|
||||
|
||||
```nix
|
||||
''
|
||||
This is the first line.
|
||||
This is the second line.
|
||||
This is the third line.
|
||||
''
|
||||
```
|
||||
|
||||
This kind of string literal intelligently strips indentation from
|
||||
the start of each line. To be precise, it strips from each line a
|
||||
number of spaces equal to the minimal indentation of the string as a
|
||||
whole (disregarding the indentation of empty lines). For instance,
|
||||
the first and second line are indented two spaces, while the third
|
||||
line is indented four spaces. Thus, two spaces are stripped from
|
||||
each line, so the resulting string is
|
||||
|
||||
```nix
|
||||
"This is the first line.\nThis is the second line.\n This is the third line.\n"
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Whitespace and newline following the opening `''` is ignored if there is no non-whitespace text on the initial line.
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> Prefixed tab characters are not stripped.
|
||||
>
|
||||
> > **Example**
|
||||
> >
|
||||
> > The following indented string is prefixed with tabs:
|
||||
> >
|
||||
> > <pre><code class="nohighlight">''
|
||||
> > all:
|
||||
> > @echo hello
|
||||
> > ''
|
||||
> > </code></pre>
|
||||
> >
|
||||
> > "\tall:\n\t\t@echo hello\n"
|
||||
|
||||
Indented strings support [string interpolation].
|
||||
|
||||
The following must be escaped to represent them in an indented string:
|
||||
|
||||
- `$` is escaped by prefixing it with two single quotes (`''`)
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> ''
|
||||
> ''$
|
||||
> ''
|
||||
> ```
|
||||
>
|
||||
> "$\n"
|
||||
|
||||
- `''` is escaped by prefixing it with one single quote (`'`)
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> ''
|
||||
> '''
|
||||
> ''
|
||||
> ```
|
||||
>
|
||||
> "''\n"
|
||||
|
||||
These special characters are escaped as follows:
|
||||
- Linefeed (`\n`): `''\n`
|
||||
- Carriage return (`\r`): `''\r`
|
||||
- Tab (`\t`): `''\t`
|
||||
|
||||
`''\` escapes any other character.
|
||||
|
||||
A "dollar-curly" (`${`) can be written as follows:
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> ''
|
||||
> echo ''${PATH}
|
||||
> ''
|
||||
> ```
|
||||
>
|
||||
> "echo ${PATH}\n"
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> This differs from the syntax for escaping a dollar-curly within double quotes (`"\${"`). Be aware of which one is needed at a given moment.
|
||||
|
||||
A "double-dollar-curly" (`$${`) can be written literally.
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> ''
|
||||
> $${
|
||||
> ''
|
||||
> ```
|
||||
>
|
||||
> "$\${\n"
|
||||
|
||||
Indented strings are primarily useful in that they allow multi-line
|
||||
string literals to follow the indentation of the enclosing Nix
|
||||
expression, and that less escaping is typically necessary for
|
||||
strings representing languages such as shell scripts and
|
||||
configuration files because `''` is much less common than `"`.
|
||||
Example:
|
||||
|
||||
```nix
|
||||
stdenv.mkDerivation {
|
||||
...
|
||||
postInstall =
|
||||
''
|
||||
mkdir $out/bin $out/etc
|
||||
cp foo $out/bin
|
||||
echo "Hello World" > $out/etc/foo.conf
|
||||
${if enableBar then "cp bar $out/bin" else ""}
|
||||
'';
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Finally, as a convenience, *URIs* as defined in appendix B of
|
||||
[RFC 2396](http://www.ietf.org/rfc/rfc2396.txt) can be written *as
|
||||
is*, without quotes. For instance, the string
|
||||
`"http://example.org/foo.tar.bz2"` can also be written as
|
||||
`http://example.org/foo.tar.bz2`.
|
||||
@@ -62,6 +62,15 @@ These options are for deleting old [profiles] prior to deleting unreachable [sto
|
||||
This is the equivalent of invoking [`nix-env --delete-generations <period>`](@docroot@/command-ref/nix-env/delete-generations.md#generations-time) on each found profile.
|
||||
See the documentation of that command for additional information about the *period* argument.
|
||||
|
||||
- <span id="opt-max-freed">[`--max-freed`](#opt-max-freed)</span> *bytes*
|
||||
|
||||
<!-- duplication from https://github.com/NixOS/nix/blob/442a2623e48357ff72c77bb11cf2cf06d94d2f90/doc/manual/source/command-ref/nix-store/gc.md?plain=1#L39-L44 -->
|
||||
|
||||
Keep deleting paths until at least *bytes* bytes have been deleted,
|
||||
then stop. The argument *bytes* can be followed by the
|
||||
multiplicative suffix `K`, `M`, `G` or `T`, denoting KiB, MiB, GiB
|
||||
or TiB units.
|
||||
|
||||
{{#include ./opt-common.md}}
|
||||
|
||||
{{#include ./env-common.md}}
|
||||
|
||||
@@ -62,7 +62,7 @@ These pages can be viewed offline:
|
||||
|
||||
Several operations, such as [`nix-env --query`](./nix-env/query.md) and [`nix-env --install`](./nix-env/install.md), take a list of *arguments* that specify the packages on which to operate.
|
||||
|
||||
Packages are identified based on a `name` part and a `version` part of a [symbolic derivation name](@docroot@/language/derivations.md#attr-names):
|
||||
Packages are identified based on a `name` part and a `version` part of a [symbolic derivation name](@docroot@/language/derivations.md#attr-name):
|
||||
|
||||
- `name`: Everything up to but not including the first dash (`-`) that is *not* followed by a letter.
|
||||
- `version`: The rest, excluding the separating dash.
|
||||
|
||||
@@ -21,6 +21,9 @@ This operation has the following options:
|
||||
Use recursive instead of flat hashing mode, used when adding
|
||||
directories to the store.
|
||||
|
||||
*paths* that refer to symlinks are not dereferenced, but added to the store
|
||||
as symlinks with the same target.
|
||||
|
||||
{{#include ./opt-common.md}}
|
||||
|
||||
{{#include ../opt-common.md}}
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
The operation `--add` adds the specified paths to the Nix store. It
|
||||
prints the resulting paths in the Nix store on standard output.
|
||||
|
||||
*paths* that refer to symlinks are not dereferenced, but added to the store
|
||||
as symlinks with the same target.
|
||||
|
||||
{{#include ./opt-common.md}}
|
||||
|
||||
{{#include ../opt-common.md}}
|
||||
|
||||
@@ -104,7 +104,7 @@ symlink.
|
||||
|
||||
Prints a set of derivation files (`.drv`) which are supposed produce
|
||||
said paths when realized. Might print nothing, for example for source paths
|
||||
or paths subsituted from a binary cache.
|
||||
or paths substituted from a binary cache.
|
||||
|
||||
- `--graph`
|
||||
|
||||
@@ -241,4 +241,3 @@ $ nix-store --query --roots $(which svn)
|
||||
/nix/var/nix/profiles/default-82-link
|
||||
/home/eelco/.local/state/nix/profiles/profile-97-link
|
||||
```
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ This representation is extensible and preserves the ordering:
|
||||
|
||||
## Self-describing values
|
||||
|
||||
As described in the previous section, it's crucial that schemas can be extended with with new fields without breaking compatibility.
|
||||
As described in the previous section, it's crucial that schemas can be extended with new fields without breaking compatibility.
|
||||
However, that should *not* mean we use the presence/absence of fields to indicate optional information *within* a version of the schema.
|
||||
Instead, always include the field, and use `null` to indicate the "nothing" case.
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ Creating a Cachix cache for your installer tests and adding its authorisation to
|
||||
- `armv7l-linux`
|
||||
- `x86_64-darwin`
|
||||
|
||||
- The `installer_test` job (which runs on `ubuntu-latest` and `macos-latest`) will try to install Nix with the cached installer and run a trivial Nix command.
|
||||
- The `installer_test` job (which runs on `ubuntu-24.04` and `macos-14`) will try to install Nix with the cached installer and run a trivial Nix command.
|
||||
|
||||
### One-time setup
|
||||
|
||||
|
||||
@@ -14,6 +14,14 @@ This option requires either:
|
||||
* Linux running systemd, with SELinux disabled
|
||||
* MacOS
|
||||
|
||||
> **Updating to macOS 15 Sequoia**
|
||||
>
|
||||
> If you recently updated to macOS 15 Sequoia and are getting
|
||||
> ```console
|
||||
> error: the user '_nixbld1' in the group 'nixbld' does not exist
|
||||
> ```
|
||||
> when running Nix commands, refer to GitHub issue [NixOS/nix#10892](https://github.com/NixOS/nix/issues/10892) for instructions to fix your installation without reinstalling.
|
||||
|
||||
```console
|
||||
$ bash <(curl -L https://nixos.org/nix/install) --daemon
|
||||
```
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Installing a Binary Distribution
|
||||
|
||||
> **Updating to macOS 15 Sequoia**
|
||||
>
|
||||
> If you recently updated to macOS 15 Sequoia and are getting
|
||||
> ```console
|
||||
> error: the user '_nixbld1' in the group 'nixbld' does not exist
|
||||
> ```
|
||||
> when running Nix commands, refer to GitHub issue [NixOS/nix#10892](https://github.com/NixOS/nix/issues/10892) for instructions to fix your installation without reinstalling.
|
||||
|
||||
To install the latest version Nix, run the following command:
|
||||
|
||||
```console
|
||||
|
||||
@@ -39,8 +39,6 @@
|
||||
`pkgconfig` and the Boehm garbage collector, and pass the flag
|
||||
`--enable-gc` to `configure`.
|
||||
|
||||
For `bdw-gc` <= 8.2.4 Nix needs a [small patch](https://github.com/NixOS/nix/blob/ac4d2e7b857acdfeac35ac8a592bdecee2d29838/boehmgc-traceable_allocator-public.diff) to be applied.
|
||||
|
||||
- The `boost` library of version 1.66.0 or higher. It can be obtained
|
||||
from the official web site <https://www.boost.org/>.
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ If you are on Linux with systemd:
|
||||
Remove files created by Nix:
|
||||
|
||||
```console
|
||||
sudo rm -rf /etc/nix /etc/profile.d/nix.sh /etc/tmpfiles.d/nix-daemon.conf /nix ~root/.nix-channels ~root/.nix-defexpr ~root/.nix-profile
|
||||
sudo rm -rf /etc/nix /etc/profile.d/nix.sh /etc/tmpfiles.d/nix-daemon.conf /nix ~root/.nix-channels ~root/.nix-defexpr ~root/.nix-profile ~root/.cache/nix
|
||||
```
|
||||
|
||||
Remove build users and their group:
|
||||
@@ -43,6 +43,14 @@ which you may remove.
|
||||
|
||||
### macOS
|
||||
|
||||
> **Updating to macOS 15 Sequoia**
|
||||
>
|
||||
> If you recently updated to macOS 15 Sequoia and are getting
|
||||
> ```console
|
||||
> error: the user '_nixbld1' in the group 'nixbld' does not exist
|
||||
> ```
|
||||
> when running Nix commands, refer to GitHub issue [NixOS/nix#10892](https://github.com/NixOS/nix/issues/10892) for instructions to fix your installation without reinstalling.
|
||||
|
||||
1. If system-wide shell initialisation files haven't been altered since installing Nix, use the backups made by the installer:
|
||||
|
||||
```console
|
||||
@@ -133,7 +141,9 @@ which you may remove.
|
||||
diskutil list
|
||||
```
|
||||
|
||||
If you _do_ find a "Nix Store" volume, delete it by running `diskutil deleteVolume` with the store volume's `diskXsY` identifier.
|
||||
If you _do_ find a "Nix Store" volume, delete it by running `diskutil apfs deleteVolume` with the store volume's `diskXsY` identifier.
|
||||
|
||||
If you get an error that the volume is in use by the kernel, reboot and immediately delete the volume before starting any other process.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
|
||||
@@ -113,7 +113,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect
|
||||
|
||||
### Optional
|
||||
|
||||
- [`args`]{#attr-args} ([List](@docroot@/language/types.md#list) of [String](@docroot@/language/types.md#type-string))
|
||||
- [`args`]{#attr-args} ([List](@docroot@/language/types.md#type-list) of [String](@docroot@/language/types.md#type-string))
|
||||
|
||||
Default: `[ ]`
|
||||
|
||||
@@ -132,7 +132,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect
|
||||
> };
|
||||
> ```
|
||||
|
||||
- [`outputs`]{#attr-outputs} ([List](@docroot@/language/types.md#list) of [String](@docroot@/language/types.md#type-string))
|
||||
- [`outputs`]{#attr-outputs} ([List](@docroot@/language/types.md#type-list) of [String](@docroot@/language/types.md#type-string))
|
||||
|
||||
Default: `[ "out" ]`
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
| Name | Syntax | Associativity | Precedence |
|
||||
|----------------------------------------|--------------------------------------------|---------------|------------|
|
||||
| [Attribute selection] | *attrset* `.` *attrpath* \[ `or` *expr* \] | none | 1 |
|
||||
| Function application | *func* *expr* | left | 2 |
|
||||
| [Function application] | *func* *expr* | left | 2 |
|
||||
| [Arithmetic negation][arithmetic] | `-` *number* | none | 3 |
|
||||
| [Has attribute] | *attrset* `?` *attrpath* | none | 4 |
|
||||
| List concatenation | *list* `++` *list* | right | 5 |
|
||||
@@ -32,8 +32,8 @@
|
||||
[string]: ./types.md#type-string
|
||||
[path]: ./types.md#type-path
|
||||
[number]: ./types.md#type-float
|
||||
[list]: ./types.md#list
|
||||
[attribute set]: ./types.md#attribute-set
|
||||
[list]: ./types.md#type-list
|
||||
[attribute set]: ./types.md#type-attrs
|
||||
|
||||
<!-- TODO(@rhendric, #10970): ^ rationalize number -> int/float -->
|
||||
|
||||
@@ -48,6 +48,22 @@ If the attribute doesn’t exist, return the *expr* after `or` if provided, othe
|
||||
|
||||
[Attribute selection]: #attribute-selection
|
||||
|
||||
## Function application
|
||||
|
||||
> **Syntax**
|
||||
>
|
||||
> *func* *expr*
|
||||
|
||||
Apply the callable value *func* to the argument *expr*. Note the absence of any visible operator symbol.
|
||||
A callable value is either:
|
||||
- a [user-defined function][function]
|
||||
- a [built-in][builtins] function
|
||||
- an attribute set with a [`__functor` attribute](./syntax.md#attr-__functor)
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> [List][list] items are also separated by whitespace, which means that function calls in list items must be enclosed by parentheses.
|
||||
|
||||
## Has attribute
|
||||
|
||||
> **Syntax**
|
||||
@@ -59,7 +75,7 @@ The result is a [Boolean] value.
|
||||
|
||||
See also: [`builtins.hasAttr`](@docroot@/language/builtins.md#builtins-hasAttr)
|
||||
|
||||
[Boolean]: ./types.md#type-boolean
|
||||
[Boolean]: ./types.md#type-bool
|
||||
|
||||
[Has attribute]: #has-attribute
|
||||
|
||||
@@ -211,3 +227,5 @@ Equivalent to `!`*b1* `||` *b2*.
|
||||
> ```
|
||||
|
||||
[Pipe operator]: #pipe-operators
|
||||
[builtins]: ./builtins.md
|
||||
[Function application]: #function-application
|
||||
|
||||
@@ -379,7 +379,7 @@ a string), that attribute is simply not added to the set:
|
||||
|
||||
This will evaluate to `{}` if `foo` evaluates to `false`.
|
||||
|
||||
A set that has a `__functor` attribute whose value is callable (i.e. is
|
||||
A set that has a [`__functor`]{#attr-__functor} attribute whose value is callable (i.e. is
|
||||
itself a function or a set with a `__functor` attribute whose value is
|
||||
callable) can be applied as if it were a function, with the set itself
|
||||
passed in first , e.g.,
|
||||
|
||||
@@ -82,7 +82,7 @@ where
|
||||
|
||||
- if `type` = `"source:" ...`:
|
||||
|
||||
the the hash of the [Nix Archive (NAR)] serialization of the [file system object](@docroot@/store/file-system-object.md) of the store object.
|
||||
the hash of the [Nix Archive (NAR)] serialization of the [file system object](@docroot@/store/file-system-object.md) of the store object.
|
||||
|
||||
- if `type` = `"output:" id`:
|
||||
|
||||
|
||||
@@ -75,3 +75,7 @@
|
||||
(experimental) can be found by any program that follows the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html).
|
||||
|
||||
- A new command `nix store add` has been added. It replaces `nix store add-file` and `nix store add-path` which are now deprecated.
|
||||
|
||||
- A new option [`always-allow-substitutes`](@docroot@/command-ref/conf-file.md#conf-always-allow-substitutes) has been added.
|
||||
|
||||
When set to `true`, Nix will always try to substitute a derivation, even if it has the [`allowSubstitutes`]{#adv-attr-allowSubstitutes} attribute set to `false`.
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
- Store object info JSON format now uses `null` rather than omitting fields [#9995](https://github.com/NixOS/nix/pull/9995)
|
||||
|
||||
The [store object info JSON format](@docroot@/protocols/json/store-object-info.md), used for e.g. `nix path-info`, no longer omits fields to indicate absent information, but instead includes the fields with a `null` value.
|
||||
For example, `"ca": null` is used to to indicate a store object that isn't content-addressed rather than omitting the `ca` field entirely.
|
||||
For example, `"ca": null` is used to indicate a store object that isn't content-addressed rather than omitting the `ca` field entirely.
|
||||
This makes records of this sort more self-describing, and easier to consume programmatically.
|
||||
|
||||
We will follow this design principle going forward;
|
||||
@@ -96,7 +96,7 @@
|
||||
Nix can now warn when evaluation of a Nix expression causes a large
|
||||
path to be copied to the Nix store. The threshold for this warning can
|
||||
be configured using [the `warn-large-path-threshold`
|
||||
setting](@docroot@/command-ref/conf-file.md#warn-large-path-threshold),
|
||||
setting](@docroot@/command-ref/conf-file.md#conf-warn-large-path-threshold),
|
||||
e.g. `--warn-large-path-threshold 100M` will warn about paths larger
|
||||
than 100 MiB.
|
||||
|
||||
|
||||
@@ -274,6 +274,21 @@
|
||||
be configured using the `warn-large-path-threshold` setting,
|
||||
e.g. `--warn-large-path-threshold 100M`.
|
||||
|
||||
- Wrap filesystem exceptions more correctly [#11378](https://github.com/NixOS/nix/pull/11378)
|
||||
|
||||
With the switch to `std::filesystem` in different places, Nix started to throw `std::filesystem::filesystem_error` in many places instead of its own exceptions.
|
||||
|
||||
This led to no longer generating error traces, for example when listing a non-existing directory.
|
||||
|
||||
This version catches these types of exception correctly and wraps them into Nix's own exeception type.
|
||||
|
||||
Author: [**@Mic92**](https://github.com/Mic92)
|
||||
|
||||
- `<nix/fetchurl.nix>` uses TLS verification [#11585](https://github.com/NixOS/nix/pull/11585)
|
||||
|
||||
Previously `<nix/fetchurl.nix>` did not do TLS verification. This was because the Nix sandbox in the past did not have access to TLS certificates, and Nix checks the hash of the fetched file anyway. However, this can expose authentication data from `netrc` and URLs to man-in-the-middle attackers. In addition, Nix now in some cases (such as when using impure derivations) does *not* check the hash. Therefore we have now enabled TLS verification. This means that downloads by `<nix/fetchurl.nix>` will now fail if you're fetching from a HTTPS server that does not have a valid certificate.
|
||||
|
||||
`<nix/fetchurl.nix>` is also known as the builtin derivation builder `builtin:fetchurl`. It's not to be confused with the evaluation-time function `builtins.fetchurl`, which was not affected by this issue.
|
||||
|
||||
# Contributors
|
||||
|
||||
|
||||
@@ -11,10 +11,15 @@ rec {
|
||||
|
||||
concatStrings = concatStringsSep "";
|
||||
|
||||
attrsToList = a:
|
||||
map (name: { inherit name; value = a.${name}; }) (builtins.attrNames a);
|
||||
attrsToList =
|
||||
a:
|
||||
map (name: {
|
||||
inherit name;
|
||||
value = a.${name};
|
||||
}) (builtins.attrNames a);
|
||||
|
||||
replaceStringsRec = from: to: string:
|
||||
replaceStringsRec =
|
||||
from: to: string:
|
||||
# recursively replace occurrences of `from` with `to` within `string`
|
||||
# example:
|
||||
# replaceStringRec "--" "-" "hello-----world"
|
||||
@@ -22,16 +27,18 @@ rec {
|
||||
let
|
||||
replaced = replaceStrings [ from ] [ to ] string;
|
||||
in
|
||||
if replaced == string then string else replaceStringsRec from to replaced;
|
||||
if replaced == string then string else replaceStringsRec from to replaced;
|
||||
|
||||
toLower = replaceStrings upperChars lowerChars;
|
||||
|
||||
squash = replaceStringsRec "\n\n\n" "\n\n";
|
||||
|
||||
trim = string:
|
||||
trim =
|
||||
string:
|
||||
# trim trailing spaces and squash non-leading spaces
|
||||
let
|
||||
trimLine = line:
|
||||
trimLine =
|
||||
line:
|
||||
let
|
||||
# separate leading spaces from the rest
|
||||
parts = split "(^ *)" line;
|
||||
@@ -39,19 +46,30 @@ rec {
|
||||
rest = elemAt parts 2;
|
||||
# drop trailing spaces
|
||||
body = head (split " *$" rest);
|
||||
in spaces + replaceStringsRec " " " " body;
|
||||
in concatStringsSep "\n" (map trimLine (splitLines string));
|
||||
in
|
||||
spaces + replaceStringsRec " " " " body;
|
||||
in
|
||||
concatStringsSep "\n" (map trimLine (splitLines string));
|
||||
|
||||
# FIXME: O(n^2)
|
||||
unique = foldl' (acc: e: if elem e acc then acc else acc ++ [ e ]) [];
|
||||
unique = foldl' (acc: e: if elem e acc then acc else acc ++ [ e ]) [ ];
|
||||
|
||||
nameValuePair = name: value: { inherit name value; };
|
||||
|
||||
filterAttrs = pred: set:
|
||||
listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set));
|
||||
filterAttrs =
|
||||
pred: set:
|
||||
listToAttrs (
|
||||
concatMap (
|
||||
name:
|
||||
let
|
||||
v = set.${name};
|
||||
in
|
||||
if pred name v then [ (nameValuePair name v) ] else [ ]
|
||||
) (attrNames set)
|
||||
);
|
||||
|
||||
optionalString = cond: string: if cond then string else "";
|
||||
|
||||
indent = prefix: s:
|
||||
concatStringsSep "\n" (map (x: if x == "" then x else "${prefix}${x}") (splitLines s));
|
||||
indent =
|
||||
prefix: s: concatStringsSep "\n" (map (x: if x == "" then x else "${prefix}${x}") (splitLines s));
|
||||
}
|
||||
|
||||
381
docker.nix
381
docker.nix
@@ -1,70 +1,72 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, lib ? pkgs.lib
|
||||
, name ? "nix"
|
||||
, tag ? "latest"
|
||||
, bundleNixpkgs ? true
|
||||
, channelName ? "nixpkgs"
|
||||
, channelURL ? "https://nixos.org/channels/nixpkgs-unstable"
|
||||
, extraPkgs ? []
|
||||
, maxLayers ? 100
|
||||
, nixConf ? {}
|
||||
, flake-registry ? null
|
||||
{
|
||||
pkgs ? import <nixpkgs> { },
|
||||
lib ? pkgs.lib,
|
||||
name ? "nix",
|
||||
tag ? "latest",
|
||||
bundleNixpkgs ? true,
|
||||
channelName ? "nixpkgs",
|
||||
channelURL ? "https://nixos.org/channels/nixpkgs-unstable",
|
||||
extraPkgs ? [ ],
|
||||
maxLayers ? 100,
|
||||
nixConf ? { },
|
||||
flake-registry ? null,
|
||||
}:
|
||||
let
|
||||
defaultPkgs = with pkgs; [
|
||||
nix
|
||||
bashInteractive
|
||||
coreutils-full
|
||||
gnutar
|
||||
gzip
|
||||
gnugrep
|
||||
which
|
||||
curl
|
||||
less
|
||||
wget
|
||||
man
|
||||
cacert.out
|
||||
findutils
|
||||
iana-etc
|
||||
git
|
||||
openssh
|
||||
] ++ extraPkgs;
|
||||
defaultPkgs =
|
||||
with pkgs;
|
||||
[
|
||||
nix
|
||||
bashInteractive
|
||||
coreutils-full
|
||||
gnutar
|
||||
gzip
|
||||
gnugrep
|
||||
which
|
||||
curl
|
||||
less
|
||||
wget
|
||||
man
|
||||
cacert.out
|
||||
findutils
|
||||
iana-etc
|
||||
git
|
||||
openssh
|
||||
]
|
||||
++ extraPkgs;
|
||||
|
||||
users = {
|
||||
users =
|
||||
{
|
||||
|
||||
root = {
|
||||
uid = 0;
|
||||
shell = "${pkgs.bashInteractive}/bin/bash";
|
||||
home = "/root";
|
||||
gid = 0;
|
||||
groups = [ "root" ];
|
||||
description = "System administrator";
|
||||
};
|
||||
root = {
|
||||
uid = 0;
|
||||
shell = "${pkgs.bashInteractive}/bin/bash";
|
||||
home = "/root";
|
||||
gid = 0;
|
||||
groups = [ "root" ];
|
||||
description = "System administrator";
|
||||
};
|
||||
|
||||
nobody = {
|
||||
uid = 65534;
|
||||
shell = "${pkgs.shadow}/bin/nologin";
|
||||
home = "/var/empty";
|
||||
gid = 65534;
|
||||
groups = [ "nobody" ];
|
||||
description = "Unprivileged account (don't use!)";
|
||||
};
|
||||
nobody = {
|
||||
uid = 65534;
|
||||
shell = "${pkgs.shadow}/bin/nologin";
|
||||
home = "/var/empty";
|
||||
gid = 65534;
|
||||
groups = [ "nobody" ];
|
||||
description = "Unprivileged account (don't use!)";
|
||||
};
|
||||
|
||||
} // lib.listToAttrs (
|
||||
map
|
||||
(
|
||||
n: {
|
||||
name = "nixbld${toString n}";
|
||||
value = {
|
||||
uid = 30000 + n;
|
||||
gid = 30000;
|
||||
groups = [ "nixbld" ];
|
||||
description = "Nix build user ${toString n}";
|
||||
};
|
||||
}
|
||||
)
|
||||
(lib.lists.range 1 32)
|
||||
);
|
||||
}
|
||||
// lib.listToAttrs (
|
||||
map (n: {
|
||||
name = "nixbld${toString n}";
|
||||
value = {
|
||||
uid = 30000 + n;
|
||||
gid = 30000;
|
||||
groups = [ "nixbld" ];
|
||||
description = "Nix build user ${toString n}";
|
||||
};
|
||||
}) (lib.lists.range 1 32)
|
||||
);
|
||||
|
||||
groups = {
|
||||
root.gid = 0;
|
||||
@@ -74,24 +76,20 @@ let
|
||||
|
||||
userToPasswd = (
|
||||
k:
|
||||
{ uid
|
||||
, gid ? 65534
|
||||
, home ? "/var/empty"
|
||||
, description ? ""
|
||||
, shell ? "/bin/false"
|
||||
, groups ? [ ]
|
||||
}: "${k}:x:${toString uid}:${toString gid}:${description}:${home}:${shell}"
|
||||
);
|
||||
passwdContents = (
|
||||
lib.concatStringsSep "\n"
|
||||
(lib.attrValues (lib.mapAttrs userToPasswd users))
|
||||
{
|
||||
uid,
|
||||
gid ? 65534,
|
||||
home ? "/var/empty",
|
||||
description ? "",
|
||||
shell ? "/bin/false",
|
||||
groups ? [ ],
|
||||
}:
|
||||
"${k}:x:${toString uid}:${toString gid}:${description}:${home}:${shell}"
|
||||
);
|
||||
passwdContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs userToPasswd users)));
|
||||
|
||||
userToShadow = k: { ... }: "${k}:!:1::::::";
|
||||
shadowContents = (
|
||||
lib.concatStringsSep "\n"
|
||||
(lib.attrValues (lib.mapAttrs userToShadow users))
|
||||
);
|
||||
shadowContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs userToShadow users)));
|
||||
|
||||
# Map groups to members
|
||||
# {
|
||||
@@ -101,42 +99,35 @@ let
|
||||
let
|
||||
# Create a flat list of user/group mappings
|
||||
mappings = (
|
||||
builtins.foldl'
|
||||
(
|
||||
acc: user:
|
||||
let
|
||||
groups = users.${user}.groups or [ ];
|
||||
in
|
||||
acc ++ map
|
||||
(group: {
|
||||
inherit user group;
|
||||
})
|
||||
groups
|
||||
)
|
||||
[ ]
|
||||
(lib.attrNames users)
|
||||
builtins.foldl' (
|
||||
acc: user:
|
||||
let
|
||||
groups = users.${user}.groups or [ ];
|
||||
in
|
||||
acc
|
||||
++ map (group: {
|
||||
inherit user group;
|
||||
}) groups
|
||||
) [ ] (lib.attrNames users)
|
||||
);
|
||||
in
|
||||
(
|
||||
builtins.foldl'
|
||||
(
|
||||
acc: v: acc // {
|
||||
${v.group} = acc.${v.group} or [ ] ++ [ v.user ];
|
||||
}
|
||||
)
|
||||
{ }
|
||||
mappings)
|
||||
(builtins.foldl' (
|
||||
acc: v:
|
||||
acc
|
||||
// {
|
||||
${v.group} = acc.${v.group} or [ ] ++ [ v.user ];
|
||||
}
|
||||
) { } mappings)
|
||||
);
|
||||
|
||||
groupToGroup = k: { gid }:
|
||||
groupToGroup =
|
||||
k:
|
||||
{ gid }:
|
||||
let
|
||||
members = groupMemberMap.${k} or [ ];
|
||||
in
|
||||
"${k}:x:${toString gid}:${lib.concatStringsSep "," members}";
|
||||
groupContents = (
|
||||
lib.concatStringsSep "\n"
|
||||
(lib.attrValues (lib.mapAttrs groupToGroup groups))
|
||||
);
|
||||
groupContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs groupToGroup groups)));
|
||||
|
||||
defaultNixConf = {
|
||||
sandbox = "false";
|
||||
@@ -144,11 +135,17 @@ let
|
||||
trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ];
|
||||
};
|
||||
|
||||
nixConfContents = (lib.concatStringsSep "\n" (lib.mapAttrsFlatten (n: v:
|
||||
let
|
||||
vStr = if builtins.isList v then lib.concatStringsSep " " v else v;
|
||||
in
|
||||
"${n} = ${vStr}") (defaultNixConf // nixConf))) + "\n";
|
||||
nixConfContents =
|
||||
(lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsFlatten (
|
||||
n: v:
|
||||
let
|
||||
vStr = if builtins.isList v then lib.concatStringsSep " " v else v;
|
||||
in
|
||||
"${n} = ${vStr}"
|
||||
) (defaultNixConf // nixConf)
|
||||
))
|
||||
+ "\n";
|
||||
|
||||
baseSystem =
|
||||
let
|
||||
@@ -167,21 +164,29 @@ let
|
||||
manifest = pkgs.buildPackages.runCommand "manifest.nix" { } ''
|
||||
cat > $out <<EOF
|
||||
[
|
||||
${lib.concatStringsSep "\n" (builtins.map (drv: let
|
||||
outputs = drv.outputsToInstall or [ "out" ];
|
||||
in ''
|
||||
{
|
||||
${lib.concatStringsSep "\n" (builtins.map (output: ''
|
||||
${output} = { outPath = "${lib.getOutput output drv}"; };
|
||||
'') outputs)}
|
||||
outputs = [ ${lib.concatStringsSep " " (builtins.map (x: "\"${x}\"") outputs)} ];
|
||||
name = "${drv.name}";
|
||||
outPath = "${drv}";
|
||||
system = "${drv.system}";
|
||||
type = "derivation";
|
||||
meta = { };
|
||||
}
|
||||
'') defaultPkgs)}
|
||||
${lib.concatStringsSep "\n" (
|
||||
builtins.map (
|
||||
drv:
|
||||
let
|
||||
outputs = drv.outputsToInstall or [ "out" ];
|
||||
in
|
||||
''
|
||||
{
|
||||
${lib.concatStringsSep "\n" (
|
||||
builtins.map (output: ''
|
||||
${output} = { outPath = "${lib.getOutput output drv}"; };
|
||||
'') outputs
|
||||
)}
|
||||
outputs = [ ${lib.concatStringsSep " " (builtins.map (x: "\"${x}\"") outputs)} ];
|
||||
name = "${drv.name}";
|
||||
outPath = "${drv}";
|
||||
system = "${drv.system}";
|
||||
type = "derivation";
|
||||
meta = { };
|
||||
}
|
||||
''
|
||||
) defaultPkgs
|
||||
)}
|
||||
]
|
||||
EOF
|
||||
'';
|
||||
@@ -190,16 +195,22 @@ let
|
||||
cp -a ${rootEnv}/* $out/
|
||||
ln -s ${manifest} $out/manifest.nix
|
||||
'';
|
||||
flake-registry-path = if (flake-registry == null) then
|
||||
null
|
||||
else if (builtins.readFileType (toString flake-registry)) == "directory" then
|
||||
"${flake-registry}/flake-registry.json"
|
||||
else
|
||||
flake-registry;
|
||||
flake-registry-path =
|
||||
if (flake-registry == null) then
|
||||
null
|
||||
else if (builtins.readFileType (toString flake-registry)) == "directory" then
|
||||
"${flake-registry}/flake-registry.json"
|
||||
else
|
||||
flake-registry;
|
||||
in
|
||||
pkgs.runCommand "base-system"
|
||||
{
|
||||
inherit passwdContents groupContents shadowContents nixConfContents;
|
||||
inherit
|
||||
passwdContents
|
||||
groupContents
|
||||
shadowContents
|
||||
nixConfContents
|
||||
;
|
||||
passAsFile = [
|
||||
"passwdContents"
|
||||
"groupContents"
|
||||
@@ -208,62 +219,66 @@ let
|
||||
];
|
||||
allowSubstitutes = false;
|
||||
preferLocalBuild = true;
|
||||
} (''
|
||||
env
|
||||
set -x
|
||||
mkdir -p $out/etc
|
||||
}
|
||||
(
|
||||
''
|
||||
env
|
||||
set -x
|
||||
mkdir -p $out/etc
|
||||
|
||||
mkdir -p $out/etc/ssl/certs
|
||||
ln -s /nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt $out/etc/ssl/certs
|
||||
mkdir -p $out/etc/ssl/certs
|
||||
ln -s /nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt $out/etc/ssl/certs
|
||||
|
||||
cat $passwdContentsPath > $out/etc/passwd
|
||||
echo "" >> $out/etc/passwd
|
||||
cat $passwdContentsPath > $out/etc/passwd
|
||||
echo "" >> $out/etc/passwd
|
||||
|
||||
cat $groupContentsPath > $out/etc/group
|
||||
echo "" >> $out/etc/group
|
||||
cat $groupContentsPath > $out/etc/group
|
||||
echo "" >> $out/etc/group
|
||||
|
||||
cat $shadowContentsPath > $out/etc/shadow
|
||||
echo "" >> $out/etc/shadow
|
||||
cat $shadowContentsPath > $out/etc/shadow
|
||||
echo "" >> $out/etc/shadow
|
||||
|
||||
mkdir -p $out/usr
|
||||
ln -s /nix/var/nix/profiles/share $out/usr/
|
||||
mkdir -p $out/usr
|
||||
ln -s /nix/var/nix/profiles/share $out/usr/
|
||||
|
||||
mkdir -p $out/nix/var/nix/gcroots
|
||||
mkdir -p $out/nix/var/nix/gcroots
|
||||
|
||||
mkdir $out/tmp
|
||||
mkdir $out/tmp
|
||||
|
||||
mkdir -p $out/var/tmp
|
||||
mkdir -p $out/var/tmp
|
||||
|
||||
mkdir -p $out/etc/nix
|
||||
cat $nixConfContentsPath > $out/etc/nix/nix.conf
|
||||
mkdir -p $out/etc/nix
|
||||
cat $nixConfContentsPath > $out/etc/nix/nix.conf
|
||||
|
||||
mkdir -p $out/root
|
||||
mkdir -p $out/nix/var/nix/profiles/per-user/root
|
||||
mkdir -p $out/root
|
||||
mkdir -p $out/nix/var/nix/profiles/per-user/root
|
||||
|
||||
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 $out/root/.nix-profile
|
||||
ln -s ${profile} $out/nix/var/nix/profiles/default-1-link
|
||||
ln -s /nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default
|
||||
ln -s /nix/var/nix/profiles/default $out/root/.nix-profile
|
||||
|
||||
ln -s ${channel} $out/nix/var/nix/profiles/per-user/root/channels-1-link
|
||||
ln -s $out/nix/var/nix/profiles/per-user/root/channels-1-link $out/nix/var/nix/profiles/per-user/root/channels
|
||||
ln -s ${channel} $out/nix/var/nix/profiles/per-user/root/channels-1-link
|
||||
ln -s /nix/var/nix/profiles/per-user/root/channels-1-link $out/nix/var/nix/profiles/per-user/root/channels
|
||||
|
||||
mkdir -p $out/root/.nix-defexpr
|
||||
ln -s $out/nix/var/nix/profiles/per-user/root/channels $out/root/.nix-defexpr/channels
|
||||
echo "${channelURL} ${channelName}" > $out/root/.nix-channels
|
||||
mkdir -p $out/root/.nix-defexpr
|
||||
ln -s /nix/var/nix/profiles/per-user/root/channels $out/root/.nix-defexpr/channels
|
||||
echo "${channelURL} ${channelName}" > $out/root/.nix-channels
|
||||
|
||||
mkdir -p $out/bin $out/usr/bin
|
||||
ln -s ${pkgs.coreutils}/bin/env $out/usr/bin/env
|
||||
ln -s ${pkgs.bashInteractive}/bin/bash $out/bin/sh
|
||||
mkdir -p $out/bin $out/usr/bin
|
||||
ln -s ${pkgs.coreutils}/bin/env $out/usr/bin/env
|
||||
ln -s ${pkgs.bashInteractive}/bin/bash $out/bin/sh
|
||||
|
||||
'' + (lib.optionalString (flake-registry-path != null) ''
|
||||
nixCacheDir="/root/.cache/nix"
|
||||
mkdir -p $out$nixCacheDir
|
||||
globalFlakeRegistryPath="$nixCacheDir/flake-registry.json"
|
||||
ln -s ${flake-registry-path} $out$globalFlakeRegistryPath
|
||||
mkdir -p $out/nix/var/nix/gcroots/auto
|
||||
rootName=$(${pkgs.nix}/bin/nix --extra-experimental-features nix-command hash file --type sha1 --base32 <(echo -n $globalFlakeRegistryPath))
|
||||
ln -s $globalFlakeRegistryPath $out/nix/var/nix/gcroots/auto/$rootName
|
||||
''));
|
||||
''
|
||||
+ (lib.optionalString (flake-registry-path != null) ''
|
||||
nixCacheDir="/root/.cache/nix"
|
||||
mkdir -p $out$nixCacheDir
|
||||
globalFlakeRegistryPath="$nixCacheDir/flake-registry.json"
|
||||
ln -s ${flake-registry-path} $out$globalFlakeRegistryPath
|
||||
mkdir -p $out/nix/var/nix/gcroots/auto
|
||||
rootName=$(${pkgs.nix}/bin/nix --extra-experimental-features nix-command hash file --type sha1 --base32 <(echo -n $globalFlakeRegistryPath))
|
||||
ln -s $globalFlakeRegistryPath $out/nix/var/nix/gcroots/auto/$rootName
|
||||
'')
|
||||
);
|
||||
|
||||
in
|
||||
pkgs.dockerTools.buildLayeredImageWithNixDb {
|
||||
@@ -285,15 +300,19 @@ pkgs.dockerTools.buildLayeredImageWithNixDb {
|
||||
Cmd = [ "/root/.nix-profile/bin/bash" ];
|
||||
Env = [
|
||||
"USER=root"
|
||||
"PATH=${lib.concatStringsSep ":" [
|
||||
"/root/.nix-profile/bin"
|
||||
"/nix/var/nix/profiles/default/bin"
|
||||
"/nix/var/nix/profiles/default/sbin"
|
||||
]}"
|
||||
"MANPATH=${lib.concatStringsSep ":" [
|
||||
"/root/.nix-profile/share/man"
|
||||
"/nix/var/nix/profiles/default/share/man"
|
||||
]}"
|
||||
"PATH=${
|
||||
lib.concatStringsSep ":" [
|
||||
"/root/.nix-profile/bin"
|
||||
"/nix/var/nix/profiles/default/bin"
|
||||
"/nix/var/nix/profiles/default/sbin"
|
||||
]
|
||||
}"
|
||||
"MANPATH=${
|
||||
lib.concatStringsSep ":" [
|
||||
"/root/.nix-profile/share/man"
|
||||
"/nix/var/nix/profiles/default/share/man"
|
||||
]
|
||||
}"
|
||||
"SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
|
||||
"GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
|
||||
"NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
|
||||
|
||||
6
flake.lock
generated
6
flake.lock
generated
@@ -80,11 +80,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1721548954,
|
||||
"narHash": "sha256-7cCC8+Tdq1+3OPyc3+gVo9dzUNkNIQfwSDJ2HSi2u3o=",
|
||||
"lastModified": 1723688146,
|
||||
"narHash": "sha256-sqLwJcHYeWLOeP/XoLwAtYjr01TISlkOfz+NG82pbdg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "63d37ccd2d178d54e7fb691d7ec76000740ea24a",
|
||||
"rev": "c3d4ac725177c030b1e289015989da2ad9d56af0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
571
flake.nix
571
flake.nix
@@ -4,8 +4,14 @@
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||
inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
|
||||
inputs.nixpkgs-23-11.url = "github:NixOS/nixpkgs/a62e6edd6d5e1fa0329b8653c801147986f8d446";
|
||||
inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
|
||||
inputs.libgit2 = { url = "github:libgit2/libgit2/v1.8.1"; flake = false; };
|
||||
inputs.flake-compat = {
|
||||
url = "github:edolstra/flake-compat";
|
||||
flake = false;
|
||||
};
|
||||
inputs.libgit2 = {
|
||||
url = "github:libgit2/libgit2/v1.8.1";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
# dev tooling
|
||||
inputs.flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
@@ -18,24 +24,39 @@
|
||||
inputs.git-hooks-nix.inputs.flake-compat.follows = "";
|
||||
inputs.git-hooks-nix.inputs.gitignore.follows = "";
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, nixpkgs-regression, libgit2, ... }:
|
||||
|
||||
outputs =
|
||||
inputs@{
|
||||
self,
|
||||
nixpkgs,
|
||||
nixpkgs-regression,
|
||||
libgit2,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (nixpkgs) lib;
|
||||
|
||||
officialRelease = false;
|
||||
officialRelease = true;
|
||||
|
||||
version = lib.fileContents ./.version + versionSuffix;
|
||||
versionSuffix =
|
||||
if officialRelease
|
||||
then ""
|
||||
else "pre${builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}_${self.shortRev or "dirty"}";
|
||||
if officialRelease then
|
||||
""
|
||||
else
|
||||
"pre${
|
||||
builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")
|
||||
}_${self.shortRev or "dirty"}";
|
||||
|
||||
linux32BitSystems = [ "i686-linux" ];
|
||||
linux64BitSystems = [ "x86_64-linux" "aarch64-linux" ];
|
||||
linux64BitSystems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
linuxSystems = linux32BitSystems ++ linux64BitSystems;
|
||||
darwinSystems = [ "x86_64-darwin" "aarch64-darwin" ];
|
||||
darwinSystems = [
|
||||
"x86_64-darwin"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
systems = linuxSystems ++ darwinSystems;
|
||||
|
||||
crossSystems = [
|
||||
@@ -64,62 +85,76 @@
|
||||
(Provided that the names are unique.)
|
||||
|
||||
See https://nixos.org/manual/nixpkgs/stable/index.html#function-library-lib.attrsets.concatMapAttrs
|
||||
*/
|
||||
*/
|
||||
flatMapAttrs = attrs: f: lib.concatMapAttrs f attrs;
|
||||
|
||||
forAllSystems = lib.genAttrs systems;
|
||||
|
||||
forAllCrossSystems = lib.genAttrs crossSystems;
|
||||
|
||||
forAllStdenvs = f:
|
||||
lib.listToAttrs
|
||||
(map
|
||||
(stdenvName: {
|
||||
name = "${stdenvName}Packages";
|
||||
value = f stdenvName;
|
||||
})
|
||||
stdenvs);
|
||||
|
||||
forAllStdenvs =
|
||||
f:
|
||||
lib.listToAttrs (
|
||||
map (stdenvName: {
|
||||
name = "${stdenvName}Packages";
|
||||
value = f stdenvName;
|
||||
}) stdenvs
|
||||
);
|
||||
|
||||
# We don't apply flake-parts to the whole flake so that non-development attributes
|
||||
# load without fetching any development inputs.
|
||||
devFlake = inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
imports = [ ./maintainers/flake-module.nix ];
|
||||
systems = lib.subtractLists crossSystems systems;
|
||||
perSystem = { system, ... }: {
|
||||
_module.args.pkgs = nixpkgsFor.${system}.native;
|
||||
};
|
||||
perSystem =
|
||||
{ system, ... }:
|
||||
{
|
||||
_module.args.pkgs = nixpkgsFor.${system}.native;
|
||||
};
|
||||
};
|
||||
|
||||
# Memoize nixpkgs for different platforms for efficiency.
|
||||
nixpkgsFor = forAllSystems
|
||||
(system: let
|
||||
make-pkgs = crossSystem: stdenv: import nixpkgs {
|
||||
localSystem = {
|
||||
inherit system;
|
||||
nixpkgsFor = forAllSystems (
|
||||
system:
|
||||
let
|
||||
make-pkgs =
|
||||
crossSystem: stdenv:
|
||||
import nixpkgs {
|
||||
localSystem = {
|
||||
inherit system;
|
||||
};
|
||||
crossSystem =
|
||||
if crossSystem == null then
|
||||
null
|
||||
else
|
||||
{
|
||||
config = crossSystem;
|
||||
}
|
||||
// lib.optionalAttrs (crossSystem == "x86_64-unknown-freebsd13") {
|
||||
useLLVM = true;
|
||||
};
|
||||
overlays = [
|
||||
(overlayFor (p: p.${stdenv}))
|
||||
];
|
||||
};
|
||||
crossSystem = if crossSystem == null then null else {
|
||||
config = crossSystem;
|
||||
} // lib.optionalAttrs (crossSystem == "x86_64-unknown-freebsd13") {
|
||||
useLLVM = true;
|
||||
};
|
||||
overlays = [
|
||||
(overlayFor (p: p.${stdenv}))
|
||||
];
|
||||
};
|
||||
stdenvs = forAllStdenvs (make-pkgs null);
|
||||
native = stdenvs.stdenvPackages;
|
||||
in {
|
||||
in
|
||||
{
|
||||
inherit stdenvs native;
|
||||
static = native.pkgsStatic;
|
||||
cross = forAllCrossSystems (crossSystem: make-pkgs crossSystem "stdenv");
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
binaryTarball = nix: pkgs: pkgs.callPackage ./scripts/binary-tarball.nix {
|
||||
inherit nix;
|
||||
};
|
||||
binaryTarball =
|
||||
nix: pkgs:
|
||||
pkgs.callPackage ./scripts/binary-tarball.nix {
|
||||
inherit nix;
|
||||
};
|
||||
|
||||
overlayFor = getStdenv: final: prev:
|
||||
overlayFor =
|
||||
getStdenv: final: prev:
|
||||
let
|
||||
stdenv = getStdenv final;
|
||||
in
|
||||
@@ -134,10 +169,12 @@
|
||||
|
||||
# The dependencies are in their own scope, so that they don't have to be
|
||||
# in Nixpkgs top level `pkgs` or `nixComponents`.
|
||||
nixDependencies = lib.makeScope final.newScope (import ./packaging/dependencies.nix {
|
||||
inherit inputs stdenv versionSuffix;
|
||||
pkgs = final;
|
||||
});
|
||||
nixDependencies = lib.makeScope final.newScope (
|
||||
import ./packaging/dependencies.nix {
|
||||
inherit inputs stdenv versionSuffix;
|
||||
pkgs = final;
|
||||
}
|
||||
);
|
||||
|
||||
nix = final.nixComponents.nix;
|
||||
|
||||
@@ -149,13 +186,20 @@
|
||||
# See https://github.com/NixOS/nixpkgs/pull/214409
|
||||
# Remove when fixed in this flake's nixpkgs
|
||||
pre-commit =
|
||||
if prev.stdenv.hostPlatform.system == "i686-linux"
|
||||
then (prev.pre-commit.override (o: { dotnet-sdk = ""; })).overridePythonAttrs (o: { doCheck = false; })
|
||||
else prev.pre-commit;
|
||||
if prev.stdenv.hostPlatform.system == "i686-linux" then
|
||||
(prev.pre-commit.override (o: {
|
||||
dotnet-sdk = "";
|
||||
})).overridePythonAttrs
|
||||
(o: {
|
||||
doCheck = false;
|
||||
})
|
||||
else
|
||||
prev.pre-commit;
|
||||
|
||||
};
|
||||
|
||||
in {
|
||||
in
|
||||
{
|
||||
# A Nixpkgs overlay that overrides the 'nix' and
|
||||
# 'nix-perl-bindings' packages.
|
||||
overlays.default = overlayFor (p: p.stdenv);
|
||||
@@ -173,200 +217,261 @@
|
||||
;
|
||||
};
|
||||
|
||||
checks = forAllSystems (system: {
|
||||
binaryTarball = self.hydraJobs.binaryTarball.${system};
|
||||
installTests = self.hydraJobs.installTests.${system};
|
||||
nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system};
|
||||
rl-next =
|
||||
let pkgs = nixpkgsFor.${system}.native;
|
||||
in pkgs.buildPackages.runCommand "test-rl-next-release-notes" { } ''
|
||||
LANG=C.UTF-8 ${pkgs.changelog-d}/bin/changelog-d ${./doc/manual/rl-next} >$out
|
||||
'';
|
||||
repl-completion = nixpkgsFor.${system}.native.callPackage ./tests/repl-completion.nix { };
|
||||
} // (lib.optionalAttrs (builtins.elem system linux64BitSystems)) {
|
||||
dockerImage = self.hydraJobs.dockerImage.${system};
|
||||
} // (lib.optionalAttrs (!(builtins.elem system linux32BitSystems))) {
|
||||
# Some perl dependencies are broken on i686-linux.
|
||||
# Since the support is only best-effort there, disable the perl
|
||||
# bindings
|
||||
checks = forAllSystems (
|
||||
system:
|
||||
{
|
||||
installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system};
|
||||
installTests = self.hydraJobs.installTests.${system};
|
||||
nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system};
|
||||
rl-next =
|
||||
let
|
||||
pkgs = nixpkgsFor.${system}.native;
|
||||
in
|
||||
pkgs.buildPackages.runCommand "test-rl-next-release-notes" { } ''
|
||||
LANG=C.UTF-8 ${pkgs.changelog-d}/bin/changelog-d ${./doc/manual/rl-next} >$out
|
||||
'';
|
||||
repl-completion = nixpkgsFor.${system}.native.callPackage ./tests/repl-completion.nix { };
|
||||
}
|
||||
// (lib.optionalAttrs (builtins.elem system linux64BitSystems)) {
|
||||
dockerImage = self.hydraJobs.dockerImage.${system};
|
||||
}
|
||||
// (lib.optionalAttrs (!(builtins.elem system linux32BitSystems))) {
|
||||
# Some perl dependencies are broken on i686-linux.
|
||||
# Since the support is only best-effort there, disable the perl
|
||||
# bindings
|
||||
|
||||
# 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
|
||||
// flatMapAttrs ({
|
||||
"" = nixpkgsFor.${system}.native;
|
||||
} // lib.optionalAttrs (! nixpkgsFor.${system}.native.stdenv.hostPlatform.isDarwin) {
|
||||
# TODO: enable static builds for darwin, blocked on:
|
||||
# https://github.com/NixOS/nixpkgs/issues/320448
|
||||
"static-" = nixpkgsFor.${system}.static;
|
||||
})
|
||||
(nixpkgsPrefix: nixpkgs:
|
||||
flatMapAttrs nixpkgs.nixComponents
|
||||
(pkgName: pkg:
|
||||
flatMapAttrs pkg.tests or {}
|
||||
(testName: test: {
|
||||
"${nixpkgsPrefix}${pkgName}-${testName}" = test;
|
||||
})
|
||||
# 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
|
||||
//
|
||||
flatMapAttrs
|
||||
(
|
||||
{
|
||||
"" = nixpkgsFor.${system}.native;
|
||||
}
|
||||
// lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.hostPlatform.isDarwin) {
|
||||
# TODO: enable static builds for darwin, blocked on:
|
||||
# https://github.com/NixOS/nixpkgs/issues/320448
|
||||
"static-" = nixpkgsFor.${system}.static;
|
||||
}
|
||||
)
|
||||
)
|
||||
// devFlake.checks.${system} or {}
|
||||
(
|
||||
nixpkgsPrefix: nixpkgs:
|
||||
flatMapAttrs nixpkgs.nixComponents (
|
||||
pkgName: pkg:
|
||||
flatMapAttrs pkg.tests or { } (
|
||||
testName: test: {
|
||||
"${nixpkgsPrefix}${pkgName}-${testName}" = test;
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
// devFlake.checks.${system} or { }
|
||||
);
|
||||
|
||||
packages = forAllSystems (system:
|
||||
{ # Here we put attributes that map 1:1 into packages.<system>, ie
|
||||
packages = forAllSystems (
|
||||
system:
|
||||
{
|
||||
# Here we put attributes that map 1:1 into packages.<system>, ie
|
||||
# for which we don't apply the full build matrix such as cross or static.
|
||||
inherit (nixpkgsFor.${system}.native)
|
||||
changelog-d;
|
||||
changelog-d
|
||||
;
|
||||
default = self.packages.${system}.nix;
|
||||
binaryTarball = self.hydraJobs.binaryTarball.${system};
|
||||
installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system};
|
||||
nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-internal-api-docs;
|
||||
nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs;
|
||||
}
|
||||
# We need to flatten recursive attribute sets of derivations to pass `flake check`.
|
||||
// flatMapAttrs
|
||||
{ # Components we'll iterate over in the upcoming lambda
|
||||
"nix" = { };
|
||||
# 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 these.
|
||||
#"nix-util" = { };
|
||||
#"nix-store" = { };
|
||||
#"nix-fetchers" = { };
|
||||
}
|
||||
(pkgName: {}: {
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}" = nixpkgsFor.${system}.native.nixComponents.${pkgName};
|
||||
"${pkgName}-static" = nixpkgsFor.${system}.static.nixComponents.${pkgName};
|
||||
}
|
||||
// flatMapAttrs (lib.genAttrs crossSystems (_: { })) (crossSystem: {}: {
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}-${crossSystem}" = nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName};
|
||||
})
|
||||
// flatMapAttrs (lib.genAttrs stdenvs (_: { })) (stdenvName: {}: {
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}-${stdenvName}" = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".nixComponents.${pkgName};
|
||||
})
|
||||
)
|
||||
// lib.optionalAttrs (builtins.elem system linux64BitSystems) {
|
||||
dockerImage =
|
||||
let
|
||||
pkgs = nixpkgsFor.${system}.native;
|
||||
image = import ./docker.nix { inherit pkgs; tag = version; };
|
||||
in
|
||||
pkgs.runCommand
|
||||
"docker-image-tarball-${version}"
|
||||
{ meta.description = "Docker image with Nix for ${system}"; }
|
||||
''
|
||||
mkdir -p $out/nix-support
|
||||
image=$out/image.tar.gz
|
||||
ln -s ${image} $image
|
||||
echo "file binary-dist $image" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
});
|
||||
|
||||
devShells = let
|
||||
makeShell = pkgs: stdenv: (pkgs.nix.override { inherit stdenv; forDevShell = true; }).overrideAttrs (attrs:
|
||||
let
|
||||
modular = devFlake.getSystem stdenv.buildPlatform.system;
|
||||
transformFlag = prefix: flag:
|
||||
assert builtins.isString flag;
|
||||
let
|
||||
rest = builtins.substring 2 (builtins.stringLength flag) flag;
|
||||
in
|
||||
"-D${prefix}:${rest}";
|
||||
havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix;
|
||||
ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags;
|
||||
in {
|
||||
pname = "shell-for-" + attrs.pname;
|
||||
|
||||
# Remove the version suffix to avoid unnecessary attempts to substitute in nix develop
|
||||
version = lib.fileContents ./.version;
|
||||
name = attrs.pname;
|
||||
|
||||
installFlags = "sysconfdir=$(out)/etc";
|
||||
shellHook = ''
|
||||
PATH=$prefix/bin:$PATH
|
||||
unset PYTHONPATH
|
||||
export MANPATH=$out/share/man:$MANPATH
|
||||
|
||||
# Make bash completion work.
|
||||
XDG_DATA_DIRS+=:$out/share
|
||||
'';
|
||||
|
||||
# We use this shell with the local checkout, not unpackPhase.
|
||||
src = null;
|
||||
|
||||
env = {
|
||||
# Needed for Meson to find Boost.
|
||||
# https://github.com/NixOS/nixpkgs/issues/86131.
|
||||
BOOST_INCLUDEDIR = "${lib.getDev pkgs.nixDependencies.boost}/include";
|
||||
BOOST_LIBRARYDIR = "${lib.getLib pkgs.nixDependencies.boost}/lib";
|
||||
# For `make format`, to work without installing pre-commit
|
||||
_NIX_PRE_COMMIT_HOOKS_CONFIG =
|
||||
"${(pkgs.formats.yaml { }).generate "pre-commit-config.yaml" modular.pre-commit.settings.rawConfig}";
|
||||
};
|
||||
|
||||
mesonFlags =
|
||||
map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents.nix-util.mesonFlags)
|
||||
++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents.nix-store.mesonFlags)
|
||||
++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents.nix-fetchers.mesonFlags)
|
||||
++ lib.optionals havePerl (map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents.nix-perl-bindings.mesonFlags))
|
||||
++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents.nix-expr.mesonFlags)
|
||||
++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents.nix-cmd.mesonFlags)
|
||||
;
|
||||
|
||||
nativeBuildInputs = attrs.nativeBuildInputs or []
|
||||
++ pkgs.nixComponents.nix-util.nativeBuildInputs
|
||||
++ pkgs.nixComponents.nix-store.nativeBuildInputs
|
||||
++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs
|
||||
++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs
|
||||
++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs
|
||||
++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs
|
||||
++ lib.optional
|
||||
(!stdenv.buildPlatform.canExecute stdenv.hostPlatform
|
||||
# Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479
|
||||
&& !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin)
|
||||
&& stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages
|
||||
&& lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages))
|
||||
pkgs.buildPackages.mesonEmulatorHook
|
||||
++ [
|
||||
pkgs.buildPackages.cmake
|
||||
pkgs.buildPackages.shellcheck
|
||||
pkgs.buildPackages.changelog-d
|
||||
modular.pre-commit.settings.package
|
||||
(pkgs.writeScriptBin "pre-commit-hooks-install"
|
||||
modular.pre-commit.settings.installationScript)
|
||||
]
|
||||
# TODO: Remove the darwin check once
|
||||
# https://github.com/NixOS/nixpkgs/pull/291814 is available
|
||||
++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear
|
||||
++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) pkgs.buildPackages.clang-tools;
|
||||
|
||||
buildInputs = attrs.buildInputs or []
|
||||
++ [
|
||||
pkgs.gtest
|
||||
pkgs.rapidcheck
|
||||
]
|
||||
++ lib.optional havePerl pkgs.perl
|
||||
;
|
||||
});
|
||||
in
|
||||
forAllSystems (system:
|
||||
let
|
||||
makeShells = prefix: pkgs:
|
||||
lib.mapAttrs'
|
||||
(k: v: lib.nameValuePair "${prefix}-${k}" v)
|
||||
(forAllStdenvs (stdenvName: makeShell pkgs pkgs.${stdenvName}));
|
||||
in
|
||||
(makeShells "native" nixpkgsFor.${system}.native) //
|
||||
(lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin)
|
||||
(makeShells "static" nixpkgsFor.${system}.static) //
|
||||
(forAllCrossSystems (crossSystem: let pkgs = nixpkgsFor.${system}.cross.${crossSystem}; in makeShell pkgs pkgs.stdenv))) //
|
||||
//
|
||||
flatMapAttrs
|
||||
{
|
||||
default = self.devShells.${system}.native-stdenvPackages;
|
||||
# Components we'll iterate over in the upcoming lambda
|
||||
"nix" = { };
|
||||
# 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 these.
|
||||
#"nix-util" = { };
|
||||
#"nix-store" = { };
|
||||
#"nix-fetchers" = { };
|
||||
}
|
||||
(
|
||||
pkgName:
|
||||
{ }:
|
||||
{
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}" = nixpkgsFor.${system}.native.nixComponents.${pkgName};
|
||||
"${pkgName}-static" = nixpkgsFor.${system}.static.nixComponents.${pkgName};
|
||||
}
|
||||
// flatMapAttrs (lib.genAttrs crossSystems (_: { })) (
|
||||
crossSystem:
|
||||
{ }:
|
||||
{
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}-${crossSystem}" = nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName};
|
||||
}
|
||||
)
|
||||
// flatMapAttrs (lib.genAttrs stdenvs (_: { })) (
|
||||
stdenvName:
|
||||
{ }:
|
||||
{
|
||||
# These attributes go right into `packages.<system>`.
|
||||
"${pkgName}-${stdenvName}" =
|
||||
nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".nixComponents.${pkgName};
|
||||
}
|
||||
)
|
||||
)
|
||||
// lib.optionalAttrs (builtins.elem system linux64BitSystems) {
|
||||
dockerImage =
|
||||
let
|
||||
pkgs = nixpkgsFor.${system}.native;
|
||||
image = import ./docker.nix {
|
||||
inherit pkgs;
|
||||
tag = version;
|
||||
};
|
||||
in
|
||||
pkgs.runCommand "docker-image-tarball-${version}"
|
||||
{ meta.description = "Docker image with Nix for ${system}"; }
|
||||
''
|
||||
mkdir -p $out/nix-support
|
||||
image=$out/image.tar.gz
|
||||
ln -s ${image} $image
|
||||
echo "file binary-dist $image" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
}
|
||||
);
|
||||
|
||||
devShells =
|
||||
let
|
||||
makeShell =
|
||||
pkgs: stdenv:
|
||||
(pkgs.nix.override {
|
||||
inherit stdenv;
|
||||
forDevShell = true;
|
||||
}).overrideAttrs
|
||||
(
|
||||
attrs:
|
||||
let
|
||||
modular = devFlake.getSystem stdenv.buildPlatform.system;
|
||||
transformFlag =
|
||||
prefix: flag:
|
||||
assert builtins.isString flag;
|
||||
let
|
||||
rest = builtins.substring 2 (builtins.stringLength flag) flag;
|
||||
in
|
||||
"-D${prefix}:${rest}";
|
||||
havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix;
|
||||
ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags;
|
||||
in
|
||||
{
|
||||
pname = "shell-for-" + attrs.pname;
|
||||
|
||||
# Remove the version suffix to avoid unnecessary attempts to substitute in nix develop
|
||||
version = lib.fileContents ./.version;
|
||||
name = attrs.pname;
|
||||
|
||||
installFlags = "sysconfdir=$(out)/etc";
|
||||
shellHook = ''
|
||||
PATH=$prefix/bin:$PATH
|
||||
unset PYTHONPATH
|
||||
export MANPATH=$out/share/man:$MANPATH
|
||||
|
||||
# Make bash completion work.
|
||||
XDG_DATA_DIRS+=:$out/share
|
||||
'';
|
||||
|
||||
# We use this shell with the local checkout, not unpackPhase.
|
||||
src = null;
|
||||
|
||||
env = {
|
||||
# Needed for Meson to find Boost.
|
||||
# https://github.com/NixOS/nixpkgs/issues/86131.
|
||||
BOOST_INCLUDEDIR = "${lib.getDev pkgs.nixDependencies.boost}/include";
|
||||
BOOST_LIBRARYDIR = "${lib.getLib pkgs.nixDependencies.boost}/lib";
|
||||
# For `make format`, to work without installing pre-commit
|
||||
_NIX_PRE_COMMIT_HOOKS_CONFIG = "${(pkgs.formats.yaml { }).generate "pre-commit-config.yaml"
|
||||
modular.pre-commit.settings.rawConfig
|
||||
}";
|
||||
};
|
||||
|
||||
mesonFlags =
|
||||
map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents.nix-util.mesonFlags)
|
||||
++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents.nix-store.mesonFlags)
|
||||
++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents.nix-fetchers.mesonFlags)
|
||||
++ lib.optionals havePerl (
|
||||
map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents.nix-perl-bindings.mesonFlags)
|
||||
)
|
||||
++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents.nix-expr.mesonFlags)
|
||||
++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents.nix-cmd.mesonFlags);
|
||||
|
||||
nativeBuildInputs =
|
||||
attrs.nativeBuildInputs or [ ]
|
||||
++ pkgs.nixComponents.nix-util.nativeBuildInputs
|
||||
++ pkgs.nixComponents.nix-store.nativeBuildInputs
|
||||
++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs
|
||||
++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs
|
||||
++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs
|
||||
++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs
|
||||
++ lib.optional (
|
||||
!stdenv.buildPlatform.canExecute stdenv.hostPlatform
|
||||
# Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479
|
||||
&& !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin)
|
||||
&& stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages
|
||||
&& lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages)
|
||||
) pkgs.buildPackages.mesonEmulatorHook
|
||||
++ [
|
||||
pkgs.buildPackages.cmake
|
||||
pkgs.buildPackages.shellcheck
|
||||
pkgs.buildPackages.changelog-d
|
||||
modular.pre-commit.settings.package
|
||||
(pkgs.writeScriptBin "pre-commit-hooks-install" modular.pre-commit.settings.installationScript)
|
||||
]
|
||||
# TODO: Remove the darwin check once
|
||||
# https://github.com/NixOS/nixpkgs/pull/291814 is available
|
||||
++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear
|
||||
++ lib.optional (
|
||||
stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform
|
||||
) pkgs.buildPackages.clang-tools;
|
||||
|
||||
buildInputs =
|
||||
attrs.buildInputs or [ ]
|
||||
++ [
|
||||
pkgs.gtest
|
||||
pkgs.rapidcheck
|
||||
]
|
||||
++ lib.optional havePerl pkgs.perl;
|
||||
}
|
||||
);
|
||||
in
|
||||
forAllSystems (
|
||||
system:
|
||||
let
|
||||
makeShells =
|
||||
prefix: pkgs:
|
||||
lib.mapAttrs' (k: v: lib.nameValuePair "${prefix}-${k}" v) (
|
||||
forAllStdenvs (stdenvName: makeShell pkgs pkgs.${stdenvName})
|
||||
);
|
||||
in
|
||||
(makeShells "native" nixpkgsFor.${system}.native)
|
||||
// (
|
||||
lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin) (
|
||||
makeShells "static" nixpkgsFor.${system}.static
|
||||
)
|
||||
// (forAllCrossSystems (
|
||||
crossSystem:
|
||||
let
|
||||
pkgs = nixpkgsFor.${system}.cross.${crossSystem};
|
||||
in
|
||||
makeShell pkgs pkgs.stdenv
|
||||
))
|
||||
)
|
||||
// {
|
||||
default = self.devShells.${system}.native-stdenvPackages;
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,8 @@
|
||||
# vim: set filetype=bash:
|
||||
#!nix shell .#changelog-d --command bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# --- CONFIGURATION ---
|
||||
|
||||
# This does double duty for
|
||||
|
||||
@@ -42,7 +42,7 @@ my $flakeUrl = $evalInfo->{flake};
|
||||
my $flakeInfo = decode_json(`nix flake metadata --json "$flakeUrl"` or die) if $flakeUrl;
|
||||
my $nixRev = ($flakeInfo ? $flakeInfo->{revision} : $evalInfo->{jobsetevalinputs}->{nix}->{revision}) or die;
|
||||
|
||||
my $buildInfo = decode_json(fetch("$evalUrl/job/build.x86_64-linux", 'application/json'));
|
||||
my $buildInfo = decode_json(fetch("$evalUrl/job/build.nix.x86_64-linux", 'application/json'));
|
||||
#print Dumper($buildInfo);
|
||||
|
||||
my $releaseName = $buildInfo->{nixname};
|
||||
@@ -91,7 +91,7 @@ sub getStorePath {
|
||||
sub copyManual {
|
||||
my $manual;
|
||||
eval {
|
||||
$manual = getStorePath("build.x86_64-linux", "doc");
|
||||
$manual = getStorePath("build.nix.x86_64-linux", "doc");
|
||||
};
|
||||
if ($@) {
|
||||
warn "$@";
|
||||
@@ -112,7 +112,7 @@ sub copyManual {
|
||||
system("xz -d < '$manualNar' | nix-store --restore $tmpDir/manual.tmp") == 0
|
||||
or die "unable to unpack $manualNar\n";
|
||||
rename("$tmpDir/manual.tmp/share/doc/nix/manual", "$tmpDir/manual") or die;
|
||||
system("rm -rf '$tmpDir/manual.tmp'") == 0 or die;
|
||||
File::Path::remove_tree("$tmpDir/manual.tmp", {safe => 1});
|
||||
}
|
||||
|
||||
system("aws s3 sync '$tmpDir/manual' s3://$releasesBucketName/$releaseDir/manual") == 0
|
||||
@@ -240,12 +240,12 @@ if ($haveDocker) {
|
||||
# Upload nix-fallback-paths.nix.
|
||||
write_file("$tmpDir/fallback-paths.nix",
|
||||
"{\n" .
|
||||
" x86_64-linux = \"" . getStorePath("build.x86_64-linux") . "\";\n" .
|
||||
" i686-linux = \"" . getStorePath("build.i686-linux") . "\";\n" .
|
||||
" aarch64-linux = \"" . getStorePath("build.aarch64-linux") . "\";\n" .
|
||||
" riscv64-linux = \"" . getStorePath("buildCross.riscv64-unknown-linux-gnu.x86_64-linux") . "\";\n" .
|
||||
" x86_64-darwin = \"" . getStorePath("build.x86_64-darwin") . "\";\n" .
|
||||
" aarch64-darwin = \"" . getStorePath("build.aarch64-darwin") . "\";\n" .
|
||||
" x86_64-linux = \"" . getStorePath("build.nix.x86_64-linux") . "\";\n" .
|
||||
" i686-linux = \"" . getStorePath("build.nix.i686-linux") . "\";\n" .
|
||||
" aarch64-linux = \"" . getStorePath("build.nix.aarch64-linux") . "\";\n" .
|
||||
" riscv64-linux = \"" . getStorePath("buildCross.nix.riscv64-unknown-linux-gnu.x86_64-linux") . "\";\n" .
|
||||
" x86_64-darwin = \"" . getStorePath("build.nix.x86_64-darwin") . "\";\n" .
|
||||
" aarch64-darwin = \"" . getStorePath("build.nix.aarch64-darwin") . "\";\n" .
|
||||
"}\n");
|
||||
|
||||
# Upload release files to S3.
|
||||
@@ -281,3 +281,6 @@ system("git remote update origin") == 0 or die;
|
||||
system("git tag --force --sign $version $nixRev -m 'Tagging release $version'") == 0 or die;
|
||||
system("git push --tags") == 0 or die;
|
||||
system("git push --force-with-lease origin $nixRev:refs/heads/latest-release") == 0 or die if $isLatest;
|
||||
|
||||
File::Path::remove_tree($narCache, {safe => 1});
|
||||
File::Path::remove_tree($tmpDir, {safe => 1});
|
||||
|
||||
@@ -12,9 +12,16 @@ function _complete_nix {
|
||||
elif [[ $completion == attrs ]]; then
|
||||
compopt -o nospace
|
||||
fi
|
||||
else
|
||||
COMPREPLY+=("$completion")
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "${cur}" =~ "=" ]]; then
|
||||
# drop everything up to the first =. if a = is included, bash assumes this to be
|
||||
# an arg=value argument and the completion gets mangled (see #11208)
|
||||
completion="${completion#*=}"
|
||||
fi
|
||||
|
||||
COMPREPLY+=("${completion}")
|
||||
done < <(NIX_GET_COMPLETIONS=$cword "${words[@]}" 2>/dev/null)
|
||||
__ltrim_colon_completions "$cur"
|
||||
}
|
||||
|
||||
@@ -86,7 +86,9 @@ define build-library
|
||||
else
|
||||
ifndef HOST_DARWIN
|
||||
ifndef HOST_WINDOWS
|
||||
$(1)_LDFLAGS += -Wl,-z,defs
|
||||
ifndef HOST_OPENBSD
|
||||
$(1)_LDFLAGS += -Wl,-z,defs
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -21,6 +21,10 @@ ifdef HOST_OS
|
||||
HOST_NETBSD = 1
|
||||
HOST_UNIX = 1
|
||||
endif
|
||||
ifeq ($(patsubst openbsd%,,$(HOST_KERNEL)),)
|
||||
HOST_OPENBSD = 1
|
||||
HOST_UNIX = 1
|
||||
endif
|
||||
ifeq ($(HOST_KERNEL), linux)
|
||||
HOST_LINUX = 1
|
||||
HOST_UNIX = 1
|
||||
|
||||
668
package.nix
668
package.nix
@@ -1,112 +1,116 @@
|
||||
{ lib
|
||||
, stdenv
|
||||
, releaseTools
|
||||
, autoconf-archive
|
||||
, autoreconfHook
|
||||
, aws-sdk-cpp
|
||||
, boehmgc
|
||||
, nlohmann_json
|
||||
, bison
|
||||
, boost
|
||||
, brotli
|
||||
, bzip2
|
||||
, curl
|
||||
, editline
|
||||
, readline
|
||||
, flex
|
||||
, git
|
||||
, gtest
|
||||
, jq
|
||||
, libarchive
|
||||
, libcpuid
|
||||
, libgit2
|
||||
, libseccomp
|
||||
, libsodium
|
||||
, man
|
||||
, lowdown
|
||||
, mdbook
|
||||
, mdbook-linkcheck
|
||||
, mercurial
|
||||
, openssh
|
||||
, openssl
|
||||
, pkg-config
|
||||
, rapidcheck
|
||||
, sqlite
|
||||
, toml11
|
||||
, unixtools
|
||||
, xz
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
releaseTools,
|
||||
autoconf-archive,
|
||||
autoreconfHook,
|
||||
aws-sdk-cpp,
|
||||
boehmgc,
|
||||
nlohmann_json,
|
||||
bison,
|
||||
boost,
|
||||
brotli,
|
||||
bzip2,
|
||||
curl,
|
||||
editline,
|
||||
readline,
|
||||
flex,
|
||||
git,
|
||||
gtest,
|
||||
jq,
|
||||
libarchive,
|
||||
libcpuid,
|
||||
libgit2,
|
||||
libseccomp,
|
||||
libsodium,
|
||||
man,
|
||||
darwin,
|
||||
lowdown,
|
||||
mdbook,
|
||||
mdbook-linkcheck,
|
||||
mercurial,
|
||||
openssh,
|
||||
openssl,
|
||||
pkg-config,
|
||||
rapidcheck,
|
||||
sqlite,
|
||||
toml11,
|
||||
unixtools,
|
||||
xz,
|
||||
|
||||
, busybox-sandbox-shell ? null
|
||||
busybox-sandbox-shell ? null,
|
||||
|
||||
# Configuration Options
|
||||
#:
|
||||
# This probably seems like too many degrees of freedom, but it
|
||||
# faithfully reflects how the underlying configure + make build system
|
||||
# work. The top-level flake.nix will choose useful combinations of these
|
||||
# options to CI.
|
||||
# Configuration Options
|
||||
#:
|
||||
# This probably seems like too many degrees of freedom, but it
|
||||
# faithfully reflects how the underlying configure + make build system
|
||||
# work. The top-level flake.nix will choose useful combinations of these
|
||||
# options to CI.
|
||||
|
||||
, pname ? "nix"
|
||||
pname ? "nix",
|
||||
|
||||
, versionSuffix ? ""
|
||||
versionSuffix ? "",
|
||||
|
||||
# Whether to build Nix. Useful to skip for tasks like testing existing pre-built versions of Nix
|
||||
, doBuild ? true
|
||||
# Whether to build Nix. Useful to skip for tasks like testing existing pre-built versions of Nix
|
||||
doBuild ? true,
|
||||
|
||||
# Run the unit tests as part of the build. See `installUnitTests` for an
|
||||
# alternative to this.
|
||||
, doCheck ? __forDefaults.canRunInstalled
|
||||
# Run the unit tests as part of the build. See `installUnitTests` for an
|
||||
# alternative to this.
|
||||
doCheck ? __forDefaults.canRunInstalled,
|
||||
|
||||
# Run the functional tests as part of the build.
|
||||
, doInstallCheck ? test-client != null || __forDefaults.canRunInstalled
|
||||
# Run the functional tests as part of the build.
|
||||
doInstallCheck ? test-client != null || __forDefaults.canRunInstalled,
|
||||
|
||||
# Check test coverage of Nix. Probably want to use with with at least
|
||||
# one of `doCHeck` or `doInstallCheck` enabled.
|
||||
, withCoverageChecks ? false
|
||||
# Check test coverage of Nix. Probably want to use with at least
|
||||
# one of `doCHeck` or `doInstallCheck` enabled.
|
||||
withCoverageChecks ? false,
|
||||
|
||||
# Whether to build the regular manual
|
||||
, enableManual ? __forDefaults.canRunInstalled
|
||||
# Whether to build the regular manual
|
||||
enableManual ? __forDefaults.canRunInstalled,
|
||||
|
||||
# Whether to use garbage collection for the Nix language evaluator.
|
||||
#
|
||||
# If it is disabled, we just leak memory, but this is not as bad as it
|
||||
# sounds so long as evaluation just takes places within short-lived
|
||||
# processes. (When the process exits, the memory is reclaimed; it is
|
||||
# only leaked *within* the process.)
|
||||
#
|
||||
# Temporarily disabled on Windows because the `GC_throw_bad_alloc`
|
||||
# symbol is missing during linking.
|
||||
, enableGC ? !stdenv.hostPlatform.isWindows
|
||||
# Whether to use garbage collection for the Nix language evaluator.
|
||||
#
|
||||
# If it is disabled, we just leak memory, but this is not as bad as it
|
||||
# sounds so long as evaluation just takes places within short-lived
|
||||
# processes. (When the process exits, the memory is reclaimed; it is
|
||||
# only leaked *within* the process.)
|
||||
#
|
||||
# Temporarily disabled on Windows because the `GC_throw_bad_alloc`
|
||||
# symbol is missing during linking.
|
||||
#
|
||||
# Disabled on OpenBSD because of missing `_data_start` symbol while linking
|
||||
enableGC ? !stdenv.hostPlatform.isWindows && !stdenv.hostPlatform.isOpenBSD,
|
||||
|
||||
# Whether to enable Markdown rendering in the Nix binary.
|
||||
, enableMarkdown ? !stdenv.hostPlatform.isWindows
|
||||
# Whether to enable Markdown rendering in the Nix binary.
|
||||
enableMarkdown ? !stdenv.hostPlatform.isWindows,
|
||||
|
||||
# Which interactive line editor library to use for Nix's repl.
|
||||
#
|
||||
# Currently supported choices are:
|
||||
#
|
||||
# - editline (default)
|
||||
# - readline
|
||||
, readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline"
|
||||
# Which interactive line editor library to use for Nix's repl.
|
||||
#
|
||||
# Currently supported choices are:
|
||||
#
|
||||
# - editline (default)
|
||||
# - readline
|
||||
readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline",
|
||||
|
||||
# Whether to install unit tests. This is useful when cross compiling
|
||||
# since we cannot run them natively during the build, but can do so
|
||||
# later.
|
||||
, installUnitTests ? doBuild && !__forDefaults.canExecuteHost
|
||||
# Whether to install unit tests. This is useful when cross compiling
|
||||
# since we cannot run them natively during the build, but can do so
|
||||
# later.
|
||||
installUnitTests ? doBuild && !__forDefaults.canExecuteHost,
|
||||
|
||||
# For running the functional tests against a pre-built Nix. Probably
|
||||
# want to use in conjunction with `doBuild = false;`.
|
||||
, test-daemon ? null
|
||||
, test-client ? null
|
||||
# For running the functional tests against a pre-built Nix. Probably
|
||||
# want to use in conjunction with `doBuild = false;`.
|
||||
test-daemon ? null,
|
||||
test-client ? null,
|
||||
|
||||
# Avoid setting things that would interfere with a functioning devShell
|
||||
, forDevShell ? false
|
||||
# Avoid setting things that would interfere with a functioning devShell
|
||||
forDevShell ? false,
|
||||
|
||||
# Not a real argument, just the only way to approximate let-binding some
|
||||
# stuff for argument defaults.
|
||||
, __forDefaults ? {
|
||||
# Not a real argument, just the only way to approximate let-binding some
|
||||
# stuff for argument defaults.
|
||||
__forDefaults ? {
|
||||
canExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
|
||||
canRunInstalled = doBuild && __forDefaults.canExecuteHost;
|
||||
}
|
||||
},
|
||||
}:
|
||||
|
||||
let
|
||||
@@ -122,248 +126,304 @@ let
|
||||
};
|
||||
|
||||
mkDerivation =
|
||||
if withCoverageChecks
|
||||
then
|
||||
if withCoverageChecks then
|
||||
# TODO support `finalAttrs` args function in
|
||||
# `releaseTools.coverageAnalysis`.
|
||||
argsFun:
|
||||
releaseTools.coverageAnalysis (let args = argsFun args; in args)
|
||||
else stdenv.mkDerivation;
|
||||
releaseTools.coverageAnalysis (
|
||||
let
|
||||
args = argsFun args;
|
||||
in
|
||||
args
|
||||
)
|
||||
else
|
||||
stdenv.mkDerivation;
|
||||
in
|
||||
|
||||
mkDerivation (finalAttrs: let
|
||||
mkDerivation (
|
||||
finalAttrs:
|
||||
let
|
||||
|
||||
inherit (finalAttrs)
|
||||
doCheck
|
||||
doInstallCheck
|
||||
;
|
||||
inherit (finalAttrs)
|
||||
doCheck
|
||||
doInstallCheck
|
||||
;
|
||||
|
||||
doBuild = !finalAttrs.dontBuild;
|
||||
doBuild = !finalAttrs.dontBuild;
|
||||
|
||||
# Either running the unit tests during the build, or installing them
|
||||
# to be run later, requiresthe unit tests to be built.
|
||||
buildUnitTests = doCheck || installUnitTests;
|
||||
# Either running the unit tests during the build, or installing them
|
||||
# to be run later, requiresthe unit tests to be built.
|
||||
buildUnitTests = doCheck || installUnitTests;
|
||||
|
||||
in {
|
||||
inherit pname version;
|
||||
in
|
||||
{
|
||||
inherit pname version;
|
||||
|
||||
src =
|
||||
let
|
||||
baseFiles = fileset.fileFilter (f: f.name != ".gitignore") ./.;
|
||||
in
|
||||
src =
|
||||
let
|
||||
baseFiles = fileset.fileFilter (f: f.name != ".gitignore") ./.;
|
||||
in
|
||||
fileset.toSource {
|
||||
root = ./.;
|
||||
fileset = fileset.intersection baseFiles (fileset.unions ([
|
||||
# For configure
|
||||
./.version
|
||||
./configure.ac
|
||||
./m4
|
||||
# TODO: do we really need README.md? It doesn't seem used in the build.
|
||||
./README.md
|
||||
# This could be put behind a conditional
|
||||
./maintainers/local.mk
|
||||
# For make, regardless of what we are building
|
||||
./local.mk
|
||||
./Makefile
|
||||
./Makefile.config.in
|
||||
./mk
|
||||
(fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts)
|
||||
] ++ lib.optionals doBuild [
|
||||
./doc
|
||||
./misc
|
||||
./precompiled-headers.h
|
||||
(fileset.difference ./src ./src/perl)
|
||||
./COPYING
|
||||
./scripts/local.mk
|
||||
] ++ lib.optionals enableManual [
|
||||
./doc/manual
|
||||
] ++ lib.optionals buildUnitTests [
|
||||
./tests/unit
|
||||
] ++ lib.optionals doInstallCheck [
|
||||
./tests/functional
|
||||
]));
|
||||
fileset = fileset.intersection baseFiles (
|
||||
fileset.unions (
|
||||
[
|
||||
# For configure
|
||||
./.version
|
||||
./configure.ac
|
||||
./m4
|
||||
# TODO: do we really need README.md? It doesn't seem used in the build.
|
||||
./README.md
|
||||
# This could be put behind a conditional
|
||||
./maintainers/local.mk
|
||||
# For make, regardless of what we are building
|
||||
./local.mk
|
||||
./Makefile
|
||||
./Makefile.config.in
|
||||
./mk
|
||||
(fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts)
|
||||
]
|
||||
++ lib.optionals doBuild [
|
||||
./doc
|
||||
./misc
|
||||
./precompiled-headers.h
|
||||
(fileset.difference ./src ./src/perl)
|
||||
./COPYING
|
||||
./scripts/local.mk
|
||||
]
|
||||
++ lib.optionals enableManual [
|
||||
./doc/manual
|
||||
]
|
||||
++ lib.optionals buildUnitTests [
|
||||
./tests/unit
|
||||
]
|
||||
++ lib.optionals doInstallCheck [
|
||||
./tests/functional
|
||||
]
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
VERSION_SUFFIX = versionSuffix;
|
||||
VERSION_SUFFIX = versionSuffix;
|
||||
|
||||
outputs = [ "out" ]
|
||||
++ lib.optional doBuild "dev"
|
||||
# If we are doing just build or just docs, the one thing will use
|
||||
# "out". We only need additional outputs if we are doing both.
|
||||
++ lib.optional (doBuild && enableManual) "doc"
|
||||
++ lib.optional installUnitTests "check"
|
||||
++ lib.optional doCheck "testresults"
|
||||
;
|
||||
outputs =
|
||||
[ "out" ]
|
||||
++ lib.optional doBuild "dev"
|
||||
# If we are doing just build or just docs, the one thing will use
|
||||
# "out". We only need additional outputs if we are doing both.
|
||||
++ lib.optional (doBuild && enableManual) "doc"
|
||||
++ lib.optional installUnitTests "check"
|
||||
++ lib.optional doCheck "testresults";
|
||||
|
||||
nativeBuildInputs = [
|
||||
autoconf-archive
|
||||
autoreconfHook
|
||||
pkg-config
|
||||
] ++ lib.optionals doBuild [
|
||||
bison
|
||||
flex
|
||||
] ++ lib.optionals enableManual [
|
||||
(lib.getBin lowdown)
|
||||
mdbook
|
||||
mdbook-linkcheck
|
||||
] ++ lib.optionals doInstallCheck [
|
||||
git
|
||||
mercurial
|
||||
openssh
|
||||
man # for testing `nix-* --help`
|
||||
] ++ lib.optionals (doInstallCheck || enableManual) [
|
||||
jq # Also for custom mdBook preprocessor.
|
||||
] ++ lib.optional stdenv.hostPlatform.isStatic unixtools.hexdump
|
||||
;
|
||||
nativeBuildInputs =
|
||||
[
|
||||
autoconf-archive
|
||||
autoreconfHook
|
||||
pkg-config
|
||||
]
|
||||
++ lib.optionals doBuild [
|
||||
bison
|
||||
flex
|
||||
]
|
||||
++ lib.optionals enableManual [
|
||||
(lib.getBin lowdown)
|
||||
mdbook
|
||||
mdbook-linkcheck
|
||||
]
|
||||
++ lib.optionals doInstallCheck [
|
||||
git
|
||||
mercurial
|
||||
openssh
|
||||
]
|
||||
++ lib.optionals (doInstallCheck || enableManual) [
|
||||
jq # Also for custom mdBook preprocessor.
|
||||
]
|
||||
++ lib.optionals enableManual [
|
||||
man
|
||||
]
|
||||
++ lib.optional stdenv.hostPlatform.isStatic unixtools.hexdump;
|
||||
|
||||
buildInputs = lib.optionals doBuild (
|
||||
[
|
||||
brotli
|
||||
bzip2
|
||||
curl
|
||||
libarchive
|
||||
libgit2
|
||||
libsodium
|
||||
openssl
|
||||
sqlite
|
||||
toml11
|
||||
xz
|
||||
({ inherit readline editline; }.${readlineFlavor})
|
||||
] ++ lib.optionals enableMarkdown [
|
||||
lowdown
|
||||
] ++ lib.optionals buildUnitTests [
|
||||
gtest
|
||||
rapidcheck
|
||||
] ++ lib.optional stdenv.isLinux libseccomp
|
||||
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid
|
||||
# There have been issues building these dependencies
|
||||
++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin))
|
||||
aws-sdk-cpp
|
||||
);
|
||||
buildInputs = lib.optionals doBuild (
|
||||
[
|
||||
brotli
|
||||
bzip2
|
||||
curl
|
||||
libarchive
|
||||
libgit2
|
||||
libsodium
|
||||
openssl
|
||||
sqlite
|
||||
toml11
|
||||
xz
|
||||
({ inherit readline editline; }.${readlineFlavor})
|
||||
]
|
||||
++ lib.optionals enableMarkdown [
|
||||
lowdown
|
||||
]
|
||||
++ lib.optionals buildUnitTests [
|
||||
gtest
|
||||
rapidcheck
|
||||
]
|
||||
++ lib.optional stdenv.isLinux libseccomp
|
||||
++ lib.optional stdenv.hostPlatform.isDarwin darwin.apple_sdk.libs.sandbox
|
||||
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid
|
||||
# There have been issues building these dependencies
|
||||
++ lib.optional (
|
||||
stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin)
|
||||
) aws-sdk-cpp
|
||||
);
|
||||
|
||||
propagatedBuildInputs = lib.optionals doBuild ([
|
||||
boost
|
||||
nlohmann_json
|
||||
] ++ lib.optional enableGC boehmgc
|
||||
);
|
||||
propagatedBuildInputs = lib.optionals doBuild (
|
||||
[
|
||||
boost
|
||||
nlohmann_json
|
||||
]
|
||||
++ lib.optional enableGC boehmgc
|
||||
);
|
||||
|
||||
dontBuild = !attrs.doBuild;
|
||||
doCheck = attrs.doCheck;
|
||||
dontBuild = !attrs.doBuild;
|
||||
doCheck = attrs.doCheck;
|
||||
|
||||
configureFlags = [
|
||||
(lib.enableFeature doBuild "build")
|
||||
(lib.enableFeature buildUnitTests "unit-tests")
|
||||
(lib.enableFeature doInstallCheck "functional-tests")
|
||||
(lib.enableFeature enableManual "doc-gen")
|
||||
(lib.enableFeature enableGC "gc")
|
||||
(lib.enableFeature enableMarkdown "markdown")
|
||||
(lib.enableFeature installUnitTests "install-unit-tests")
|
||||
(lib.withFeatureAs true "readline-flavor" readlineFlavor)
|
||||
] ++ lib.optionals (!forDevShell) [
|
||||
"--sysconfdir=/etc"
|
||||
] ++ lib.optionals installUnitTests [
|
||||
"--with-check-bin-dir=${builtins.placeholder "check"}/bin"
|
||||
"--with-check-lib-dir=${builtins.placeholder "check"}/lib"
|
||||
] ++ lib.optionals (doBuild) [
|
||||
"--with-boost=${boost}/lib"
|
||||
] ++ lib.optionals (doBuild && stdenv.isLinux) [
|
||||
"--with-sandbox-shell=${busybox-sandbox-shell}/bin/busybox"
|
||||
] ++ lib.optional (doBuild && stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
|
||||
"LDFLAGS=-fuse-ld=gold"
|
||||
++ lib.optional (doBuild && stdenv.hostPlatform.isStatic) "--enable-embedded-sandbox-shell"
|
||||
;
|
||||
configureFlags =
|
||||
[
|
||||
(lib.enableFeature doBuild "build")
|
||||
(lib.enableFeature buildUnitTests "unit-tests")
|
||||
(lib.enableFeature doInstallCheck "functional-tests")
|
||||
(lib.enableFeature enableManual "doc-gen")
|
||||
(lib.enableFeature enableGC "gc")
|
||||
(lib.enableFeature enableMarkdown "markdown")
|
||||
(lib.enableFeature installUnitTests "install-unit-tests")
|
||||
(lib.withFeatureAs true "readline-flavor" readlineFlavor)
|
||||
]
|
||||
++ lib.optionals (!forDevShell) [
|
||||
"--sysconfdir=/etc"
|
||||
]
|
||||
++ lib.optionals installUnitTests [
|
||||
"--with-check-bin-dir=${builtins.placeholder "check"}/bin"
|
||||
"--with-check-lib-dir=${builtins.placeholder "check"}/lib"
|
||||
]
|
||||
++ lib.optionals (doBuild) [
|
||||
"--with-boost=${boost}/lib"
|
||||
]
|
||||
++ lib.optionals (doBuild && stdenv.isLinux) [
|
||||
"--with-sandbox-shell=${busybox-sandbox-shell}/bin/busybox"
|
||||
]
|
||||
++ lib.optional (
|
||||
doBuild && stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")
|
||||
) "LDFLAGS=-fuse-ld=gold"
|
||||
++ lib.optional (doBuild && stdenv.hostPlatform.isStatic) "--enable-embedded-sandbox-shell";
|
||||
|
||||
enableParallelBuilding = true;
|
||||
enableParallelBuilding = true;
|
||||
|
||||
makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1";
|
||||
makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1";
|
||||
|
||||
preCheck = ''
|
||||
mkdir $testresults
|
||||
'';
|
||||
|
||||
installTargets = lib.optional doBuild "install";
|
||||
|
||||
installFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
# In this case we are probably just running tests, and so there isn't
|
||||
# anything to install, we just make an empty directory to signify tests
|
||||
# succeeded.
|
||||
installPhase = if finalAttrs.installTargets != [] then null else ''
|
||||
mkdir -p $out
|
||||
'';
|
||||
|
||||
postInstall = lib.optionalString doBuild (
|
||||
lib.optionalString stdenv.hostPlatform.isStatic ''
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products
|
||||
''
|
||||
) + lib.optionalString enableManual ''
|
||||
mkdir -p ''${!outputDoc}/nix-support
|
||||
echo "doc manual ''${!outputDoc}/share/doc/nix/manual" >> ''${!outputDoc}/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
# So the check output gets links for DLLs in the out output.
|
||||
preFixup = lib.optionalString (stdenv.hostPlatform.isWindows && builtins.elem "check" finalAttrs.outputs) ''
|
||||
ln -s "$check/lib/"*.dll "$check/bin"
|
||||
ln -s "$out/bin/"*.dll "$check/bin"
|
||||
'';
|
||||
|
||||
doInstallCheck = attrs.doInstallCheck;
|
||||
|
||||
installCheckFlags = "sysconfdir=$(out)/etc";
|
||||
# Work around buggy detection in stdenv.
|
||||
installCheckTarget = "installcheck";
|
||||
|
||||
# Work around weird bug where it doesn't think there is a Makefile.
|
||||
installCheckPhase = if (!doBuild && doInstallCheck) then ''
|
||||
runHook preInstallCheck
|
||||
mkdir -p src/nix-channel
|
||||
make installcheck -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES
|
||||
'' else null;
|
||||
|
||||
# Needed for tests if we are not doing a build, but testing existing
|
||||
# built Nix.
|
||||
preInstallCheck =
|
||||
lib.optionalString (! doBuild) ''
|
||||
mkdir -p src/nix-channel
|
||||
''
|
||||
# See https://github.com/NixOS/nix/issues/2523
|
||||
# Occurs often in tests since https://github.com/NixOS/nix/pull/9900
|
||||
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
|
||||
preCheck = ''
|
||||
mkdir $testresults
|
||||
'';
|
||||
|
||||
separateDebugInfo = !stdenv.hostPlatform.isStatic;
|
||||
installTargets = lib.optional doBuild "install";
|
||||
|
||||
# TODO Always true after https://github.com/NixOS/nixpkgs/issues/318564
|
||||
strictDeps = !withCoverageChecks;
|
||||
installFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
|
||||
# In this case we are probably just running tests, and so there isn't
|
||||
# anything to install, we just make an empty directory to signify tests
|
||||
# succeeded.
|
||||
installPhase =
|
||||
if finalAttrs.installTargets != [ ] then
|
||||
null
|
||||
else
|
||||
''
|
||||
mkdir -p $out
|
||||
'';
|
||||
|
||||
meta = {
|
||||
platforms = lib.platforms.unix ++ lib.platforms.windows;
|
||||
mainProgram = "nix";
|
||||
broken = !(lib.all (a: a) [
|
||||
# We cannot run or install unit tests if we don't build them or
|
||||
# Nix proper (which they depend on).
|
||||
(installUnitTests -> doBuild)
|
||||
(doCheck -> doBuild)
|
||||
# The build process for the manual currently requires extracting
|
||||
# data from the Nix executable we are trying to document.
|
||||
(enableManual -> doBuild)
|
||||
]);
|
||||
};
|
||||
postInstall =
|
||||
lib.optionalString doBuild (
|
||||
lib.optionalString stdenv.hostPlatform.isStatic ''
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products
|
||||
''
|
||||
)
|
||||
+ lib.optionalString enableManual ''
|
||||
mkdir -p ''${!outputDoc}/nix-support
|
||||
echo "doc manual ''${!outputDoc}/share/doc/nix/manual" >> ''${!outputDoc}/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
} // lib.optionalAttrs withCoverageChecks {
|
||||
lcovFilter = [ "*/boost/*" "*-tab.*" ];
|
||||
# So the check output gets links for DLLs in the out output.
|
||||
preFixup =
|
||||
lib.optionalString (stdenv.hostPlatform.isWindows && builtins.elem "check" finalAttrs.outputs)
|
||||
''
|
||||
ln -s "$check/lib/"*.dll "$check/bin"
|
||||
ln -s "$out/bin/"*.dll "$check/bin"
|
||||
'';
|
||||
|
||||
hardeningDisable = ["fortify"];
|
||||
doInstallCheck = attrs.doInstallCheck;
|
||||
|
||||
NIX_CFLAGS_COMPILE = "-DCOVERAGE=1";
|
||||
installCheckFlags = "sysconfdir=$(out)/etc";
|
||||
# Work around buggy detection in stdenv.
|
||||
installCheckTarget = "installcheck";
|
||||
|
||||
dontInstall = false;
|
||||
} // lib.optionalAttrs (test-daemon != null) {
|
||||
NIX_DAEMON_PACKAGE = test-daemon;
|
||||
} // lib.optionalAttrs (test-client != null) {
|
||||
NIX_CLIENT_PACKAGE = test-client;
|
||||
})
|
||||
# Work around weird bug where it doesn't think there is a Makefile.
|
||||
installCheckPhase =
|
||||
if (!doBuild && doInstallCheck) then
|
||||
''
|
||||
runHook preInstallCheck
|
||||
mkdir -p src/nix-channel
|
||||
make installcheck -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES
|
||||
''
|
||||
else
|
||||
null;
|
||||
|
||||
# Needed for tests if we are not doing a build, but testing existing
|
||||
# built Nix.
|
||||
preInstallCheck =
|
||||
lib.optionalString (!doBuild) ''
|
||||
mkdir -p src/nix-channel
|
||||
''
|
||||
# See https://github.com/NixOS/nix/issues/2523
|
||||
# Occurs often in tests since https://github.com/NixOS/nix/pull/9900
|
||||
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
|
||||
'';
|
||||
|
||||
separateDebugInfo = !stdenv.hostPlatform.isStatic;
|
||||
|
||||
# TODO Always true after https://github.com/NixOS/nixpkgs/issues/318564
|
||||
strictDeps = !withCoverageChecks;
|
||||
|
||||
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
|
||||
|
||||
meta = {
|
||||
platforms = lib.platforms.unix ++ lib.platforms.windows;
|
||||
mainProgram = "nix";
|
||||
broken =
|
||||
!(lib.all (a: a) [
|
||||
# We cannot run or install unit tests if we don't build them or
|
||||
# Nix proper (which they depend on).
|
||||
(installUnitTests -> doBuild)
|
||||
(doCheck -> doBuild)
|
||||
# The build process for the manual currently requires extracting
|
||||
# data from the Nix executable we are trying to document.
|
||||
(enableManual -> doBuild)
|
||||
]);
|
||||
};
|
||||
|
||||
}
|
||||
// lib.optionalAttrs withCoverageChecks {
|
||||
lcovFilter = [
|
||||
"*/boost/*"
|
||||
"*-tab.*"
|
||||
];
|
||||
|
||||
hardeningDisable = [ "fortify" ];
|
||||
|
||||
NIX_CFLAGS_COMPILE = "-DCOVERAGE=1";
|
||||
|
||||
dontInstall = false;
|
||||
}
|
||||
// lib.optionalAttrs (test-daemon != null) {
|
||||
NIX_DAEMON_PACKAGE = test-daemon;
|
||||
}
|
||||
// lib.optionalAttrs (test-client != null) {
|
||||
NIX_CLIENT_PACKAGE = test-client;
|
||||
}
|
||||
)
|
||||
|
||||
@@ -20,9 +20,7 @@ let
|
||||
|
||||
root = ../.;
|
||||
|
||||
stdenv = if prevStdenv.isDarwin && prevStdenv.isx86_64
|
||||
then darwinStdenv
|
||||
else prevStdenv;
|
||||
stdenv = if prevStdenv.isDarwin && prevStdenv.isx86_64 then darwinStdenv else prevStdenv;
|
||||
|
||||
# Fix the following error with the default x86_64-darwin SDK:
|
||||
#
|
||||
@@ -39,7 +37,8 @@ let
|
||||
# Indirection for Nixpkgs to override when package.nix files are vendored
|
||||
filesetToSource = lib.fileset.toSource;
|
||||
|
||||
localSourceLayer = finalAttrs: prevAttrs:
|
||||
localSourceLayer =
|
||||
finalAttrs: prevAttrs:
|
||||
let
|
||||
workDirPath =
|
||||
# Ideally we'd pick finalAttrs.workDir, but for now `mkDerivation` has
|
||||
@@ -48,8 +47,13 @@ let
|
||||
prevAttrs.workDir;
|
||||
|
||||
workDirSubpath = lib.path.removePrefix root workDirPath;
|
||||
sources = assert prevAttrs.fileset._type == "fileset"; prevAttrs.fileset;
|
||||
src = lib.fileset.toSource { fileset = sources; inherit root; };
|
||||
sources =
|
||||
assert prevAttrs.fileset._type == "fileset";
|
||||
prevAttrs.fileset;
|
||||
src = lib.fileset.toSource {
|
||||
fileset = sources;
|
||||
inherit root;
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
@@ -63,30 +67,35 @@ let
|
||||
|
||||
# Work around weird `--as-needed` linker behavior with BSD, see
|
||||
# https://github.com/mesonbuild/meson/issues/3593
|
||||
bsdNoLinkAsNeeded = finalAttrs: prevAttrs:
|
||||
bsdNoLinkAsNeeded =
|
||||
finalAttrs: prevAttrs:
|
||||
lib.optionalAttrs stdenv.hostPlatform.isBSD {
|
||||
mesonFlags = [ (lib.mesonBool "b_asneeded" false) ] ++ prevAttrs.mesonFlags or [];
|
||||
mesonFlags = [ (lib.mesonBool "b_asneeded" false) ] ++ prevAttrs.mesonFlags or [ ];
|
||||
};
|
||||
|
||||
miscGoodPractice = finalAttrs: prevAttrs:
|
||||
{
|
||||
strictDeps = prevAttrs.strictDeps or true;
|
||||
enableParallelBuilding = true;
|
||||
};
|
||||
miscGoodPractice = finalAttrs: prevAttrs: {
|
||||
strictDeps = prevAttrs.strictDeps or true;
|
||||
enableParallelBuilding = true;
|
||||
};
|
||||
|
||||
in
|
||||
scope: {
|
||||
inherit stdenv versionSuffix;
|
||||
version = lib.fileContents ../.version + versionSuffix;
|
||||
|
||||
aws-sdk-cpp = (pkgs.aws-sdk-cpp.override {
|
||||
apis = [ "s3" "transfer" ];
|
||||
customMemoryManagement = false;
|
||||
}).overrideAttrs {
|
||||
# only a stripped down version is built, which takes a lot less resources
|
||||
# to build, so we don't need a "big-parallel" machine.
|
||||
requiredSystemFeatures = [ ];
|
||||
};
|
||||
aws-sdk-cpp =
|
||||
(pkgs.aws-sdk-cpp.override {
|
||||
apis = [
|
||||
"s3"
|
||||
"transfer"
|
||||
];
|
||||
customMemoryManagement = false;
|
||||
}).overrideAttrs
|
||||
{
|
||||
# only a stripped down version is built, which takes a lot less resources
|
||||
# to build, so we don't need a "big-parallel" machine.
|
||||
requiredSystemFeatures = [ ];
|
||||
};
|
||||
|
||||
libseccomp = pkgs.libseccomp.overrideAttrs (_: rec {
|
||||
version = "2.5.5";
|
||||
@@ -101,48 +110,50 @@ scope: {
|
||||
};
|
||||
|
||||
# TODO Hack until https://github.com/NixOS/nixpkgs/issues/45462 is fixed.
|
||||
boost = (pkgs.boost.override {
|
||||
extraB2Args = [
|
||||
"--with-container"
|
||||
"--with-context"
|
||||
"--with-coroutine"
|
||||
];
|
||||
}).overrideAttrs (old: {
|
||||
# Need to remove `--with-*` to use `--with-libraries=...`
|
||||
buildPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.buildPhase;
|
||||
installPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.installPhase;
|
||||
});
|
||||
boost =
|
||||
(pkgs.boost.override {
|
||||
extraB2Args = [
|
||||
"--with-container"
|
||||
"--with-context"
|
||||
"--with-coroutine"
|
||||
];
|
||||
}).overrideAttrs
|
||||
(old: {
|
||||
# Need to remove `--with-*` to use `--with-libraries=...`
|
||||
buildPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.buildPhase;
|
||||
installPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.installPhase;
|
||||
});
|
||||
|
||||
libgit2 = pkgs.libgit2.overrideAttrs (attrs: {
|
||||
src = inputs.libgit2;
|
||||
version = inputs.libgit2.lastModifiedDate;
|
||||
cmakeFlags = attrs.cmakeFlags or []
|
||||
++ [ "-DUSE_SSH=exec" ];
|
||||
cmakeFlags = attrs.cmakeFlags or [ ] ++ [ "-DUSE_SSH=exec" ];
|
||||
});
|
||||
|
||||
busybox-sandbox-shell = pkgs.busybox-sandbox-shell or (pkgs.busybox.override {
|
||||
useMusl = true;
|
||||
enableStatic = true;
|
||||
enableMinimal = true;
|
||||
extraConfig = ''
|
||||
CONFIG_FEATURE_FANCY_ECHO y
|
||||
CONFIG_FEATURE_SH_MATH y
|
||||
CONFIG_FEATURE_SH_MATH_64 y
|
||||
busybox-sandbox-shell =
|
||||
pkgs.busybox-sandbox-shell or (pkgs.busybox.override {
|
||||
useMusl = true;
|
||||
enableStatic = true;
|
||||
enableMinimal = true;
|
||||
extraConfig = ''
|
||||
CONFIG_FEATURE_FANCY_ECHO y
|
||||
CONFIG_FEATURE_SH_MATH y
|
||||
CONFIG_FEATURE_SH_MATH_64 y
|
||||
|
||||
CONFIG_ASH y
|
||||
CONFIG_ASH_OPTIMIZE_FOR_SIZE y
|
||||
CONFIG_ASH y
|
||||
CONFIG_ASH_OPTIMIZE_FOR_SIZE y
|
||||
|
||||
CONFIG_ASH_ALIAS y
|
||||
CONFIG_ASH_BASH_COMPAT y
|
||||
CONFIG_ASH_CMDCMD y
|
||||
CONFIG_ASH_ECHO y
|
||||
CONFIG_ASH_GETOPTS y
|
||||
CONFIG_ASH_INTERNAL_GLOB y
|
||||
CONFIG_ASH_JOB_CONTROL y
|
||||
CONFIG_ASH_PRINTF y
|
||||
CONFIG_ASH_TEST y
|
||||
'';
|
||||
});
|
||||
CONFIG_ASH_ALIAS y
|
||||
CONFIG_ASH_BASH_COMPAT y
|
||||
CONFIG_ASH_CMDCMD y
|
||||
CONFIG_ASH_ECHO y
|
||||
CONFIG_ASH_GETOPTS y
|
||||
CONFIG_ASH_INTERNAL_GLOB y
|
||||
CONFIG_ASH_JOB_CONTROL y
|
||||
CONFIG_ASH_PRINTF y
|
||||
CONFIG_ASH_TEST y
|
||||
'';
|
||||
});
|
||||
|
||||
# TODO change in Nixpkgs, Windows works fine. First commit of
|
||||
# https://github.com/NixOS/nixpkgs/pull/322977 backported will fix.
|
||||
@@ -152,14 +163,14 @@ scope: {
|
||||
|
||||
inherit resolvePath filesetToSource;
|
||||
|
||||
mkMesonDerivation = f: let
|
||||
exts = [
|
||||
miscGoodPractice
|
||||
bsdNoLinkAsNeeded
|
||||
localSourceLayer
|
||||
];
|
||||
in stdenv.mkDerivation
|
||||
(lib.extends
|
||||
(lib.foldr lib.composeExtensions (_: _: {}) exts)
|
||||
f);
|
||||
mkMesonDerivation =
|
||||
f:
|
||||
let
|
||||
exts = [
|
||||
miscGoodPractice
|
||||
bsdNoLinkAsNeeded
|
||||
localSourceLayer
|
||||
];
|
||||
in
|
||||
stdenv.mkDerivation (lib.extends (lib.foldr lib.composeExtensions (_: _: { }) exts) f);
|
||||
}
|
||||
|
||||
@@ -1,28 +1,31 @@
|
||||
{ inputs
|
||||
, binaryTarball
|
||||
, forAllCrossSystems
|
||||
, forAllSystems
|
||||
, lib
|
||||
, linux64BitSystems
|
||||
, nixpkgsFor
|
||||
, self
|
||||
{
|
||||
inputs,
|
||||
binaryTarball,
|
||||
forAllCrossSystems,
|
||||
forAllSystems,
|
||||
lib,
|
||||
linux64BitSystems,
|
||||
nixpkgsFor,
|
||||
self,
|
||||
}:
|
||||
let
|
||||
inherit (inputs) nixpkgs nixpkgs-regression;
|
||||
|
||||
installScriptFor = tarballs:
|
||||
installScriptFor =
|
||||
tarballs:
|
||||
nixpkgsFor.x86_64-linux.native.callPackage ../scripts/installer.nix {
|
||||
inherit tarballs;
|
||||
};
|
||||
|
||||
testNixVersions = pkgs: client: daemon:
|
||||
testNixVersions =
|
||||
pkgs: client: daemon:
|
||||
pkgs.callPackage ../package.nix {
|
||||
pname =
|
||||
"nix-tests"
|
||||
+ lib.optionalString
|
||||
(lib.versionAtLeast daemon.version "2.4pre20211005" &&
|
||||
lib.versionAtLeast client.version "2.4pre20211005")
|
||||
"-${client.version}-against-${daemon.version}";
|
||||
+ lib.optionalString (
|
||||
lib.versionAtLeast daemon.version "2.4pre20211005"
|
||||
&& lib.versionAtLeast client.version "2.4pre20211005"
|
||||
) "-${client.version}-against-${daemon.version}";
|
||||
|
||||
test-client = client;
|
||||
test-daemon = daemon;
|
||||
@@ -59,27 +62,35 @@ let
|
||||
in
|
||||
{
|
||||
# Binary package for various platforms.
|
||||
build = forAllPackages (pkgName:
|
||||
forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.${pkgName}));
|
||||
build = forAllPackages (
|
||||
pkgName: forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.${pkgName})
|
||||
);
|
||||
|
||||
shellInputs = forAllSystems (system: self.devShells.${system}.default.inputDerivation);
|
||||
|
||||
buildStatic = forAllPackages (pkgName:
|
||||
lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName}));
|
||||
|
||||
buildCross = forAllPackages (pkgName:
|
||||
forAllCrossSystems (crossSystem:
|
||||
lib.genAttrs [ "x86_64-linux" ] (system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName})));
|
||||
|
||||
buildNoGc = forAllSystems (system:
|
||||
self.packages.${system}.nix.override { enableGC = false; }
|
||||
buildStatic = forAllPackages (
|
||||
pkgName:
|
||||
lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName})
|
||||
);
|
||||
|
||||
buildCross = forAllPackages (
|
||||
pkgName:
|
||||
forAllCrossSystems (
|
||||
crossSystem:
|
||||
lib.genAttrs [ "x86_64-linux" ] (
|
||||
system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName}
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
buildNoGc = forAllSystems (system: self.packages.${system}.nix.override { enableGC = false; });
|
||||
|
||||
buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nix_noTests);
|
||||
|
||||
# Toggles some settings for better coverage. Windows needs these
|
||||
# library combinations, and Debian build Nix with GNU readline too.
|
||||
buildReadlineNoMarkdown = forAllSystems (system:
|
||||
buildReadlineNoMarkdown = forAllSystems (
|
||||
system:
|
||||
self.packages.${system}.nix.override {
|
||||
enableMarkdown = false;
|
||||
readlineFlavor = "readline";
|
||||
@@ -92,13 +103,18 @@ in
|
||||
# Binary tarball for various platforms, containing a Nix store
|
||||
# with the closure of 'nix' package, and the second half of
|
||||
# the installation script.
|
||||
binaryTarball = forAllSystems (system: binaryTarball nixpkgsFor.${system}.native.nix nixpkgsFor.${system}.native);
|
||||
binaryTarball = forAllSystems (
|
||||
system: binaryTarball nixpkgsFor.${system}.native.nix nixpkgsFor.${system}.native
|
||||
);
|
||||
|
||||
binaryTarballCross = lib.genAttrs [ "x86_64-linux" ] (system:
|
||||
forAllCrossSystems (crossSystem:
|
||||
binaryTarball
|
||||
nixpkgsFor.${system}.cross.${crossSystem}.nix
|
||||
nixpkgsFor.${system}.cross.${crossSystem}));
|
||||
binaryTarballCross = lib.genAttrs [ "x86_64-linux" ] (
|
||||
system:
|
||||
forAllCrossSystems (
|
||||
crossSystem:
|
||||
binaryTarball nixpkgsFor.${system}.cross.${crossSystem}.nix
|
||||
nixpkgsFor.${system}.cross.${crossSystem}
|
||||
)
|
||||
);
|
||||
|
||||
# The first half of the installation script. This is uploaded
|
||||
# to https://nixos.org/nix/install. It downloads the binary
|
||||
@@ -116,15 +132,13 @@ in
|
||||
self.hydraJobs.binaryTarballCross."x86_64-linux"."armv7l-unknown-linux-gnueabihf"
|
||||
self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu"
|
||||
];
|
||||
installerScriptForGHA = installScriptFor [
|
||||
# Native
|
||||
self.hydraJobs.binaryTarball."x86_64-linux"
|
||||
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"
|
||||
];
|
||||
|
||||
installerScriptForGHA = forAllSystems (
|
||||
system:
|
||||
nixpkgsFor.${system}.native.callPackage ../scripts/installer.nix {
|
||||
tarballs = [ self.hydraJobs.binaryTarball.${system} ];
|
||||
}
|
||||
);
|
||||
|
||||
# docker image with Nix inside
|
||||
dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage);
|
||||
@@ -142,16 +156,24 @@ in
|
||||
external-api-docs = nixpkgsFor.x86_64-linux.native.nixComponents.nix-external-api-docs;
|
||||
|
||||
# System tests.
|
||||
tests = import ../tests/nixos { inherit lib nixpkgs nixpkgsFor self; } // {
|
||||
tests =
|
||||
import ../tests/nixos {
|
||||
inherit
|
||||
lib
|
||||
nixpkgs
|
||||
nixpkgsFor
|
||||
self
|
||||
;
|
||||
}
|
||||
// {
|
||||
|
||||
# Make sure that nix-env still produces the exact same result
|
||||
# on a particular version of Nixpkgs.
|
||||
evalNixpkgs =
|
||||
let
|
||||
inherit (nixpkgsFor.x86_64-linux.native) runCommand nix;
|
||||
in
|
||||
runCommand "eval-nixos" { buildInputs = [ nix ]; }
|
||||
''
|
||||
# Make sure that nix-env still produces the exact same result
|
||||
# on a particular version of Nixpkgs.
|
||||
evalNixpkgs =
|
||||
let
|
||||
inherit (nixpkgsFor.x86_64-linux.native) runCommand nix;
|
||||
in
|
||||
runCommand "eval-nixos" { buildInputs = [ nix ]; } ''
|
||||
type -p nix-env
|
||||
# Note: we're filtering out nixos-install-tools because https://github.com/NixOS/nixpkgs/pull/153594#issuecomment-1020530593.
|
||||
(
|
||||
@@ -162,36 +184,36 @@ in
|
||||
mkdir $out
|
||||
'';
|
||||
|
||||
nixpkgsLibTests =
|
||||
forAllSystems (system:
|
||||
import (nixpkgs + "/lib/tests/test-with-nix.nix")
|
||||
{
|
||||
lib = nixpkgsFor.${system}.native.lib;
|
||||
nix = self.packages.${system}.nix;
|
||||
pkgs = nixpkgsFor.${system}.native;
|
||||
}
|
||||
nixpkgsLibTests = forAllSystems (
|
||||
system:
|
||||
import (nixpkgs + "/lib/tests/test-with-nix.nix") {
|
||||
lib = nixpkgsFor.${system}.native.lib;
|
||||
nix = self.packages.${system}.nix;
|
||||
pkgs = nixpkgsFor.${system}.native;
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
metrics.nixpkgs = import "${nixpkgs-regression}/pkgs/top-level/metrics.nix" {
|
||||
pkgs = nixpkgsFor.x86_64-linux.native;
|
||||
nixpkgs = nixpkgs-regression;
|
||||
};
|
||||
|
||||
installTests = forAllSystems (system:
|
||||
let pkgs = nixpkgsFor.${system}.native; in
|
||||
pkgs.runCommand "install-tests"
|
||||
{
|
||||
againstSelf = testNixVersions pkgs pkgs.nix pkgs.pkgs.nix;
|
||||
againstCurrentLatest =
|
||||
# FIXME: temporarily disable this on macOS because of #3605.
|
||||
if system == "x86_64-linux"
|
||||
then testNixVersions pkgs pkgs.nix pkgs.nixVersions.latest
|
||||
else null;
|
||||
# Disabled because the latest stable version doesn't handle
|
||||
# `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work
|
||||
# againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable;
|
||||
} "touch $out");
|
||||
installTests = forAllSystems (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgsFor.${system}.native;
|
||||
in
|
||||
pkgs.runCommand "install-tests" {
|
||||
againstSelf = testNixVersions pkgs pkgs.nix pkgs.pkgs.nix;
|
||||
againstCurrentLatest =
|
||||
# FIXME: temporarily disable this on macOS because of #3605.
|
||||
if system == "x86_64-linux" then testNixVersions pkgs pkgs.nix pkgs.nixVersions.latest else null;
|
||||
# Disabled because the latest stable version doesn't handle
|
||||
# `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work
|
||||
# againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable;
|
||||
} "touch $out"
|
||||
);
|
||||
|
||||
installerTests = import ../tests/installer {
|
||||
binaryTarballs = self.hydraJobs.binaryTarball;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
((NEW_NIX_FIRST_BUILD_UID=301))
|
||||
((NEW_NIX_FIRST_BUILD_UID=351))
|
||||
|
||||
id_available(){
|
||||
dscl . list /Users UniqueID | grep -E '\b'"$1"'\b' >/dev/null
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
{ runCommand
|
||||
, system
|
||||
, buildPackages
|
||||
, cacert
|
||||
, nix
|
||||
{
|
||||
runCommand,
|
||||
system,
|
||||
buildPackages,
|
||||
cacert,
|
||||
nix,
|
||||
}:
|
||||
|
||||
let
|
||||
|
||||
installerClosureInfo = buildPackages.closureInfo {
|
||||
rootPaths = [ nix cacert ];
|
||||
rootPaths = [
|
||||
nix
|
||||
cacert
|
||||
];
|
||||
};
|
||||
|
||||
inherit (nix) version;
|
||||
@@ -65,7 +69,7 @@ runCommand "nix-binary-tarball-${version}" env ''
|
||||
fn=$out/$dir.tar.xz
|
||||
mkdir -p $out/nix-support
|
||||
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 \
|
||||
--mtime='1970-01-01' \
|
||||
--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
|
||||
:a
|
||||
UUID=$uuid $escaped_mountpoint apfs rw,noauto,nobrowse,suid,owners
|
||||
UUID=$uuid $escaped_mountpoint apfs rw,noauto,nobrowse,nosuid,noatime,owners
|
||||
.
|
||||
:x
|
||||
EOF
|
||||
|
||||
@@ -4,7 +4,17 @@ set -eu
|
||||
set -o pipefail
|
||||
|
||||
# System specific settings
|
||||
export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-301}"
|
||||
# Notes:
|
||||
# - up to macOS Big Sur we used the same GID/UIDs as Linux (30000:30001-32)
|
||||
# - we changed UID to 301 because Big Sur updates failed into recovery mode
|
||||
# we're targeting the 200-400 UID range for role users mentioned in the
|
||||
# usage note for sysadminctl
|
||||
# - we changed UID to 351 because Sequoia now uses UIDs 300-304 for its own
|
||||
# daemon users
|
||||
# - we changed GID to 350 alongside above just because it hides the nixbld
|
||||
# group from the Users & Groups settings panel :)
|
||||
export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-351}"
|
||||
export NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-350}"
|
||||
export NIX_BUILD_USER_NAME_TEMPLATE="_nixbld%d"
|
||||
|
||||
readonly NIX_DAEMON_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
|
||||
@@ -23,10 +23,10 @@ readonly RED='\033[31m'
|
||||
# installer allows overriding build user count to speed up installation
|
||||
# as creating each user takes non-trivial amount of time on macos
|
||||
readonly NIX_USER_COUNT=${NIX_USER_COUNT:-32}
|
||||
readonly NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-30000}"
|
||||
readonly NIX_BUILD_GROUP_NAME="nixbld"
|
||||
# each system specific installer must set these:
|
||||
# NIX_FIRST_BUILD_UID
|
||||
# NIX_BUILD_GROUP_ID
|
||||
# NIX_BUILD_USER_NAME_TEMPLATE
|
||||
# Please don't change this. We don't support it, because the
|
||||
# default shell profile that comes with Nix doesn't support it.
|
||||
@@ -530,9 +530,7 @@ It seems the build group $NIX_BUILD_GROUP_NAME already exists, but
|
||||
with the UID $primary_group_id. This script can't really handle
|
||||
that right now, so I'm going to give up.
|
||||
|
||||
You can fix this by editing this script and changing the
|
||||
NIX_BUILD_GROUP_ID variable near the top to from $NIX_BUILD_GROUP_ID
|
||||
to $primary_group_id and re-run.
|
||||
You can export NIX_BUILD_GROUP_ID=$primary_group_id and re-run.
|
||||
EOF
|
||||
else
|
||||
row " Exists" "Yes"
|
||||
|
||||
@@ -5,6 +5,7 @@ set -o pipefail
|
||||
|
||||
# System specific settings
|
||||
export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-30001}"
|
||||
export NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-30000}"
|
||||
export NIX_BUILD_USER_NAME_TEMPLATE="nixbld%d"
|
||||
|
||||
readonly SERVICE_SRC=/lib/systemd/system/nix-daemon.service
|
||||
@@ -95,6 +96,9 @@ poly_configure_nix_daemon_service() {
|
||||
if [ -e /run/systemd/system ]; then
|
||||
task "Setting up the nix-daemon systemd service"
|
||||
|
||||
_sudo "to create parent of the nix-daemon tmpfiles config" \
|
||||
mkdir -p "$(dirname "$TMPFILES_DEST")"
|
||||
|
||||
_sudo "to create the nix-daemon tmpfiles config" \
|
||||
ln -sfn "/nix/var/nix/profiles/default$TMPFILES_SRC" "$TMPFILES_DEST"
|
||||
|
||||
|
||||
@@ -1,36 +1,42 @@
|
||||
{ lib
|
||||
, runCommand
|
||||
, nix
|
||||
, tarballs
|
||||
{
|
||||
lib,
|
||||
runCommand,
|
||||
nix,
|
||||
tarballs,
|
||||
}:
|
||||
|
||||
runCommand "installer-script" {
|
||||
buildInputs = [ nix ];
|
||||
} ''
|
||||
mkdir -p $out/nix-support
|
||||
|
||||
# Converts /nix/store/50p3qk8k...-nix-2.4pre20201102_550e11f/bin/nix to 50p3qk8k.../bin/nix.
|
||||
tarballPath() {
|
||||
# Remove the store prefix
|
||||
local path=''${1#${builtins.storeDir}/}
|
||||
# Get the path relative to the derivation root
|
||||
local rest=''${path#*/}
|
||||
# Get the derivation hash
|
||||
local drvHash=''${path%%-*}
|
||||
echo "$drvHash/$rest"
|
||||
runCommand "installer-script"
|
||||
{
|
||||
buildInputs = [ nix ];
|
||||
}
|
||||
''
|
||||
mkdir -p $out/nix-support
|
||||
|
||||
substitute ${./install.in} $out/install \
|
||||
${lib.concatMapStrings
|
||||
(tarball: let
|
||||
inherit (tarball.stdenv.hostPlatform) system;
|
||||
in '' \
|
||||
--replace '@tarballHash_${system}@' $(nix --experimental-features nix-command hash-file --base16 --type sha256 ${tarball}/*.tar.xz) \
|
||||
--replace '@tarballPath_${system}@' $(tarballPath ${tarball}/*.tar.xz) \
|
||||
''
|
||||
)
|
||||
tarballs
|
||||
} --replace '@nixVersion@' ${nix.version}
|
||||
# Converts /nix/store/50p3qk8k...-nix-2.4pre20201102_550e11f/bin/nix to 50p3qk8k.../bin/nix.
|
||||
tarballPath() {
|
||||
# Remove the store prefix
|
||||
local path=''${1#${builtins.storeDir}/}
|
||||
# Get the path relative to the derivation root
|
||||
local rest=''${path#*/}
|
||||
# Get the derivation hash
|
||||
local drvHash=''${path%%-*}
|
||||
echo "$drvHash/$rest"
|
||||
}
|
||||
|
||||
echo "file installer $out/install" >> $out/nix-support/hydra-build-products
|
||||
''
|
||||
substitute ${./install.in} $out/install \
|
||||
${
|
||||
lib.concatMapStrings (
|
||||
tarball:
|
||||
let
|
||||
inherit (tarball.stdenv.hostPlatform) system;
|
||||
in
|
||||
''
|
||||
\
|
||||
--replace '@tarballHash_${system}@' $(nix --experimental-features nix-command hash-file --base16 --type sha256 ${tarball}/*.tar.xz) \
|
||||
--replace '@tarballPath_${system}@' $(tarballPath ${tarball}/*.tar.xz) \
|
||||
''
|
||||
) tarballs
|
||||
} --replace '@nixVersion@' ${nix.version}
|
||||
|
||||
echo "file installer $out/install" >> $out/nix-support/hydra-build-products
|
||||
''
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Only execute this file once per shell.
|
||||
# This file is tested by tests/installer/default.nix.
|
||||
if [ -n "${__ETC_PROFILE_NIX_SOURCED:-}" ]; then return; fi
|
||||
__ETC_PROFILE_NIX_SOURCED=1
|
||||
export __ETC_PROFILE_NIX_SOURCED=1
|
||||
|
||||
NIX_LINK=$HOME/.nix-profile
|
||||
if [ -n "${XDG_STATE_HOME-}" ]; then
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# This file is tested by tests/installer/default.nix.
|
||||
if [ -n "$HOME" ] && [ -n "$USER" ]; then
|
||||
if [ -n "${HOME-}" ] && [ -n "${USER-}" ]; then
|
||||
|
||||
# Set up the per-user profile.
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -euo pipefail
|
||||
|
||||
script=$(nix-build -A outputs.hydraJobs.installerScriptForGHA --no-out-link)
|
||||
installerHash=$(echo "$script" | cut -b12-43 -)
|
||||
nix build -L ".#installerScriptForGHA" ".#binaryTarball"
|
||||
|
||||
installerURL=https://$CACHIX_NAME.cachix.org/serve/$installerHash/install
|
||||
|
||||
echo "::set-output name=installerURL::$installerURL"
|
||||
mkdir -p out
|
||||
cp ./result/install "out/install"
|
||||
name="$(basename "$(realpath ./result-1)")"
|
||||
# everything before the first dash
|
||||
cp -r ./result-1 "out/${name%%-*}"
|
||||
|
||||
172
scripts/sequoia-nixbld-user-migration.sh
Executable file
172
scripts/sequoia-nixbld-user-migration.sh
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
# stock path to avoid unexpected command versions
|
||||
PATH="$(/usr/bin/getconf PATH)"
|
||||
|
||||
((NEW_NIX_FIRST_BUILD_UID=351))
|
||||
((TEMP_NIX_FIRST_BUILD_UID=31000))
|
||||
|
||||
nix_user_n() {
|
||||
printf "_nixbld%d" "$1"
|
||||
}
|
||||
|
||||
id_unavailable(){
|
||||
dscl . list /Users UniqueID | grep -E '\b'"$1"'\b' >/dev/null
|
||||
}
|
||||
|
||||
any_nixbld(){
|
||||
dscl . list /Users UniqueID | grep -E '\b_nixbld' >/dev/null
|
||||
}
|
||||
|
||||
dsclattr() {
|
||||
dscl . -read "$1" | awk "/$2/ { print \$2 }"
|
||||
}
|
||||
|
||||
re_create_nixbld_user(){
|
||||
local name uid
|
||||
|
||||
name="$1"
|
||||
uid="$2"
|
||||
gid="$3"
|
||||
|
||||
sudo /usr/bin/dscl . -create "/Users/$name" "UniqueID" "$uid"
|
||||
sudo /usr/bin/dscl . -create "/Users/$name" "IsHidden" "1"
|
||||
sudo /usr/bin/dscl . -create "/Users/$name" "NFSHomeDirectory" "/var/empty"
|
||||
sudo /usr/bin/dscl . -create "/Users/$name" "RealName" "Nix build user $name"
|
||||
sudo /usr/bin/dscl . -create "/Users/$name" "UserShell" "/sbin/nologin"
|
||||
sudo /usr/bin/dscl . -create "/Users/$name" "PrimaryGroupID" "$gid"
|
||||
}
|
||||
|
||||
hit_id_cap(){
|
||||
echo "We've hit UID 400 without placing all of your users :("
|
||||
echo "You should use the commands in this script as a starting"
|
||||
echo "point to review your UID-space and manually move the"
|
||||
echo "remaining users (or delete them, if you don't need them)."
|
||||
}
|
||||
|
||||
# evacuate the role-uid space to simplify final placement logic
|
||||
temporarily_move_existing_nixbld_uids(){
|
||||
local name uid next_id user_n
|
||||
|
||||
((next_id=TEMP_NIX_FIRST_BUILD_UID))
|
||||
|
||||
echo ""
|
||||
echo "Step 1: move existing _nixbld users out of the destination UID range."
|
||||
|
||||
while read -r name uid; do
|
||||
# iterate for a clean ID
|
||||
while id_unavailable "$next_id"; do
|
||||
((next_id++))
|
||||
# We really want to get these all placed, but I guess there's
|
||||
# some risk we iterate forever--so we'll give up after 9k uids.
|
||||
if ((next_id >= 40000)); then
|
||||
echo "We've hit UID 40000 without temporarily placing all of your users :("
|
||||
echo "You should use the commands in this script as a starting"
|
||||
echo "point to review your UID-space and manually move the"
|
||||
echo "remaining users to any open UID over 1000."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
sudo dscl . -create "/Users/$name" UniqueID "$next_id"
|
||||
echo " Temporarily moved $name from uid $uid -> $next_id"
|
||||
|
||||
done < <(dscl . list /Users UniqueID | grep _nixbld | sort -n -k2)
|
||||
}
|
||||
|
||||
change_nixbld_uids(){
|
||||
local existing_gid name next_id user_n
|
||||
|
||||
((next_id=NEW_NIX_FIRST_BUILD_UID))
|
||||
((user_n=1))
|
||||
name="$(nix_user_n "$user_n")"
|
||||
existing_gid="$(dsclattr "/Groups/nixbld" "PrimaryGroupID")"
|
||||
|
||||
# we know that we have *some* nixbld users, but macOS may have
|
||||
# already clobbered the first few users if this system has been
|
||||
# upgraded
|
||||
|
||||
echo ""
|
||||
echo "Step 2: re-create missing early _nixbld# users."
|
||||
|
||||
until dscl . read "/Users/$name" &>/dev/null; do
|
||||
# iterate for a clean ID
|
||||
while id_unavailable "$next_id"; do
|
||||
((next_id++))
|
||||
if ((next_id >= 400)); then
|
||||
hit_id_cap
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
re_create_nixbld_user "$name" "$next_id" "$existing_gid"
|
||||
echo " $name was missing; created with uid: $next_id"
|
||||
|
||||
((user_n++))
|
||||
name="$(nix_user_n "$user_n")"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Step 3: relocate remaining _nixbld# UIDs to $next_id+"
|
||||
|
||||
# start at first _nixbld# not re-created above and increment
|
||||
# until _nixbld<n> doesn't exist
|
||||
while dscl . read "/Users/$name" &>/dev/null; do
|
||||
# iterate for a clean ID
|
||||
while id_unavailable "$next_id"; do
|
||||
((next_id++))
|
||||
if ((next_id >= 400)); then
|
||||
hit_id_cap
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
sudo dscl . -create "/Users/$name" UniqueID "$next_id"
|
||||
echo " $name migrated to uid: $next_id"
|
||||
|
||||
((user_n++))
|
||||
name="$(nix_user_n "$user_n")"
|
||||
done
|
||||
|
||||
if ((user_n == 1)); then
|
||||
echo "Didn't find _nixbld1. Perhaps you have single-user Nix?"
|
||||
exit 1
|
||||
else
|
||||
echo "Migrated $((user_n - 1)) users. If you want to double-check, try:"
|
||||
echo "dscl . list /Users UniqueID | grep _nixbld | sort -n -k2"
|
||||
fi
|
||||
}
|
||||
needs_migration(){
|
||||
local name uid next_id user_n
|
||||
|
||||
((next_id=NEW_NIX_FIRST_BUILD_UID))
|
||||
((user_n=1))
|
||||
|
||||
while read -r name uid; do
|
||||
expected_name="$(nix_user_n "$user_n")"
|
||||
if [[ "$expected_name" != "$name" ]]; then
|
||||
return 0
|
||||
fi
|
||||
if [[ "$next_id" != "$uid" ]]; then
|
||||
return 0
|
||||
fi
|
||||
((next_id++))
|
||||
((user_n++))
|
||||
done < <(dscl . list /Users UniqueID | grep _nixbld | sort -n -k2)
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
if any_nixbld; then
|
||||
if needs_migration; then
|
||||
echo "Attempting to migrate _nixbld users."
|
||||
temporarily_move_existing_nixbld_uids
|
||||
change_nixbld_uids
|
||||
else
|
||||
echo "_nixbld users already appear to be migrated."
|
||||
fi
|
||||
else
|
||||
echo "Didn't find any _nixbld users. Perhaps you have single-user Nix?"
|
||||
exit 1
|
||||
fi
|
||||
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"
|
||||
@@ -1,13 +1,14 @@
|
||||
{ lib
|
||||
, mkMesonDerivation
|
||||
{
|
||||
lib,
|
||||
mkMesonDerivation,
|
||||
|
||||
, meson
|
||||
, ninja
|
||||
, doxygen
|
||||
meson,
|
||||
ninja,
|
||||
doxygen,
|
||||
|
||||
# Configuration Options
|
||||
# Configuration Options
|
||||
|
||||
, version
|
||||
version,
|
||||
}:
|
||||
|
||||
let
|
||||
@@ -42,11 +43,10 @@ mkMesonDerivation (finalAttrs: {
|
||||
doxygen
|
||||
];
|
||||
|
||||
preConfigure =
|
||||
''
|
||||
chmod u+w ./.version
|
||||
echo ${finalAttrs.version} > ./.version
|
||||
'';
|
||||
preConfigure = ''
|
||||
chmod u+w ./.version
|
||||
echo ${finalAttrs.version} > ./.version
|
||||
'';
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p ''${!outputDoc}/nix-support
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
{ lib
|
||||
, mkMesonDerivation
|
||||
{
|
||||
lib,
|
||||
mkMesonDerivation,
|
||||
|
||||
, meson
|
||||
, ninja
|
||||
, doxygen
|
||||
meson,
|
||||
ninja,
|
||||
doxygen,
|
||||
|
||||
# Configuration Options
|
||||
# Configuration Options
|
||||
|
||||
, version
|
||||
version,
|
||||
}:
|
||||
|
||||
let
|
||||
@@ -19,17 +20,19 @@ mkMesonDerivation (finalAttrs: {
|
||||
inherit version;
|
||||
|
||||
workDir = ./.;
|
||||
fileset = let
|
||||
cpp = fileset.fileFilter (file: file.hasExt "cc" || file.hasExt "hh");
|
||||
in fileset.unions [
|
||||
./.version
|
||||
../../.version
|
||||
./meson.build
|
||||
./doxygen.cfg.in
|
||||
# Source is not compiled, but still must be available for Doxygen
|
||||
# to gather comments.
|
||||
(cpp ../.)
|
||||
];
|
||||
fileset =
|
||||
let
|
||||
cpp = fileset.fileFilter (file: file.hasExt "cc" || file.hasExt "hh");
|
||||
in
|
||||
fileset.unions [
|
||||
./.version
|
||||
../../.version
|
||||
./meson.build
|
||||
./doxygen.cfg.in
|
||||
# Source is not compiled, but still must be available for Doxygen
|
||||
# to gather comments.
|
||||
(cpp ../.)
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
@@ -37,11 +40,10 @@ mkMesonDerivation (finalAttrs: {
|
||||
doxygen
|
||||
];
|
||||
|
||||
preConfigure =
|
||||
''
|
||||
chmod u+w ./.version
|
||||
echo ${finalAttrs.version} > ./.version
|
||||
'';
|
||||
preConfigure = ''
|
||||
chmod u+w ./.version
|
||||
echo ${finalAttrs.version} > ./.version
|
||||
'';
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p ''${!outputDoc}/nix-support
|
||||
|
||||
@@ -171,7 +171,9 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * bas
|
||||
{
|
||||
if (EvalSettings::isPseudoUrl(s)) {
|
||||
auto accessor = fetchers::downloadTarball(
|
||||
EvalSettings::resolvePseudoUrl(s)).accessor;
|
||||
state.store,
|
||||
state.fetchSettings,
|
||||
EvalSettings::resolvePseudoUrl(s));
|
||||
auto storePath = fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy);
|
||||
return state.rootPath(CanonPath(state.store->toRealPath(storePath)));
|
||||
}
|
||||
|
||||
@@ -32,16 +32,6 @@ InstallableDerivedPath InstallableDerivedPath::parse(
|
||||
// store path.
|
||||
[&](const ExtendedOutputsSpec::Default &) -> DerivedPath {
|
||||
auto storePath = store->followLinksToStorePath(prefix);
|
||||
// Remove this prior to stabilizing the new CLI.
|
||||
if (storePath.isDerivation()) {
|
||||
auto oldDerivedPath = DerivedPath::Built {
|
||||
.drvPath = makeConstantStorePathRef(storePath),
|
||||
.outputs = OutputsSpec::All { },
|
||||
};
|
||||
warn(
|
||||
"The interpretation of store paths arguments ending in `.drv` recently changed. If this command is now failing try again with '%s'",
|
||||
oldDerivedPath.to_string(*store));
|
||||
};
|
||||
return DerivedPath::Opaque {
|
||||
.path = std::move(storePath),
|
||||
};
|
||||
|
||||
@@ -86,7 +86,7 @@ MixFlakeOptions::MixFlakeOptions()
|
||||
|
||||
> **DEPRECATED**
|
||||
>
|
||||
> Use [`--no-use-registries`](#opt-no-use-registries) instead.
|
||||
> Use [`--no-use-registries`](@docroot@/command-ref/conf-file.md#conf-use-registries) instead.
|
||||
)",
|
||||
.category = category,
|
||||
.handler = {[&]() {
|
||||
|
||||
@@ -16,13 +16,25 @@ static std::string doRenderMarkdownToTerminal(std::string_view markdown)
|
||||
{
|
||||
int windowWidth = getWindowSize().second;
|
||||
|
||||
struct lowdown_opts opts
|
||||
{
|
||||
.type = LOWDOWN_TERM,
|
||||
.maxdepth = 20,
|
||||
#if HAVE_LOWDOWN_1_4
|
||||
struct lowdown_opts_term opts_term {
|
||||
.cols = (size_t) std::max(windowWidth - 5, 60),
|
||||
.hmargin = 0,
|
||||
.vmargin = 0,
|
||||
};
|
||||
#endif
|
||||
struct lowdown_opts opts
|
||||
{
|
||||
.type = LOWDOWN_TERM,
|
||||
#if HAVE_LOWDOWN_1_4
|
||||
.term = opts_term,
|
||||
#endif
|
||||
.maxdepth = 20,
|
||||
#if !HAVE_LOWDOWN_1_4
|
||||
.cols = (size_t) std::max(windowWidth - 5, 60),
|
||||
.hmargin = 0,
|
||||
.vmargin = 0,
|
||||
#endif
|
||||
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
|
||||
.oflags = LOWDOWN_TERM_NOLINK,
|
||||
};
|
||||
|
||||
@@ -38,6 +38,8 @@ deps_public += nlohmann_json
|
||||
lowdown = dependency('lowdown', version : '>= 0.9.0', required : get_option('markdown'))
|
||||
deps_private += lowdown
|
||||
configdata.set('HAVE_LOWDOWN', lowdown.found().to_int())
|
||||
# The API changed slightly around terminal initialization.
|
||||
configdata.set('HAVE_LOWDOWN_1_4', lowdown.version().version_compare('>= 1.4.0').to_int())
|
||||
|
||||
readline_flavor = get_option('readline-flavor')
|
||||
if readline_flavor == 'editline'
|
||||
|
||||
@@ -1,37 +1,38 @@
|
||||
{ lib
|
||||
, stdenv
|
||||
, mkMesonDerivation
|
||||
, releaseTools
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
mkMesonDerivation,
|
||||
releaseTools,
|
||||
|
||||
, meson
|
||||
, ninja
|
||||
, pkg-config
|
||||
meson,
|
||||
ninja,
|
||||
pkg-config,
|
||||
|
||||
, nix-util
|
||||
, nix-store
|
||||
, nix-fetchers
|
||||
, nix-expr
|
||||
, nix-flake
|
||||
, nix-main
|
||||
, editline
|
||||
, readline
|
||||
, lowdown
|
||||
, nlohmann_json
|
||||
nix-util,
|
||||
nix-store,
|
||||
nix-fetchers,
|
||||
nix-expr,
|
||||
nix-flake,
|
||||
nix-main,
|
||||
editline,
|
||||
readline,
|
||||
lowdown,
|
||||
nlohmann_json,
|
||||
|
||||
# Configuration Options
|
||||
# Configuration Options
|
||||
|
||||
, version
|
||||
version,
|
||||
|
||||
# Whether to enable Markdown rendering in the Nix binary.
|
||||
, enableMarkdown ? !stdenv.hostPlatform.isWindows
|
||||
# Whether to enable Markdown rendering in the Nix binary.
|
||||
enableMarkdown ? !stdenv.hostPlatform.isWindows,
|
||||
|
||||
# Which interactive line editor library to use for Nix's repl.
|
||||
#
|
||||
# Currently supported choices are:
|
||||
#
|
||||
# - editline (default)
|
||||
# - readline
|
||||
, readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline"
|
||||
# Which interactive line editor library to use for Nix's repl.
|
||||
#
|
||||
# Currently supported choices are:
|
||||
#
|
||||
# - editline (default)
|
||||
# - readline
|
||||
readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline",
|
||||
}:
|
||||
|
||||
let
|
||||
@@ -54,7 +55,10 @@ mkMesonDerivation (finalAttrs: {
|
||||
(fileset.fileFilter (file: file.hasExt "hh") ./.)
|
||||
];
|
||||
|
||||
outputs = [ "out" "dev" ];
|
||||
outputs = [
|
||||
"out"
|
||||
"dev"
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
@@ -89,9 +93,12 @@ mkMesonDerivation (finalAttrs: {
|
||||
(lib.mesonOption "readline-flavor" readlineFlavor)
|
||||
];
|
||||
|
||||
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
|
||||
LDFLAGS = "-fuse-ld=gold";
|
||||
};
|
||||
env =
|
||||
lib.optionalAttrs
|
||||
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
|
||||
{
|
||||
LDFLAGS = "-fuse-ld=gold";
|
||||
};
|
||||
|
||||
separateDebugInfo = !stdenv.hostPlatform.isStatic;
|
||||
|
||||
|
||||
@@ -157,16 +157,13 @@ static std::ostream & showDebugTrace(std::ostream & out, const PosTable & positi
|
||||
out << ANSI_RED "error: " << ANSI_NORMAL;
|
||||
out << dt.hint.str() << "\n";
|
||||
|
||||
// prefer direct pos, but if noPos then try the expr.
|
||||
auto pos = dt.pos
|
||||
? dt.pos
|
||||
: positions[dt.expr.getPos() ? dt.expr.getPos() : noPos];
|
||||
auto pos = dt.getPos(positions);
|
||||
|
||||
if (pos) {
|
||||
out << *pos;
|
||||
if (auto loc = pos->getCodeLines()) {
|
||||
out << pos;
|
||||
if (auto loc = pos.getCodeLines()) {
|
||||
out << "\n";
|
||||
printCodeLines(out, "", *pos, *loc);
|
||||
printCodeLines(out, "", pos, *loc);
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,16 @@
|
||||
#include "nix_api_util.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef __has_c_attribute
|
||||
# define __has_c_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#if __has_c_attribute(deprecated)
|
||||
# define NIX_DEPRECATED(msg) [[deprecated(msg)]]
|
||||
#else
|
||||
# define NIX_DEPRECATED(msg)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -45,7 +55,7 @@ typedef struct EvalState EvalState; // nix::EvalState
|
||||
* @see nix_value_incref, nix_value_decref
|
||||
*/
|
||||
typedef struct nix_value nix_value;
|
||||
[[deprecated("use nix_value instead")]] typedef nix_value Value;
|
||||
NIX_DEPRECATED("use nix_value instead") typedef nix_value Value;
|
||||
|
||||
// Function prototypes
|
||||
/**
|
||||
|
||||
@@ -619,12 +619,8 @@ nix_realised_string * nix_string_realise(nix_c_context * context, EvalState * st
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_in(value);
|
||||
nix::NixStringContext stringContext;
|
||||
auto rawStr = state->state.coerceToString(nix::noPos, v, stringContext, "while realising a string").toOwned();
|
||||
nix::StorePathSet storePaths;
|
||||
auto rewrites = state->state.realiseContext(stringContext, &storePaths);
|
||||
|
||||
auto s = nix::rewriteStrings(rawStr, rewrites);
|
||||
auto s = state->state.realiseString(v, &storePaths, isIFD);
|
||||
|
||||
// Convert to the C API StorePath type and convert to vector for index-based access
|
||||
std::vector<StorePath> vec;
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
{ lib
|
||||
, stdenv
|
||||
, mkMesonDerivation
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
mkMesonDerivation,
|
||||
|
||||
, meson
|
||||
, ninja
|
||||
, pkg-config
|
||||
meson,
|
||||
ninja,
|
||||
pkg-config,
|
||||
|
||||
, nix-store-c
|
||||
, nix-expr
|
||||
nix-store-c,
|
||||
nix-expr,
|
||||
|
||||
# Configuration Options
|
||||
# Configuration Options
|
||||
|
||||
, version
|
||||
version,
|
||||
}:
|
||||
|
||||
let
|
||||
@@ -35,7 +36,10 @@ mkMesonDerivation (finalAttrs: {
|
||||
(fileset.fileFilter (file: file.hasExt "h") ./.)
|
||||
];
|
||||
|
||||
outputs = [ "out" "dev" ];
|
||||
outputs = [
|
||||
"out"
|
||||
"dev"
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
@@ -59,9 +63,12 @@ mkMesonDerivation (finalAttrs: {
|
||||
mesonFlags = [
|
||||
];
|
||||
|
||||
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
|
||||
LDFLAGS = "-fuse-ld=gold";
|
||||
};
|
||||
env =
|
||||
lib.optionalAttrs
|
||||
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
|
||||
{
|
||||
LDFLAGS = "-fuse-ld=gold";
|
||||
};
|
||||
|
||||
separateDebugInfo = !stdenv.hostPlatform.isStatic;
|
||||
|
||||
|
||||
@@ -17,69 +17,69 @@ let
|
||||
# Resolve a input spec into a node name. An input spec is
|
||||
# either a node name, or a 'follows' path from the root
|
||||
# node.
|
||||
resolveInput = inputSpec:
|
||||
if builtins.isList inputSpec
|
||||
then getInputByPath lockFile.root inputSpec
|
||||
else inputSpec;
|
||||
resolveInput =
|
||||
inputSpec: if builtins.isList inputSpec then getInputByPath lockFile.root inputSpec else inputSpec;
|
||||
|
||||
# Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the
|
||||
# root node, returning the final node.
|
||||
getInputByPath = nodeName: path:
|
||||
if path == []
|
||||
then nodeName
|
||||
getInputByPath =
|
||||
nodeName: path:
|
||||
if path == [ ] then
|
||||
nodeName
|
||||
else
|
||||
getInputByPath
|
||||
# Since this could be a 'follows' input, call resolveInput.
|
||||
(resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path})
|
||||
(builtins.tail path);
|
||||
|
||||
allNodes =
|
||||
builtins.mapAttrs
|
||||
(key: node:
|
||||
let
|
||||
allNodes = builtins.mapAttrs (
|
||||
key: node:
|
||||
let
|
||||
|
||||
sourceInfo =
|
||||
if overrides ? ${key}
|
||||
then
|
||||
overrides.${key}.sourceInfo
|
||||
else
|
||||
# FIXME: remove obsolete node.info.
|
||||
fetchTree (node.info or {} // removeAttrs node.locked ["dir"]);
|
||||
sourceInfo =
|
||||
if overrides ? ${key} then
|
||||
overrides.${key}.sourceInfo
|
||||
else
|
||||
# FIXME: remove obsolete node.info.
|
||||
fetchTree (node.info or { } // removeAttrs node.locked [ "dir" ]);
|
||||
|
||||
subdir = overrides.${key}.dir or node.locked.dir or "";
|
||||
subdir = overrides.${key}.dir or node.locked.dir or "";
|
||||
|
||||
outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir);
|
||||
outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir);
|
||||
|
||||
flake = import (outPath + "/flake.nix");
|
||||
flake = import (outPath + "/flake.nix");
|
||||
|
||||
inputs = builtins.mapAttrs
|
||||
(inputName: inputSpec: allNodes.${resolveInput inputSpec})
|
||||
(node.inputs or {});
|
||||
inputs = builtins.mapAttrs (inputName: inputSpec: allNodes.${resolveInput inputSpec}) (
|
||||
node.inputs or { }
|
||||
);
|
||||
|
||||
outputs = flake.outputs (inputs // { self = result; });
|
||||
outputs = flake.outputs (inputs // { self = result; });
|
||||
|
||||
result =
|
||||
outputs
|
||||
# We add the sourceInfo attribute for its metadata, as they are
|
||||
# relevant metadata for the flake. However, the outPath of the
|
||||
# sourceInfo does not necessarily match the outPath of the flake,
|
||||
# as the flake may be in a subdirectory of a source.
|
||||
# This is shadowed in the next //
|
||||
// sourceInfo
|
||||
// {
|
||||
# This shadows the sourceInfo.outPath
|
||||
inherit outPath;
|
||||
result =
|
||||
outputs
|
||||
# We add the sourceInfo attribute for its metadata, as they are
|
||||
# relevant metadata for the flake. However, the outPath of the
|
||||
# sourceInfo does not necessarily match the outPath of the flake,
|
||||
# as the flake may be in a subdirectory of a source.
|
||||
# This is shadowed in the next //
|
||||
// sourceInfo
|
||||
// {
|
||||
# This shadows the sourceInfo.outPath
|
||||
inherit outPath;
|
||||
|
||||
inherit inputs; inherit outputs; inherit sourceInfo; _type = "flake";
|
||||
};
|
||||
inherit inputs;
|
||||
inherit outputs;
|
||||
inherit sourceInfo;
|
||||
_type = "flake";
|
||||
};
|
||||
|
||||
in
|
||||
if node.flake or true then
|
||||
assert builtins.isFunction flake.outputs;
|
||||
result
|
||||
else
|
||||
sourceInfo
|
||||
)
|
||||
lockFile.nodes;
|
||||
in
|
||||
if node.flake or true then
|
||||
assert builtins.isFunction flake.outputs;
|
||||
result
|
||||
else
|
||||
sourceInfo
|
||||
) lockFile.nodes;
|
||||
|
||||
in allNodes.${lockFile.root}
|
||||
in
|
||||
allNodes.${lockFile.root}
|
||||
|
||||
@@ -45,7 +45,7 @@ EvalErrorBuilder<T> & EvalErrorBuilder<T>::withFrame(const Env & env, const Expr
|
||||
// TODO: check compatibility with nested debugger calls.
|
||||
// TODO: What side-effects??
|
||||
error.state.debugTraces.push_front(DebugTrace{
|
||||
.pos = error.state.positions[expr.getPos()],
|
||||
.pos = expr.getPos(),
|
||||
.expr = expr,
|
||||
.env = env,
|
||||
.hint = HintFmt("Fake frame for debugging purposes"),
|
||||
|
||||
@@ -32,122 +32,6 @@ static void * oomHandler(size_t requested)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
class BoehmGCStackAllocator : public StackAllocator
|
||||
{
|
||||
boost::coroutines2::protected_fixedsize_stack stack{
|
||||
// We allocate 8 MB, the default max stack size on NixOS.
|
||||
// A smaller stack might be quicker to allocate but reduces the stack
|
||||
// depth available for source filter expressions etc.
|
||||
std::max(boost::context::stack_traits::default_size(), static_cast<std::size_t>(8 * 1024 * 1024))};
|
||||
|
||||
// This is specific to boost::coroutines2::protected_fixedsize_stack.
|
||||
// The stack protection page is included in sctx.size, so we have to
|
||||
// subtract one page size from the stack size.
|
||||
std::size_t pfss_usable_stack_size(boost::context::stack_context & sctx)
|
||||
{
|
||||
return sctx.size - boost::context::stack_traits::page_size();
|
||||
}
|
||||
|
||||
public:
|
||||
boost::context::stack_context allocate() override
|
||||
{
|
||||
auto sctx = stack.allocate();
|
||||
|
||||
// Stacks generally start at a high address and grow to lower addresses.
|
||||
// Architectures that do the opposite are rare; in fact so rare that
|
||||
// boost_routine does not implement it.
|
||||
// So we subtract the stack size.
|
||||
GC_add_roots(static_cast<char *>(sctx.sp) - pfss_usable_stack_size(sctx), sctx.sp);
|
||||
return sctx;
|
||||
}
|
||||
|
||||
void deallocate(boost::context::stack_context sctx) override
|
||||
{
|
||||
GC_remove_roots(static_cast<char *>(sctx.sp) - pfss_usable_stack_size(sctx), sctx.sp);
|
||||
stack.deallocate(sctx);
|
||||
}
|
||||
};
|
||||
|
||||
static BoehmGCStackAllocator boehmGCStackAllocator;
|
||||
|
||||
/**
|
||||
* When a thread goes into a coroutine, we lose its original sp until
|
||||
* control flow returns to the thread.
|
||||
* While in the coroutine, the sp points outside the thread stack,
|
||||
* so we can detect this and push the entire thread stack instead,
|
||||
* as an approximation.
|
||||
* The coroutine's stack is covered by `BoehmGCStackAllocator`.
|
||||
* This is not an optimal solution, because the garbage is scanned when a
|
||||
* coroutine is active, for both the coroutine and the original thread stack.
|
||||
* However, the implementation is quite lean, and usually we don't have active
|
||||
* coroutines during evaluation, so this is acceptable.
|
||||
*/
|
||||
void fixupBoehmStackPointer(void ** sp_ptr, void * _pthread_id)
|
||||
{
|
||||
void *& sp = *sp_ptr;
|
||||
auto pthread_id = reinterpret_cast<pthread_t>(_pthread_id);
|
||||
# ifndef __APPLE__
|
||||
pthread_attr_t pattr;
|
||||
# endif
|
||||
size_t osStackSize;
|
||||
// The low address of the stack, which grows down.
|
||||
void * osStackLimit;
|
||||
void * osStackBase;
|
||||
|
||||
# ifdef __APPLE__
|
||||
osStackSize = pthread_get_stacksize_np(pthread_id);
|
||||
osStackLimit = pthread_get_stackaddr_np(pthread_id);
|
||||
# else
|
||||
if (pthread_attr_init(&pattr)) {
|
||||
throw Error("fixupBoehmStackPointer: pthread_attr_init failed");
|
||||
}
|
||||
# ifdef HAVE_PTHREAD_GETATTR_NP
|
||||
if (pthread_getattr_np(pthread_id, &pattr)) {
|
||||
throw Error("fixupBoehmStackPointer: pthread_getattr_np failed");
|
||||
}
|
||||
# elif HAVE_PTHREAD_ATTR_GET_NP
|
||||
if (!pthread_attr_init(&pattr)) {
|
||||
throw Error("fixupBoehmStackPointer: pthread_attr_init failed");
|
||||
}
|
||||
if (!pthread_attr_get_np(pthread_id, &pattr)) {
|
||||
throw Error("fixupBoehmStackPointer: pthread_attr_get_np failed");
|
||||
}
|
||||
# else
|
||||
# error "Need one of `pthread_attr_get_np` or `pthread_getattr_np`"
|
||||
# endif
|
||||
if (pthread_attr_getstack(&pattr, &osStackLimit, &osStackSize)) {
|
||||
throw Error("fixupBoehmStackPointer: pthread_attr_getstack failed");
|
||||
}
|
||||
if (pthread_attr_destroy(&pattr)) {
|
||||
throw Error("fixupBoehmStackPointer: pthread_attr_destroy failed");
|
||||
}
|
||||
# endif
|
||||
osStackBase = (char *) osStackLimit + osStackSize;
|
||||
// NOTE: We assume the stack grows down, as it does on all architectures we support.
|
||||
// Architectures that grow the stack up are rare.
|
||||
if (sp >= osStackBase || sp < osStackLimit) { // sp is outside the os stack
|
||||
sp = osStackLimit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable GC while this object lives. Used by CoroutineContext.
|
||||
*
|
||||
* Boehm keeps a count of GC_disable() and GC_enable() calls,
|
||||
* and only enables GC when the count matches.
|
||||
*/
|
||||
class BoehmDisableGC
|
||||
{
|
||||
public:
|
||||
BoehmDisableGC()
|
||||
{
|
||||
GC_disable();
|
||||
};
|
||||
~BoehmDisableGC()
|
||||
{
|
||||
GC_enable();
|
||||
};
|
||||
};
|
||||
|
||||
static inline void initGCReal()
|
||||
{
|
||||
/* Initialise the Boehm garbage collector. */
|
||||
@@ -168,24 +52,6 @@ static inline void initGCReal()
|
||||
|
||||
GC_set_oom_fn(oomHandler);
|
||||
|
||||
StackAllocator::defaultAllocator = &boehmGCStackAllocator;
|
||||
|
||||
// TODO: Remove __APPLE__ condition.
|
||||
// Comment suggests an implementation that works on darwin and windows
|
||||
// https://github.com/ivmai/bdwgc/issues/362#issuecomment-1936672196
|
||||
# if GC_VERSION_MAJOR >= 8 && GC_VERSION_MINOR >= 2 && GC_VERSION_MICRO >= 4 && !defined(__APPLE__)
|
||||
GC_set_sp_corrector(&fixupBoehmStackPointer);
|
||||
|
||||
if (!GC_get_sp_corrector()) {
|
||||
printTalkative("BoehmGC on this platform does not support sp_corrector; will disable GC inside coroutines");
|
||||
/* Used to disable GC when entering coroutines on macOS */
|
||||
create_coro_gc_hook = []() -> std::shared_ptr<void> { return std::make_shared<BoehmDisableGC>(); };
|
||||
}
|
||||
# else
|
||||
# warning \
|
||||
"BoehmGC version does not support GC while coroutine exists. GC will be disabled inside coroutines. Consider updating bdw-gc to 8.2.4 or later."
|
||||
# endif
|
||||
|
||||
/* Set the initial heap size to something fairly big (25% of
|
||||
physical RAM, up to a maximum of 384 MiB) so that in most cases
|
||||
we don't need to garbage collect at all. (Collection has a
|
||||
|
||||
@@ -57,7 +57,7 @@ Strings EvalSettings::getDefaultNixPath()
|
||||
{
|
||||
Strings res;
|
||||
auto add = [&](const Path & p, const std::string & s = std::string()) {
|
||||
if (pathAccessible(p)) {
|
||||
if (std::filesystem::exists(p)) {
|
||||
if (s.empty()) {
|
||||
res.push_back(p);
|
||||
} else {
|
||||
|
||||
@@ -379,6 +379,16 @@ void EvalState::allowPath(const StorePath & 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)
|
||||
{
|
||||
allowPath(storePath);
|
||||
@@ -428,7 +438,7 @@ void EvalState::checkURI(const std::string & uri)
|
||||
|
||||
/* If the URI is a path, then check it against allowedPaths as
|
||||
well. */
|
||||
if (hasPrefix(uri, "/")) {
|
||||
if (isAbsolute(uri)) {
|
||||
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListSourceAccessor>())
|
||||
rootFS2->checkAccess(CanonPath(uri));
|
||||
return;
|
||||
@@ -746,18 +756,26 @@ void EvalState::runDebugRepl(const Error * error, const Env & env, const Expr &
|
||||
if (!debugRepl || inDebugger)
|
||||
return;
|
||||
|
||||
auto dts =
|
||||
error && expr.getPos()
|
||||
? std::make_unique<DebugTraceStacker>(
|
||||
*this,
|
||||
DebugTrace {
|
||||
.pos = error->info().pos ? error->info().pos : positions[expr.getPos()],
|
||||
auto dts = [&]() -> std::unique_ptr<DebugTraceStacker> {
|
||||
if (error && expr.getPos()) {
|
||||
auto trace = DebugTrace{
|
||||
.pos = [&]() -> std::variant<Pos, PosIdx> {
|
||||
if (error->info().pos) {
|
||||
if (auto * pos = error->info().pos.get())
|
||||
return *pos;
|
||||
return noPos;
|
||||
}
|
||||
return expr.getPos();
|
||||
}(),
|
||||
.expr = expr,
|
||||
.env = env,
|
||||
.hint = error->info().msg,
|
||||
.isError = true
|
||||
})
|
||||
: nullptr;
|
||||
.isError = true};
|
||||
|
||||
return std::make_unique<DebugTraceStacker>(*this, std::move(trace));
|
||||
}
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
if (error)
|
||||
{
|
||||
@@ -802,7 +820,7 @@ static std::unique_ptr<DebugTraceStacker> makeDebugTraceStacker(
|
||||
EvalState & state,
|
||||
Expr & expr,
|
||||
Env & env,
|
||||
std::shared_ptr<Pos> && pos,
|
||||
std::variant<Pos, PosIdx> pos,
|
||||
const Args & ... formatArgs)
|
||||
{
|
||||
return std::make_unique<DebugTraceStacker>(state,
|
||||
@@ -1078,7 +1096,7 @@ void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial)
|
||||
*this,
|
||||
*e,
|
||||
this->baseEnv,
|
||||
e->getPos() ? std::make_shared<Pos>(positions[e->getPos()]) : nullptr,
|
||||
e->getPos(),
|
||||
"while evaluating the file '%1%':", resolvedPath.to_string())
|
||||
: nullptr;
|
||||
|
||||
@@ -1304,9 +1322,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
|
||||
state,
|
||||
*this,
|
||||
env2,
|
||||
getPos()
|
||||
? std::make_shared<Pos>(state.positions[getPos()])
|
||||
: nullptr,
|
||||
getPos(),
|
||||
"while evaluating a '%1%' expression",
|
||||
"let"
|
||||
)
|
||||
@@ -1375,7 +1391,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||
state,
|
||||
*this,
|
||||
env,
|
||||
state.positions[getPos()],
|
||||
getPos(),
|
||||
"while evaluating the attribute '%1%'",
|
||||
showAttrPath(state, env, attrPath))
|
||||
: nullptr;
|
||||
@@ -1593,7 +1609,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||
try {
|
||||
auto dts = debugRepl
|
||||
? makeDebugTraceStacker(
|
||||
*this, *lambda.body, env2, positions[lambda.pos],
|
||||
*this, *lambda.body, env2, lambda.pos,
|
||||
"while calling %s",
|
||||
lambda.name
|
||||
? concatStrings("'", symbols[lambda.name], "'")
|
||||
@@ -1732,9 +1748,7 @@ void ExprCall::eval(EvalState & state, Env & env, Value & v)
|
||||
state,
|
||||
*this,
|
||||
env,
|
||||
getPos()
|
||||
? std::make_shared<Pos>(state.positions[getPos()])
|
||||
: nullptr,
|
||||
getPos(),
|
||||
"while calling a function"
|
||||
)
|
||||
: nullptr;
|
||||
@@ -2112,7 +2126,7 @@ void EvalState::forceValueDeep(Value & v)
|
||||
try {
|
||||
// If the value is a thunk, we're evaling. Otherwise no trace necessary.
|
||||
auto dts = debugRepl && i.value->isThunk()
|
||||
? makeDebugTraceStacker(*this, *i.value->payload.thunk.expr, *i.value->payload.thunk.env, positions[i.pos],
|
||||
? makeDebugTraceStacker(*this, *i.value->payload.thunk.expr, *i.value->payload.thunk.env, i.pos,
|
||||
"while evaluating the attribute '%1%'", symbols[i.name])
|
||||
: nullptr;
|
||||
|
||||
@@ -2390,7 +2404,7 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat
|
||||
: [&]() {
|
||||
auto dstPath = fetchToStore(
|
||||
*store,
|
||||
path.resolveSymlinks(),
|
||||
path.resolveSymlinks(SymlinkResolution::Ancestors),
|
||||
settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy,
|
||||
path.baseName(),
|
||||
ContentAddressMethod::Raw::NixArchive,
|
||||
@@ -3074,8 +3088,11 @@ std::optional<std::string> EvalState::resolveLookupPathPath(const LookupPath::Pa
|
||||
auto i = lookupPathResolved.find(value);
|
||||
if (i != lookupPathResolved.end()) return i->second;
|
||||
|
||||
auto finish = [&](std::string res) {
|
||||
debug("resolved search path element '%s' to '%s'", value, res);
|
||||
auto finish = [&](std::optional<std::string> res) {
|
||||
if (res)
|
||||
debug("resolved search path element '%s' to '%s'", value, *res);
|
||||
else
|
||||
debug("failed to resolve search path element '%s'", value);
|
||||
lookupPathResolved.emplace(value, res);
|
||||
return res;
|
||||
};
|
||||
@@ -3083,7 +3100,9 @@ std::optional<std::string> EvalState::resolveLookupPathPath(const LookupPath::Pa
|
||||
if (EvalSettings::isPseudoUrl(value)) {
|
||||
try {
|
||||
auto accessor = fetchers::downloadTarball(
|
||||
EvalSettings::resolvePseudoUrl(value)).accessor;
|
||||
store,
|
||||
fetchSettings,
|
||||
EvalSettings::resolvePseudoUrl(value));
|
||||
auto storePath = fetchToStore(*store, SourcePath(accessor), FetchMode::Copy);
|
||||
return finish(store->toRealPath(storePath));
|
||||
} catch (Error & e) {
|
||||
@@ -3111,10 +3130,7 @@ std::optional<std::string> EvalState::resolveLookupPathPath(const LookupPath::Pa
|
||||
allowPath(path);
|
||||
if (store->isInStore(path)) {
|
||||
try {
|
||||
StorePathSet closure;
|
||||
store->computeFSClosure(store->toStorePath(path).first, closure);
|
||||
for (auto & p : closure)
|
||||
allowPath(p);
|
||||
allowClosure(store->toStorePath(path).first);
|
||||
} catch (InvalidPath &) { }
|
||||
}
|
||||
}
|
||||
@@ -3128,9 +3144,7 @@ std::optional<std::string> EvalState::resolveLookupPathPath(const LookupPath::Pa
|
||||
}
|
||||
}
|
||||
|
||||
debug("failed to resolve search path element '%s'", value);
|
||||
return std::nullopt;
|
||||
|
||||
return finish(std::nullopt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -155,11 +155,28 @@ struct RegexCache;
|
||||
std::shared_ptr<RegexCache> makeRegexCache();
|
||||
|
||||
struct DebugTrace {
|
||||
std::shared_ptr<Pos> pos;
|
||||
/* WARNING: Converting PosIdx -> Pos should be done with extra care. This is
|
||||
due to the fact that operator[] of PosTable is incredibly expensive. */
|
||||
std::variant<Pos, PosIdx> pos;
|
||||
const Expr & expr;
|
||||
const Env & env;
|
||||
HintFmt hint;
|
||||
bool isError;
|
||||
|
||||
Pos getPos(const PosTable & table) const
|
||||
{
|
||||
return std::visit(
|
||||
overloaded{
|
||||
[&](PosIdx idx) {
|
||||
// Prefer direct pos, but if noPos then try the expr.
|
||||
if (!idx)
|
||||
idx = expr.getPos();
|
||||
return table[idx];
|
||||
},
|
||||
[&](Pos pos) { return pos; },
|
||||
},
|
||||
pos);
|
||||
}
|
||||
};
|
||||
|
||||
class EvalState : public std::enable_shared_from_this<EvalState>
|
||||
@@ -392,6 +409,11 @@ public:
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@@ -781,6 +803,15 @@ public:
|
||||
*/
|
||||
[[nodiscard]] StringMap realiseContext(const NixStringContext & context, StorePathSet * maybePaths = nullptr, bool isIFD = true);
|
||||
|
||||
/**
|
||||
* Realise the given string with context, and return the string with outputs instead of downstream output placeholders.
|
||||
* @param[in] str the string to realise
|
||||
* @param[out] paths all referenced store paths will be added to this set
|
||||
* @return the realised string
|
||||
* @throw EvalError if the value is not a string, path or derivation (see `coerceToString`)
|
||||
*/
|
||||
std::string realiseString(Value & str, StorePathSet * storePathsOutMaybe, bool isIFD = true, const PosIdx pos = noPos);
|
||||
|
||||
/* Call the binary path filter predicate used builtins.path etc. */
|
||||
bool callPathFilter(
|
||||
Value * filterFun,
|
||||
|
||||
@@ -1,40 +1,72 @@
|
||||
{ system ? "" # obsolete
|
||||
, url
|
||||
, hash ? "" # an SRI hash
|
||||
{
|
||||
system ? "", # obsolete
|
||||
url,
|
||||
hash ? "", # an SRI hash
|
||||
|
||||
# Legacy hash specification
|
||||
, md5 ? "", sha1 ? "", sha256 ? "", sha512 ? ""
|
||||
, outputHash ?
|
||||
if hash != "" then hash else if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256
|
||||
, outputHashAlgo ?
|
||||
if hash != "" then "" else if sha512 != "" then "sha512" else if sha1 != "" then "sha1" else if md5 != "" then "md5" else "sha256"
|
||||
# Legacy hash specification
|
||||
md5 ? "",
|
||||
sha1 ? "",
|
||||
sha256 ? "",
|
||||
sha512 ? "",
|
||||
outputHash ?
|
||||
if hash != "" then
|
||||
hash
|
||||
else if sha512 != "" then
|
||||
sha512
|
||||
else if sha1 != "" then
|
||||
sha1
|
||||
else if md5 != "" then
|
||||
md5
|
||||
else
|
||||
sha256,
|
||||
outputHashAlgo ?
|
||||
if hash != "" then
|
||||
""
|
||||
else if sha512 != "" then
|
||||
"sha512"
|
||||
else if sha1 != "" then
|
||||
"sha1"
|
||||
else if md5 != "" then
|
||||
"md5"
|
||||
else
|
||||
"sha256",
|
||||
|
||||
, executable ? false
|
||||
, unpack ? false
|
||||
, name ? baseNameOf (toString url)
|
||||
, impure ? false
|
||||
executable ? false,
|
||||
unpack ? false,
|
||||
name ? baseNameOf (toString url),
|
||||
impure ? false,
|
||||
}:
|
||||
|
||||
derivation ({
|
||||
builder = "builtin:fetchurl";
|
||||
derivation (
|
||||
{
|
||||
builder = "builtin:fetchurl";
|
||||
|
||||
# New-style output content requirements.
|
||||
outputHashMode = if unpack || executable then "recursive" else "flat";
|
||||
# New-style output content requirements.
|
||||
outputHashMode = if unpack || executable then "recursive" else "flat";
|
||||
|
||||
inherit name url executable unpack;
|
||||
inherit
|
||||
name
|
||||
url
|
||||
executable
|
||||
unpack
|
||||
;
|
||||
|
||||
system = "builtin";
|
||||
system = "builtin";
|
||||
|
||||
# No need to double the amount of network traffic
|
||||
preferLocalBuild = true;
|
||||
# No need to double the amount of network traffic
|
||||
preferLocalBuild = true;
|
||||
|
||||
# This attribute does nothing; it's here to avoid changing evaluation results.
|
||||
impureEnvVars = [
|
||||
"http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy"
|
||||
];
|
||||
# This attribute does nothing; it's here to avoid changing evaluation results.
|
||||
impureEnvVars = [
|
||||
"http_proxy"
|
||||
"https_proxy"
|
||||
"ftp_proxy"
|
||||
"all_proxy"
|
||||
"no_proxy"
|
||||
];
|
||||
|
||||
# To make "nix-prefetch-url" work.
|
||||
urls = [ url ];
|
||||
} // (if impure
|
||||
then { __impure = true; }
|
||||
else { inherit outputHashAlgo outputHash; }))
|
||||
# To make "nix-prefetch-url" work.
|
||||
urls = [ url ];
|
||||
}
|
||||
// (if impure then { __impure = true; } else { inherit outputHashAlgo outputHash; })
|
||||
)
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
attrs @ { drvPath, outputs, name, ... }:
|
||||
attrs@{
|
||||
drvPath,
|
||||
outputs,
|
||||
name,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
|
||||
commonAttrs = (builtins.listToAttrs outputsList) //
|
||||
{ all = map (x: x.value) outputsList;
|
||||
inherit drvPath name;
|
||||
type = "derivation";
|
||||
};
|
||||
commonAttrs = (builtins.listToAttrs outputsList) // {
|
||||
all = map (x: x.value) outputsList;
|
||||
inherit drvPath name;
|
||||
type = "derivation";
|
||||
};
|
||||
|
||||
outputToAttrListElement = outputName:
|
||||
{ name = outputName;
|
||||
value = commonAttrs // {
|
||||
outPath = builtins.getAttr outputName attrs;
|
||||
inherit outputName;
|
||||
};
|
||||
outputToAttrListElement = outputName: {
|
||||
name = outputName;
|
||||
value = commonAttrs // {
|
||||
outPath = builtins.getAttr outputName attrs;
|
||||
inherit outputName;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
outputsList = map outputToAttrListElement outputs;
|
||||
|
||||
in (builtins.head outputsList).value
|
||||
|
||||
in
|
||||
(builtins.head outputsList).value
|
||||
|
||||
@@ -62,6 +62,7 @@ toml11 = dependency(
|
||||
method : 'cmake',
|
||||
include_type: 'system',
|
||||
)
|
||||
|
||||
deps_other += toml11
|
||||
|
||||
config_h = configure_file(
|
||||
@@ -175,8 +176,6 @@ headers = [config_h] + files(
|
||||
# internal: 'lexer-helpers.hh',
|
||||
'nixexpr.hh',
|
||||
'parser-state.hh',
|
||||
'pos-idx.hh',
|
||||
'pos-table.hh',
|
||||
'primops.hh',
|
||||
'print-ambiguous.hh',
|
||||
'print-options.hh',
|
||||
|
||||
@@ -601,41 +601,6 @@ void ExprLambda::setDocComment(DocComment docComment) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Position table. */
|
||||
|
||||
Pos PosTable::operator[](PosIdx p) const
|
||||
{
|
||||
auto origin = resolve(p);
|
||||
if (!origin)
|
||||
return {};
|
||||
|
||||
const auto offset = origin->offsetOf(p);
|
||||
|
||||
Pos result{0, 0, origin->origin};
|
||||
auto lines = this->lines.lock();
|
||||
auto linesForInput = (*lines)[origin->offset];
|
||||
|
||||
if (linesForInput.empty()) {
|
||||
auto source = result.getSource().value_or("");
|
||||
const char * begin = source.data();
|
||||
for (Pos::LinesIterator it(source), end; it != end; it++)
|
||||
linesForInput.push_back(it->data() - begin);
|
||||
if (linesForInput.empty())
|
||||
linesForInput.push_back(0);
|
||||
}
|
||||
// as above: the first line starts at byte 0 and is always present
|
||||
auto lineStartOffset = std::prev(
|
||||
std::upper_bound(linesForInput.begin(), linesForInput.end(), offset));
|
||||
|
||||
result.line = 1 + (lineStartOffset - linesForInput.begin());
|
||||
result.column = 1 + (offset - *lineStartOffset);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Symbol table. */
|
||||
|
||||
size_t SymbolTable::totalSize() const
|
||||
|
||||
@@ -1,37 +1,38 @@
|
||||
{ lib
|
||||
, stdenv
|
||||
, mkMesonDerivation
|
||||
, releaseTools
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
mkMesonDerivation,
|
||||
releaseTools,
|
||||
|
||||
, meson
|
||||
, ninja
|
||||
, pkg-config
|
||||
, bison
|
||||
, flex
|
||||
, cmake # for resolving toml11 dep
|
||||
meson,
|
||||
ninja,
|
||||
pkg-config,
|
||||
bison,
|
||||
flex,
|
||||
cmake, # for resolving toml11 dep
|
||||
|
||||
, nix-util
|
||||
, nix-store
|
||||
, nix-fetchers
|
||||
, boost
|
||||
, boehmgc
|
||||
, nlohmann_json
|
||||
, toml11
|
||||
nix-util,
|
||||
nix-store,
|
||||
nix-fetchers,
|
||||
boost,
|
||||
boehmgc,
|
||||
nlohmann_json,
|
||||
toml11,
|
||||
|
||||
# Configuration Options
|
||||
# Configuration Options
|
||||
|
||||
, version
|
||||
version,
|
||||
|
||||
# Whether to use garbage collection for the Nix language evaluator.
|
||||
#
|
||||
# If it is disabled, we just leak memory, but this is not as bad as it
|
||||
# sounds so long as evaluation just takes places within short-lived
|
||||
# processes. (When the process exits, the memory is reclaimed; it is
|
||||
# only leaked *within* the process.)
|
||||
#
|
||||
# Temporarily disabled on Windows because the `GC_throw_bad_alloc`
|
||||
# symbol is missing during linking.
|
||||
, enableGC ? !stdenv.hostPlatform.isWindows
|
||||
# Whether to use garbage collection for the Nix language evaluator.
|
||||
#
|
||||
# If it is disabled, we just leak memory, but this is not as bad as it
|
||||
# sounds so long as evaluation just takes places within short-lived
|
||||
# processes. (When the process exits, the memory is reclaimed; it is
|
||||
# only leaked *within* the process.)
|
||||
#
|
||||
# Temporarily disabled on Windows because the `GC_throw_bad_alloc`
|
||||
# symbol is missing during linking.
|
||||
enableGC ? !stdenv.hostPlatform.isWindows,
|
||||
}:
|
||||
|
||||
let
|
||||
@@ -58,7 +59,10 @@ mkMesonDerivation (finalAttrs: {
|
||||
(fileset.fileFilter (file: file.hasExt "nix") ./.)
|
||||
];
|
||||
|
||||
outputs = [ "out" "dev" ];
|
||||
outputs = [
|
||||
"out"
|
||||
"dev"
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
@@ -93,14 +97,18 @@ mkMesonDerivation (finalAttrs: {
|
||||
(lib.mesonEnable "gc" enableGC)
|
||||
];
|
||||
|
||||
env = {
|
||||
# Needed for Meson to find Boost.
|
||||
# https://github.com/NixOS/nixpkgs/issues/86131.
|
||||
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
|
||||
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
|
||||
} // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
|
||||
LDFLAGS = "-fuse-ld=gold";
|
||||
};
|
||||
env =
|
||||
{
|
||||
# Needed for Meson to find Boost.
|
||||
# https://github.com/NixOS/nixpkgs/issues/86131.
|
||||
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
|
||||
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
|
||||
}
|
||||
// lib.optionalAttrs
|
||||
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
|
||||
{
|
||||
LDFLAGS = "-fuse-ld=gold";
|
||||
};
|
||||
|
||||
separateDebugInfo = !stdenv.hostPlatform.isStatic;
|
||||
|
||||
|
||||
@@ -86,7 +86,8 @@ struct ParserState
|
||||
|
||||
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
|
||||
void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos);
|
||||
void addAttr(ExprAttrs * attrs, AttrPath && attrPath, Expr * e, const PosIdx pos);
|
||||
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 = {});
|
||||
Expr * stripIndentation(const PosIdx pos,
|
||||
std::vector<std::pair<PosIdx, std::variant<Expr *, StringToken>>> && es);
|
||||
@@ -110,75 +111,101 @@ inline void ParserState::dupAttr(Symbol attr, const PosIdx pos, const PosIdx pre
|
||||
});
|
||||
}
|
||||
|
||||
inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, Expr * e, const PosIdx pos)
|
||||
inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, const ParserLocation & loc, Expr * e, const ParserLocation & exprLoc)
|
||||
{
|
||||
AttrPath::iterator i;
|
||||
// All attrpaths have at least one attr
|
||||
assert(!attrPath.empty());
|
||||
auto pos = at(loc);
|
||||
// Checking attrPath validity.
|
||||
// ===========================
|
||||
for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
|
||||
ExprAttrs * nested;
|
||||
if (i->symbol) {
|
||||
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
|
||||
if (j != attrs->attrs.end()) {
|
||||
if (j->second.kind != ExprAttrs::AttrDef::Kind::Inherited) {
|
||||
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e);
|
||||
if (!attrs2) dupAttr(attrPath, pos, j->second.pos);
|
||||
attrs = attrs2;
|
||||
} else
|
||||
nested = dynamic_cast<ExprAttrs *>(j->second.e);
|
||||
if (!nested) {
|
||||
attrPath.erase(i + 1, attrPath.end());
|
||||
dupAttr(attrPath, pos, j->second.pos);
|
||||
}
|
||||
} else {
|
||||
ExprAttrs * nested = new ExprAttrs;
|
||||
nested = new ExprAttrs;
|
||||
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
|
||||
attrs = nested;
|
||||
}
|
||||
} else {
|
||||
ExprAttrs *nested = new ExprAttrs;
|
||||
nested = new ExprAttrs;
|
||||
attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, nested, pos));
|
||||
attrs = nested;
|
||||
}
|
||||
attrs = nested;
|
||||
}
|
||||
// Expr insertion.
|
||||
// ==========================
|
||||
if (i->symbol) {
|
||||
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->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 *>(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);
|
||||
}
|
||||
addAttr(attrs, attrPath, i->symbol, ExprAttrs::AttrDef(e, pos));
|
||||
} else {
|
||||
attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, e, pos));
|
||||
}
|
||||
|
||||
auto it = lexerState.positionToDocComment.find(pos);
|
||||
if (it != lexerState.positionToDocComment.end()) {
|
||||
e->setDocComment(it->second);
|
||||
lexerState.positionToDocComment.emplace(at(exprLoc), it->second);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
||||
@@ -180,22 +180,22 @@ expr_function
|
||||
$$ = me;
|
||||
SET_DOC_POS(me, @1);
|
||||
}
|
||||
| '{' formals '}' ':' expr_function
|
||||
{ auto me = new ExprLambda(CUR_POS, state->validateFormals($2), $5);
|
||||
| '{' formals '}' ':' expr_function[body]
|
||||
{ auto me = new ExprLambda(CUR_POS, state->validateFormals($formals), $body);
|
||||
$$ = me;
|
||||
SET_DOC_POS(me, @1);
|
||||
}
|
||||
| '{' formals '}' '@' ID ':' expr_function
|
||||
| '{' formals '}' '@' ID ':' expr_function[body]
|
||||
{
|
||||
auto arg = state->symbols.create($5);
|
||||
auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($2, CUR_POS, arg), $7);
|
||||
auto arg = state->symbols.create($ID);
|
||||
auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($formals, CUR_POS, arg), $body);
|
||||
$$ = me;
|
||||
SET_DOC_POS(me, @1);
|
||||
}
|
||||
| ID '@' '{' formals '}' ':' expr_function
|
||||
| ID '@' '{' formals '}' ':' expr_function[body]
|
||||
{
|
||||
auto arg = state->symbols.create($1);
|
||||
auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($4, CUR_POS, arg), $7);
|
||||
auto arg = state->symbols.create($ID);
|
||||
auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($formals, CUR_POS, arg), $body);
|
||||
$$ = me;
|
||||
SET_DOC_POS(me, @1);
|
||||
}
|
||||
@@ -364,50 +364,39 @@ ind_string_parts
|
||||
;
|
||||
|
||||
binds
|
||||
: binds attrpath '=' expr ';' {
|
||||
$$ = $1;
|
||||
|
||||
auto pos = state->at(@2);
|
||||
auto exprPos = state->at(@4);
|
||||
{
|
||||
auto it = state->lexerState.positionToDocComment.find(pos);
|
||||
if (it != state->lexerState.positionToDocComment.end()) {
|
||||
$4->setDocComment(it->second);
|
||||
state->lexerState.positionToDocComment.emplace(exprPos, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
state->addAttr($$, std::move(*$2), $4, pos);
|
||||
delete $2;
|
||||
: binds[accum] attrpath '=' expr ';' {
|
||||
$$ = $accum;
|
||||
state->addAttr($$, std::move(*$attrpath), @attrpath, $expr, @expr);
|
||||
delete $attrpath;
|
||||
}
|
||||
| binds INHERIT attrs ';'
|
||||
{ $$ = $1;
|
||||
for (auto & [i, iPos] : *$3) {
|
||||
if ($$->attrs.find(i.symbol) != $$->attrs.end())
|
||||
state->dupAttr(i.symbol, iPos, $$->attrs[i.symbol].pos);
|
||||
$$->attrs.emplace(
|
||||
| binds[accum] INHERIT attrs ';'
|
||||
{ $$ = $accum;
|
||||
for (auto & [i, iPos] : *$attrs) {
|
||||
if ($accum->attrs.find(i.symbol) != $accum->attrs.end())
|
||||
state->dupAttr(i.symbol, iPos, $accum->attrs[i.symbol].pos);
|
||||
$accum->attrs.emplace(
|
||||
i.symbol,
|
||||
ExprAttrs::AttrDef(new ExprVar(iPos, i.symbol), iPos, ExprAttrs::AttrDef::Kind::Inherited));
|
||||
}
|
||||
delete $3;
|
||||
delete $attrs;
|
||||
}
|
||||
| binds INHERIT '(' expr ')' attrs ';'
|
||||
{ $$ = $1;
|
||||
if (!$$->inheritFromExprs)
|
||||
$$->inheritFromExprs = std::make_unique<std::vector<Expr *>>();
|
||||
$$->inheritFromExprs->push_back($4);
|
||||
auto from = new nix::ExprInheritFrom(state->at(@4), $$->inheritFromExprs->size() - 1);
|
||||
for (auto & [i, iPos] : *$6) {
|
||||
if ($$->attrs.find(i.symbol) != $$->attrs.end())
|
||||
state->dupAttr(i.symbol, iPos, $$->attrs[i.symbol].pos);
|
||||
$$->attrs.emplace(
|
||||
| binds[accum] INHERIT '(' expr ')' attrs ';'
|
||||
{ $$ = $accum;
|
||||
if (!$accum->inheritFromExprs)
|
||||
$accum->inheritFromExprs = std::make_unique<std::vector<Expr *>>();
|
||||
$accum->inheritFromExprs->push_back($expr);
|
||||
auto from = new nix::ExprInheritFrom(state->at(@expr), $accum->inheritFromExprs->size() - 1);
|
||||
for (auto & [i, iPos] : *$attrs) {
|
||||
if ($accum->attrs.find(i.symbol) != $accum->attrs.end())
|
||||
state->dupAttr(i.symbol, iPos, $accum->attrs[i.symbol].pos);
|
||||
$accum->attrs.emplace(
|
||||
i.symbol,
|
||||
ExprAttrs::AttrDef(
|
||||
new ExprSelect(iPos, from, i.symbol),
|
||||
iPos,
|
||||
ExprAttrs::AttrDef::Kind::InheritedFrom));
|
||||
}
|
||||
delete $6;
|
||||
delete $attrs;
|
||||
}
|
||||
| { $$ = new ExprAttrs(state->at(@0)); }
|
||||
;
|
||||
@@ -468,10 +457,10 @@ expr_list
|
||||
;
|
||||
|
||||
formals
|
||||
: formal ',' formals
|
||||
{ $$ = $3; $$->formals.emplace_back(*$1); delete $1; }
|
||||
: formal ',' formals[accum]
|
||||
{ $$ = $accum; $$->formals.emplace_back(*$formal); delete $formal; }
|
||||
| formal
|
||||
{ $$ = new Formals; $$->formals.emplace_back(*$1); $$->ellipsis = false; delete $1; }
|
||||
{ $$ = new Formals; $$->formals.emplace_back(*$formal); $$->ellipsis = false; delete $formal; }
|
||||
|
|
||||
{ $$ = new Formals; $$->ellipsis = false; }
|
||||
| ELLIPSIS
|
||||
|
||||
@@ -40,6 +40,15 @@ namespace nix {
|
||||
* Miscellaneous
|
||||
*************************************************************/
|
||||
|
||||
std::string EvalState::realiseString(Value & s, StorePathSet * storePathsOutMaybe, bool isIFD, const PosIdx pos)
|
||||
{
|
||||
nix::NixStringContext stringContext;
|
||||
auto rawStr = coerceToString(pos, s, stringContext, "while realising a string").toOwned();
|
||||
auto rewrites = realiseContext(stringContext, storePathsOutMaybe, isIFD);
|
||||
|
||||
return nix::rewriteStrings(rawStr, rewrites);
|
||||
}
|
||||
|
||||
StringMap EvalState::realiseContext(const NixStringContext & context, StorePathSet * maybePathsOut, bool isIFD)
|
||||
{
|
||||
std::vector<DerivedPath::Built> drvs;
|
||||
@@ -113,11 +122,9 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS
|
||||
if (store != buildStore) copyClosure(*buildStore, *store, outputsToCopyAndAllow);
|
||||
|
||||
if (isIFD) {
|
||||
for (auto & outputPath : outputsToCopyAndAllow) {
|
||||
/* Add the output of this derivations to the allowed
|
||||
paths. */
|
||||
allowPath(outputPath);
|
||||
}
|
||||
/* Allow access to the output closures of this derivation. */
|
||||
for (auto & outputPath : outputsToCopyAndAllow)
|
||||
allowClosure(outputPath);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -941,6 +948,9 @@ static RegisterPrimOp primop_tryEval({
|
||||
`let e = { x = throw ""; }; in
|
||||
(builtins.tryEval (builtins.deepSeq e e)).success` will be
|
||||
`false`.
|
||||
|
||||
`tryEval` intentionally does not return the error message, because that risks bringing non-determinism into the evaluation result, and it would become very difficult to improve error reporting without breaking existing expressions.
|
||||
Instead, use [`builtins.addErrorContext`](@docroot@/language/builtins.md#builtins-addErrorContext) to add context to the error message, and use a Nix unit testing tool for testing.
|
||||
)",
|
||||
.fun = prim_tryEval,
|
||||
});
|
||||
@@ -3136,7 +3146,11 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg
|
||||
std::optional<ListBuilder> list;
|
||||
};
|
||||
|
||||
#if HAVE_BOEHMGC
|
||||
std::map<Symbol, Item, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, Item>>> attrsSeen;
|
||||
#else
|
||||
std::map<Symbol, Item> attrsSeen;
|
||||
#endif
|
||||
|
||||
state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.zipAttrsWith");
|
||||
state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.zipAttrsWith");
|
||||
@@ -3993,7 +4007,7 @@ static RegisterPrimOp primop_toString({
|
||||
});
|
||||
|
||||
/* `substring start len str' returns the substring of `str' starting
|
||||
at character position `min(start, stringLength str)' inclusive and
|
||||
at byte position `min(start, stringLength str)' inclusive and
|
||||
ending at `min(start + len, stringLength str)'. `start' must be
|
||||
non-negative. */
|
||||
static void prim_substring(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||
@@ -4026,7 +4040,7 @@ static RegisterPrimOp primop_substring({
|
||||
.name = "__substring",
|
||||
.args = {"start", "len", "s"},
|
||||
.doc = R"(
|
||||
Return the substring of *s* from character position *start*
|
||||
Return the substring of *s* from byte position *start*
|
||||
(zero-based) up to but not including *start + len*. If *start* is
|
||||
greater than the length of the string, an empty string is returned.
|
||||
If *start + len* lies beyond the end of the string or *len* is `-1`,
|
||||
|
||||
@@ -86,7 +86,7 @@ static RegisterPrimOp primop_unsafeDiscardOutputDependency({
|
||||
|
||||
This is the opposite of [`builtins.addDrvOutputDependencies`](#builtins-addDrvOutputDependencies).
|
||||
|
||||
This is unsafe because it allows us to "forget" store objects we would have otherwise refered to with the string context,
|
||||
This is unsafe because it allows us to "forget" store objects we would have otherwise referred to with the string context,
|
||||
whereas Nix normally tracks all dependencies consistently.
|
||||
Safe operations "grow" but never "shrink" string contexts.
|
||||
[`builtins.addDrvOutputDependencies`] in contrast is safe because "derivation deep" string context element always refers to the underlying derivation (among many more things).
|
||||
|
||||
@@ -26,27 +26,34 @@
|
||||
Note that `derivation` is very bare-bones, and provides almost no commands during the build.
|
||||
Most likely, you'll want to use functions like `stdenv.mkDerivation` in Nixpkgs to set up a basic environment.
|
||||
*/
|
||||
drvAttrs @ { outputs ? [ "out" ], ... }:
|
||||
drvAttrs@{
|
||||
outputs ? [ "out" ],
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
|
||||
strict = derivationStrict drvAttrs;
|
||||
|
||||
commonAttrs = drvAttrs // (builtins.listToAttrs outputsList) //
|
||||
{ all = map (x: x.value) outputsList;
|
||||
commonAttrs =
|
||||
drvAttrs
|
||||
// (builtins.listToAttrs outputsList)
|
||||
// {
|
||||
all = map (x: x.value) outputsList;
|
||||
inherit drvAttrs;
|
||||
};
|
||||
|
||||
outputToAttrListElement = outputName:
|
||||
{ name = outputName;
|
||||
value = commonAttrs // {
|
||||
outPath = builtins.getAttr outputName strict;
|
||||
drvPath = strict.drvPath;
|
||||
type = "derivation";
|
||||
inherit outputName;
|
||||
};
|
||||
outputToAttrListElement = outputName: {
|
||||
name = outputName;
|
||||
value = commonAttrs // {
|
||||
outPath = builtins.getAttr outputName strict;
|
||||
drvPath = strict.drvPath;
|
||||
type = "derivation";
|
||||
inherit outputName;
|
||||
};
|
||||
};
|
||||
|
||||
outputsList = map outputToAttrListElement outputs;
|
||||
|
||||
in (builtins.head outputsList).value
|
||||
in
|
||||
(builtins.head outputsList).value
|
||||
|
||||
@@ -240,7 +240,7 @@ static RegisterPrimOp primop_fetchTree({
|
||||
The following source types and associated input attributes are supported.
|
||||
|
||||
<!-- TODO: It would be soooo much more predictable to work with (and
|
||||
document) if `fetchTree` was a curried call with the first paramter for
|
||||
document) if `fetchTree` was a curried call with the first parameter for
|
||||
`type` or an attribute like `builtins.fetchTree.git`! -->
|
||||
|
||||
- `"file"`
|
||||
@@ -501,7 +501,11 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
|
||||
// https://github.com/NixOS/nix/issues/4313
|
||||
auto storePath =
|
||||
unpack
|
||||
? fetchToStore(*state.store, fetchers::downloadTarball(*url).accessor, FetchMode::Copy, name)
|
||||
? fetchToStore(
|
||||
*state.store,
|
||||
fetchers::downloadTarball(state.store, state.fetchSettings, *url),
|
||||
FetchMode::Copy,
|
||||
name)
|
||||
: fetchers::downloadFile(state.store, *url, name).storePath;
|
||||
|
||||
if (expectedHash) {
|
||||
|
||||
@@ -7,7 +7,84 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, Value & val)
|
||||
#ifdef HAVE_TOML11_4
|
||||
|
||||
/**
|
||||
* This is what toml11 < 4.0 did when choosing the subsecond precision.
|
||||
* TOML 1.0.0 spec doesn't define how sub-millisecond ranges should be handled and calls it
|
||||
* implementation defined behavior. For a lack of a better choice we stick with what older versions
|
||||
* of toml11 did [1].
|
||||
*
|
||||
* [1]: https://github.com/ToruNiina/toml11/blob/dcfe39a783a94e8d52c885e5883a6fbb21529019/toml/datetime.hpp#L282
|
||||
*/
|
||||
static size_t normalizeSubsecondPrecision(toml::local_time lt)
|
||||
{
|
||||
auto millis = lt.millisecond;
|
||||
auto micros = lt.microsecond;
|
||||
auto nanos = lt.nanosecond;
|
||||
if (millis != 0 || micros != 0 || nanos != 0) {
|
||||
if (micros != 0 || nanos != 0) {
|
||||
if (nanos != 0)
|
||||
return 9;
|
||||
return 6;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize date/time formats to serialize to the same strings as versions prior to toml11 4.0.
|
||||
*
|
||||
* Several things to consider:
|
||||
*
|
||||
* 1. Sub-millisecond range is represented the same way as in toml11 versions prior to 4.0. Precisioun is rounded
|
||||
* towards the next multiple of 3 or capped at 9 digits.
|
||||
* 2. Seconds must be specified. This may become optional in (yet unreleased) TOML 1.1.0, but 1.0.0 defined local time
|
||||
* in terms of RFC3339 [1].
|
||||
* 3. date-time separator (`t`, `T` or space ` `) is canonicalized to an upper T. This is compliant with RFC3339
|
||||
* [1] 5.6:
|
||||
* > Applications that generate this format SHOULD use upper case letters.
|
||||
*
|
||||
* [1]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6
|
||||
*/
|
||||
static void normalizeDatetimeFormat(toml::value & t)
|
||||
{
|
||||
if (t.is_local_datetime()) {
|
||||
auto & ldt = t.as_local_datetime();
|
||||
t.as_local_datetime_fmt() = {
|
||||
.delimiter = toml::datetime_delimiter_kind::upper_T,
|
||||
// https://datatracker.ietf.org/doc/html/rfc3339#section-5.6
|
||||
.has_seconds = true, // Mandated by TOML 1.0.0
|
||||
.subsecond_precision = normalizeSubsecondPrecision(ldt.time),
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.is_offset_datetime()) {
|
||||
auto & odt = t.as_offset_datetime();
|
||||
t.as_offset_datetime_fmt() = {
|
||||
.delimiter = toml::datetime_delimiter_kind::upper_T,
|
||||
// https://datatracker.ietf.org/doc/html/rfc3339#section-5.6
|
||||
.has_seconds = true, // Mandated by TOML 1.0.0
|
||||
.subsecond_precision = normalizeSubsecondPrecision(odt.time),
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.is_local_time()) {
|
||||
auto & lt = t.as_local_time();
|
||||
t.as_local_time_fmt() = {
|
||||
.has_seconds = true, // Mandated by TOML 1.0.0
|
||||
.subsecond_precision = normalizeSubsecondPrecision(lt),
|
||||
};
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Value & val)
|
||||
{
|
||||
auto toml = state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.fromTOML");
|
||||
|
||||
@@ -16,81 +93,87 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V
|
||||
std::function<void(Value &, toml::value)> visit;
|
||||
|
||||
visit = [&](Value & v, toml::value t) {
|
||||
switch (t.type()) {
|
||||
case toml::value_t::table: {
|
||||
auto table = toml::get<toml::table>(t);
|
||||
|
||||
switch(t.type())
|
||||
{
|
||||
case toml::value_t::table:
|
||||
{
|
||||
auto table = toml::get<toml::table>(t);
|
||||
size_t size = 0;
|
||||
for (auto & i : table) {
|
||||
(void) i;
|
||||
size++;
|
||||
}
|
||||
|
||||
size_t size = 0;
|
||||
for (auto & i : table) { (void) i; size++; }
|
||||
auto attrs = state.buildBindings(size);
|
||||
|
||||
auto attrs = state.buildBindings(size);
|
||||
for (auto & elem : table)
|
||||
visit(attrs.alloc(elem.first), elem.second);
|
||||
|
||||
for(auto & elem : table)
|
||||
visit(attrs.alloc(elem.first), elem.second);
|
||||
|
||||
v.mkAttrs(attrs);
|
||||
}
|
||||
break;;
|
||||
case toml::value_t::array:
|
||||
{
|
||||
auto array = toml::get<std::vector<toml::value>>(t);
|
||||
|
||||
auto list = state.buildList(array.size());
|
||||
for (const auto & [n, v] : enumerate(list))
|
||||
visit(*(v = state.allocValue()), array[n]);
|
||||
v.mkList(list);
|
||||
}
|
||||
break;;
|
||||
case toml::value_t::boolean:
|
||||
v.mkBool(toml::get<bool>(t));
|
||||
break;;
|
||||
case toml::value_t::integer:
|
||||
v.mkInt(toml::get<int64_t>(t));
|
||||
break;;
|
||||
case toml::value_t::floating:
|
||||
v.mkFloat(toml::get<NixFloat>(t));
|
||||
break;;
|
||||
case toml::value_t::string:
|
||||
v.mkString(toml::get<std::string>(t));
|
||||
break;;
|
||||
case toml::value_t::local_datetime:
|
||||
case toml::value_t::offset_datetime:
|
||||
case toml::value_t::local_date:
|
||||
case toml::value_t::local_time:
|
||||
{
|
||||
if (experimentalFeatureSettings.isEnabled(Xp::ParseTomlTimestamps)) {
|
||||
auto attrs = state.buildBindings(2);
|
||||
attrs.alloc("_type").mkString("timestamp");
|
||||
std::ostringstream s;
|
||||
s << t;
|
||||
attrs.alloc("value").mkString(s.str());
|
||||
v.mkAttrs(attrs);
|
||||
} else {
|
||||
throw std::runtime_error("Dates and times are not supported");
|
||||
}
|
||||
}
|
||||
break;;
|
||||
case toml::value_t::empty:
|
||||
v.mkNull();
|
||||
break;;
|
||||
v.mkAttrs(attrs);
|
||||
} break;
|
||||
case toml::value_t::array: {
|
||||
auto array = toml::get<std::vector<toml::value>>(t);
|
||||
|
||||
auto list = state.buildList(array.size());
|
||||
for (const auto & [n, v] : enumerate(list))
|
||||
visit(*(v = state.allocValue()), array[n]);
|
||||
v.mkList(list);
|
||||
} break;
|
||||
case toml::value_t::boolean:
|
||||
v.mkBool(toml::get<bool>(t));
|
||||
break;
|
||||
case toml::value_t::integer:
|
||||
v.mkInt(toml::get<int64_t>(t));
|
||||
break;
|
||||
case toml::value_t::floating:
|
||||
v.mkFloat(toml::get<NixFloat>(t));
|
||||
break;
|
||||
case toml::value_t::string:
|
||||
v.mkString(toml::get<std::string>(t));
|
||||
break;
|
||||
case toml::value_t::local_datetime:
|
||||
case toml::value_t::offset_datetime:
|
||||
case toml::value_t::local_date:
|
||||
case toml::value_t::local_time: {
|
||||
if (experimentalFeatureSettings.isEnabled(Xp::ParseTomlTimestamps)) {
|
||||
#if HAVE_TOML11_4
|
||||
normalizeDatetimeFormat(t);
|
||||
#endif
|
||||
auto attrs = state.buildBindings(2);
|
||||
attrs.alloc("_type").mkString("timestamp");
|
||||
std::ostringstream s;
|
||||
s << t;
|
||||
attrs.alloc("value").mkString(s.str());
|
||||
v.mkAttrs(attrs);
|
||||
} else {
|
||||
throw std::runtime_error("Dates and times are not supported");
|
||||
}
|
||||
} break;
|
||||
case toml::value_t::empty:
|
||||
v.mkNull();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
visit(val, toml::parse(tomlStream, "fromTOML" /* the "filename" */));
|
||||
visit(
|
||||
val,
|
||||
toml::parse(
|
||||
tomlStream,
|
||||
"fromTOML" /* the "filename" */
|
||||
#if HAVE_TOML11_4
|
||||
,
|
||||
toml::spec::v(1, 0, 0) // Be explicit that we are parsing TOML 1.0.0 without extensions
|
||||
#endif
|
||||
));
|
||||
} catch (std::exception & e) { // TODO: toml::syntax_error
|
||||
state.error<EvalError>("while parsing TOML: %s", e.what()).atPos(pos).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
static RegisterPrimOp primop_fromTOML({
|
||||
.name = "fromTOML",
|
||||
.args = {"e"},
|
||||
.doc = R"(
|
||||
static RegisterPrimOp primop_fromTOML(
|
||||
{.name = "fromTOML",
|
||||
.args = {"e"},
|
||||
.doc = R"(
|
||||
Convert a TOML string to a Nix value. For example,
|
||||
|
||||
```nix
|
||||
@@ -104,7 +187,6 @@ static RegisterPrimOp primop_fromTOML({
|
||||
|
||||
returns the value `{ s = "a"; table = { y = 2; }; x = 1; }`.
|
||||
)",
|
||||
.fun = prim_fromTOML
|
||||
});
|
||||
.fun = prim_fromTOML});
|
||||
|
||||
}
|
||||
|
||||
@@ -108,7 +108,11 @@ json printValueAsJSON(EvalState & state, bool strict,
|
||||
void printValueAsJSON(EvalState & state, bool strict,
|
||||
Value & v, const PosIdx pos, std::ostream & str, NixStringContext & context, bool copyToStore)
|
||||
{
|
||||
str << printValueAsJSON(state, strict, v, pos, context, copyToStore);
|
||||
try {
|
||||
str << printValueAsJSON(state, strict, v, pos, context, copyToStore);
|
||||
} catch (nlohmann::json::exception & e) {
|
||||
throw JSONSerializationError("JSON serialization error: %s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
json ExternalValueBase::printValueAsJSON(EvalState & state, bool strict,
|
||||
|
||||
@@ -16,4 +16,7 @@ nlohmann::json printValueAsJSON(EvalState & state, bool strict,
|
||||
void printValueAsJSON(EvalState & state, bool strict,
|
||||
Value & v, const PosIdx pos, std::ostream & str, NixStringContext & context, bool copyToStore = true);
|
||||
|
||||
|
||||
MakeError(JSONSerializationError, Error);
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ struct CacheImpl : Cache
|
||||
{
|
||||
auto state(_state.lock());
|
||||
|
||||
auto dbPath = getCacheDir() + "/nix/fetcher-cache-v2.sqlite";
|
||||
auto dbPath = getCacheDir() + "/nix/fetcher-cache-v3.sqlite";
|
||||
createDirs(dirOf(dbPath));
|
||||
|
||||
state->db = SQLite(dbPath);
|
||||
|
||||
@@ -4,6 +4,21 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
fetchers::Cache::Key makeFetchToStoreCacheKey(
|
||||
const std::string &name,
|
||||
const std::string &fingerprint,
|
||||
ContentAddressMethod method,
|
||||
const std::string &path)
|
||||
{
|
||||
return fetchers::Cache::Key{"fetchToStore", {
|
||||
{"name", name},
|
||||
{"fingerprint", fingerprint},
|
||||
{"method", std::string{method.render()}},
|
||||
{"path", path}
|
||||
}};
|
||||
|
||||
}
|
||||
|
||||
StorePath fetchToStore(
|
||||
Store & store,
|
||||
const SourcePath & path,
|
||||
@@ -19,12 +34,7 @@ StorePath fetchToStore(
|
||||
std::optional<fetchers::Cache::Key> cacheKey;
|
||||
|
||||
if (!filter && path.accessor->fingerprint) {
|
||||
cacheKey = fetchers::Cache::Key{"fetchToStore", {
|
||||
{"name", std::string{name}},
|
||||
{"fingerprint", *path.accessor->fingerprint},
|
||||
{"method", std::string{method.render()}},
|
||||
{"path", path.path.abs()}
|
||||
}};
|
||||
cacheKey = makeFetchToStoreCacheKey(std::string{name}, *path.accessor->fingerprint, method, path.path.abs());
|
||||
if (auto res = fetchers::getCache()->lookupStorePath(*cacheKey, store)) {
|
||||
debug("store path cache hit for '%s'", path);
|
||||
return res->storePath;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "file-system.hh"
|
||||
#include "repair-flag.hh"
|
||||
#include "file-content-address.hh"
|
||||
#include "cache.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
@@ -22,4 +23,7 @@ StorePath fetchToStore(
|
||||
PathFilter * filter = nullptr,
|
||||
RepairFlag repair = NoRepair);
|
||||
|
||||
fetchers::Cache::Key makeFetchToStoreCacheKey(
|
||||
const std::string & name, const std::string & fingerprint, ContentAddressMethod method, const std::string & path);
|
||||
|
||||
}
|
||||
|
||||
@@ -159,6 +159,32 @@ static Object peelToTreeOrBlob(git_object * obj)
|
||||
return peelObject<Object>(obj, GIT_OBJECT_TREE);
|
||||
}
|
||||
|
||||
static void initRepoAtomically(std::filesystem::path &path, bool bare)
|
||||
{
|
||||
if (pathExists(path.string())) return;
|
||||
|
||||
Path tmpDir = createTempDir(std::filesystem::path(path).parent_path());
|
||||
AutoDelete delTmpDir(tmpDir, true);
|
||||
Repository tmpRepo;
|
||||
|
||||
if (git_repository_init(Setter(tmpRepo), tmpDir.c_str(), bare))
|
||||
throw Error("creating Git repository %s: %s", path, git_error_last()->message);
|
||||
try {
|
||||
std::filesystem::rename(tmpDir, path);
|
||||
} catch (std::filesystem::filesystem_error & e) {
|
||||
// Someone may race us to create the repository.
|
||||
if (e.code() == std::errc::file_exists
|
||||
// `path` may be attempted to be deleted by s::f::rename, in which case the code is:
|
||||
|| e.code() == std::errc::directory_not_empty) {
|
||||
return;
|
||||
}
|
||||
else
|
||||
throw SysError("moving temporary git repository from %s to %s", tmpDir, path);
|
||||
}
|
||||
// we successfully moved the repository, so the temporary directory no longer exists.
|
||||
delTmpDir.cancel();
|
||||
}
|
||||
|
||||
struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
||||
{
|
||||
/** Location of the repository on disk. */
|
||||
@@ -170,13 +196,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
||||
{
|
||||
initLibGit2();
|
||||
|
||||
if (pathExists(path.string())) {
|
||||
if (git_repository_open(Setter(repo), path.string().c_str()))
|
||||
throw Error("opening Git repository '%s': %s", path, git_error_last()->message);
|
||||
} else {
|
||||
if (git_repository_init(Setter(repo), path.string().c_str(), bare))
|
||||
throw Error("creating Git repository '%s': %s", path, git_error_last()->message);
|
||||
}
|
||||
initRepoAtomically(path, bare);
|
||||
if (git_repository_open(Setter(repo), path.string().c_str()))
|
||||
throw Error("opening Git repository '%s': %s", path, git_error_last()->message);
|
||||
|
||||
}
|
||||
|
||||
operator git_repository * ()
|
||||
@@ -394,13 +417,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
||||
// then use code that was removed in this commit (see blame)
|
||||
|
||||
auto dir = this->path;
|
||||
Strings gitArgs;
|
||||
if (shallow) {
|
||||
gitArgs = { "-C", dir.string(), "fetch", "--quiet", "--force", "--depth", "1", "--", url, refspec };
|
||||
}
|
||||
else {
|
||||
gitArgs = { "-C", dir.string(), "fetch", "--quiet", "--force", "--", url, refspec };
|
||||
}
|
||||
Strings gitArgs{"-C", dir.string(), "--git-dir", ".", "fetch", "--quiet", "--force"};
|
||||
if (shallow)
|
||||
append(gitArgs, {"--depth", "1"});
|
||||
append(gitArgs, {std::string("--"), url, refspec});
|
||||
|
||||
runProgram(RunOptions {
|
||||
.program = "git",
|
||||
@@ -460,7 +480,13 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
||||
std::string re = R"(Good "git" signature for \* with .* key SHA256:[)";
|
||||
for (const fetchers::PublicKey & k : publicKeys){
|
||||
// Calculate sha256 fingerprint from public key and escape the regex symbol '+' to match the key literally
|
||||
auto fingerprint = trim(hashString(HashAlgorithm::SHA256, base64Decode(k.key)).to_string(nix::HashFormat::Base64, false), "=");
|
||||
std::string keyDecoded;
|
||||
try {
|
||||
keyDecoded = base64Decode(k.key);
|
||||
} catch (Error & e) {
|
||||
e.addTrace({}, "while decoding public key '%s' used for git signature", k.key);
|
||||
}
|
||||
auto fingerprint = trim(hashString(HashAlgorithm::SHA256, keyDecoded).to_string(nix::HashFormat::Base64, false), "=");
|
||||
auto escaped_fingerprint = std::regex_replace(fingerprint, std::regex("\\+"), "\\+" );
|
||||
re += "(" + escaped_fingerprint + ")";
|
||||
}
|
||||
@@ -601,12 +627,16 @@ struct GitSourceAccessor : SourceAccessor
|
||||
return readBlob(path, true);
|
||||
}
|
||||
|
||||
Hash getSubmoduleRev(const CanonPath & path)
|
||||
/**
|
||||
* If `path` exists and is a submodule, return its
|
||||
* revision. Otherwise return nothing.
|
||||
*/
|
||||
std::optional<Hash> getSubmoduleRev(const CanonPath & path)
|
||||
{
|
||||
auto entry = need(path);
|
||||
auto entry = lookup(path);
|
||||
|
||||
if (git_tree_entry_type(entry) != GIT_OBJECT_COMMIT)
|
||||
throw Error("'%s' is not a submodule", showPath(path));
|
||||
if (!entry || git_tree_entry_type(entry) != GIT_OBJECT_COMMIT)
|
||||
return std::nullopt;
|
||||
|
||||
return toHash(*git_tree_entry_id(entry));
|
||||
}
|
||||
@@ -827,8 +857,24 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
||||
|
||||
void pushBuilder(std::string name)
|
||||
{
|
||||
const git_tree_entry * entry;
|
||||
Tree prevTree = nullptr;
|
||||
|
||||
if (!pendingDirs.empty() &&
|
||||
(entry = git_treebuilder_get(pendingDirs.back().builder.get(), name.c_str())))
|
||||
{
|
||||
/* Clone a tree that we've already finished. This happens
|
||||
if a tarball has directory entries that are not
|
||||
contiguous. */
|
||||
if (git_tree_entry_type(entry) != GIT_OBJECT_TREE)
|
||||
throw Error("parent of '%s' is not a directory", name);
|
||||
|
||||
if (git_tree_entry_to_object((git_object * *) (git_tree * *) Setter(prevTree), *repo, entry))
|
||||
throw Error("looking up parent of '%s': %s", name, git_error_last()->message);
|
||||
}
|
||||
|
||||
git_treebuilder * b;
|
||||
if (git_treebuilder_new(&b, *repo, nullptr))
|
||||
if (git_treebuilder_new(&b, *repo, prevTree.get()))
|
||||
throw Error("creating a tree builder: %s", git_error_last()->message);
|
||||
pendingDirs.push_back({ .name = std::move(name), .builder = TreeBuilder(b) });
|
||||
};
|
||||
@@ -1074,8 +1120,10 @@ std::vector<std::tuple<GitRepoImpl::Submodule, Hash>> GitRepoImpl::getSubmodules
|
||||
auto rawAccessor = getRawAccessor(rev);
|
||||
|
||||
for (auto & submodule : parseSubmodules(pathTemp)) {
|
||||
auto rev = rawAccessor->getSubmoduleRev(submodule.path);
|
||||
result.push_back({std::move(submodule), rev});
|
||||
/* Filter out .gitmodules entries that don't exist or are not
|
||||
submodules. */
|
||||
if (auto rev = rawAccessor->getSubmoduleRev(submodule.path))
|
||||
result.push_back({std::move(submodule), *rev});
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -425,7 +425,26 @@ struct GitInputScheme : InputScheme
|
||||
auto url = parseURL(getStrAttr(input.attrs, "url"));
|
||||
bool isBareRepository = url.scheme == "file" && !pathExists(url.path + "/.git");
|
||||
repoInfo.isLocal = url.scheme == "file" && !forceHttp && !isBareRepository;
|
||||
repoInfo.url = repoInfo.isLocal ? url.path : url.base;
|
||||
//
|
||||
// FIXME: here we turn a possibly relative path into an absolute path.
|
||||
// This allows relative git flake inputs to be resolved against the
|
||||
// **current working directory** (as in POSIX), which tends to work out
|
||||
// ok in the context of flakes, but is the wrong behavior,
|
||||
// as it should resolve against the flake.nix base directory instead.
|
||||
//
|
||||
// See: https://discourse.nixos.org/t/57783 and #9708
|
||||
//
|
||||
if (repoInfo.isLocal) {
|
||||
if (!isAbsolute(url.path)) {
|
||||
warn(
|
||||
"Fetching Git repository '%s', which uses a path relative to the current directory. "
|
||||
"This is not supported and will stop working in a future release. "
|
||||
"See https://github.com/NixOS/nix/issues/12281 for details.",
|
||||
url.to_string());
|
||||
}
|
||||
repoInfo.url = std::filesystem::absolute(url.path).string();
|
||||
} else
|
||||
repoInfo.url = url.to_string();
|
||||
|
||||
// If this is a local directory and no ref or revision is
|
||||
// given, then allow the use of an unclean working tree.
|
||||
@@ -584,9 +603,10 @@ struct GitInputScheme : InputScheme
|
||||
}
|
||||
|
||||
try {
|
||||
setWriteTime(localRefFile, now, now);
|
||||
if (!input.getRev())
|
||||
setWriteTime(localRefFile, now, now);
|
||||
} catch (Error & e) {
|
||||
warn("could not update mtime for file '%s': %s", localRefFile, e.msg());
|
||||
warn("could not update mtime for file '%s': %s", localRefFile, e.info().msg);
|
||||
}
|
||||
if (!originalRef && !storeCachedHead(repoInfo.url, ref))
|
||||
warn("could not update cached head '%s' for '%s'", ref, repoInfo.url);
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
{ lib
|
||||
, stdenv
|
||||
, mkMesonDerivation
|
||||
, releaseTools
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
mkMesonDerivation,
|
||||
releaseTools,
|
||||
|
||||
, meson
|
||||
, ninja
|
||||
, pkg-config
|
||||
meson,
|
||||
ninja,
|
||||
pkg-config,
|
||||
|
||||
, nix-util
|
||||
, nix-store
|
||||
, nlohmann_json
|
||||
, libgit2
|
||||
, man
|
||||
nix-util,
|
||||
nix-store,
|
||||
nlohmann_json,
|
||||
libgit2,
|
||||
man,
|
||||
|
||||
# Configuration Options
|
||||
# Configuration Options
|
||||
|
||||
, version
|
||||
version,
|
||||
}:
|
||||
|
||||
let
|
||||
@@ -37,7 +38,10 @@ mkMesonDerivation (finalAttrs: {
|
||||
(fileset.fileFilter (file: file.hasExt "hh") ./.)
|
||||
];
|
||||
|
||||
outputs = [ "out" "dev" ];
|
||||
outputs = [
|
||||
"out"
|
||||
"dev"
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
@@ -63,9 +67,12 @@ mkMesonDerivation (finalAttrs: {
|
||||
echo ${version} > ../../.version
|
||||
'';
|
||||
|
||||
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
|
||||
LDFLAGS = "-fuse-ld=gold";
|
||||
};
|
||||
env =
|
||||
lib.optionalAttrs
|
||||
(stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux"))
|
||||
{
|
||||
LDFLAGS = "-fuse-ld=gold";
|
||||
};
|
||||
|
||||
separateDebugInfo = !stdenv.hostPlatform.isStatic;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "store-api.hh"
|
||||
#include "archive.hh"
|
||||
#include "store-path-accessor.hh"
|
||||
#include "fetch-to-store.hh"
|
||||
|
||||
namespace nix::fetchers {
|
||||
|
||||
@@ -96,7 +97,7 @@ struct PathInputScheme : InputScheme
|
||||
std::optional<std::string> isRelative(const Input & input) const
|
||||
{
|
||||
auto path = getStrAttr(input.attrs, "path");
|
||||
if (hasPrefix(path, "/"))
|
||||
if (isAbsolute(path))
|
||||
return std::nullopt;
|
||||
else
|
||||
return path;
|
||||
@@ -157,6 +158,15 @@ struct PathInputScheme : InputScheme
|
||||
});
|
||||
storePath = store->addToStoreFromDump(*src, "source");
|
||||
}
|
||||
|
||||
// To avoid copying the path again to the /nix/store, we need to add a cache entry.
|
||||
ContentAddressMethod method = ContentAddressMethod::Raw::NixArchive;
|
||||
auto fp = getFingerprint(store, input);
|
||||
if (fp) {
|
||||
auto cacheKey = makeFetchToStoreCacheKey(input.getName(), *fp, method, "/");
|
||||
fetchers::getCache()->upsert(cacheKey, *store, {}, *storePath);
|
||||
}
|
||||
|
||||
input.attrs.insert_or_assign("lastModified", uint64_t(mtime));
|
||||
|
||||
return {makeStorePathAccessor(store, *storePath), std::move(input)};
|
||||
|
||||
@@ -156,7 +156,7 @@ static std::shared_ptr<Registry> getGlobalRegistry(const Settings & settings, re
|
||||
return std::make_shared<Registry>(settings, Registry::Global); // empty registry
|
||||
}
|
||||
|
||||
if (!hasPrefix(path, "/")) {
|
||||
if (!isAbsolute(path)) {
|
||||
auto storePath = downloadFile(store, path, "flake-registry.json").storePath;
|
||||
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
|
||||
store2->addPermRoot(storePath, getCacheDir() + "/nix/flake-registry.json");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user