Merge branch 'master' into indexed-store-path-outputs

This commit is contained in:
John Ericson 2022-11-25 08:14:32 -05:00 committed by GitHub
commit 26534f141c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 1494 additions and 510 deletions

5
.github/assign-by-files.yml vendored Normal file
View file

@ -0,0 +1,5 @@
---
# This files is used by https://github.com/marketplace/actions/auto-assign-reviewer-by-files
# to assign maintainers
"doc/**/*":
- fricklerhandwerk

12
.github/workflows/assign-reviewer.yml vendored Normal file
View file

@ -0,0 +1,12 @@
name: "Auto Assign"
on:
- pull_request
jobs:
assign_reviewer:
runs-on: ubuntu-latest
steps:
- uses: shufo/auto-assign-reviewer-by-files@v1.1.4
with:
config: ".github/assign-by-files.yml"
token: ${{ secrets.GITHUB_TOKEN }}

View file

@ -21,7 +21,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- uses: cachix/install-nix-action@v18 - uses: cachix/install-nix-action@v18
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: cachix/cachix-action@v11 - uses: cachix/cachix-action@v12
if: needs.check_secrets.outputs.cachix == 'true' if: needs.check_secrets.outputs.cachix == 'true'
with: with:
name: '${{ env.CACHIX_NAME }}' name: '${{ env.CACHIX_NAME }}'
@ -59,7 +59,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: cachix/install-nix-action@v18 - uses: cachix/install-nix-action@v18
- uses: cachix/cachix-action@v11 - uses: cachix/cachix-action@v12
with: with:
name: '${{ env.CACHIX_NAME }}' name: '${{ env.CACHIX_NAME }}'
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
@ -105,7 +105,7 @@ jobs:
- uses: cachix/install-nix-action@v18 - uses: cachix/install-nix-action@v18
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - 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 - run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#default.version | tr -d \")" >> $GITHUB_ENV
- uses: cachix/cachix-action@v11 - uses: cachix/cachix-action@v12
if: needs.check_secrets.outputs.cachix == 'true' if: needs.check_secrets.outputs.cachix == 'true'
with: with:
name: '${{ env.CACHIX_NAME }}' name: '${{ env.CACHIX_NAME }}'

View file

@ -1,330 +1,424 @@
// Redirects from old DocBook manual. // redirect rules for anchors ensure backwards compatibility of URLs.
var redirects = { // this must be done on the client side, as web servers do not see the anchor part of the URL.
"#part-advanced-topics": "advanced-topics/advanced-topics.html",
"#chap-tuning-cores-and-jobs": "advanced-topics/cores-vs-jobs.html", // redirections are declared as follows:
"#chap-diff-hook": "advanced-topics/diff-hook.html", // each entry has as its key a path matching the requested URL path, relative to the mdBook document root.
"#check-dirs-are-unregistered": "advanced-topics/diff-hook.html#check-dirs-are-unregistered", //
"#chap-distributed-builds": "advanced-topics/distributed-builds.html", // IMPORTANT: it must specify the full path with file name and suffix
"#chap-post-build-hook": "advanced-topics/post-build-hook.html", //
"#chap-post-build-hook-caveats": "advanced-topics/post-build-hook.html#implementation-caveats", // each entry is itself a set of key-value pairs, where
"#part-command-ref": "command-ref/command-ref.html", // - keys are anchors on the matched path.
"#conf-allow-import-from-derivation": "command-ref/conf-file.html#conf-allow-import-from-derivation", // - values are redirection targets relative to the current path.
"#conf-allow-new-privileges": "command-ref/conf-file.html#conf-allow-new-privileges",
"#conf-allowed-uris": "command-ref/conf-file.html#conf-allowed-uris", const redirects = {
"#conf-allowed-users": "command-ref/conf-file.html#conf-allowed-users", "index.html": {
"#conf-auto-optimise-store": "command-ref/conf-file.html#conf-auto-optimise-store", "part-advanced-topics": "advanced-topics/advanced-topics.html",
"#conf-binary-cache-public-keys": "command-ref/conf-file.html#conf-binary-cache-public-keys", "chap-tuning-cores-and-jobs": "advanced-topics/cores-vs-jobs.html",
"#conf-binary-caches": "command-ref/conf-file.html#conf-binary-caches", "chap-diff-hook": "advanced-topics/diff-hook.html",
"#conf-build-compress-log": "command-ref/conf-file.html#conf-build-compress-log", "check-dirs-are-unregistered": "advanced-topics/diff-hook.html#check-dirs-are-unregistered",
"#conf-build-cores": "command-ref/conf-file.html#conf-build-cores", "chap-distributed-builds": "advanced-topics/distributed-builds.html",
"#conf-build-extra-chroot-dirs": "command-ref/conf-file.html#conf-build-extra-chroot-dirs", "chap-post-build-hook": "advanced-topics/post-build-hook.html",
"#conf-build-extra-sandbox-paths": "command-ref/conf-file.html#conf-build-extra-sandbox-paths", "chap-post-build-hook-caveats": "advanced-topics/post-build-hook.html#implementation-caveats",
"#conf-build-fallback": "command-ref/conf-file.html#conf-build-fallback", "part-command-ref": "command-ref/command-ref.html",
"#conf-build-max-jobs": "command-ref/conf-file.html#conf-build-max-jobs", "conf-allow-import-from-derivation": "command-ref/conf-file.html#conf-allow-import-from-derivation",
"#conf-build-max-log-size": "command-ref/conf-file.html#conf-build-max-log-size", "conf-allow-new-privileges": "command-ref/conf-file.html#conf-allow-new-privileges",
"#conf-build-max-silent-time": "command-ref/conf-file.html#conf-build-max-silent-time", "conf-allowed-uris": "command-ref/conf-file.html#conf-allowed-uris",
"#conf-build-repeat": "command-ref/conf-file.html#conf-build-repeat", "conf-allowed-users": "command-ref/conf-file.html#conf-allowed-users",
"#conf-build-timeout": "command-ref/conf-file.html#conf-build-timeout", "conf-auto-optimise-store": "command-ref/conf-file.html#conf-auto-optimise-store",
"#conf-build-use-chroot": "command-ref/conf-file.html#conf-build-use-chroot", "conf-binary-cache-public-keys": "command-ref/conf-file.html#conf-binary-cache-public-keys",
"#conf-build-use-sandbox": "command-ref/conf-file.html#conf-build-use-sandbox", "conf-binary-caches": "command-ref/conf-file.html#conf-binary-caches",
"#conf-build-use-substitutes": "command-ref/conf-file.html#conf-build-use-substitutes", "conf-build-compress-log": "command-ref/conf-file.html#conf-build-compress-log",
"#conf-build-users-group": "command-ref/conf-file.html#conf-build-users-group", "conf-build-cores": "command-ref/conf-file.html#conf-build-cores",
"#conf-builders": "command-ref/conf-file.html#conf-builders", "conf-build-extra-chroot-dirs": "command-ref/conf-file.html#conf-build-extra-chroot-dirs",
"#conf-builders-use-substitutes": "command-ref/conf-file.html#conf-builders-use-substitutes", "conf-build-extra-sandbox-paths": "command-ref/conf-file.html#conf-build-extra-sandbox-paths",
"#conf-compress-build-log": "command-ref/conf-file.html#conf-compress-build-log", "conf-build-fallback": "command-ref/conf-file.html#conf-build-fallback",
"#conf-connect-timeout": "command-ref/conf-file.html#conf-connect-timeout", "conf-build-max-jobs": "command-ref/conf-file.html#conf-build-max-jobs",
"#conf-cores": "command-ref/conf-file.html#conf-cores", "conf-build-max-log-size": "command-ref/conf-file.html#conf-build-max-log-size",
"#conf-diff-hook": "command-ref/conf-file.html#conf-diff-hook", "conf-build-max-silent-time": "command-ref/conf-file.html#conf-build-max-silent-time",
"#conf-enforce-determinism": "command-ref/conf-file.html#conf-enforce-determinism", "conf-build-repeat": "command-ref/conf-file.html#conf-build-repeat",
"#conf-env-keep-derivations": "command-ref/conf-file.html#conf-env-keep-derivations", "conf-build-timeout": "command-ref/conf-file.html#conf-build-timeout",
"#conf-extra-binary-caches": "command-ref/conf-file.html#conf-extra-binary-caches", "conf-build-use-chroot": "command-ref/conf-file.html#conf-build-use-chroot",
"#conf-extra-platforms": "command-ref/conf-file.html#conf-extra-platforms", "conf-build-use-sandbox": "command-ref/conf-file.html#conf-build-use-sandbox",
"#conf-extra-sandbox-paths": "command-ref/conf-file.html#conf-extra-sandbox-paths", "conf-build-use-substitutes": "command-ref/conf-file.html#conf-build-use-substitutes",
"#conf-extra-substituters": "command-ref/conf-file.html#conf-extra-substituters", "conf-build-users-group": "command-ref/conf-file.html#conf-build-users-group",
"#conf-fallback": "command-ref/conf-file.html#conf-fallback", "conf-builders": "command-ref/conf-file.html#conf-builders",
"#conf-fsync-metadata": "command-ref/conf-file.html#conf-fsync-metadata", "conf-builders-use-substitutes": "command-ref/conf-file.html#conf-builders-use-substitutes",
"#conf-gc-keep-derivations": "command-ref/conf-file.html#conf-gc-keep-derivations", "conf-compress-build-log": "command-ref/conf-file.html#conf-compress-build-log",
"#conf-gc-keep-outputs": "command-ref/conf-file.html#conf-gc-keep-outputs", "conf-connect-timeout": "command-ref/conf-file.html#conf-connect-timeout",
"#conf-hashed-mirrors": "command-ref/conf-file.html#conf-hashed-mirrors", "conf-cores": "command-ref/conf-file.html#conf-cores",
"#conf-http-connections": "command-ref/conf-file.html#conf-http-connections", "conf-diff-hook": "command-ref/conf-file.html#conf-diff-hook",
"#conf-keep-build-log": "command-ref/conf-file.html#conf-keep-build-log", "conf-enforce-determinism": "command-ref/conf-file.html#conf-enforce-determinism",
"#conf-keep-derivations": "command-ref/conf-file.html#conf-keep-derivations", "conf-env-keep-derivations": "command-ref/conf-file.html#conf-env-keep-derivations",
"#conf-keep-env-derivations": "command-ref/conf-file.html#conf-keep-env-derivations", "conf-extra-binary-caches": "command-ref/conf-file.html#conf-extra-binary-caches",
"#conf-keep-outputs": "command-ref/conf-file.html#conf-keep-outputs", "conf-extra-platforms": "command-ref/conf-file.html#conf-extra-platforms",
"#conf-max-build-log-size": "command-ref/conf-file.html#conf-max-build-log-size", "conf-extra-sandbox-paths": "command-ref/conf-file.html#conf-extra-sandbox-paths",
"#conf-max-free": "command-ref/conf-file.html#conf-max-free", "conf-extra-substituters": "command-ref/conf-file.html#conf-extra-substituters",
"#conf-max-jobs": "command-ref/conf-file.html#conf-max-jobs", "conf-fallback": "command-ref/conf-file.html#conf-fallback",
"#conf-max-silent-time": "command-ref/conf-file.html#conf-max-silent-time", "conf-fsync-metadata": "command-ref/conf-file.html#conf-fsync-metadata",
"#conf-min-free": "command-ref/conf-file.html#conf-min-free", "conf-gc-keep-derivations": "command-ref/conf-file.html#conf-gc-keep-derivations",
"#conf-narinfo-cache-negative-ttl": "command-ref/conf-file.html#conf-narinfo-cache-negative-ttl", "conf-gc-keep-outputs": "command-ref/conf-file.html#conf-gc-keep-outputs",
"#conf-narinfo-cache-positive-ttl": "command-ref/conf-file.html#conf-narinfo-cache-positive-ttl", "conf-hashed-mirrors": "command-ref/conf-file.html#conf-hashed-mirrors",
"#conf-netrc-file": "command-ref/conf-file.html#conf-netrc-file", "conf-http-connections": "command-ref/conf-file.html#conf-http-connections",
"#conf-plugin-files": "command-ref/conf-file.html#conf-plugin-files", "conf-keep-build-log": "command-ref/conf-file.html#conf-keep-build-log",
"#conf-post-build-hook": "command-ref/conf-file.html#conf-post-build-hook", "conf-keep-derivations": "command-ref/conf-file.html#conf-keep-derivations",
"#conf-pre-build-hook": "command-ref/conf-file.html#conf-pre-build-hook", "conf-keep-env-derivations": "command-ref/conf-file.html#conf-keep-env-derivations",
"#conf-repeat": "command-ref/conf-file.html#conf-repeat", "conf-keep-outputs": "command-ref/conf-file.html#conf-keep-outputs",
"#conf-require-sigs": "command-ref/conf-file.html#conf-require-sigs", "conf-max-build-log-size": "command-ref/conf-file.html#conf-max-build-log-size",
"#conf-restrict-eval": "command-ref/conf-file.html#conf-restrict-eval", "conf-max-free": "command-ref/conf-file.html#conf-max-free",
"#conf-run-diff-hook": "command-ref/conf-file.html#conf-run-diff-hook", "conf-max-jobs": "command-ref/conf-file.html#conf-max-jobs",
"#conf-sandbox": "command-ref/conf-file.html#conf-sandbox", "conf-max-silent-time": "command-ref/conf-file.html#conf-max-silent-time",
"#conf-sandbox-dev-shm-size": "command-ref/conf-file.html#conf-sandbox-dev-shm-size", "conf-min-free": "command-ref/conf-file.html#conf-min-free",
"#conf-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths", "conf-narinfo-cache-negative-ttl": "command-ref/conf-file.html#conf-narinfo-cache-negative-ttl",
"#conf-secret-key-files": "command-ref/conf-file.html#conf-secret-key-files", "conf-narinfo-cache-positive-ttl": "command-ref/conf-file.html#conf-narinfo-cache-positive-ttl",
"#conf-show-trace": "command-ref/conf-file.html#conf-show-trace", "conf-netrc-file": "command-ref/conf-file.html#conf-netrc-file",
"#conf-stalled-download-timeout": "command-ref/conf-file.html#conf-stalled-download-timeout", "conf-plugin-files": "command-ref/conf-file.html#conf-plugin-files",
"#conf-substitute": "command-ref/conf-file.html#conf-substitute", "conf-post-build-hook": "command-ref/conf-file.html#conf-post-build-hook",
"#conf-substituters": "command-ref/conf-file.html#conf-substituters", "conf-pre-build-hook": "command-ref/conf-file.html#conf-pre-build-hook",
"#conf-system": "command-ref/conf-file.html#conf-system", "conf-repeat": "command-ref/conf-file.html#conf-repeat",
"#conf-system-features": "command-ref/conf-file.html#conf-system-features", "conf-require-sigs": "command-ref/conf-file.html#conf-require-sigs",
"#conf-tarball-ttl": "command-ref/conf-file.html#conf-tarball-ttl", "conf-restrict-eval": "command-ref/conf-file.html#conf-restrict-eval",
"#conf-timeout": "command-ref/conf-file.html#conf-timeout", "conf-run-diff-hook": "command-ref/conf-file.html#conf-run-diff-hook",
"#conf-trace-function-calls": "command-ref/conf-file.html#conf-trace-function-calls", "conf-sandbox": "command-ref/conf-file.html#conf-sandbox",
"#conf-trusted-binary-caches": "command-ref/conf-file.html#conf-trusted-binary-caches", "conf-sandbox-dev-shm-size": "command-ref/conf-file.html#conf-sandbox-dev-shm-size",
"#conf-trusted-public-keys": "command-ref/conf-file.html#conf-trusted-public-keys", "conf-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths",
"#conf-trusted-substituters": "command-ref/conf-file.html#conf-trusted-substituters", "conf-secret-key-files": "command-ref/conf-file.html#conf-secret-key-files",
"#conf-trusted-users": "command-ref/conf-file.html#conf-trusted-users", "conf-show-trace": "command-ref/conf-file.html#conf-show-trace",
"#extra-sandbox-paths": "command-ref/conf-file.html#extra-sandbox-paths", "conf-stalled-download-timeout": "command-ref/conf-file.html#conf-stalled-download-timeout",
"#sec-conf-file": "command-ref/conf-file.html", "conf-substitute": "command-ref/conf-file.html#conf-substitute",
"#env-NIX_PATH": "command-ref/env-common.html#env-NIX_PATH", "conf-substituters": "command-ref/conf-file.html#conf-substituters",
"#env-common": "command-ref/env-common.html", "conf-system": "command-ref/conf-file.html#conf-system",
"#envar-remote": "command-ref/env-common.html#env-NIX_REMOTE", "conf-system-features": "command-ref/conf-file.html#conf-system-features",
"#sec-common-env": "command-ref/env-common.html", "conf-tarball-ttl": "command-ref/conf-file.html#conf-tarball-ttl",
"#ch-files": "command-ref/files.html", "conf-timeout": "command-ref/conf-file.html#conf-timeout",
"#ch-main-commands": "command-ref/main-commands.html", "conf-trace-function-calls": "command-ref/conf-file.html#conf-trace-function-calls",
"#opt-out-link": "command-ref/nix-build.html#opt-out-link", "conf-trusted-binary-caches": "command-ref/conf-file.html#conf-trusted-binary-caches",
"#sec-nix-build": "command-ref/nix-build.html", "conf-trusted-public-keys": "command-ref/conf-file.html#conf-trusted-public-keys",
"#sec-nix-channel": "command-ref/nix-channel.html", "conf-trusted-substituters": "command-ref/conf-file.html#conf-trusted-substituters",
"#sec-nix-collect-garbage": "command-ref/nix-collect-garbage.html", "conf-trusted-users": "command-ref/conf-file.html#conf-trusted-users",
"#sec-nix-copy-closure": "command-ref/nix-copy-closure.html", "extra-sandbox-paths": "command-ref/conf-file.html#extra-sandbox-paths",
"#sec-nix-daemon": "command-ref/nix-daemon.html", "sec-conf-file": "command-ref/conf-file.html",
"#refsec-nix-env-install-examples": "command-ref/nix-env.html#examples", "env-NIX_PATH": "command-ref/env-common.html#env-NIX_PATH",
"#rsec-nix-env-install": "command-ref/nix-env.html#operation---install", "env-common": "command-ref/env-common.html",
"#rsec-nix-env-set": "command-ref/nix-env.html#operation---set", "envar-remote": "command-ref/env-common.html#env-NIX_REMOTE",
"#rsec-nix-env-set-flag": "command-ref/nix-env.html#operation---set-flag", "sec-common-env": "command-ref/env-common.html",
"#rsec-nix-env-upgrade": "command-ref/nix-env.html#operation---upgrade", "ch-files": "command-ref/files.html",
"#sec-nix-env": "command-ref/nix-env.html", "ch-main-commands": "command-ref/main-commands.html",
"#ssec-version-comparisons": "command-ref/nix-env.html#versions", "opt-out-link": "command-ref/nix-build.html#opt-out-link",
"#sec-nix-hash": "command-ref/nix-hash.html", "sec-nix-build": "command-ref/nix-build.html",
"#sec-nix-instantiate": "command-ref/nix-instantiate.html", "sec-nix-channel": "command-ref/nix-channel.html",
"#sec-nix-prefetch-url": "command-ref/nix-prefetch-url.html", "sec-nix-collect-garbage": "command-ref/nix-collect-garbage.html",
"#sec-nix-shell": "command-ref/nix-shell.html", "sec-nix-copy-closure": "command-ref/nix-copy-closure.html",
"#ssec-nix-shell-shebang": "command-ref/nix-shell.html#use-as-a--interpreter", "sec-nix-daemon": "command-ref/nix-daemon.html",
"#nixref-queries": "command-ref/nix-store.html#queries", "refsec-nix-env-install-examples": "command-ref/nix-env.html#examples",
"#opt-add-root": "command-ref/nix-store.html#opt-add-root", "rsec-nix-env-install": "command-ref/nix-env.html#operation---install",
"#refsec-nix-store-dump": "command-ref/nix-store.html#operation---dump", "rsec-nix-env-set": "command-ref/nix-env.html#operation---set",
"#refsec-nix-store-export": "command-ref/nix-store.html#operation---export", "rsec-nix-env-set-flag": "command-ref/nix-env.html#operation---set-flag",
"#refsec-nix-store-import": "command-ref/nix-store.html#operation---import", "rsec-nix-env-upgrade": "command-ref/nix-env.html#operation---upgrade",
"#refsec-nix-store-query": "command-ref/nix-store.html#operation---query", "sec-nix-env": "command-ref/nix-env.html",
"#refsec-nix-store-verify": "command-ref/nix-store.html#operation---verify", "ssec-version-comparisons": "command-ref/nix-env.html#versions",
"#rsec-nix-store-gc": "command-ref/nix-store.html#operation---gc", "sec-nix-hash": "command-ref/nix-hash.html",
"#rsec-nix-store-generate-binary-cache-key": "command-ref/nix-store.html#operation---generate-binary-cache-key", "sec-nix-instantiate": "command-ref/nix-instantiate.html",
"#rsec-nix-store-realise": "command-ref/nix-store.html#operation---realise", "sec-nix-prefetch-url": "command-ref/nix-prefetch-url.html",
"#rsec-nix-store-serve": "command-ref/nix-store.html#operation---serve", "sec-nix-shell": "command-ref/nix-shell.html",
"#sec-nix-store": "command-ref/nix-store.html", "ssec-nix-shell-shebang": "command-ref/nix-shell.html#use-as-a--interpreter",
"#opt-I": "command-ref/opt-common.html#opt-I", "nixref-queries": "command-ref/nix-store.html#queries",
"#opt-attr": "command-ref/opt-common.html#opt-attr", "opt-add-root": "command-ref/nix-store.html#opt-add-root",
"#opt-common": "command-ref/opt-common.html", "refsec-nix-store-dump": "command-ref/nix-store.html#operation---dump",
"#opt-cores": "command-ref/opt-common.html#opt-cores", "refsec-nix-store-export": "command-ref/nix-store.html#operation---export",
"#opt-log-format": "command-ref/opt-common.html#opt-log-format", "refsec-nix-store-import": "command-ref/nix-store.html#operation---import",
"#opt-max-jobs": "command-ref/opt-common.html#opt-max-jobs", "refsec-nix-store-query": "command-ref/nix-store.html#operation---query",
"#opt-max-silent-time": "command-ref/opt-common.html#opt-max-silent-time", "refsec-nix-store-verify": "command-ref/nix-store.html#operation---verify",
"#opt-timeout": "command-ref/opt-common.html#opt-timeout", "rsec-nix-store-gc": "command-ref/nix-store.html#operation---gc",
"#sec-common-options": "command-ref/opt-common.html", "rsec-nix-store-generate-binary-cache-key": "command-ref/nix-store.html#operation---generate-binary-cache-key",
"#ch-utilities": "command-ref/utilities.html", "rsec-nix-store-realise": "command-ref/nix-store.html#operation---realise",
"#chap-hacking": "contributing/hacking.html", "rsec-nix-store-serve": "command-ref/nix-store.html#operation---serve",
"#adv-attr-allowSubstitutes": "language/advanced-attributes.html#adv-attr-allowSubstitutes", "sec-nix-store": "command-ref/nix-store.html",
"#adv-attr-allowedReferences": "language/advanced-attributes.html#adv-attr-allowedReferences", "opt-I": "command-ref/opt-common.html#opt-I",
"#adv-attr-allowedRequisites": "language/advanced-attributes.html#adv-attr-allowedRequisites", "opt-attr": "command-ref/opt-common.html#opt-attr",
"#adv-attr-disallowedReferences": "language/advanced-attributes.html#adv-attr-disallowedReferences", "opt-common": "command-ref/opt-common.html",
"#adv-attr-disallowedRequisites": "language/advanced-attributes.html#adv-attr-disallowedRequisites", "opt-cores": "command-ref/opt-common.html#opt-cores",
"#adv-attr-exportReferencesGraph": "language/advanced-attributes.html#adv-attr-exportReferencesGraph", "opt-log-format": "command-ref/opt-common.html#opt-log-format",
"#adv-attr-impureEnvVars": "language/advanced-attributes.html#adv-attr-impureEnvVars", "opt-max-jobs": "command-ref/opt-common.html#opt-max-jobs",
"#adv-attr-outputHash": "language/advanced-attributes.html#adv-attr-outputHash", "opt-max-silent-time": "command-ref/opt-common.html#opt-max-silent-time",
"#adv-attr-outputHashAlgo": "language/advanced-attributes.html#adv-attr-outputHashAlgo", "opt-timeout": "command-ref/opt-common.html#opt-timeout",
"#adv-attr-outputHashMode": "language/advanced-attributes.html#adv-attr-outputHashMode", "sec-common-options": "command-ref/opt-common.html",
"#adv-attr-passAsFile": "language/advanced-attributes.html#adv-attr-passAsFile", "ch-utilities": "command-ref/utilities.html",
"#adv-attr-preferLocalBuild": "language/advanced-attributes.html#adv-attr-preferLocalBuild", "chap-hacking": "contributing/hacking.html",
"#fixed-output-drvs": "language/advanced-attributes.html#adv-attr-outputHash", "adv-attr-allowSubstitutes": "language/advanced-attributes.html#adv-attr-allowSubstitutes",
"#sec-advanced-attributes": "language/advanced-attributes.html", "adv-attr-allowedReferences": "language/advanced-attributes.html#adv-attr-allowedReferences",
"#builtin-abort": "language/builtins.html#builtins-abort", "adv-attr-allowedRequisites": "language/advanced-attributes.html#adv-attr-allowedRequisites",
"#builtin-add": "language/builtins.html#builtins-add", "adv-attr-disallowedReferences": "language/advanced-attributes.html#adv-attr-disallowedReferences",
"#builtin-all": "language/builtins.html#builtins-all", "adv-attr-disallowedRequisites": "language/advanced-attributes.html#adv-attr-disallowedRequisites",
"#builtin-any": "language/builtins.html#builtins-any", "adv-attr-exportReferencesGraph": "language/advanced-attributes.html#adv-attr-exportReferencesGraph",
"#builtin-attrNames": "language/builtins.html#builtins-attrNames", "adv-attr-impureEnvVars": "language/advanced-attributes.html#adv-attr-impureEnvVars",
"#builtin-attrValues": "language/builtins.html#builtins-attrValues", "adv-attr-outputHash": "language/advanced-attributes.html#adv-attr-outputHash",
"#builtin-baseNameOf": "language/builtins.html#builtins-baseNameOf", "adv-attr-outputHashAlgo": "language/advanced-attributes.html#adv-attr-outputHashAlgo",
"#builtin-bitAnd": "language/builtins.html#builtins-bitAnd", "adv-attr-outputHashMode": "language/advanced-attributes.html#adv-attr-outputHashMode",
"#builtin-bitOr": "language/builtins.html#builtins-bitOr", "adv-attr-passAsFile": "language/advanced-attributes.html#adv-attr-passAsFile",
"#builtin-bitXor": "language/builtins.html#builtins-bitXor", "adv-attr-preferLocalBuild": "language/advanced-attributes.html#adv-attr-preferLocalBuild",
"#builtin-builtins": "language/builtins.html#builtins-builtins", "fixed-output-drvs": "language/advanced-attributes.html#adv-attr-outputHash",
"#builtin-compareVersions": "language/builtins.html#builtins-compareVersions", "sec-advanced-attributes": "language/advanced-attributes.html",
"#builtin-concatLists": "language/builtins.html#builtins-concatLists", "builtin-abort": "language/builtins.html#builtins-abort",
"#builtin-concatStringsSep": "language/builtins.html#builtins-concatStringsSep", "builtin-add": "language/builtins.html#builtins-add",
"#builtin-currentSystem": "language/builtins.html#builtins-currentSystem", "builtin-all": "language/builtins.html#builtins-all",
"#builtin-deepSeq": "language/builtins.html#builtins-deepSeq", "builtin-any": "language/builtins.html#builtins-any",
"#builtin-derivation": "language/builtins.html#builtins-derivation", "builtin-attrNames": "language/builtins.html#builtins-attrNames",
"#builtin-dirOf": "language/builtins.html#builtins-dirOf", "builtin-attrValues": "language/builtins.html#builtins-attrValues",
"#builtin-div": "language/builtins.html#builtins-div", "builtin-baseNameOf": "language/builtins.html#builtins-baseNameOf",
"#builtin-elem": "language/builtins.html#builtins-elem", "builtin-bitAnd": "language/builtins.html#builtins-bitAnd",
"#builtin-elemAt": "language/builtins.html#builtins-elemAt", "builtin-bitOr": "language/builtins.html#builtins-bitOr",
"#builtin-fetchGit": "language/builtins.html#builtins-fetchGit", "builtin-bitXor": "language/builtins.html#builtins-bitXor",
"#builtin-fetchTarball": "language/builtins.html#builtins-fetchTarball", "builtin-builtins": "language/builtins.html#builtins-builtins",
"#builtin-fetchurl": "language/builtins.html#builtins-fetchurl", "builtin-compareVersions": "language/builtins.html#builtins-compareVersions",
"#builtin-filterSource": "language/builtins.html#builtins-filterSource", "builtin-concatLists": "language/builtins.html#builtins-concatLists",
"#builtin-foldl-prime": "language/builtins.html#builtins-foldl-prime", "builtin-concatStringsSep": "language/builtins.html#builtins-concatStringsSep",
"#builtin-fromJSON": "language/builtins.html#builtins-fromJSON", "builtin-currentSystem": "language/builtins.html#builtins-currentSystem",
"#builtin-functionArgs": "language/builtins.html#builtins-functionArgs", "builtin-deepSeq": "language/builtins.html#builtins-deepSeq",
"#builtin-genList": "language/builtins.html#builtins-genList", "builtin-derivation": "language/builtins.html#builtins-derivation",
"#builtin-getAttr": "language/builtins.html#builtins-getAttr", "builtin-dirOf": "language/builtins.html#builtins-dirOf",
"#builtin-getEnv": "language/builtins.html#builtins-getEnv", "builtin-div": "language/builtins.html#builtins-div",
"#builtin-hasAttr": "language/builtins.html#builtins-hasAttr", "builtin-elem": "language/builtins.html#builtins-elem",
"#builtin-hashFile": "language/builtins.html#builtins-hashFile", "builtin-elemAt": "language/builtins.html#builtins-elemAt",
"#builtin-hashString": "language/builtins.html#builtins-hashString", "builtin-fetchGit": "language/builtins.html#builtins-fetchGit",
"#builtin-head": "language/builtins.html#builtins-head", "builtin-fetchTarball": "language/builtins.html#builtins-fetchTarball",
"#builtin-import": "language/builtins.html#builtins-import", "builtin-fetchurl": "language/builtins.html#builtins-fetchurl",
"#builtin-intersectAttrs": "language/builtins.html#builtins-intersectAttrs", "builtin-filterSource": "language/builtins.html#builtins-filterSource",
"#builtin-isAttrs": "language/builtins.html#builtins-isAttrs", "builtin-foldl-prime": "language/builtins.html#builtins-foldl-prime",
"#builtin-isBool": "language/builtins.html#builtins-isBool", "builtin-fromJSON": "language/builtins.html#builtins-fromJSON",
"#builtin-isFloat": "language/builtins.html#builtins-isFloat", "builtin-functionArgs": "language/builtins.html#builtins-functionArgs",
"#builtin-isFunction": "language/builtins.html#builtins-isFunction", "builtin-genList": "language/builtins.html#builtins-genList",
"#builtin-isInt": "language/builtins.html#builtins-isInt", "builtin-getAttr": "language/builtins.html#builtins-getAttr",
"#builtin-isList": "language/builtins.html#builtins-isList", "builtin-getEnv": "language/builtins.html#builtins-getEnv",
"#builtin-isNull": "language/builtins.html#builtins-isNull", "builtin-hasAttr": "language/builtins.html#builtins-hasAttr",
"#builtin-isString": "language/builtins.html#builtins-isString", "builtin-hashFile": "language/builtins.html#builtins-hashFile",
"#builtin-length": "language/builtins.html#builtins-length", "builtin-hashString": "language/builtins.html#builtins-hashString",
"#builtin-lessThan": "language/builtins.html#builtins-lessThan", "builtin-head": "language/builtins.html#builtins-head",
"#builtin-listToAttrs": "language/builtins.html#builtins-listToAttrs", "builtin-import": "language/builtins.html#builtins-import",
"#builtin-map": "language/builtins.html#builtins-map", "builtin-intersectAttrs": "language/builtins.html#builtins-intersectAttrs",
"#builtin-match": "language/builtins.html#builtins-match", "builtin-isAttrs": "language/builtins.html#builtins-isAttrs",
"#builtin-mul": "language/builtins.html#builtins-mul", "builtin-isBool": "language/builtins.html#builtins-isBool",
"#builtin-parseDrvName": "language/builtins.html#builtins-parseDrvName", "builtin-isFloat": "language/builtins.html#builtins-isFloat",
"#builtin-path": "language/builtins.html#builtins-path", "builtin-isFunction": "language/builtins.html#builtins-isFunction",
"#builtin-pathExists": "language/builtins.html#builtins-pathExists", "builtin-isInt": "language/builtins.html#builtins-isInt",
"#builtin-placeholder": "language/builtins.html#builtins-placeholder", "builtin-isList": "language/builtins.html#builtins-isList",
"#builtin-readDir": "language/builtins.html#builtins-readDir", "builtin-isNull": "language/builtins.html#builtins-isNull",
"#builtin-readFile": "language/builtins.html#builtins-readFile", "builtin-isString": "language/builtins.html#builtins-isString",
"#builtin-removeAttrs": "language/builtins.html#builtins-removeAttrs", "builtin-length": "language/builtins.html#builtins-length",
"#builtin-replaceStrings": "language/builtins.html#builtins-replaceStrings", "builtin-lessThan": "language/builtins.html#builtins-lessThan",
"#builtin-seq": "language/builtins.html#builtins-seq", "builtin-listToAttrs": "language/builtins.html#builtins-listToAttrs",
"#builtin-sort": "language/builtins.html#builtins-sort", "builtin-map": "language/builtins.html#builtins-map",
"#builtin-split": "language/builtins.html#builtins-split", "builtin-match": "language/builtins.html#builtins-match",
"#builtin-splitVersion": "language/builtins.html#builtins-splitVersion", "builtin-mul": "language/builtins.html#builtins-mul",
"#builtin-stringLength": "language/builtins.html#builtins-stringLength", "builtin-parseDrvName": "language/builtins.html#builtins-parseDrvName",
"#builtin-sub": "language/builtins.html#builtins-sub", "builtin-path": "language/builtins.html#builtins-path",
"#builtin-substring": "language/builtins.html#builtins-substring", "builtin-pathExists": "language/builtins.html#builtins-pathExists",
"#builtin-tail": "language/builtins.html#builtins-tail", "builtin-placeholder": "language/builtins.html#builtins-placeholder",
"#builtin-throw": "language/builtins.html#builtins-throw", "builtin-readDir": "language/builtins.html#builtins-readDir",
"#builtin-toFile": "language/builtins.html#builtins-toFile", "builtin-readFile": "language/builtins.html#builtins-readFile",
"#builtin-toJSON": "language/builtins.html#builtins-toJSON", "builtin-removeAttrs": "language/builtins.html#builtins-removeAttrs",
"#builtin-toPath": "language/builtins.html#builtins-toPath", "builtin-replaceStrings": "language/builtins.html#builtins-replaceStrings",
"#builtin-toString": "language/builtins.html#builtins-toString", "builtin-seq": "language/builtins.html#builtins-seq",
"#builtin-toXML": "language/builtins.html#builtins-toXML", "builtin-sort": "language/builtins.html#builtins-sort",
"#builtin-trace": "language/builtins.html#builtins-trace", "builtin-split": "language/builtins.html#builtins-split",
"#builtin-tryEval": "language/builtins.html#builtins-tryEval", "builtin-splitVersion": "language/builtins.html#builtins-splitVersion",
"#builtin-typeOf": "language/builtins.html#builtins-typeOf", "builtin-stringLength": "language/builtins.html#builtins-stringLength",
"#ssec-builtins": "language/builtins.html", "builtin-sub": "language/builtins.html#builtins-sub",
"#attr-system": "language/derivations.html#attr-system", "builtin-substring": "language/builtins.html#builtins-substring",
"#ssec-derivation": "language/derivations.html", "builtin-tail": "language/builtins.html#builtins-tail",
"#ch-expression-language": "language/index.html", "builtin-throw": "language/builtins.html#builtins-throw",
"#sec-constructs": "language/constructs.html", "builtin-toFile": "language/builtins.html#builtins-toFile",
"#sect-let-language": "language/constructs.html#let-language", "builtin-toJSON": "language/builtins.html#builtins-toJSON",
"#ss-functions": "language/constructs.html#functions", "builtin-toPath": "language/builtins.html#builtins-toPath",
"#sec-language-operators": "language/operators.html", "builtin-toString": "language/builtins.html#builtins-toString",
"#table-operators": "language/operators.html", "builtin-toXML": "language/builtins.html#builtins-toXML",
"#ssec-values": "language/values.html", "builtin-trace": "language/builtins.html#builtins-trace",
"#gloss-closure": "glossary.html#gloss-closure", "builtin-tryEval": "language/builtins.html#builtins-tryEval",
"#gloss-derivation": "glossary.html#gloss-derivation", "builtin-typeOf": "language/builtins.html#builtins-typeOf",
"#gloss-deriver": "glossary.html#gloss-deriver", "ssec-builtins": "language/builtins.html",
"#gloss-nar": "glossary.html#gloss-nar", "attr-system": "language/derivations.html#attr-system",
"#gloss-output-path": "glossary.html#gloss-output-path", "ssec-derivation": "language/derivations.html",
"#gloss-profile": "glossary.html#gloss-profile", "ch-expression-language": "language/index.html",
"#gloss-reachable": "glossary.html#gloss-reachable", "sec-constructs": "language/constructs.html",
"#gloss-reference": "glossary.html#gloss-reference", "sect-let-language": "language/constructs.html#let-language",
"#gloss-substitute": "glossary.html#gloss-substitute", "ss-functions": "language/constructs.html#functions",
"#gloss-user-env": "glossary.html#gloss-user-env", "sec-language-operators": "language/operators.html",
"#gloss-validity": "glossary.html#gloss-validity", "table-operators": "language/operators.html",
"#part-glossary": "glossary.html", "ssec-values": "language/values.html",
"#sec-building-source": "installation/building-source.html", "gloss-closure": "glossary.html#gloss-closure",
"#ch-env-variables": "installation/env-variables.html", "gloss-derivation": "glossary.html#gloss-derivation",
"#sec-installer-proxy-settings": "installation/env-variables.html#proxy-environment-variables", "gloss-deriver": "glossary.html#gloss-deriver",
"#sec-nix-ssl-cert-file": "installation/env-variables.html#nix_ssl_cert_file", "gloss-nar": "glossary.html#gloss-nar",
"#sec-nix-ssl-cert-file-with-nix-daemon-and-macos": "installation/env-variables.html#nix_ssl_cert_file-with-macos-and-the-nix-daemon", "gloss-output-path": "glossary.html#gloss-output-path",
"#chap-installation": "installation/installation.html", "gloss-profile": "glossary.html#gloss-profile",
"#ch-installing-binary": "installation/installing-binary.html", "gloss-reachable": "glossary.html#gloss-reachable",
"#sect-macos-installation": "installation/installing-binary.html#macos-installation", "gloss-reference": "glossary.html#gloss-reference",
"#sect-macos-installation-change-store-prefix": "installation/installing-binary.html#macos-installation", "gloss-substitute": "glossary.html#gloss-substitute",
"#sect-macos-installation-encrypted-volume": "installation/installing-binary.html#macos-installation", "gloss-user-env": "glossary.html#gloss-user-env",
"#sect-macos-installation-recommended-notes": "installation/installing-binary.html#macos-installation", "gloss-validity": "glossary.html#gloss-validity",
"#sect-macos-installation-symlink": "installation/installing-binary.html#macos-installation", "part-glossary": "glossary.html",
"#sect-multi-user-installation": "installation/installing-binary.html#multi-user-installation", "sec-building-source": "installation/building-source.html",
"#sect-nix-install-binary-tarball": "installation/installing-binary.html#installing-from-a-binary-tarball", "ch-env-variables": "installation/env-variables.html",
"#sect-nix-install-pinned-version-url": "installation/installing-binary.html#installing-a-pinned-nix-version-from-a-url", "sec-installer-proxy-settings": "installation/env-variables.html#proxy-environment-variables",
"#sect-single-user-installation": "installation/installing-binary.html#single-user-installation", "sec-nix-ssl-cert-file": "installation/env-variables.html#nix_ssl_cert_file",
"#ch-installing-source": "installation/installing-source.html", "sec-nix-ssl-cert-file-with-nix-daemon-and-macos": "installation/env-variables.html#nix_ssl_cert_file-with-macos-and-the-nix-daemon",
"#ssec-multi-user": "installation/multi-user.html", "chap-installation": "installation/installation.html",
"#ch-nix-security": "installation/nix-security.html", "ch-installing-binary": "installation/installing-binary.html",
"#sec-obtaining-source": "installation/obtaining-source.html", "sect-macos-installation": "installation/installing-binary.html#macos-installation",
"#sec-prerequisites-source": "installation/prerequisites-source.html", "sect-macos-installation-change-store-prefix": "installation/installing-binary.html#macos-installation",
"#sec-single-user": "installation/single-user.html", "sect-macos-installation-encrypted-volume": "installation/installing-binary.html#macos-installation",
"#ch-supported-platforms": "installation/supported-platforms.html", "sect-macos-installation-recommended-notes": "installation/installing-binary.html#macos-installation",
"#ch-upgrading-nix": "installation/upgrading.html", "sect-macos-installation-symlink": "installation/installing-binary.html#macos-installation",
"#ch-about-nix": "introduction.html", "sect-multi-user-installation": "installation/installing-binary.html#multi-user-installation",
"#chap-introduction": "introduction.html", "sect-nix-install-binary-tarball": "installation/installing-binary.html#installing-from-a-binary-tarball",
"#ch-basic-package-mgmt": "package-management/basic-package-mgmt.html", "sect-nix-install-pinned-version-url": "installation/installing-binary.html#installing-a-pinned-nix-version-from-a-url",
"#ssec-binary-cache-substituter": "package-management/binary-cache-substituter.html", "sect-single-user-installation": "installation/installing-binary.html#single-user-installation",
"#sec-channels": "package-management/channels.html", "ch-installing-source": "installation/installing-source.html",
"#ssec-copy-closure": "package-management/copy-closure.html", "ssec-multi-user": "installation/multi-user.html",
"#sec-garbage-collection": "package-management/garbage-collection.html", "ch-nix-security": "installation/nix-security.html",
"#ssec-gc-roots": "package-management/garbage-collector-roots.html", "sec-obtaining-source": "installation/obtaining-source.html",
"#chap-package-management": "package-management/package-management.html", "sec-prerequisites-source": "installation/prerequisites-source.html",
"#sec-profiles": "package-management/profiles.html", "sec-single-user": "installation/single-user.html",
"#ssec-s3-substituter": "package-management/s3-substituter.html", "ch-supported-platforms": "installation/supported-platforms.html",
"#ssec-s3-substituter-anonymous-reads": "package-management/s3-substituter.html#anonymous-reads-to-your-s3-compatible-binary-cache", "ch-upgrading-nix": "installation/upgrading.html",
"#ssec-s3-substituter-authenticated-reads": "package-management/s3-substituter.html#authenticated-reads-to-your-s3-binary-cache", "ch-about-nix": "introduction.html",
"#ssec-s3-substituter-authenticated-writes": "package-management/s3-substituter.html#authenticated-writes-to-your-s3-compatible-binary-cache", "chap-introduction": "introduction.html",
"#sec-sharing-packages": "package-management/sharing-packages.html", "ch-basic-package-mgmt": "package-management/basic-package-mgmt.html",
"#ssec-ssh-substituter": "package-management/ssh-substituter.html", "ssec-binary-cache-substituter": "package-management/binary-cache-substituter.html",
"#chap-quick-start": "quick-start.html", "sec-channels": "package-management/channels.html",
"#sec-relnotes": "release-notes/release-notes.html", "ssec-copy-closure": "package-management/copy-closure.html",
"#ch-relnotes-0.10.1": "release-notes/rl-0.10.1.html", "sec-garbage-collection": "package-management/garbage-collection.html",
"#ch-relnotes-0.10": "release-notes/rl-0.10.html", "ssec-gc-roots": "package-management/garbage-collector-roots.html",
"#ssec-relnotes-0.11": "release-notes/rl-0.11.html", "chap-package-management": "package-management/package-management.html",
"#ssec-relnotes-0.12": "release-notes/rl-0.12.html", "sec-profiles": "package-management/profiles.html",
"#ssec-relnotes-0.13": "release-notes/rl-0.13.html", "ssec-s3-substituter": "package-management/s3-substituter.html",
"#ssec-relnotes-0.14": "release-notes/rl-0.14.html", "ssec-s3-substituter-anonymous-reads": "package-management/s3-substituter.html#anonymous-reads-to-your-s3-compatible-binary-cache",
"#ssec-relnotes-0.15": "release-notes/rl-0.15.html", "ssec-s3-substituter-authenticated-reads": "package-management/s3-substituter.html#authenticated-reads-to-your-s3-binary-cache",
"#ssec-relnotes-0.16": "release-notes/rl-0.16.html", "ssec-s3-substituter-authenticated-writes": "package-management/s3-substituter.html#authenticated-writes-to-your-s3-compatible-binary-cache",
"#ch-relnotes-0.5": "release-notes/rl-0.5.html", "sec-sharing-packages": "package-management/sharing-packages.html",
"#ch-relnotes-0.6": "release-notes/rl-0.6.html", "ssec-ssh-substituter": "package-management/ssh-substituter.html",
"#ch-relnotes-0.7": "release-notes/rl-0.7.html", "chap-quick-start": "quick-start.html",
"#ch-relnotes-0.8.1": "release-notes/rl-0.8.1.html", "sec-relnotes": "release-notes/release-notes.html",
"#ch-relnotes-0.8": "release-notes/rl-0.8.html", "ch-relnotes-0.10.1": "release-notes/rl-0.10.1.html",
"#ch-relnotes-0.9.1": "release-notes/rl-0.9.1.html", "ch-relnotes-0.10": "release-notes/rl-0.10.html",
"#ch-relnotes-0.9.2": "release-notes/rl-0.9.2.html", "ssec-relnotes-0.11": "release-notes/rl-0.11.html",
"#ch-relnotes-0.9": "release-notes/rl-0.9.html", "ssec-relnotes-0.12": "release-notes/rl-0.12.html",
"#ssec-relnotes-1.0": "release-notes/rl-1.0.html", "ssec-relnotes-0.13": "release-notes/rl-0.13.html",
"#ssec-relnotes-1.1": "release-notes/rl-1.1.html", "ssec-relnotes-0.14": "release-notes/rl-0.14.html",
"#ssec-relnotes-1.10": "release-notes/rl-1.10.html", "ssec-relnotes-0.15": "release-notes/rl-0.15.html",
"#ssec-relnotes-1.11.10": "release-notes/rl-1.11.10.html", "ssec-relnotes-0.16": "release-notes/rl-0.16.html",
"#ssec-relnotes-1.11": "release-notes/rl-1.11.html", "ch-relnotes-0.5": "release-notes/rl-0.5.html",
"#ssec-relnotes-1.2": "release-notes/rl-1.2.html", "ch-relnotes-0.6": "release-notes/rl-0.6.html",
"#ssec-relnotes-1.3": "release-notes/rl-1.3.html", "ch-relnotes-0.7": "release-notes/rl-0.7.html",
"#ssec-relnotes-1.4": "release-notes/rl-1.4.html", "ch-relnotes-0.8.1": "release-notes/rl-0.8.1.html",
"#ssec-relnotes-1.5.1": "release-notes/rl-1.5.1.html", "ch-relnotes-0.8": "release-notes/rl-0.8.html",
"#ssec-relnotes-1.5.2": "release-notes/rl-1.5.2.html", "ch-relnotes-0.9.1": "release-notes/rl-0.9.1.html",
"#ssec-relnotes-1.5": "release-notes/rl-1.5.html", "ch-relnotes-0.9.2": "release-notes/rl-0.9.2.html",
"#ssec-relnotes-1.6.1": "release-notes/rl-1.6.1.html", "ch-relnotes-0.9": "release-notes/rl-0.9.html",
"#ssec-relnotes-1.6.0": "release-notes/rl-1.6.html", "ssec-relnotes-1.0": "release-notes/rl-1.0.html",
"#ssec-relnotes-1.7": "release-notes/rl-1.7.html", "ssec-relnotes-1.1": "release-notes/rl-1.1.html",
"#ssec-relnotes-1.8": "release-notes/rl-1.8.html", "ssec-relnotes-1.10": "release-notes/rl-1.10.html",
"#ssec-relnotes-1.9": "release-notes/rl-1.9.html", "ssec-relnotes-1.11.10": "release-notes/rl-1.11.10.html",
"#ssec-relnotes-2.0": "release-notes/rl-2.0.html", "ssec-relnotes-1.11": "release-notes/rl-1.11.html",
"#ssec-relnotes-2.1": "release-notes/rl-2.1.html", "ssec-relnotes-1.2": "release-notes/rl-1.2.html",
"#ssec-relnotes-2.2": "release-notes/rl-2.2.html", "ssec-relnotes-1.3": "release-notes/rl-1.3.html",
"#ssec-relnotes-2.3": "release-notes/rl-2.3.html" "ssec-relnotes-1.4": "release-notes/rl-1.4.html",
"ssec-relnotes-1.5.1": "release-notes/rl-1.5.1.html",
"ssec-relnotes-1.5.2": "release-notes/rl-1.5.2.html",
"ssec-relnotes-1.5": "release-notes/rl-1.5.html",
"ssec-relnotes-1.6.1": "release-notes/rl-1.6.1.html",
"ssec-relnotes-1.6.0": "release-notes/rl-1.6.html",
"ssec-relnotes-1.7": "release-notes/rl-1.7.html",
"ssec-relnotes-1.8": "release-notes/rl-1.8.html",
"ssec-relnotes-1.9": "release-notes/rl-1.9.html",
"ssec-relnotes-2.0": "release-notes/rl-2.0.html",
"ssec-relnotes-2.1": "release-notes/rl-2.1.html",
"ssec-relnotes-2.2": "release-notes/rl-2.2.html",
"ssec-relnotes-2.3": "release-notes/rl-2.3.html"
},
"language/values.html": {
"simple-values": "#primitives",
"lists": "#list",
"strings": "#string",
"lists": "#list",
"attribute-sets": "#attribute-set"
}
}; };
var isRoot = (document.location.pathname.endsWith('/') || document.location.pathname.endsWith('/index.html')) && path_to_root === ''; // the following code matches the current page's URL against the set of redirects.
if (isRoot && redirects[document.location.hash]) { //
document.location.href = path_to_root + redirects[document.location.hash]; // it is written to minimize the latency between page load and redirect.
// therefore we avoid function calls, copying data, and unnecessary loops.
// IMPORTANT: we use stateful array operations and their order matters!
//
// matching URLs is more involved than it should be:
//
// 1. `document.location.pathname` can have an arbitrary prefix.
//
// 2. `path_to_root` is set by mdBook. it consists only of `../`s and
// determines the depth of `<path>` relative to the prefix:
//
// `document.location.pathname`
// |------------------------------|
// /<prefix>/<path>/[<file>[.html]][#<anchor>]
// |----|
// `path_to_root` has same number of path segments
//
// source: https://phaiax.github.io/mdBook/format/theme/index-hbs.html#data
//
// 3. the following paths are equivalent:
//
// /foo/bar/
// /foo/bar/index.html
// /foo/bar/index
//
// 4. the following paths are also equivalent:
//
// /foo/bar/baz
// /foo/bar/baz.html
//
let segments = document.location.pathname.split('/');
let file = segments.pop();
// normalize file name
if (file === '') { file = "index.html"; }
else if (!file.endsWith('.html')) { file = file + '.html'; }
segments.push(file);
// use `path_to_root` to discern prefix from path.
const depth = path_to_root.split('/').length;
// remove segments containing prefix. the following works because
// 1. the original `document.location.pathname` is absolute,
// hence first element of `segments` is always empty.
// 2. last element of splitting `path_to_root` is also always empty.
// 3. last element of `segments` is the file name.
//
// visual example:
//
// '/foo/bar/baz.html'.split('/') -> [ '', 'foo', 'bar', 'baz.html' ]
// '../'.split('/') -> [ '..', '' ]
//
// the following operations will then result in
//
// path = 'bar/baz.html'
//
segments.splice(0, segments.length - depth);
const path = segments.join('/');
// anchor starts with the hash character (`#`),
// but our redirect declarations don't, so we strip it.
// example:
// document.location.hash -> '#foo'
// document.location.hash.substring(1) -> 'foo'
const anchor = document.location.hash.substring(1);
const redirect = redirects[path];
if (redirect) {
const target = redirect[anchor];
if (target) {
document.location.href = target;
}
} }

View file

@ -8,6 +8,6 @@
# Description # Description
The Nix daemon is necessary in multi-user Nix installations. It performs The Nix daemon is necessary in multi-user Nix installations. It runs
build actions and other operations on the Nix store on behalf of build tasks and other operations on the Nix store on behalf of
unprivileged users. unprivileged users.

View file

@ -71,7 +71,7 @@ paths. Realisation is a somewhat overloaded term:
outputs are already valid, in which case we are done outputs are already valid, in which case we are done
immediately. Otherwise, there may be [substitutes](../glossary.md) immediately. Otherwise, there may be [substitutes](../glossary.md)
that produce the outputs (e.g., by downloading them). Finally, the that produce the outputs (e.g., by downloading them). Finally, the
outputs can be produced by performing the build action described outputs can be produced by running the build task described
by the derivation. by the derivation.
- If the store path is not a derivation, realisation ensures that the - If the store path is not a derivation, realisation ensures that the

View file

@ -1,7 +1,7 @@
# Glossary # Glossary
- [derivation]{#gloss-derivation}\ - [derivation]{#gloss-derivation}\
A description of a build action. The result of a derivation is a A description of a build task. The result of a derivation is a
store object. Derivations are typically specified in Nix expressions store object. Derivations are typically specified in Nix expressions
using the [`derivation` primitive](language/derivations.md). These are using the [`derivation` primitive](language/derivations.md). These are
translated into low-level *store derivations* (implicitly by translated into low-level *store derivations* (implicitly by
@ -53,8 +53,8 @@
A file that is an immediate child of the Nix store directory. These A file that is an immediate child of the Nix store directory. These
can be regular files, but also entire directory trees. Store objects can be regular files, but also entire directory trees. Store objects
can be sources (objects copied from outside of the store), can be sources (objects copied from outside of the store),
derivation outputs (objects produced by running a build action), or derivation outputs (objects produced by running a build task), or
derivations (files describing a build action). derivations (files describing a build task).
- [input-addressed store object]{#gloss-input-addressed-store-object}\ - [input-addressed store object]{#gloss-input-addressed-store-object}\
A store object produced by building a A store object produced by building a

View file

@ -88,10 +88,24 @@ extension. The installer will also create `/etc/profile.d/nix.sh`.
### Linux ### Linux
```console Remove files created by Nix:
sudo rm -rf /etc/profile/nix.sh /etc/nix /nix ~root/.nix-profile ~root/.nix-defexpr ~root/.nix-channels ~/.nix-profile ~/.nix-defexpr ~/.nix-channels
# If you are on Linux with systemd, you will need to run: ```console
sudo rm -rf /nix /etc/nix /etc/profile/nix.sh ~root/.nix-profile ~root/.nix-defexpr ~root/.nix-channels ~/.nix-profile ~/.nix-defexpr ~/.nix-channels
```
Remove build users and their group:
```console
for i in $(seq 30001 30032); do
sudo userdel $i
done
sudo groupdel 30000
```
If you are on Linux with systemd, remove the Nix daemon service:
```console
sudo systemctl stop nix-daemon.socket sudo systemctl stop nix-daemon.socket
sudo systemctl stop nix-daemon.service sudo systemctl stop nix-daemon.service
sudo systemctl disable nix-daemon.socket sudo systemctl disable nix-daemon.socket
@ -99,8 +113,13 @@ sudo systemctl disable nix-daemon.service
sudo systemctl daemon-reload sudo systemctl daemon-reload
``` ```
There may also be references to Nix in `/etc/profile`, `/etc/bashrc`, There may also be references to Nix in
and `/etc/zshrc` which you may remove.
- `/etc/profile`
- `/etc/bashrc`
- `/etc/zshrc`
which you may remove.
### macOS ### macOS

View file

@ -104,7 +104,7 @@ a currently running program.
Packages are built from _Nix expressions_, which is a simple Packages are built from _Nix expressions_, which is a simple
functional language. A Nix expression describes everything that goes functional language. A Nix expression describes everything that goes
into a package build action (a “derivation”): other packages, sources, into a package build task (a “derivation”): other packages, sources,
the build script, environment variables for the build script, etc. the build script, environment variables for the build script, etc.
Nix tries very hard to ensure that Nix expressions are Nix tries very hard to ensure that Nix expressions are
_deterministic_: building a Nix expression twice should yield the same _deterministic_: building a Nix expression twice should yield the same

View file

@ -1,7 +1,7 @@
# Derivations # Derivations
The most important built-in function is `derivation`, which is used to The most important built-in function is `derivation`, which is used to
describe a single derivation (a build action). It takes as input a set, describe a single derivation (a build task). It takes as input a set,
the attributes of which specify the inputs of the build. the attributes of which specify the inputs of the build.
- There must be an attribute named [`system`]{#attr-system} whose value must be a - There must be an attribute named [`system`]{#attr-system} whose value must be a

View file

@ -31,3 +31,551 @@ The Nix language is
Type errors are only detected when expressions are evaluated. Type errors are only detected when expressions are evaluated.
# Overview
This is an incomplete overview of language features, by example.
<table>
<tr>
<th>
Example
</th>
<th>
Description
</th>
</tr>
<tr>
<td>
*Basic values*
</td>
<td>
</td>
</tr>
<tr>
<td>
`"hello world"`
</td>
<td>
A string
</td>
</tr>
<tr>
<td>
```
''
multi
line
string
''
```
</td>
<td>
A multi-line string. Strips common prefixed whitespace. Evaluates to `"multi\n line\n string"`.
</td>
</tr>
<tr>
<td>
`"hello ${ { a = "world" }.a }"`
`"1 2 ${toString 3}"`
`"${pkgs.bash}/bin/sh"`
</td>
<td>
String interpolation (expands to `"hello world"`, `"1 2 3"`, `"/nix/store/<hash>-bash-<version>/bin/sh"`)
</td>
</tr>
<tr>
<td>
`true`, `false`
</td>
<td>
Booleans
</td>
</tr>
<tr>
<td>
`null`
</td>
<td>
Null value
</td>
</tr>
<tr>
<td>
`123`
</td>
<td>
An integer
</td>
</tr>
<tr>
<td>
`3.141`
</td>
<td>
A floating point number
</td>
</tr>
<tr>
<td>
`/etc`
</td>
<td>
An absolute path
</td>
</tr>
<tr>
<td>
`./foo.png`
</td>
<td>
A path relative to the file containing this Nix expression
</td>
</tr>
<tr>
<td>
`~/.config`
</td>
<td>
A home path. Evaluates to the `"<user's home directory>/.config"`.
</td>
</tr>
<tr>
<td>
<nixpkgs>
</td>
<td>
Search path. Value determined by [`$NIX_PATH` environment variable](../command-ref/env-common.md#env-NIX_PATH).
</td>
</tr>
<tr>
<td>
*Compound values*
</td>
<td>
</td>
</tr>
<tr>
<td>
`{ x = 1; y = 2; }`
</td>
<td>
A set with attributes named `x` and `y`
</td>
</tr>
<tr>
<td>
`{ foo.bar = 1; }`
</td>
<td>
A nested set, equivalent to `{ foo = { bar = 1; }; }`
</td>
</tr>
<tr>
<td>
`rec { x = "foo"; y = x + "bar"; }`
</td>
<td>
A recursive set, equivalent to `{ x = "foo"; y = "foobar"; }`
</td>
</tr>
<tr>
<td>
`[ "foo" "bar" "baz" ]`
`[ 1 2 3 ]`
`[ (f 1) { a = 1; b = 2; } [ "c" ] ]`
</td>
<td>
Lists with three elements.
</td>
</tr>
<tr>
<td>
*Operators*
</td>
<td>
</td>
</tr>
<tr>
<td>
`"foo" + "bar"`
</td>
<td>
String concatenation
</td>
</tr>
<tr>
<td>
`1 + 2`
</td>
<td>
Integer addition
</td>
</tr>
<tr>
<td>
`"foo" == "f" + "oo"`
</td>
<td>
Equality test (evaluates to `true`)
</td>
</tr>
<tr>
<td>
`"foo" != "bar"`
</td>
<td>
Inequality test (evaluates to `true`)
</td>
</tr>
<tr>
<td>
`!true`
</td>
<td>
Boolean negation
</td>
</tr>
<tr>
<td>
`{ x = 1; y = 2; }.x`
</td>
<td>
Attribute selection (evaluates to `1`)
</td>
</tr>
<tr>
<td>
`{ x = 1; y = 2; }.z or 3`
</td>
<td>
Attribute selection with default (evaluates to `3`)
</td>
</tr>
<tr>
<td>
`{ x = 1; y = 2; } // { z = 3; }`
</td>
<td>
Merge two sets (attributes in the right-hand set taking precedence)
</td>
</tr>
<tr>
<td>
*Control structures*
</td>
<td>
</td>
</tr>
<tr>
<td>
`if 1 + 1 == 2 then "yes!" else "no!"`
</td>
<td>
Conditional expression
</td>
</tr>
<tr>
<td>
`assert 1 + 1 == 2; "yes!"`
</td>
<td>
Assertion check (evaluates to `"yes!"`).
</td>
</tr>
<tr>
<td>
`let x = "foo"; y = "bar"; in x + y`
</td>
<td>
Variable definition
</td>
</tr>
<tr>
<td>
`with builtins; head [ 1 2 3 ]`
</td>
<td>
Add all attributes from the given set to the scope (evaluates to `1`)
</td>
</tr>
<tr>
<td>
*Functions (lambdas)*
</td>
<td>
</td>
</tr>
<tr>
<td>
`x: x + 1`
</td>
<td>
A function that expects an integer and returns it increased by 1
</td>
</tr>
<tr>
<td>
`x: y: x + y`
</td>
<td>
Curried function, equivalent to `x: (y: x + y)`. Can be used like a function that takes two arguments and returns their sum.
</td>
</tr>
<tr>
<td>
`(x: x + 1) 100`
</td>
<td>
A function call (evaluates to 101)
</td>
</tr>
<tr>
<td>
`let inc = x: x + 1; in inc (inc (inc 100))`
</td>
<td>
A function bound to a variable and subsequently called by name (evaluates to 103)
</td>
</tr>
<tr>
<td>
`{ x, y }: x + y`
</td>
<td>
A function that expects a set with required attributes `x` and `y` and concatenates them
</td>
</tr>
<tr>
<td>
`{ x, y ? "bar" }: x + y`
</td>
<td>
A function that expects a set with required attribute `x` and optional `y`, using `"bar"` as default value for `y`
</td>
</tr>
<tr>
<td>
`{ x, y, ... }: x + y`
</td>
<td>
A function that expects a set with required attributes `x` and `y` and ignores any other attributes
</td>
</tr>
<tr>
<td>
`{ x, y } @ args: x + y`
`args @ { x, y }: x + y`
</td>
<td>
A function that expects a set with required attributes `x` and `y`, and binds the whole set to `args`
</td>
</tr>
<tr>
<td>
*Built-in functions*
</td>
<td>
</td>
</tr>
<tr>
<td>
`import ./foo.nix`
</td>
<td>
Load and return Nix expression in given file
</td>
</tr>
<tr>
<td>
`map (x: x + x) [ 1 2 3 ]`
</td>
<td>
Apply a function to every element of a list (evaluates to `[ 2 4 6 ]`)
</td>
</tr>
</table>

View file

@ -5,4 +5,10 @@
arguments will be ignored and the resulting derivation will have arguments will be ignored and the resulting derivation will have
`__impure` set to `true`, making it an impure derivation. `__impure` set to `true`, making it an impure derivation.
* If `builtins.readFile` is called on a file with context, then only the parts
of that context that appear in the content of the file are retained.
This avoids a lot of spurious errors where some benign strings end-up having
a context just because they are read from a store path
([#7260](https://github.com/NixOS/nix/pull/7260)).
* Allow explicitly selecting outputs with *store derivations* installable syntax too. * Allow explicitly selecting outputs with *store derivations* installable syntax too.

View file

@ -58,7 +58,7 @@ readonly EXTRACTED_NIX_PATH="$(dirname "$0")"
readonly ROOT_HOME=~root readonly ROOT_HOME=~root
if [ -t 0 ]; then if [ -t 0 ] && [ -z "${NIX_INSTALLER_YES:-}" ]; then
readonly IS_HEADLESS='no' readonly IS_HEADLESS='no'
else else
readonly IS_HEADLESS='yes' readonly IS_HEADLESS='yes'

View file

@ -71,6 +71,8 @@ while [ $# -gt 0 ]; do
# # intentional tail space # # intentional tail space
# ACTIONS="${ACTIONS}uninstall " # ACTIONS="${ACTIONS}uninstall "
# ;; # ;;
--yes)
export NIX_INSTALLER_YES=1;;
--no-channel-add) --no-channel-add)
export NIX_INSTALLER_NO_CHANNEL_ADD=1;; export NIX_INSTALLER_NO_CHANNEL_ADD=1;;
--daemon-user-count) --daemon-user-count)
@ -90,7 +92,7 @@ while [ $# -gt 0 ]; do
shift;; shift;;
*) *)
{ {
echo "Nix Installer [--daemon|--no-daemon] [--daemon-user-count INT] [--no-channel-add] [--no-modify-profile] [--nix-extra-conf-file FILE]" echo "Nix Installer [--daemon|--no-daemon] [--daemon-user-count INT] [--yes] [--no-channel-add] [--no-modify-profile] [--nix-extra-conf-file FILE]"
echo "Choose installation method." echo "Choose installation method."
echo "" echo ""
@ -104,6 +106,8 @@ while [ $# -gt 0 ]; do
echo " trivial to uninstall." echo " trivial to uninstall."
echo " (default)" echo " (default)"
echo "" echo ""
echo " --yes: Run the script non-interactively, accepting all prompts."
echo ""
echo " --no-channel-add: Don't add any channels. nixpkgs-unstable is installed by default." echo " --no-channel-add: Don't add any channels. nixpkgs-unstable is installed by default."
echo "" echo ""
echo " --no-modify-profile: Don't modify the user profile to automatically load nix." echo " --no-modify-profile: Don't modify the user profile to automatically load nix."

View file

@ -186,12 +186,12 @@ static int main_build_remote(int argc, char * * argv)
// build the hint template. // build the hint template.
std::string errorText = std::string errorText =
"Failed to find a machine for remote build!\n" "Failed to find a machine for remote build!\n"
"derivation: %s\nrequired (system, features): (%s, %s)"; "derivation: %s\nrequired (system, features): (%s, [%s])";
errorText += "\n%s available machines:"; errorText += "\n%s available machines:";
errorText += "\n(systems, maxjobs, supportedFeatures, mandatoryFeatures)"; errorText += "\n(systems, maxjobs, supportedFeatures, mandatoryFeatures)";
for (unsigned int i = 0; i < machines.size(); ++i) for (unsigned int i = 0; i < machines.size(); ++i)
errorText += "\n(%s, %s, %s, %s)"; errorText += "\n([%s], %s, [%s], [%s])";
// add the template values. // add the template values.
std::string drvstr; std::string drvstr;

View file

@ -207,55 +207,59 @@ Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
void SourceExprCommand::completeInstallable(std::string_view prefix) void SourceExprCommand::completeInstallable(std::string_view prefix)
{ {
if (file) { try {
completionType = ctAttrs; if (file) {
completionType = ctAttrs;
evalSettings.pureEval = false; evalSettings.pureEval = false;
auto state = getEvalState(); auto state = getEvalState();
Expr *e = state->parseExprFromFile( Expr *e = state->parseExprFromFile(
resolveExprPath(state->checkSourcePath(lookupFileArg(*state, *file))) resolveExprPath(state->checkSourcePath(lookupFileArg(*state, *file)))
); );
Value root; Value root;
state->eval(e, root); state->eval(e, root);
auto autoArgs = getAutoArgs(*state); auto autoArgs = getAutoArgs(*state);
std::string prefix_ = std::string(prefix); std::string prefix_ = std::string(prefix);
auto sep = prefix_.rfind('.'); auto sep = prefix_.rfind('.');
std::string searchWord; std::string searchWord;
if (sep != std::string::npos) { if (sep != std::string::npos) {
searchWord = prefix_.substr(sep + 1, std::string::npos); searchWord = prefix_.substr(sep + 1, std::string::npos);
prefix_ = prefix_.substr(0, sep); prefix_ = prefix_.substr(0, sep);
} else { } else {
searchWord = prefix_; searchWord = prefix_;
prefix_ = ""; prefix_ = "";
} }
auto [v, pos] = findAlongAttrPath(*state, prefix_, *autoArgs, root); auto [v, pos] = findAlongAttrPath(*state, prefix_, *autoArgs, root);
Value &v1(*v); Value &v1(*v);
state->forceValue(v1, pos); state->forceValue(v1, pos);
Value v2; Value v2;
state->autoCallFunction(*autoArgs, v1, v2); state->autoCallFunction(*autoArgs, v1, v2);
if (v2.type() == nAttrs) { if (v2.type() == nAttrs) {
for (auto & i : *v2.attrs) { for (auto & i : *v2.attrs) {
std::string name = state->symbols[i.name]; std::string name = state->symbols[i.name];
if (name.find(searchWord) == 0) { if (name.find(searchWord) == 0) {
if (prefix_ == "") if (prefix_ == "")
completions->add(name); completions->add(name);
else else
completions->add(prefix_ + "." + name); completions->add(prefix_ + "." + name);
}
} }
} }
} else {
completeFlakeRefWithFragment(
getEvalState(),
lockFlags,
getDefaultFlakeAttrPathPrefixes(),
getDefaultFlakeAttrPaths(),
prefix);
} }
} else { } catch (EvalError&) {
completeFlakeRefWithFragment( // Don't want eval errors to mess-up with the completion engine, so let's just swallow them
getEvalState(),
lockFlags,
getDefaultFlakeAttrPathPrefixes(),
getDefaultFlakeAttrPaths(),
prefix);
} }
} }
@ -867,20 +871,20 @@ std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
return installables.front(); return installables.front();
} }
BuiltPaths Installable::build( std::vector<BuiltPathWithResult> Installable::build(
ref<Store> evalStore, ref<Store> evalStore,
ref<Store> store, ref<Store> store,
Realise mode, Realise mode,
const std::vector<std::shared_ptr<Installable>> & installables, const std::vector<std::shared_ptr<Installable>> & installables,
BuildMode bMode) BuildMode bMode)
{ {
BuiltPaths res; std::vector<BuiltPathWithResult> res;
for (auto & [_, builtPath] : build2(evalStore, store, mode, installables, bMode)) for (auto & [_, builtPathWithResult] : build2(evalStore, store, mode, installables, bMode))
res.push_back(builtPath); res.push_back(builtPathWithResult);
return res; return res;
} }
std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::build2( std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> Installable::build2(
ref<Store> evalStore, ref<Store> evalStore,
ref<Store> store, ref<Store> store,
Realise mode, Realise mode,
@ -900,7 +904,7 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::bui
} }
} }
std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> res; std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> res;
switch (mode) { switch (mode) {
@ -941,10 +945,10 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::bui
output, *drvOutput->second); output, *drvOutput->second);
} }
} }
res.push_back({installable, BuiltPath::Built { bfd.drvPath, outputs }}); res.push_back({installable, {.path = BuiltPath::Built { bfd.drvPath, outputs }}});
}, },
[&](const DerivedPath::Opaque & bo) { [&](const DerivedPath::Opaque & bo) {
res.push_back({installable, BuiltPath::Opaque { bo.path }}); res.push_back({installable, {.path = BuiltPath::Opaque { bo.path }}});
}, },
}, path.raw()); }, path.raw());
} }
@ -966,10 +970,10 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::bui
std::map<std::string, StorePath> outputs; std::map<std::string, StorePath> outputs;
for (auto & path : buildResult.builtOutputs) for (auto & path : buildResult.builtOutputs)
outputs.emplace(path.first.outputName, path.second.outPath); outputs.emplace(path.first.outputName, path.second.outPath);
res.push_back({installable, BuiltPath::Built { bfd.drvPath, outputs }}); res.push_back({installable, {.path = BuiltPath::Built { bfd.drvPath, outputs }, .result = buildResult}});
}, },
[&](const DerivedPath::Opaque & bo) { [&](const DerivedPath::Opaque & bo) {
res.push_back({installable, BuiltPath::Opaque { bo.path }}); res.push_back({installable, {.path = BuiltPath::Opaque { bo.path }, .result = buildResult}});
}, },
}, buildResult.path.raw()); }, buildResult.path.raw());
} }
@ -992,9 +996,12 @@ BuiltPaths Installable::toBuiltPaths(
OperateOn operateOn, OperateOn operateOn,
const std::vector<std::shared_ptr<Installable>> & installables) const std::vector<std::shared_ptr<Installable>> & installables)
{ {
if (operateOn == OperateOn::Output) if (operateOn == OperateOn::Output) {
return Installable::build(evalStore, store, mode, installables); BuiltPaths res;
else { for (auto & p : Installable::build(evalStore, store, mode, installables))
res.push_back(p.path);
return res;
} else {
if (mode == Realise::Nothing) if (mode == Realise::Nothing)
settings.readOnlyMode = true; settings.readOnlyMode = true;

View file

@ -7,6 +7,7 @@
#include "eval.hh" #include "eval.hh"
#include "store-api.hh" #include "store-api.hh"
#include "flake/flake.hh" #include "flake/flake.hh"
#include "build-result.hh"
#include <optional> #include <optional>
@ -51,6 +52,12 @@ enum class OperateOn {
Derivation Derivation
}; };
struct BuiltPathWithResult
{
BuiltPath path;
std::optional<BuildResult> result;
};
struct Installable struct Installable
{ {
virtual ~Installable() { } virtual ~Installable() { }
@ -91,14 +98,14 @@ struct Installable
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}}); return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
} }
static BuiltPaths build( static std::vector<BuiltPathWithResult> build(
ref<Store> evalStore, ref<Store> evalStore,
ref<Store> store, ref<Store> store,
Realise mode, Realise mode,
const std::vector<std::shared_ptr<Installable>> & installables, const std::vector<std::shared_ptr<Installable>> & installables,
BuildMode bMode = bmNormal); BuildMode bMode = bmNormal);
static std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> build2( static std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> build2(
ref<Store> evalStore, ref<Store> evalStore,
ref<Store> store, ref<Store> store,
Realise mode, Realise mode,

View file

@ -8,7 +8,7 @@ libcmd_SOURCES := $(wildcard $(d)/*.cc)
libcmd_CXXFLAGS += -I src/libutil -I src/libstore -I src/libexpr -I src/libmain -I src/libfetchers -I src/nix libcmd_CXXFLAGS += -I src/libutil -I src/libstore -I src/libexpr -I src/libmain -I src/libfetchers -I src/nix
libcmd_LDFLAGS = $(EDITLINE_LIBS) -llowdown -pthread libcmd_LDFLAGS = $(EDITLINE_LIBS) $(LOWDOWN_LIBS) -pthread
libcmd_LIBS = libstore libutil libexpr libmain libfetchers libcmd_LIBS = libstore libutil libexpr libmain libfetchers

View file

@ -384,6 +384,10 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
i++; i++;
} }
} else { } else {
/* Temporarily disable the debugger, to avoid re-entering readline. */
auto debug_repl = state->debugRepl;
state->debugRepl = nullptr;
Finally restoreDebug([&]() { state->debugRepl = debug_repl; });
try { try {
/* This is an expression that should evaluate to an /* This is an expression that should evaluate to an
attribute set. Evaluate it to get the names of the attribute set. Evaluate it to get the names of the

View file

@ -904,7 +904,7 @@ void EvalState::throwEvalError(const char * s, const std::string & s2,
const std::string & s3) const std::string & s3)
{ {
debugThrowLastTrace(EvalError({ debugThrowLastTrace(EvalError({
.msg = hintfmt(s, s2), .msg = hintfmt(s, s2, s3),
.errPos = positions[noPos] .errPos = positions[noPos]
})); }));
} }
@ -913,7 +913,7 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri
const std::string & s3) const std::string & s3)
{ {
debugThrowLastTrace(EvalError({ debugThrowLastTrace(EvalError({
.msg = hintfmt(s, s2), .msg = hintfmt(s, s2, s3),
.errPos = positions[pos] .errPos = positions[pos]
})); }));
} }
@ -922,7 +922,7 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri
const std::string & s3, Env & env, Expr & expr) const std::string & s3, Env & env, Expr & expr)
{ {
debugThrow(EvalError({ debugThrow(EvalError({
.msg = hintfmt(s, s2), .msg = hintfmt(s, s2, s3),
.errPos = positions[pos] .errPos = positions[pos]
}), env, expr); }), env, expr);
} }

View file

@ -5,6 +5,7 @@
#include "globals.hh" #include "globals.hh"
#include "json-to-value.hh" #include "json-to-value.hh"
#include "names.hh" #include "names.hh"
#include "references.hh"
#include "store-api.hh" #include "store-api.hh"
#include "util.hh" #include "util.hh"
#include "json.hh" #include "json.hh"
@ -1542,6 +1543,10 @@ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, V
refs = state.store->queryPathInfo(state.store->toStorePath(path).first)->references; refs = state.store->queryPathInfo(state.store->toStorePath(path).first)->references;
} catch (Error &) { // FIXME: should be InvalidPathError } catch (Error &) { // FIXME: should be InvalidPathError
} }
// Re-scan references to filter down to just the ones that actually occur in the file.
auto refsSink = PathRefScanSink::fromPaths(refs);
refsSink << s;
refs = refsSink.getResultPaths();
} }
auto context = state.store->printStorePathSet(refs); auto context = state.store->printStorePathSet(refs);
v.mkString(s, context); v.mkString(s, context);

View file

@ -262,17 +262,20 @@ struct GitHubInputScheme : GitArchiveInputScheme
DownloadUrl getDownloadUrl(const Input & input) const override DownloadUrl getDownloadUrl(const Input & input) const override
{ {
// FIXME: use regular /archive URLs instead? api.github.com
// might have stricter rate limits.
auto host = maybeGetStrAttr(input.attrs, "host").value_or("github.com"); auto host = maybeGetStrAttr(input.attrs, "host").value_or("github.com");
auto url = fmt( Headers headers = makeHeadersWithAuthTokens(host);
host == "github.com" // If we have no auth headers then we default to the public archive
? "https://api.%s/repos/%s/%s/tarball/%s" // urls so we do not run into rate limits.
: "https://%s/api/v3/repos/%s/%s/tarball/%s", const auto urlFmt =
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"), host != "github.com"
? "https://%s/api/v3/repos/%s/%s/tarball/%s"
: headers.empty()
? "https://%s/%s/%s/archive/%s.tar.gz"
: "https://api.%s/repos/%s/%s/tarball/%s";
const auto url = fmt(urlFmt, host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
input.getRev()->to_string(Base16, false)); input.getRev()->to_string(Base16, false));
Headers headers = makeHeadersWithAuthTokens(host);
return DownloadUrl { url, headers }; return DownloadUrl { url, headers };
} }

View file

@ -33,6 +33,7 @@
namespace nix { namespace nix {
char * * savedArgv;
static bool gcWarning = true; static bool gcWarning = true;

View file

@ -528,13 +528,31 @@ void DerivationGoal::inputsRealised()
/* Add the relevant output closures of the input derivation /* Add the relevant output closures of the input derivation
`i' as input paths. Only add the closures of output paths `i' as input paths. Only add the closures of output paths
that are specified as inputs. */ that are specified as inputs. */
for (auto & j : wantedDepOutputs) for (auto & j : wantedDepOutputs) {
if (auto outPath = get(inputDrvOutputs, { depDrvPath, j })) /* TODO (impure derivations-induced tech debt):
Tracking input derivation outputs statefully through the
goals is error prone and has led to bugs.
For a robust nix, we need to move towards the `else` branch,
which does not rely on goal state to match up with the
reality of the store, which is our real source of truth.
However, the impure derivations feature still relies on this
fragile way of doing things, because its builds do not have
a representation in the store, which is a usability problem
in itself */
if (auto outPath = get(inputDrvOutputs, { depDrvPath, j })) {
worker.store.computeFSClosure(*outPath, inputPaths); worker.store.computeFSClosure(*outPath, inputPaths);
else }
throw Error( else {
"derivation '%s' requires non-existent output '%s' from input derivation '%s'", auto outMap = worker.evalStore.queryDerivationOutputMap(depDrvPath);
worker.store.printStorePath(drvPath), j, worker.store.printStorePath(depDrvPath)); auto outMapPath = outMap.find(j);
if (outMapPath == outMap.end()) {
throw Error(
"derivation '%s' requires non-existent output '%s' from input derivation '%s'",
worker.store.printStorePath(drvPath), j, worker.store.printStorePath(depDrvPath));
}
worker.store.computeFSClosure(outMapPath->second, inputPaths);
}
}
} }
} }

View file

@ -1552,6 +1552,22 @@ void setupSeccomp()
seccomp_arch_add(ctx, SCMP_ARCH_ARM) != 0) seccomp_arch_add(ctx, SCMP_ARCH_ARM) != 0)
printError("unable to add ARM seccomp architecture; this may result in spurious build failures if running 32-bit ARM processes"); printError("unable to add ARM seccomp architecture; this may result in spurious build failures if running 32-bit ARM processes");
if (nativeSystem == "mips64-linux" &&
seccomp_arch_add(ctx, SCMP_ARCH_MIPS) != 0)
printError("unable to add mips seccomp architecture");
if (nativeSystem == "mips64-linux" &&
seccomp_arch_add(ctx, SCMP_ARCH_MIPS64N32) != 0)
printError("unable to add mips64-*abin32 seccomp architecture");
if (nativeSystem == "mips64el-linux" &&
seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL) != 0)
printError("unable to add mipsel seccomp architecture");
if (nativeSystem == "mips64el-linux" &&
seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL64N32) != 0)
printError("unable to add mips64el-*abin32 seccomp architecture");
/* Prevent builders from creating setuid/setgid binaries. */ /* Prevent builders from creating setuid/setgid binaries. */
for (int perm : { S_ISUID, S_ISGID }) { for (int perm : { S_ISUID, S_ISGID }) {
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(chmod), 1, if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(chmod), 1,

View file

@ -53,28 +53,13 @@ StorePathSet BuiltPath::outPaths() const
); );
} }
template<typename T> std::string DerivedPath::Opaque::to_string(const Store & store) const
nlohmann::json stuffToJSON(const std::vector<T> & ts, ref<Store> store) { {
auto res = nlohmann::json::array();
for (const T & t : ts) {
std::visit([&res, store](const auto & t) {
res.push_back(t.toJSON(store));
}, t.raw());
}
return res;
}
nlohmann::json derivedPathsWithHintsToJSON(const BuiltPaths & buildables, ref<Store> store)
{ return stuffToJSON<BuiltPath>(buildables, store); }
nlohmann::json derivedPathsToJSON(const DerivedPaths & paths, ref<Store> store)
{ return stuffToJSON<DerivedPath>(paths, store); }
std::string DerivedPath::Opaque::to_string(const Store & store) const {
return store.printStorePath(path); return store.printStorePath(path);
} }
std::string DerivedPath::Built::to_string(const Store & store) const { std::string DerivedPath::Built::to_string(const Store & store) const
{
return store.printStorePath(drvPath) return store.printStorePath(drvPath)
+ "!" + "!"
+ (outputs.empty() ? std::string { "*" } : concatStringsSep(",", outputs)); + (outputs.empty() ? std::string { "*" } : concatStringsSep(",", outputs));

View file

@ -125,7 +125,4 @@ struct BuiltPath : _BuiltPathRaw {
typedef std::vector<DerivedPath> DerivedPaths; typedef std::vector<DerivedPath> DerivedPaths;
typedef std::vector<BuiltPath> BuiltPaths; typedef std::vector<BuiltPath> BuiltPaths;
nlohmann::json derivedPathsWithHintsToJSON(const BuiltPaths & buildables, ref<Store> store);
nlohmann::json derivedPathsToJSON(const DerivedPaths & , ref<Store> store);
} }

View file

@ -20,7 +20,7 @@ endif
$(foreach file,$(libstore_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/sandbox))) $(foreach file,$(libstore_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/sandbox)))
ifeq ($(ENABLE_S3), 1) ifeq ($(ENABLE_S3), 1)
libstore_LDFLAGS += -laws-cpp-sdk-transfer -laws-cpp-sdk-s3 -laws-cpp-sdk-core libstore_LDFLAGS += -laws-cpp-sdk-transfer -laws-cpp-sdk-s3 -laws-cpp-sdk-core -laws-crt-cpp
endif endif
ifdef HOST_SOLARIS ifdef HOST_SOLARIS

View file

@ -67,6 +67,40 @@ void RefScanSink::operator () (std::string_view data)
} }
PathRefScanSink::PathRefScanSink(StringSet && hashes, std::map<std::string, StorePath> && backMap)
: RefScanSink(std::move(hashes))
, backMap(std::move(backMap))
{ }
PathRefScanSink PathRefScanSink::fromPaths(const StorePathSet & refs)
{
StringSet hashes;
std::map<std::string, StorePath> backMap;
for (auto & i : refs) {
std::string hashPart(i.hashPart());
auto inserted = backMap.emplace(hashPart, i).second;
assert(inserted);
hashes.insert(hashPart);
}
return PathRefScanSink(std::move(hashes), std::move(backMap));
}
StorePathSet PathRefScanSink::getResultPaths()
{
/* Map the hashes found back to their store paths. */
StorePathSet found;
for (auto & i : getResult()) {
auto j = backMap.find(i);
assert(j != backMap.end());
found.insert(j->second);
}
return found;
}
std::pair<StorePathSet, HashResult> scanForReferences( std::pair<StorePathSet, HashResult> scanForReferences(
const std::string & path, const std::string & path,
const StorePathSet & refs) const StorePathSet & refs)
@ -82,30 +116,13 @@ StorePathSet scanForReferences(
const Path & path, const Path & path,
const StorePathSet & refs) const StorePathSet & refs)
{ {
StringSet hashes; PathRefScanSink refsSink = PathRefScanSink::fromPaths(refs);
std::map<std::string, StorePath> backMap; TeeSink sink { refsSink, toTee };
for (auto & i : refs) {
std::string hashPart(i.hashPart());
auto inserted = backMap.emplace(hashPart, i).second;
assert(inserted);
hashes.insert(hashPart);
}
/* Look for the hashes in the NAR dump of the path. */ /* Look for the hashes in the NAR dump of the path. */
RefScanSink refsSink(std::move(hashes));
TeeSink sink { refsSink, toTee };
dumpPath(path, sink); dumpPath(path, sink);
/* Map the hashes found back to their store paths. */ return refsSink.getResultPaths();
StorePathSet found;
for (auto & i : refsSink.getResult()) {
auto j = backMap.find(i);
assert(j != backMap.end());
found.insert(j->second);
}
return found;
} }

View file

@ -27,6 +27,19 @@ public:
void operator () (std::string_view data) override; void operator () (std::string_view data) override;
}; };
class PathRefScanSink : public RefScanSink
{
std::map<std::string, StorePath> backMap;
PathRefScanSink(StringSet && hashes, std::map<std::string, StorePath> && backMap);
public:
static PathRefScanSink fromPaths(const StorePathSet & refs);
StorePathSet getResultPaths();
};
struct RewritingSink : Sink struct RewritingSink : Sink
{ {
std::string from, to, prev; std::string from, to, prev;

View file

@ -77,9 +77,7 @@ TarArchive::~TarArchive()
static void extract_archive(TarArchive & archive, const Path & destDir) static void extract_archive(TarArchive & archive, const Path & destDir)
{ {
int flags = ARCHIVE_EXTRACT_FFLAGS int flags = ARCHIVE_EXTRACT_TIME
| ARCHIVE_EXTRACT_PERM
| ARCHIVE_EXTRACT_TIME
| ARCHIVE_EXTRACT_SECURE_SYMLINKS | ARCHIVE_EXTRACT_SECURE_SYMLINKS
| ARCHIVE_EXTRACT_SECURE_NODOTDOT; | ARCHIVE_EXTRACT_SECURE_NODOTDOT;
@ -98,6 +96,10 @@ static void extract_archive(TarArchive & archive, const Path & destDir)
archive_entry_copy_pathname(entry, archive_entry_copy_pathname(entry,
(destDir + "/" + name).c_str()); (destDir + "/" + name).c_str());
// sources can and do contain dirs with no rx bits
if (archive_entry_filetype(entry) == AE_IFDIR && (archive_entry_mode(entry) & 0500) != 0500)
archive_entry_set_mode(entry, archive_entry_mode(entry) | 0500);
// Patch hardlink path // Patch hardlink path
const char *original_hardlink = archive_entry_hardlink(entry); const char *original_hardlink = archive_entry_hardlink(entry);
if (original_hardlink) { if (original_hardlink) {

View file

@ -37,11 +37,13 @@ struct InstallableDerivedPath : Installable
* Return the rewrites that are needed to resolve a string whose context is * Return the rewrites that are needed to resolve a string whose context is
* included in `dependencies`. * included in `dependencies`.
*/ */
StringPairs resolveRewrites(Store & store, const BuiltPaths dependencies) StringPairs resolveRewrites(
Store & store,
const std::vector<BuiltPathWithResult> & dependencies)
{ {
StringPairs res; StringPairs res;
for (auto & dep : dependencies) for (auto & dep : dependencies)
if (auto drvDep = std::get_if<BuiltPathBuilt>(&dep)) if (auto drvDep = std::get_if<BuiltPathBuilt>(&dep.path))
for (auto & [ outputName, outputPath ] : drvDep->outputs) for (auto & [ outputName, outputPath ] : drvDep->outputs)
res.emplace( res.emplace(
downstreamPlaceholder(store, drvDep->drvPath, outputName), downstreamPlaceholder(store, drvDep->drvPath, outputName),
@ -53,7 +55,10 @@ StringPairs resolveRewrites(Store & store, const BuiltPaths dependencies)
/** /**
* Resolve the given string assuming the given context. * Resolve the given string assuming the given context.
*/ */
std::string resolveString(Store & store, const std::string & toResolve, const BuiltPaths dependencies) std::string resolveString(
Store & store,
const std::string & toResolve,
const std::vector<BuiltPathWithResult> & dependencies)
{ {
auto rewrites = resolveRewrites(store, dependencies); auto rewrites = resolveRewrites(store, dependencies);
return rewriteStrings(toResolve, rewrites); return rewriteStrings(toResolve, rewrites);

View file

@ -10,6 +10,33 @@
using namespace nix; using namespace nix;
nlohmann::json derivedPathsToJSON(const DerivedPaths & paths, ref<Store> store)
{
auto res = nlohmann::json::array();
for (auto & t : paths) {
std::visit([&res, store](const auto & t) {
res.push_back(t.toJSON(store));
}, t.raw());
}
return res;
}
nlohmann::json builtPathsWithResultToJSON(const std::vector<BuiltPathWithResult> & buildables, ref<Store> store)
{
auto res = nlohmann::json::array();
for (auto & b : buildables) {
std::visit([&](const auto & t) {
auto j = t.toJSON(store);
if (b.result) {
j["startTime"] = b.result->startTime;
j["stopTime"] = b.result->stopTime;
}
res.push_back(j);
}, b.path.raw());
}
return res;
}
struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
{ {
Path outLink = "result"; Path outLink = "result";
@ -78,7 +105,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
Realise::Outputs, Realise::Outputs,
installables, buildMode); installables, buildMode);
if (json) logger->cout("%s", derivedPathsWithHintsToJSON(buildables, store).dump()); if (json) logger->cout("%s", builtPathsWithResultToJSON(buildables, store).dump());
if (outLink != "") if (outLink != "")
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>()) if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
@ -98,7 +125,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
store2->addPermRoot(output.second, absPath(symlink)); store2->addPermRoot(output.second, absPath(symlink));
} }
}, },
}, buildable.raw()); }, buildable.path.raw());
} }
if (printOutputPaths) { if (printOutputPaths) {
@ -113,11 +140,14 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
std::cout << store->printStorePath(output.second) << std::endl; std::cout << store->printStorePath(output.second) << std::endl;
} }
}, },
}, buildable.raw()); }, buildable.path.raw());
} }
} }
updateProfile(buildables); BuiltPaths buildables2;
for (auto & b : buildables)
buildables2.push_back(b.path);
updateProfile(buildables2);
} }
}; };

View file

@ -11,7 +11,7 @@ R""(
# Description # Description
This command runs the Nix daemon, which is a required component in This command runs the Nix daemon, which is a required component in
multi-user Nix installations. It performs build actions and other multi-user Nix installations. It runs build tasks and other
operations on the Nix store on behalf of non-root users. Usually you operations on the Nix store on behalf of non-root users. Usually you
don't run the daemon directly; instead it's managed by a service don't run the daemon directly; instead it's managed by a service
management framework such as `systemd`. management framework such as `systemd`.

View file

@ -18,7 +18,7 @@ nix_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libexpr
nix_LIBS = libexpr libmain libfetchers libstore libutil libcmd nix_LIBS = libexpr libmain libfetchers libstore libutil libcmd
nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -llowdown nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS)
$(foreach name, \ $(foreach name, \
nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \ nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \

View file

@ -53,7 +53,6 @@ static bool haveInternet()
} }
std::string programPath; std::string programPath;
char * * savedArgv;
struct HelpRequested { }; struct HelpRequested { };

View file

@ -253,11 +253,11 @@ struct ProfileManifest
static std::map<Installable *, BuiltPaths> static std::map<Installable *, BuiltPaths>
builtPathsPerInstallable( builtPathsPerInstallable(
const std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> & builtPaths) const std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> & builtPaths)
{ {
std::map<Installable *, BuiltPaths> res; std::map<Installable *, BuiltPaths> res;
for (auto & [installable, builtPath] : builtPaths) for (auto & [installable, builtPath] : builtPaths)
res[installable.get()].push_back(builtPath); res[installable.get()].push_back(builtPath.path);
return res; return res;
} }

View file

@ -83,20 +83,47 @@ struct CmdWhyDepends : SourceExprCommand
{ {
auto package = parseInstallable(store, _package); auto package = parseInstallable(store, _package);
auto packagePath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, package); auto packagePath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, package);
/* We don't need to build `dependency`. We try to get the store
* path if it's already known, and if not, then it's not a dependency.
*
* Why? If `package` does depends on `dependency`, then getting the
* store path of `package` above necessitated having the store path
* of `dependency`. The contrapositive is, if the store path of
* `dependency` is not already known at this point (i.e. it's a CA
* derivation which hasn't been built), then `package` did not need it
* to build.
*/
auto dependency = parseInstallable(store, _dependency); auto dependency = parseInstallable(store, _dependency);
auto dependencyPath = Installable::toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency); auto derivedDependency = dependency->toDerivedPath();
auto dependencyPathHash = dependencyPath.hashPart(); auto optDependencyPath = std::visit(overloaded {
[](const DerivedPath::Opaque & nodrv) -> std::optional<StorePath> {
return { nodrv.path };
},
[&](const DerivedPath::Built & hasdrv) -> std::optional<StorePath> {
if (hasdrv.outputs.size() != 1) {
throw Error("argument '%s' should evaluate to one store path", dependency->what());
}
auto outputMap = store->queryPartialDerivationOutputMap(hasdrv.drvPath);
auto maybePath = outputMap.find(*hasdrv.outputs.begin());
if (maybePath == outputMap.end()) {
throw Error("unexpected end of iterator");
}
return maybePath->second;
},
}, derivedDependency.raw());
StorePathSet closure; StorePathSet closure;
store->computeFSClosure({packagePath}, closure, false, false); store->computeFSClosure({packagePath}, closure, false, false);
if (!closure.count(dependencyPath)) { if (!optDependencyPath.has_value() || !closure.count(*optDependencyPath)) {
printError("'%s' does not depend on '%s'", printError("'%s' does not depend on '%s'", package->what(), dependency->what());
store->printStorePath(packagePath),
store->printStorePath(dependencyPath));
return; return;
} }
auto dependencyPath = *optDependencyPath;
auto dependencyPathHash = dependencyPath.hashPart();
stopProgressBar(); // FIXME stopProgressBar(); // FIXME
auto accessor = store->getFSAccessor(); auto accessor = store->getFSAccessor();

View file

@ -72,3 +72,54 @@ testNormalization () {
} }
testNormalization testNormalization
# https://github.com/NixOS/nix/issues/6572
issue_6572_independent_outputs() {
nix build -f multiple-outputs.nix --json independent --no-link > $TEST_ROOT/independent.json
# Make sure that 'nix build' can build a derivation that depends on both outputs of another derivation.
p=$(nix build -f multiple-outputs.nix use-independent --no-link --print-out-paths)
nix-store --delete "$p" # Clean up for next test
# Make sure that 'nix build' tracks input-outputs correctly when a single output is already present.
nix-store --delete "$(jq -r <$TEST_ROOT/independent.json .[0].outputs.first)"
p=$(nix build -f multiple-outputs.nix use-independent --no-link --print-out-paths)
cmp $p <<EOF
first
second
EOF
nix-store --delete "$p" # Clean up for next test
# Make sure that 'nix build' tracks input-outputs correctly when a single output is already present.
nix-store --delete "$(jq -r <$TEST_ROOT/independent.json .[0].outputs.second)"
p=$(nix build -f multiple-outputs.nix use-independent --no-link --print-out-paths)
cmp $p <<EOF
first
second
EOF
nix-store --delete "$p" # Clean up for next test
}
issue_6572_independent_outputs
# https://github.com/NixOS/nix/issues/6572
issue_6572_dependent_outputs() {
nix build -f multiple-outputs.nix --json a --no-link > $TEST_ROOT/a.json
# # Make sure that 'nix build' can build a derivation that depends on both outputs of another derivation.
p=$(nix build -f multiple-outputs.nix use-a --no-link --print-out-paths)
nix-store --delete "$p" # Clean up for next test
# Make sure that 'nix build' tracks input-outputs correctly when a single output is already present.
nix-store --delete "$(jq -r <$TEST_ROOT/a.json .[0].outputs.second)"
p=$(nix build -f multiple-outputs.nix use-a --no-link --print-out-paths)
cmp $p <<EOF
first
second
EOF
nix-store --delete "$p" # Clean up for next test
}
if isDaemonNewer "2.12pre0"; then
issue_6572_dependent_outputs
fi

5
tests/ca/why-depends.sh Normal file
View file

@ -0,0 +1,5 @@
source common.sh
export NIX_TESTS_CA_BY_DEFAULT=1
cd .. && source why-depends.sh

View file

@ -28,6 +28,10 @@ cat <<EOF > bar/flake.nix
}; };
} }
EOF EOF
mkdir -p err
cat <<EOF > err/flake.nix
throw "error"
EOF
# Test the completion of a subcommand # Test the completion of a subcommand
[[ "$(NIX_GET_COMPLETIONS=1 nix buil)" == $'normal\nbuild\t' ]] [[ "$(NIX_GET_COMPLETIONS=1 nix buil)" == $'normal\nbuild\t' ]]
@ -60,3 +64,5 @@ NIX_GET_COMPLETIONS=3 nix build --option allow-import-from | grep -- "allow-impo
# Attr path completions # Attr path completions
[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./foo\#sam)" == $'attrs\n./foo#sampleOutput\t' ]] [[ "$(NIX_GET_COMPLETIONS=2 nix eval ./foo\#sam)" == $'attrs\n./foo#sampleOutput\t' ]]
[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./foo/flake.nix outp)" == $'attrs\noutputs\t' ]] [[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./foo/flake.nix outp)" == $'attrs\noutputs\t' ]]
[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./err/flake.nix outp 2>&1)" == $'attrs' ]]
[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./err\# 2>&1)" == $'attrs' ]]

View file

@ -7,7 +7,7 @@ with import (nixpkgs + "/nixos/lib/testing-python.nix") {
let let
# Generate a fake root CA and a fake api.github.com / channels.nixos.org certificate. # Generate a fake root CA and a fake api.github.com / github.com / channels.nixos.org certificate.
cert = pkgs.runCommand "cert" { buildInputs = [ pkgs.openssl ]; } cert = pkgs.runCommand "cert" { buildInputs = [ pkgs.openssl ]; }
'' ''
mkdir -p $out mkdir -p $out
@ -18,7 +18,7 @@ let
openssl req -newkey rsa:2048 -nodes -keyout $out/server.key \ openssl req -newkey rsa:2048 -nodes -keyout $out/server.key \
-subj "/C=CN/ST=Denial/L=Springfield/O=Dis/CN=github.com" -out server.csr -subj "/C=CN/ST=Denial/L=Springfield/O=Dis/CN=github.com" -out server.csr
openssl x509 -req -extfile <(printf "subjectAltName=DNS:api.github.com,DNS:channels.nixos.org") \ openssl x509 -req -extfile <(printf "subjectAltName=DNS:api.github.com,DNS:github.com,DNS:channels.nixos.org") \
-days 36500 -in server.csr -CA $out/ca.crt -CAkey ca.key -CAcreateserial -out $out/server.crt -days 36500 -in server.csr -CA $out/ca.crt -CAkey ca.key -CAcreateserial -out $out/server.crt
''; '';
@ -37,6 +37,17 @@ let
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs" "repo": "nixpkgs"
} }
},
{
"from": {
"type": "indirect",
"id": "private-flake"
},
"to": {
"type": "github",
"owner": "fancy-enterprise",
"repo": "private-flake"
}
} }
], ],
"version": 2 "version": 2
@ -45,20 +56,40 @@ let
destination = "/flake-registry.json"; destination = "/flake-registry.json";
}; };
api = pkgs.runCommand "nixpkgs-flake" {} private-flake-rev = "9f1dd0df5b54a7dc75b618034482ed42ce34383d";
private-flake-api = pkgs.runCommand "private-flake" {}
'' ''
mkdir -p $out/tarball mkdir -p $out/{commits,tarball}
# Setup https://docs.github.com/en/rest/commits/commits#get-a-commit
echo '{"sha": "${private-flake-rev}"}' > $out/commits/HEAD
# Setup tarball download via API
dir=private-flake
mkdir $dir
echo '{ outputs = {...}: {}; }' > $dir/flake.nix
tar cfz $out/tarball/${private-flake-rev} $dir --hard-dereference
'';
nixpkgs-api = pkgs.runCommand "nixpkgs-flake" {}
''
mkdir -p $out/commits
# Setup https://docs.github.com/en/rest/commits/commits#get-a-commit
echo '{"sha": "${nixpkgs.rev}"}' > $out/commits/HEAD
'';
archive = pkgs.runCommand "nixpkgs-flake" {}
''
mkdir -p $out/archive
dir=NixOS-nixpkgs-${nixpkgs.shortRev} dir=NixOS-nixpkgs-${nixpkgs.shortRev}
cp -prd ${nixpkgs} $dir cp -prd ${nixpkgs} $dir
# Set the correct timestamp in the tarball. # Set the correct timestamp in the tarball.
find $dir -print0 | xargs -0 touch -t ${builtins.substring 0 12 nixpkgs.lastModifiedDate}.${builtins.substring 12 2 nixpkgs.lastModifiedDate} -- find $dir -print0 | xargs -0 touch -t ${builtins.substring 0 12 nixpkgs.lastModifiedDate}.${builtins.substring 12 2 nixpkgs.lastModifiedDate} --
tar cfz $out/tarball/${nixpkgs.rev} $dir --hard-dereference tar cfz $out/archive/${nixpkgs.rev}.tar.gz $dir --hard-dereference
mkdir -p $out/commits
echo '{"sha": "${nixpkgs.rev}"}' > $out/commits/HEAD
''; '';
in in
makeTest ( makeTest (
@ -93,7 +124,20 @@ makeTest (
sslServerCert = "${cert}/server.crt"; sslServerCert = "${cert}/server.crt";
servedDirs = servedDirs =
[ { urlPath = "/repos/NixOS/nixpkgs"; [ { urlPath = "/repos/NixOS/nixpkgs";
dir = api; dir = nixpkgs-api;
}
{ urlPath = "/repos/fancy-enterprise/private-flake";
dir = private-flake-api;
}
];
};
services.httpd.virtualHosts."github.com" =
{ forceSSL = true;
sslServerKey = "${cert}/server.key";
sslServerCert = "${cert}/server.crt";
servedDirs =
[ { urlPath = "/NixOS/nixpkgs";
dir = archive;
} }
]; ];
}; };
@ -107,9 +151,8 @@ makeTest (
virtualisation.memorySize = 4096; virtualisation.memorySize = 4096;
nix.binaryCaches = lib.mkForce [ ]; nix.binaryCaches = lib.mkForce [ ];
nix.extraOptions = "experimental-features = nix-command flakes"; nix.extraOptions = "experimental-features = nix-command flakes";
environment.systemPackages = [ pkgs.jq ];
networking.hosts.${(builtins.head nodes.github.config.networking.interfaces.eth1.ipv4.addresses).address} = networking.hosts.${(builtins.head nodes.github.config.networking.interfaces.eth1.ipv4.addresses).address} =
[ "channels.nixos.org" "api.github.com" ]; [ "channels.nixos.org" "api.github.com" "github.com" ];
security.pki.certificateFiles = [ "${cert}/ca.crt" ]; security.pki.certificateFiles = [ "${cert}/ca.crt" ];
}; };
}; };
@ -121,22 +164,39 @@ makeTest (
start_all() start_all()
def cat_log():
github.succeed("cat /var/log/httpd/*.log >&2")
github.wait_for_unit("httpd.service") github.wait_for_unit("httpd.service")
client.succeed("curl -v https://api.github.com/ >&2") client.succeed("curl -v https://github.com/ >&2")
client.succeed("nix registry list | grep nixpkgs") out = client.succeed("nix registry list")
print(out)
assert "github:NixOS/nixpkgs" in out, "nixpkgs flake not found"
assert "github:fancy-enterprise/private-flake" in out, "private flake not found"
cat_log()
rev = client.succeed("nix flake info nixpkgs --json | jq -r .revision") # If no github access token is provided, nix should use the public archive url...
assert rev.strip() == "${nixpkgs.rev}", "revision mismatch" out = client.succeed("nix flake metadata nixpkgs --json")
print(out)
info = json.loads(out)
assert info["revision"] == "${nixpkgs.rev}", f"revision mismatch: {info['revision']} != ${nixpkgs.rev}"
cat_log()
# ... otherwise it should use the API
out = client.succeed("nix flake metadata private-flake --json --access-tokens github.com=ghp_000000000000000000000000000000000000 --tarball-ttl 0")
print(out)
info = json.loads(out)
assert info["revision"] == "${private-flake-rev}", f"revision mismatch: {info['revision']} != ${private-flake-rev}"
cat_log()
client.succeed("nix registry pin nixpkgs") client.succeed("nix registry pin nixpkgs")
client.succeed("nix flake metadata nixpkgs --tarball-ttl 0 >&2")
client.succeed("nix flake info nixpkgs --tarball-ttl 0 >&2")
# Shut down the web server. The flake should be cached on the client. # Shut down the web server. The flake should be cached on the client.
github.succeed("systemctl stop httpd.service") github.succeed("systemctl stop httpd.service")
info = json.loads(client.succeed("nix flake info nixpkgs --json")) info = json.loads(client.succeed("nix flake metadata nixpkgs --json"))
date = time.strftime("%Y%m%d%H%M%S", time.gmtime(info['lastModified'])) date = time.strftime("%Y%m%d%H%M%S", time.gmtime(info['lastModified']))
assert date == "${nixpkgs.lastModifiedDate}", "time mismatch" assert date == "${nixpkgs.lastModifiedDate}", "time mismatch"

View file

@ -2,7 +2,7 @@ source common.sh
requireDaemonNewerThan "2.8pre20220311" requireDaemonNewerThan "2.8pre20220311"
enableFeatures "ca-derivations ca-references impure-derivations" enableFeatures "ca-derivations impure-derivations"
restartDaemon restartDaemon
set -o pipefail set -o pipefail

View file

@ -31,6 +31,15 @@ rec {
helloString = "Hello, world!"; helloString = "Hello, world!";
}; };
use-a = mkDerivation {
name = "use-a";
inherit (a) first second;
builder = builtins.toFile "builder.sh"
''
cat $first/file $second/file >$out
'';
};
b = mkDerivation { b = mkDerivation {
defaultOutput = assert a.second.helloString == "Hello, world!"; a; defaultOutput = assert a.second.helloString == "Hello, world!"; a;
firstOutput = assert a.outputName == "first"; a.first.first; firstOutput = assert a.outputName == "first"; a.first.first;
@ -87,4 +96,25 @@ rec {
buildCommand = "mkdir $a $b $c"; buildCommand = "mkdir $a $b $c";
}; };
independent = mkDerivation {
name = "multiple-outputs-independent";
outputs = [ "first" "second" ];
builder = builtins.toFile "builder.sh"
''
mkdir $first $second
test -z $all
echo "first" > $first/file
echo "second" > $second/file
'';
};
use-independent = mkDerivation {
name = "use-independent";
inherit (a) first second;
builder = builtins.toFile "builder.sh"
''
cat $first/file $second/file >$out
'';
};
} }

View file

@ -1 +0,0 @@
echo "$input" > $out

View file

@ -6,14 +6,23 @@ let
dependent = mkDerivation { dependent = mkDerivation {
name = "dependent"; name = "dependent";
builder = ./readfile-context.builder.sh; buildCommand = ''
input = "${input}/hello"; mkdir -p $out
echo -n "$input1" > "$out/file1"
echo -n "$input2" > "$out/file2"
'';
input1 = "${input}/hello";
input2 = "hello";
}; };
readDependent = mkDerivation { readDependent = mkDerivation {
name = "read-dependent"; # Will evaluate correctly because file2 doesn't have any references,
builder = ./readfile-context.builder.sh; # even though the `dependent` derivation does.
input = builtins.readFile dependent; name = builtins.readFile (dependent + "/file2");
buildCommand = ''
echo "$input" > "$out"
'';
input = builtins.readFile (dependent + "/file1");
}; };
in readDependent in readDependent