Compare commits
2 Commits
2.9.0
...
nix-init-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc711c6956 | ||
|
|
401b09b7fe |
@@ -1,7 +0,0 @@
|
||||
**Release Notes**
|
||||
Please include relevant [release notes](https://github.com/NixOS/nix/blob/master/doc/manual/src/release-notes/rl-next.md) as needed.
|
||||
|
||||
|
||||
**Testing**
|
||||
|
||||
If this issue is a regression or something that should block release, please consider including a test either in the [testsuite](https://github.com/NixOS/nix/tree/master/tests) or as a [hydraJob]( https://github.com/NixOS/nix/blob/master/flake.nix#L396) so that it can be part of the [automatic checks](https://hydra.nixos.org/jobset/nix/master).
|
||||
4
.github/workflows/backport.yml
vendored
4
.github/workflows/backport.yml
vendored
@@ -8,14 +8,14 @@ jobs:
|
||||
if: github.repository_owner == 'NixOS' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name))
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
# required to find all branches
|
||||
fetch-depth: 0
|
||||
- name: Create backport PRs
|
||||
# should be kept in sync with `version`
|
||||
uses: zeebe-io/backport-action@v0.0.8
|
||||
uses: zeebe-io/backport-action@v0.0.7
|
||||
with:
|
||||
# Config README: https://github.com/zeebe-io/backport-action#backport-action
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
16
.github/workflows/hydra_status.yml
vendored
16
.github/workflows/hydra_status.yml
vendored
@@ -1,16 +0,0 @@
|
||||
name: Hydra status
|
||||
on:
|
||||
schedule:
|
||||
- cron: "12,42 * * * *"
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
check_hydra_status:
|
||||
name: Check Hydra status
|
||||
if: github.repository_owner == 'NixOS'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: bash scripts/check-hydra-status.sh
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: "CI"
|
||||
name: "Test"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -14,10 +14,10 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2.4.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: cachix/install-nix-action@v17
|
||||
- uses: cachix/install-nix-action@v16
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- uses: cachix/cachix-action@v10
|
||||
if: needs.check_cachix.outputs.secret == 'true'
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
name: '${{ env.CACHIX_NAME }}'
|
||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
- run: nix --experimental-features 'nix-command flakes' flake check -L
|
||||
- run: nix-build -A checks.$(nix-instantiate --eval -E '(builtins.currentSystem)')
|
||||
|
||||
check_cachix:
|
||||
name: Cachix secret present for installer tests
|
||||
@@ -46,11 +46,11 @@ jobs:
|
||||
outputs:
|
||||
installerURL: ${{ steps.prepare-installer.outputs.installerURL }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2.4.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- uses: cachix/install-nix-action@v17
|
||||
- uses: cachix/install-nix-action@v16
|
||||
- uses: cachix/cachix-action@v10
|
||||
with:
|
||||
name: '${{ env.CACHIX_NAME }}'
|
||||
@@ -67,42 +67,10 @@ jobs:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- uses: cachix/install-nix-action@v17
|
||||
- uses: cachix/install-nix-action@v16
|
||||
with:
|
||||
install_url: '${{needs.installer.outputs.installerURL}}'
|
||||
install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve"
|
||||
- run: nix-instantiate -E 'builtins.currentTime' --eval
|
||||
|
||||
docker_push_image:
|
||||
needs: [check_cachix, tests]
|
||||
if: >-
|
||||
github.event_name == 'push' &&
|
||||
github.ref_name == 'master' &&
|
||||
needs.check_cachix.outputs.secret == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: cachix/install-nix-action@v17
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- run: echo NIX_VERSION="$(nix-instantiate --eval -E '(import ./default.nix).defaultPackage.${builtins.currentSystem}.version' | tr -d \")" >> $GITHUB_ENV
|
||||
- uses: cachix/cachix-action@v10
|
||||
if: needs.check_cachix.outputs.secret == 'true'
|
||||
with:
|
||||
name: '${{ env.CACHIX_NAME }}'
|
||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
- run: nix --experimental-features 'nix-command flakes' build .#dockerImage -L
|
||||
- run: docker load -i ./result/image.tar.gz
|
||||
- run: docker tag nix:$NIX_VERSION nixos/nix:$NIX_VERSION
|
||||
- run: docker tag nix:$NIX_VERSION nixos/nix:master
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- run: docker push nixos/nix:$NIX_VERSION
|
||||
- run: docker push nixos/nix:master
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -35,7 +35,6 @@ perl/Makefile.config
|
||||
/src/libexpr/parser-tab.hh
|
||||
/src/libexpr/parser-tab.output
|
||||
/src/libexpr/nix.tbl
|
||||
/src/libexpr/tests/libexpr-tests
|
||||
|
||||
# /src/libstore/
|
||||
*.gen.*
|
||||
@@ -80,7 +79,6 @@ perl/Makefile.config
|
||||
/tests/shell.drv
|
||||
/tests/config.nix
|
||||
/tests/ca/config.nix
|
||||
/tests/repl-result-out
|
||||
|
||||
# /tests/lang/
|
||||
/tests/lang/*.out
|
||||
@@ -92,7 +90,6 @@ perl/Makefile.config
|
||||
|
||||
/misc/systemd/nix-daemon.service
|
||||
/misc/systemd/nix-daemon.socket
|
||||
/misc/systemd/nix-daemon.conf
|
||||
/misc/upstart/nix-daemon.conf
|
||||
|
||||
/src/resolve-system-dependencies/resolve-system-dependencies
|
||||
@@ -123,7 +120,3 @@ GTAGS
|
||||
compile_commands.json
|
||||
|
||||
nix-rust/target
|
||||
|
||||
result
|
||||
|
||||
.vscode/
|
||||
|
||||
1
Makefile
1
Makefile
@@ -8,7 +8,6 @@ makefiles = \
|
||||
src/libfetchers/local.mk \
|
||||
src/libmain/local.mk \
|
||||
src/libexpr/local.mk \
|
||||
src/libexpr/tests/local.mk \
|
||||
src/libcmd/local.mk \
|
||||
src/nix/local.mk \
|
||||
src/resolve-system-dependencies/local.mk \
|
||||
|
||||
@@ -16,7 +16,6 @@ LDFLAGS = @LDFLAGS@
|
||||
LIBARCHIVE_LIBS = @LIBARCHIVE_LIBS@
|
||||
LIBBROTLI_LIBS = @LIBBROTLI_LIBS@
|
||||
LIBCURL_LIBS = @LIBCURL_LIBS@
|
||||
LOWDOWN_LIBS = @LOWDOWN_LIBS@
|
||||
OPENSSL_LIBS = @OPENSSL_LIBS@
|
||||
LIBSECCOMP_LIBS = @LIBSECCOMP_LIBS@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
|
||||
32
configure.ac
32
configure.ac
@@ -188,24 +188,17 @@ PKG_CHECK_MODULES([EDITLINE], [libeditline], [CXXFLAGS="$EDITLINE_CFLAGS $CXXFLA
|
||||
[AC_MSG_ERROR([Nix requires libeditline; it was not found via pkg-config, but via its header, but required functions do not work. Maybe it is too old? >= 1.14 is required.])])
|
||||
])
|
||||
|
||||
# Look for libsodium.
|
||||
# Look for libsodium, an optional dependency.
|
||||
PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"])
|
||||
|
||||
# Look for libbrotli{enc,dec}.
|
||||
PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec], [CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"])
|
||||
|
||||
# Look for libcpuid.
|
||||
have_libcpuid=
|
||||
if test "$machine_name" = "x86_64"; then
|
||||
AC_ARG_ENABLE([cpuid],
|
||||
AS_HELP_STRING([--disable-cpuid], [Do not determine microarchitecture levels with libcpuid (relevant to x86_64 only)]))
|
||||
if test "x$enable_cpuid" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBCPUID], [libcpuid],
|
||||
[CXXFLAGS="$LIBCPUID_CFLAGS $CXXFLAGS"
|
||||
have_libcpuid=1
|
||||
AC_DEFINE([HAVE_LIBCPUID], [1], [Use libcpuid])]
|
||||
)
|
||||
fi
|
||||
PKG_CHECK_MODULES([LIBCPUID], [libcpuid], [CXXFLAGS="$LIBCPUID_CFLAGS $CXXFLAGS"])
|
||||
have_libcpuid=1
|
||||
AC_DEFINE([HAVE_LIBCPUID], [1], [Use libcpuid])
|
||||
fi
|
||||
AC_SUBST(HAVE_LIBCPUID, [$have_libcpuid])
|
||||
|
||||
@@ -262,17 +255,13 @@ fi
|
||||
PKG_CHECK_MODULES([GTEST], [gtest_main])
|
||||
|
||||
|
||||
# Look for nlohmann/json.
|
||||
PKG_CHECK_MODULES([NLOHMANN_JSON], [nlohmann_json >= 3.9])
|
||||
|
||||
|
||||
# documentation generation switch
|
||||
AC_ARG_ENABLE(doc-gen, AS_HELP_STRING([--disable-doc-gen],[disable documentation generation]),
|
||||
doc_generate=$enableval, doc_generate=yes)
|
||||
AC_SUBST(doc_generate)
|
||||
|
||||
# Look for lowdown library.
|
||||
PKG_CHECK_MODULES([LOWDOWN], [lowdown >= 0.9.0], [CXXFLAGS="$LOWDOWN_CFLAGS $CXXFLAGS"])
|
||||
PKG_CHECK_MODULES([LOWDOWN], [lowdown >= 0.8.0], [CXXFLAGS="$LOWDOWN_CFLAGS $CXXFLAGS"])
|
||||
|
||||
# Setuid installations.
|
||||
AC_CHECK_FUNCS([setresuid setreuid lchown])
|
||||
@@ -294,17 +283,6 @@ esac
|
||||
AC_ARG_WITH(sandbox-shell, AS_HELP_STRING([--with-sandbox-shell=PATH],[path of a statically-linked shell to use as /bin/sh in sandboxes]),
|
||||
sandbox_shell=$withval)
|
||||
AC_SUBST(sandbox_shell)
|
||||
if test ${cross_compiling:-no} = no && ! test -z ${sandbox_shell+x}; then
|
||||
AC_MSG_CHECKING([whether sandbox-shell has the standalone feature])
|
||||
# busybox shell sometimes allows executing other busybox applets,
|
||||
# even if they are not in the path, breaking our sandbox
|
||||
if PATH= $sandbox_shell -c "busybox" 2>&1 | grep -qv "not found"; then
|
||||
AC_MSG_RESULT(enabled)
|
||||
AC_MSG_ERROR([Please disable busybox FEATURE_SH_STANDALONE])
|
||||
else
|
||||
AC_MSG_RESULT(disabled)
|
||||
fi
|
||||
fi
|
||||
|
||||
# Expand all variables in config.status.
|
||||
test "$prefix" = NONE && prefix=$ac_default_prefix
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
(import (fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz") {
|
||||
(import (fetchTarball https://github.com/edolstra/flake-compat/archive/master.tar.gz) {
|
||||
src = ./.;
|
||||
}).defaultNix
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
"\\[\\]\\{#(?<anchor>[^\\}]+?)\\}" as $empty_anchor_regex |
|
||||
"\\[(?<text>[^\\]]+?)\\]\\{#(?<anchor>[^\\}]+?)\\}" as $anchor_regex |
|
||||
|
||||
|
||||
def transform_anchors_html:
|
||||
. | gsub($empty_anchor_regex; "<a name=\"" + .anchor + "\"></a>")
|
||||
| gsub($anchor_regex; "<a href=\"#" + .anchor + "\" id=\"" + .anchor + "\">" + .text + "</a>");
|
||||
|
||||
|
||||
def transform_anchors_strip:
|
||||
. | gsub($empty_anchor_regex; "")
|
||||
| gsub($anchor_regex; .text);
|
||||
|
||||
|
||||
def map_contents_recursively(transformer):
|
||||
. + {
|
||||
Chapter: (.Chapter + {
|
||||
content: .Chapter.content | transformer,
|
||||
sub_items: .Chapter.sub_items | map(map_contents_recursively(transformer)),
|
||||
}),
|
||||
};
|
||||
|
||||
|
||||
def process_command:
|
||||
.[0] as $context |
|
||||
.[1] as $body |
|
||||
$body + {
|
||||
sections: $body.sections | map(map_contents_recursively(if $context.renderer == "html" then transform_anchors_html else transform_anchors_strip end)),
|
||||
};
|
||||
|
||||
process_command
|
||||
@@ -1,7 +1,2 @@
|
||||
[output.html]
|
||||
additional-css = ["custom.css"]
|
||||
additional-js = ["redirects.js"]
|
||||
|
||||
[preprocessor.anchors]
|
||||
renderers = ["html"]
|
||||
command = "jq --from-file doc/manual/anchors.jq"
|
||||
|
||||
@@ -6,9 +6,9 @@ builtins:
|
||||
concatStrings (map
|
||||
(name:
|
||||
let builtin = builtins.${name}; in
|
||||
"<dt id=\"builtins-${name}\"><a href=\"#builtins-${name}\"><code>${name} "
|
||||
"<dt><code>${name} "
|
||||
+ concatStringsSep " " (map (s: "<var>${s}</var>") builtin.args)
|
||||
+ "</code></a></dt>"
|
||||
+ "</code></dt>"
|
||||
+ "<dd>\n\n"
|
||||
+ builtin.doc
|
||||
+ "\n\n</dd>"
|
||||
|
||||
@@ -6,22 +6,19 @@ options:
|
||||
concatStrings (map
|
||||
(name:
|
||||
let option = options.${name}; in
|
||||
" - [`${name}`](#conf-${name})"
|
||||
+ "<p id=\"conf-${name}\"></p>\n\n"
|
||||
" - `${name}` \n\n"
|
||||
+ concatStrings (map (s: " ${s}\n") (splitLines option.description)) + "\n\n"
|
||||
+ (if option.documentDefault
|
||||
then " **Default:** " + (
|
||||
if option.value == "" || option.value == []
|
||||
then "*empty*"
|
||||
else if isBool option.value
|
||||
then (if option.value then "`true`" else "`false`")
|
||||
else
|
||||
# n.b. a StringMap value type is specified as a string, but
|
||||
# this shows the value type. The empty stringmap is "null" in
|
||||
# JSON, but that converts to "{ }" here.
|
||||
(if isAttrs option.value then "`\"\"`"
|
||||
else "`" + toString option.value + "`")) + "\n\n"
|
||||
else " **Default:** *machine-specific*\n")
|
||||
+ " **Default:** " + (
|
||||
if option.value == "" || option.value == []
|
||||
then "*empty*"
|
||||
else if isBool option.value
|
||||
then (if option.value then "`true`" else "`false`")
|
||||
else
|
||||
# n.b. a StringMap value type is specified as a string, but
|
||||
# this shows the value type. The empty stringmap is "null" in
|
||||
# JSON, but that converts to "{ }" here.
|
||||
(if isAttrs option.value then "`\"\"`"
|
||||
else "`" + toString option.value + "`")) + "\n\n"
|
||||
+ (if option.aliases != []
|
||||
then " **Deprecated alias:** " + (concatStringsSep ", " (map (s: "`${s}`") option.aliases)) + "\n\n"
|
||||
else "")
|
||||
|
||||
@@ -12,13 +12,11 @@ man-pages := $(foreach n, \
|
||||
clean-files += $(d)/*.1 $(d)/*.5 $(d)/*.8
|
||||
|
||||
# Provide a dummy environment for nix, so that it will not access files outside the macOS sandbox.
|
||||
# Set cores to 0 because otherwise nix show-config resolves the cores based on the current machine
|
||||
dummy-env = env -i \
|
||||
HOME=/dummy \
|
||||
NIX_CONF_DIR=/dummy \
|
||||
NIX_SSL_CERT_FILE=/dummy/no-ca-bundle.crt \
|
||||
NIX_STATE_DIR=/dummy \
|
||||
NIX_CONFIG='cores = 0'
|
||||
NIX_STATE_DIR=/dummy
|
||||
|
||||
nix-eval = $(dummy-env) $(bindir)/nix eval --experimental-features nix-command -I nix/corepkgs=corepkgs --store dummy:// --impure --raw
|
||||
|
||||
@@ -72,7 +70,6 @@ $(d)/builtins.json: $(bindir)/nix
|
||||
@mv $@.tmp $@
|
||||
|
||||
# Generate the HTML manual.
|
||||
html: $(docdir)/manual/index.html
|
||||
install: $(docdir)/manual/index.html
|
||||
|
||||
# Generate 'nix' manpages.
|
||||
@@ -97,7 +94,7 @@ doc/manual/generated/man1/nix3-manpages: $(d)/src/command-ref/new-cli
|
||||
done
|
||||
@touch $@
|
||||
|
||||
$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/src/SUMMARY.md $(d)/src/command-ref/new-cli $(d)/src/command-ref/conf-file.md $(d)/src/expressions/builtins.md $(call rwildcard, $(d)/src, *.md)
|
||||
$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/custom.css $(d)/src/SUMMARY.md $(d)/src/command-ref/new-cli $(d)/src/command-ref/conf-file.md $(d)/src/expressions/builtins.md $(call rwildcard, $(d)/src, *.md)
|
||||
$(trace-gen) RUST_LOG=warn mdbook build doc/manual -d $(DESTDIR)$(docdir)/manual
|
||||
|
||||
endif
|
||||
|
||||
@@ -1,337 +0,0 @@
|
||||
// Redirects from old DocBook manual.
|
||||
var redirects = {
|
||||
"#part-advanced-topics": "advanced-topics/advanced-topics.html",
|
||||
"#chap-tuning-cores-and-jobs": "advanced-topics/cores-vs-jobs.html",
|
||||
"#chap-diff-hook": "advanced-topics/diff-hook.html",
|
||||
"#check-dirs-are-unregistered": "advanced-topics/diff-hook.html#check-dirs-are-unregistered",
|
||||
"#chap-distributed-builds": "advanced-topics/distributed-builds.html",
|
||||
"#chap-post-build-hook": "advanced-topics/post-build-hook.html",
|
||||
"#chap-post-build-hook-caveats": "advanced-topics/post-build-hook.html#implementation-caveats",
|
||||
"#part-command-ref": "command-ref/command-ref.html",
|
||||
"#conf-allow-import-from-derivation": "command-ref/conf-file.html#conf-allow-import-from-derivation",
|
||||
"#conf-allow-new-privileges": "command-ref/conf-file.html#conf-allow-new-privileges",
|
||||
"#conf-allowed-uris": "command-ref/conf-file.html#conf-allowed-uris",
|
||||
"#conf-allowed-users": "command-ref/conf-file.html#conf-allowed-users",
|
||||
"#conf-auto-optimise-store": "command-ref/conf-file.html#conf-auto-optimise-store",
|
||||
"#conf-binary-cache-public-keys": "command-ref/conf-file.html#conf-binary-cache-public-keys",
|
||||
"#conf-binary-caches": "command-ref/conf-file.html#conf-binary-caches",
|
||||
"#conf-build-compress-log": "command-ref/conf-file.html#conf-build-compress-log",
|
||||
"#conf-build-cores": "command-ref/conf-file.html#conf-build-cores",
|
||||
"#conf-build-extra-chroot-dirs": "command-ref/conf-file.html#conf-build-extra-chroot-dirs",
|
||||
"#conf-build-extra-sandbox-paths": "command-ref/conf-file.html#conf-build-extra-sandbox-paths",
|
||||
"#conf-build-fallback": "command-ref/conf-file.html#conf-build-fallback",
|
||||
"#conf-build-max-jobs": "command-ref/conf-file.html#conf-build-max-jobs",
|
||||
"#conf-build-max-log-size": "command-ref/conf-file.html#conf-build-max-log-size",
|
||||
"#conf-build-max-silent-time": "command-ref/conf-file.html#conf-build-max-silent-time",
|
||||
"#conf-build-repeat": "command-ref/conf-file.html#conf-build-repeat",
|
||||
"#conf-build-timeout": "command-ref/conf-file.html#conf-build-timeout",
|
||||
"#conf-build-use-chroot": "command-ref/conf-file.html#conf-build-use-chroot",
|
||||
"#conf-build-use-sandbox": "command-ref/conf-file.html#conf-build-use-sandbox",
|
||||
"#conf-build-use-substitutes": "command-ref/conf-file.html#conf-build-use-substitutes",
|
||||
"#conf-build-users-group": "command-ref/conf-file.html#conf-build-users-group",
|
||||
"#conf-builders": "command-ref/conf-file.html#conf-builders",
|
||||
"#conf-builders-use-substitutes": "command-ref/conf-file.html#conf-builders-use-substitutes",
|
||||
"#conf-compress-build-log": "command-ref/conf-file.html#conf-compress-build-log",
|
||||
"#conf-connect-timeout": "command-ref/conf-file.html#conf-connect-timeout",
|
||||
"#conf-cores": "command-ref/conf-file.html#conf-cores",
|
||||
"#conf-diff-hook": "command-ref/conf-file.html#conf-diff-hook",
|
||||
"#conf-enforce-determinism": "command-ref/conf-file.html#conf-enforce-determinism",
|
||||
"#conf-env-keep-derivations": "command-ref/conf-file.html#conf-env-keep-derivations",
|
||||
"#conf-extra-binary-caches": "command-ref/conf-file.html#conf-extra-binary-caches",
|
||||
"#conf-extra-platforms": "command-ref/conf-file.html#conf-extra-platforms",
|
||||
"#conf-extra-sandbox-paths": "command-ref/conf-file.html#conf-extra-sandbox-paths",
|
||||
"#conf-extra-substituters": "command-ref/conf-file.html#conf-extra-substituters",
|
||||
"#conf-fallback": "command-ref/conf-file.html#conf-fallback",
|
||||
"#conf-fsync-metadata": "command-ref/conf-file.html#conf-fsync-metadata",
|
||||
"#conf-gc-keep-derivations": "command-ref/conf-file.html#conf-gc-keep-derivations",
|
||||
"#conf-gc-keep-outputs": "command-ref/conf-file.html#conf-gc-keep-outputs",
|
||||
"#conf-hashed-mirrors": "command-ref/conf-file.html#conf-hashed-mirrors",
|
||||
"#conf-http-connections": "command-ref/conf-file.html#conf-http-connections",
|
||||
"#conf-keep-build-log": "command-ref/conf-file.html#conf-keep-build-log",
|
||||
"#conf-keep-derivations": "command-ref/conf-file.html#conf-keep-derivations",
|
||||
"#conf-keep-env-derivations": "command-ref/conf-file.html#conf-keep-env-derivations",
|
||||
"#conf-keep-outputs": "command-ref/conf-file.html#conf-keep-outputs",
|
||||
"#conf-max-build-log-size": "command-ref/conf-file.html#conf-max-build-log-size",
|
||||
"#conf-max-free": "command-ref/conf-file.html#conf-max-free",
|
||||
"#conf-max-jobs": "command-ref/conf-file.html#conf-max-jobs",
|
||||
"#conf-max-silent-time": "command-ref/conf-file.html#conf-max-silent-time",
|
||||
"#conf-min-free": "command-ref/conf-file.html#conf-min-free",
|
||||
"#conf-narinfo-cache-negative-ttl": "command-ref/conf-file.html#conf-narinfo-cache-negative-ttl",
|
||||
"#conf-narinfo-cache-positive-ttl": "command-ref/conf-file.html#conf-narinfo-cache-positive-ttl",
|
||||
"#conf-netrc-file": "command-ref/conf-file.html#conf-netrc-file",
|
||||
"#conf-plugin-files": "command-ref/conf-file.html#conf-plugin-files",
|
||||
"#conf-post-build-hook": "command-ref/conf-file.html#conf-post-build-hook",
|
||||
"#conf-pre-build-hook": "command-ref/conf-file.html#conf-pre-build-hook",
|
||||
"#conf-repeat": "command-ref/conf-file.html#conf-repeat",
|
||||
"#conf-require-sigs": "command-ref/conf-file.html#conf-require-sigs",
|
||||
"#conf-restrict-eval": "command-ref/conf-file.html#conf-restrict-eval",
|
||||
"#conf-run-diff-hook": "command-ref/conf-file.html#conf-run-diff-hook",
|
||||
"#conf-sandbox": "command-ref/conf-file.html#conf-sandbox",
|
||||
"#conf-sandbox-dev-shm-size": "command-ref/conf-file.html#conf-sandbox-dev-shm-size",
|
||||
"#conf-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths",
|
||||
"#conf-secret-key-files": "command-ref/conf-file.html#conf-secret-key-files",
|
||||
"#conf-show-trace": "command-ref/conf-file.html#conf-show-trace",
|
||||
"#conf-stalled-download-timeout": "command-ref/conf-file.html#conf-stalled-download-timeout",
|
||||
"#conf-substitute": "command-ref/conf-file.html#conf-substitute",
|
||||
"#conf-substituters": "command-ref/conf-file.html#conf-substituters",
|
||||
"#conf-system": "command-ref/conf-file.html#conf-system",
|
||||
"#conf-system-features": "command-ref/conf-file.html#conf-system-features",
|
||||
"#conf-tarball-ttl": "command-ref/conf-file.html#conf-tarball-ttl",
|
||||
"#conf-timeout": "command-ref/conf-file.html#conf-timeout",
|
||||
"#conf-trace-function-calls": "command-ref/conf-file.html#conf-trace-function-calls",
|
||||
"#conf-trusted-binary-caches": "command-ref/conf-file.html#conf-trusted-binary-caches",
|
||||
"#conf-trusted-public-keys": "command-ref/conf-file.html#conf-trusted-public-keys",
|
||||
"#conf-trusted-substituters": "command-ref/conf-file.html#conf-trusted-substituters",
|
||||
"#conf-trusted-users": "command-ref/conf-file.html#conf-trusted-users",
|
||||
"#extra-sandbox-paths": "command-ref/conf-file.html#extra-sandbox-paths",
|
||||
"#sec-conf-file": "command-ref/conf-file.html",
|
||||
"#env-NIX_PATH": "command-ref/env-common.html#env-NIX_PATH",
|
||||
"#env-common": "command-ref/env-common.html",
|
||||
"#envar-remote": "command-ref/env-common.html#env-NIX_REMOTE",
|
||||
"#sec-common-env": "command-ref/env-common.html",
|
||||
"#ch-files": "command-ref/files.html",
|
||||
"#ch-main-commands": "command-ref/main-commands.html",
|
||||
"#opt-out-link": "command-ref/nix-build.html#opt-out-link",
|
||||
"#sec-nix-build": "command-ref/nix-build.html",
|
||||
"#sec-nix-channel": "command-ref/nix-channel.html",
|
||||
"#sec-nix-collect-garbage": "command-ref/nix-collect-garbage.html",
|
||||
"#sec-nix-copy-closure": "command-ref/nix-copy-closure.html",
|
||||
"#sec-nix-daemon": "command-ref/nix-daemon.html",
|
||||
"#refsec-nix-env-install-examples": "command-ref/nix-env.html#examples",
|
||||
"#rsec-nix-env-install": "command-ref/nix-env.html#operation---install",
|
||||
"#rsec-nix-env-set": "command-ref/nix-env.html#operation---set",
|
||||
"#rsec-nix-env-set-flag": "command-ref/nix-env.html#operation---set-flag",
|
||||
"#rsec-nix-env-upgrade": "command-ref/nix-env.html#operation---upgrade",
|
||||
"#sec-nix-env": "command-ref/nix-env.html",
|
||||
"#ssec-version-comparisons": "command-ref/nix-env.html#versions",
|
||||
"#sec-nix-hash": "command-ref/nix-hash.html",
|
||||
"#sec-nix-instantiate": "command-ref/nix-instantiate.html",
|
||||
"#sec-nix-prefetch-url": "command-ref/nix-prefetch-url.html",
|
||||
"#sec-nix-shell": "command-ref/nix-shell.html",
|
||||
"#ssec-nix-shell-shebang": "command-ref/nix-shell.html#use-as-a--interpreter",
|
||||
"#nixref-queries": "command-ref/nix-store.html#queries",
|
||||
"#opt-add-root": "command-ref/nix-store.html#opt-add-root",
|
||||
"#refsec-nix-store-dump": "command-ref/nix-store.html#operation---dump",
|
||||
"#refsec-nix-store-export": "command-ref/nix-store.html#operation---export",
|
||||
"#refsec-nix-store-import": "command-ref/nix-store.html#operation---import",
|
||||
"#refsec-nix-store-query": "command-ref/nix-store.html#operation---query",
|
||||
"#refsec-nix-store-verify": "command-ref/nix-store.html#operation---verify",
|
||||
"#rsec-nix-store-gc": "command-ref/nix-store.html#operation---gc",
|
||||
"#rsec-nix-store-generate-binary-cache-key": "command-ref/nix-store.html#operation---generate-binary-cache-key",
|
||||
"#rsec-nix-store-realise": "command-ref/nix-store.html#operation---realise",
|
||||
"#rsec-nix-store-serve": "command-ref/nix-store.html#operation---serve",
|
||||
"#sec-nix-store": "command-ref/nix-store.html",
|
||||
"#opt-I": "command-ref/opt-common.html#opt-I",
|
||||
"#opt-attr": "command-ref/opt-common.html#opt-attr",
|
||||
"#opt-common": "command-ref/opt-common.html",
|
||||
"#opt-cores": "command-ref/opt-common.html#opt-cores",
|
||||
"#opt-log-format": "command-ref/opt-common.html#opt-log-format",
|
||||
"#opt-max-jobs": "command-ref/opt-common.html#opt-max-jobs",
|
||||
"#opt-max-silent-time": "command-ref/opt-common.html#opt-max-silent-time",
|
||||
"#opt-timeout": "command-ref/opt-common.html#opt-timeout",
|
||||
"#sec-common-options": "command-ref/opt-common.html",
|
||||
"#ch-utilities": "command-ref/utilities.html",
|
||||
"#chap-hacking": "contributing/hacking.html",
|
||||
"#adv-attr-allowSubstitutes": "expressions/advanced-attributes.html#adv-attr-allowSubstitutes",
|
||||
"#adv-attr-allowedReferences": "expressions/advanced-attributes.html#adv-attr-allowedReferences",
|
||||
"#adv-attr-allowedRequisites": "expressions/advanced-attributes.html#adv-attr-allowedRequisites",
|
||||
"#adv-attr-disallowedReferences": "expressions/advanced-attributes.html#adv-attr-disallowedReferences",
|
||||
"#adv-attr-disallowedRequisites": "expressions/advanced-attributes.html#adv-attr-disallowedRequisites",
|
||||
"#adv-attr-exportReferencesGraph": "expressions/advanced-attributes.html#adv-attr-exportReferencesGraph",
|
||||
"#adv-attr-impureEnvVars": "expressions/advanced-attributes.html#adv-attr-impureEnvVars",
|
||||
"#adv-attr-outputHash": "expressions/advanced-attributes.html#adv-attr-outputHash",
|
||||
"#adv-attr-outputHashAlgo": "expressions/advanced-attributes.html#adv-attr-outputHashAlgo",
|
||||
"#adv-attr-outputHashMode": "expressions/advanced-attributes.html#adv-attr-outputHashMode",
|
||||
"#adv-attr-passAsFile": "expressions/advanced-attributes.html#adv-attr-passAsFile",
|
||||
"#adv-attr-preferLocalBuild": "expressions/advanced-attributes.html#adv-attr-preferLocalBuild",
|
||||
"#fixed-output-drvs": "expressions/advanced-attributes.html#adv-attr-outputHash",
|
||||
"#sec-advanced-attributes": "expressions/advanced-attributes.html",
|
||||
"#sec-arguments": "expressions/arguments-variables.html",
|
||||
"#sec-build-script": "expressions/build-script.html",
|
||||
"#builtin-abort": "expressions/builtins.html#builtins-abort",
|
||||
"#builtin-add": "expressions/builtins.html#builtins-add",
|
||||
"#builtin-all": "expressions/builtins.html#builtins-all",
|
||||
"#builtin-any": "expressions/builtins.html#builtins-any",
|
||||
"#builtin-attrNames": "expressions/builtins.html#builtins-attrNames",
|
||||
"#builtin-attrValues": "expressions/builtins.html#builtins-attrValues",
|
||||
"#builtin-baseNameOf": "expressions/builtins.html#builtins-baseNameOf",
|
||||
"#builtin-bitAnd": "expressions/builtins.html#builtins-bitAnd",
|
||||
"#builtin-bitOr": "expressions/builtins.html#builtins-bitOr",
|
||||
"#builtin-bitXor": "expressions/builtins.html#builtins-bitXor",
|
||||
"#builtin-builtins": "expressions/builtins.html#builtins-builtins",
|
||||
"#builtin-compareVersions": "expressions/builtins.html#builtins-compareVersions",
|
||||
"#builtin-concatLists": "expressions/builtins.html#builtins-concatLists",
|
||||
"#builtin-concatStringsSep": "expressions/builtins.html#builtins-concatStringsSep",
|
||||
"#builtin-currentSystem": "expressions/builtins.html#builtins-currentSystem",
|
||||
"#builtin-deepSeq": "expressions/builtins.html#builtins-deepSeq",
|
||||
"#builtin-derivation": "expressions/builtins.html#builtins-derivation",
|
||||
"#builtin-dirOf": "expressions/builtins.html#builtins-dirOf",
|
||||
"#builtin-div": "expressions/builtins.html#builtins-div",
|
||||
"#builtin-elem": "expressions/builtins.html#builtins-elem",
|
||||
"#builtin-elemAt": "expressions/builtins.html#builtins-elemAt",
|
||||
"#builtin-fetchGit": "expressions/builtins.html#builtins-fetchGit",
|
||||
"#builtin-fetchTarball": "expressions/builtins.html#builtins-fetchTarball",
|
||||
"#builtin-fetchurl": "expressions/builtins.html#builtins-fetchurl",
|
||||
"#builtin-filterSource": "expressions/builtins.html#builtins-filterSource",
|
||||
"#builtin-foldl-prime": "expressions/builtins.html#builtins-foldl-prime",
|
||||
"#builtin-fromJSON": "expressions/builtins.html#builtins-fromJSON",
|
||||
"#builtin-functionArgs": "expressions/builtins.html#builtins-functionArgs",
|
||||
"#builtin-genList": "expressions/builtins.html#builtins-genList",
|
||||
"#builtin-getAttr": "expressions/builtins.html#builtins-getAttr",
|
||||
"#builtin-getEnv": "expressions/builtins.html#builtins-getEnv",
|
||||
"#builtin-hasAttr": "expressions/builtins.html#builtins-hasAttr",
|
||||
"#builtin-hashFile": "expressions/builtins.html#builtins-hashFile",
|
||||
"#builtin-hashString": "expressions/builtins.html#builtins-hashString",
|
||||
"#builtin-head": "expressions/builtins.html#builtins-head",
|
||||
"#builtin-import": "expressions/builtins.html#builtins-import",
|
||||
"#builtin-intersectAttrs": "expressions/builtins.html#builtins-intersectAttrs",
|
||||
"#builtin-isAttrs": "expressions/builtins.html#builtins-isAttrs",
|
||||
"#builtin-isBool": "expressions/builtins.html#builtins-isBool",
|
||||
"#builtin-isFloat": "expressions/builtins.html#builtins-isFloat",
|
||||
"#builtin-isFunction": "expressions/builtins.html#builtins-isFunction",
|
||||
"#builtin-isInt": "expressions/builtins.html#builtins-isInt",
|
||||
"#builtin-isList": "expressions/builtins.html#builtins-isList",
|
||||
"#builtin-isNull": "expressions/builtins.html#builtins-isNull",
|
||||
"#builtin-isString": "expressions/builtins.html#builtins-isString",
|
||||
"#builtin-length": "expressions/builtins.html#builtins-length",
|
||||
"#builtin-lessThan": "expressions/builtins.html#builtins-lessThan",
|
||||
"#builtin-listToAttrs": "expressions/builtins.html#builtins-listToAttrs",
|
||||
"#builtin-map": "expressions/builtins.html#builtins-map",
|
||||
"#builtin-match": "expressions/builtins.html#builtins-match",
|
||||
"#builtin-mul": "expressions/builtins.html#builtins-mul",
|
||||
"#builtin-parseDrvName": "expressions/builtins.html#builtins-parseDrvName",
|
||||
"#builtin-path": "expressions/builtins.html#builtins-path",
|
||||
"#builtin-pathExists": "expressions/builtins.html#builtins-pathExists",
|
||||
"#builtin-placeholder": "expressions/builtins.html#builtins-placeholder",
|
||||
"#builtin-readDir": "expressions/builtins.html#builtins-readDir",
|
||||
"#builtin-readFile": "expressions/builtins.html#builtins-readFile",
|
||||
"#builtin-removeAttrs": "expressions/builtins.html#builtins-removeAttrs",
|
||||
"#builtin-replaceStrings": "expressions/builtins.html#builtins-replaceStrings",
|
||||
"#builtin-seq": "expressions/builtins.html#builtins-seq",
|
||||
"#builtin-sort": "expressions/builtins.html#builtins-sort",
|
||||
"#builtin-split": "expressions/builtins.html#builtins-split",
|
||||
"#builtin-splitVersion": "expressions/builtins.html#builtins-splitVersion",
|
||||
"#builtin-stringLength": "expressions/builtins.html#builtins-stringLength",
|
||||
"#builtin-sub": "expressions/builtins.html#builtins-sub",
|
||||
"#builtin-substring": "expressions/builtins.html#builtins-substring",
|
||||
"#builtin-tail": "expressions/builtins.html#builtins-tail",
|
||||
"#builtin-throw": "expressions/builtins.html#builtins-throw",
|
||||
"#builtin-toFile": "expressions/builtins.html#builtins-toFile",
|
||||
"#builtin-toJSON": "expressions/builtins.html#builtins-toJSON",
|
||||
"#builtin-toPath": "expressions/builtins.html#builtins-toPath",
|
||||
"#builtin-toString": "expressions/builtins.html#builtins-toString",
|
||||
"#builtin-toXML": "expressions/builtins.html#builtins-toXML",
|
||||
"#builtin-trace": "expressions/builtins.html#builtins-trace",
|
||||
"#builtin-tryEval": "expressions/builtins.html#builtins-tryEval",
|
||||
"#builtin-typeOf": "expressions/builtins.html#builtins-typeOf",
|
||||
"#ssec-builtins": "expressions/builtins.html",
|
||||
"#attr-system": "expressions/derivations.html#attr-system",
|
||||
"#ssec-derivation": "expressions/derivations.html",
|
||||
"#ch-expression-language": "expressions/expression-language.html",
|
||||
"#sec-expression-syntax": "expressions/expression-syntax.html",
|
||||
"#sec-generic-builder": "expressions/generic-builder.html",
|
||||
"#sec-constructs": "expressions/language-constructs.html",
|
||||
"#sect-let-expressions": "expressions/language-constructs.html#let-expressions",
|
||||
"#ss-functions": "expressions/language-constructs.html#functions",
|
||||
"#sec-language-operators": "expressions/language-operators.html",
|
||||
"#table-operators": "expressions/language-operators.html",
|
||||
"#ssec-values": "expressions/language-values.html",
|
||||
"#sec-building-simple": "expressions/simple-building-testing.html",
|
||||
"#ch-simple-expression": "expressions/simple-expression.html",
|
||||
"#chap-writing-nix-expressions": "expressions/writing-nix-expressions.html",
|
||||
"#gloss-closure": "glossary.html#gloss-closure",
|
||||
"#gloss-derivation": "glossary.html#gloss-derivation",
|
||||
"#gloss-deriver": "glossary.html#gloss-deriver",
|
||||
"#gloss-nar": "glossary.html#gloss-nar",
|
||||
"#gloss-output-path": "glossary.html#gloss-output-path",
|
||||
"#gloss-profile": "glossary.html#gloss-profile",
|
||||
"#gloss-reachable": "glossary.html#gloss-reachable",
|
||||
"#gloss-reference": "glossary.html#gloss-reference",
|
||||
"#gloss-substitute": "glossary.html#gloss-substitute",
|
||||
"#gloss-user-env": "glossary.html#gloss-user-env",
|
||||
"#gloss-validity": "glossary.html#gloss-validity",
|
||||
"#part-glossary": "glossary.html",
|
||||
"#sec-building-source": "installation/building-source.html",
|
||||
"#ch-env-variables": "installation/env-variables.html",
|
||||
"#sec-installer-proxy-settings": "installation/env-variables.html#proxy-environment-variables",
|
||||
"#sec-nix-ssl-cert-file": "installation/env-variables.html#nix_ssl_cert_file",
|
||||
"#sec-nix-ssl-cert-file-with-nix-daemon-and-macos": "installation/env-variables.html#nix_ssl_cert_file-with-macos-and-the-nix-daemon",
|
||||
"#chap-installation": "installation/installation.html",
|
||||
"#ch-installing-binary": "installation/installing-binary.html",
|
||||
"#sect-macos-installation": "installation/installing-binary.html#macos-installation",
|
||||
"#sect-macos-installation-change-store-prefix": "installation/installing-binary.html#macos-installation",
|
||||
"#sect-macos-installation-encrypted-volume": "installation/installing-binary.html#macos-installation",
|
||||
"#sect-macos-installation-recommended-notes": "installation/installing-binary.html#macos-installation",
|
||||
"#sect-macos-installation-symlink": "installation/installing-binary.html#macos-installation",
|
||||
"#sect-multi-user-installation": "installation/installing-binary.html#multi-user-installation",
|
||||
"#sect-nix-install-binary-tarball": "installation/installing-binary.html#installing-from-a-binary-tarball",
|
||||
"#sect-nix-install-pinned-version-url": "installation/installing-binary.html#installing-a-pinned-nix-version-from-a-url",
|
||||
"#sect-single-user-installation": "installation/installing-binary.html#single-user-installation",
|
||||
"#ch-installing-source": "installation/installing-source.html",
|
||||
"#ssec-multi-user": "installation/multi-user.html",
|
||||
"#ch-nix-security": "installation/nix-security.html",
|
||||
"#sec-obtaining-source": "installation/obtaining-source.html",
|
||||
"#sec-prerequisites-source": "installation/prerequisites-source.html",
|
||||
"#sec-single-user": "installation/single-user.html",
|
||||
"#ch-supported-platforms": "installation/supported-platforms.html",
|
||||
"#ch-upgrading-nix": "installation/upgrading.html",
|
||||
"#ch-about-nix": "introduction.html",
|
||||
"#chap-introduction": "introduction.html",
|
||||
"#ch-basic-package-mgmt": "package-management/basic-package-mgmt.html",
|
||||
"#ssec-binary-cache-substituter": "package-management/binary-cache-substituter.html",
|
||||
"#sec-channels": "package-management/channels.html",
|
||||
"#ssec-copy-closure": "package-management/copy-closure.html",
|
||||
"#sec-garbage-collection": "package-management/garbage-collection.html",
|
||||
"#ssec-gc-roots": "package-management/garbage-collector-roots.html",
|
||||
"#chap-package-management": "package-management/package-management.html",
|
||||
"#sec-profiles": "package-management/profiles.html",
|
||||
"#ssec-s3-substituter": "package-management/s3-substituter.html",
|
||||
"#ssec-s3-substituter-anonymous-reads": "package-management/s3-substituter.html#anonymous-reads-to-your-s3-compatible-binary-cache",
|
||||
"#ssec-s3-substituter-authenticated-reads": "package-management/s3-substituter.html#authenticated-reads-to-your-s3-binary-cache",
|
||||
"#ssec-s3-substituter-authenticated-writes": "package-management/s3-substituter.html#authenticated-writes-to-your-s3-compatible-binary-cache",
|
||||
"#sec-sharing-packages": "package-management/sharing-packages.html",
|
||||
"#ssec-ssh-substituter": "package-management/ssh-substituter.html",
|
||||
"#chap-quick-start": "quick-start.html",
|
||||
"#sec-relnotes": "release-notes/release-notes.html",
|
||||
"#ch-relnotes-0.10.1": "release-notes/rl-0.10.1.html",
|
||||
"#ch-relnotes-0.10": "release-notes/rl-0.10.html",
|
||||
"#ssec-relnotes-0.11": "release-notes/rl-0.11.html",
|
||||
"#ssec-relnotes-0.12": "release-notes/rl-0.12.html",
|
||||
"#ssec-relnotes-0.13": "release-notes/rl-0.13.html",
|
||||
"#ssec-relnotes-0.14": "release-notes/rl-0.14.html",
|
||||
"#ssec-relnotes-0.15": "release-notes/rl-0.15.html",
|
||||
"#ssec-relnotes-0.16": "release-notes/rl-0.16.html",
|
||||
"#ch-relnotes-0.5": "release-notes/rl-0.5.html",
|
||||
"#ch-relnotes-0.6": "release-notes/rl-0.6.html",
|
||||
"#ch-relnotes-0.7": "release-notes/rl-0.7.html",
|
||||
"#ch-relnotes-0.8.1": "release-notes/rl-0.8.1.html",
|
||||
"#ch-relnotes-0.8": "release-notes/rl-0.8.html",
|
||||
"#ch-relnotes-0.9.1": "release-notes/rl-0.9.1.html",
|
||||
"#ch-relnotes-0.9.2": "release-notes/rl-0.9.2.html",
|
||||
"#ch-relnotes-0.9": "release-notes/rl-0.9.html",
|
||||
"#ssec-relnotes-1.0": "release-notes/rl-1.0.html",
|
||||
"#ssec-relnotes-1.1": "release-notes/rl-1.1.html",
|
||||
"#ssec-relnotes-1.10": "release-notes/rl-1.10.html",
|
||||
"#ssec-relnotes-1.11.10": "release-notes/rl-1.11.10.html",
|
||||
"#ssec-relnotes-1.11": "release-notes/rl-1.11.html",
|
||||
"#ssec-relnotes-1.2": "release-notes/rl-1.2.html",
|
||||
"#ssec-relnotes-1.3": "release-notes/rl-1.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"
|
||||
};
|
||||
|
||||
var isRoot = (document.location.pathname.endsWith('/') || document.location.pathname.endsWith('/index.html')) && path_to_root === '';
|
||||
if (isRoot && redirects[document.location.hash]) {
|
||||
document.location.href = path_to_root + redirects[document.location.hash];
|
||||
}
|
||||
@@ -71,11 +71,7 @@
|
||||
- [Hacking](contributing/hacking.md)
|
||||
- [CLI guideline](contributing/cli-guideline.md)
|
||||
- [Release Notes](release-notes/release-notes.md)
|
||||
- [Release 2.9 (2022-05-30)](release-notes/rl-2.9.md)
|
||||
- [Release 2.8 (2022-04-19)](release-notes/rl-2.8.md)
|
||||
- [Release 2.7 (2022-03-07)](release-notes/rl-2.7.md)
|
||||
- [Release 2.6 (2022-01-24)](release-notes/rl-2.6.md)
|
||||
- [Release 2.5 (2021-12-13)](release-notes/rl-2.5.md)
|
||||
- [Release X.Y (202?-??-??)](release-notes/rl-next.md)
|
||||
- [Release 2.4 (2021-11-01)](release-notes/rl-2.4.md)
|
||||
- [Release 2.3 (2019-09-04)](release-notes/rl-2.3.md)
|
||||
- [Release 2.2 (2019-01-11)](release-notes/rl-2.2.md)
|
||||
|
||||
@@ -101,7 +101,7 @@ In particular, notice the
|
||||
`/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable.check` output. Nix
|
||||
has copied the build results to that directory where you can examine it.
|
||||
|
||||
> []{#check-dirs-are-unregistered} **Note**
|
||||
> **Note**
|
||||
>
|
||||
> Check paths are not protected against garbage collection, and this
|
||||
> path will be deleted on the next garbage collection.
|
||||
|
||||
@@ -53,8 +53,8 @@ example, the following command allows you to build a derivation for
|
||||
$ uname
|
||||
Linux
|
||||
|
||||
$ nix build --impure \
|
||||
--expr '(with import <nixpkgs> { system = "x86_64-darwin"; }; runCommand "foo" {} "uname > $out")' \
|
||||
$ nix build \
|
||||
'(with import <nixpkgs> { system = "x86_64-darwin"; }; runCommand "foo" {} "uname > $out")' \
|
||||
--builders 'ssh://mac x86_64-darwin'
|
||||
[1/0/1 built, 0.0 MiB DL] building foo on ssh://mac
|
||||
|
||||
@@ -110,7 +110,7 @@ default, set it to `-`.
|
||||
7. A comma-separated list of *mandatory features*. A machine will only
|
||||
be used to build a derivation if all of the machine’s mandatory
|
||||
features appear in the derivation’s `requiredSystemFeatures`
|
||||
attribute.
|
||||
attribute..
|
||||
|
||||
8. The (base64-encoded) public host key of the remote machine. If omitted, SSH
|
||||
will use its regular known-hosts file. Specifically, the field is calculated
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
Most Nix commands interpret the following environment variables:
|
||||
|
||||
- [`IN_NIX_SHELL`]{#env-IN_NIX_SHELL}\
|
||||
- `IN_NIX_SHELL`\
|
||||
Indicator that tells if the current environment was set up by
|
||||
`nix-shell`. It can have the values `pure` or `impure`.
|
||||
`nix-shell`. Since Nix 2.0 the values are `"pure"` and `"impure"`
|
||||
|
||||
- [`NIX_PATH`]{#env-NIX_PATH}\
|
||||
- `NIX_PATH`\
|
||||
A colon-separated list of directories used to look up Nix
|
||||
expressions enclosed in angle brackets (i.e., `<path>`). For
|
||||
instance, the value
|
||||
@@ -44,7 +44,7 @@ Most Nix commands interpret the following environment variables:
|
||||
The Nix search path can also be extended using the `-I` option to
|
||||
many Nix commands, which takes precedence over `NIX_PATH`.
|
||||
|
||||
- [`NIX_IGNORE_SYMLINK_STORE`]{#env-NIX_IGNORE_SYMLINK_STORE}\
|
||||
- `NIX_IGNORE_SYMLINK_STORE`\
|
||||
Normally, the Nix store directory (typically `/nix/store`) is not
|
||||
allowed to contain any symlink components. This is to prevent
|
||||
“impure” builds. Builders sometimes “canonicalise” paths by
|
||||
@@ -66,41 +66,41 @@ Most Nix commands interpret the following environment variables:
|
||||
|
||||
Consult the mount 8 manual page for details.
|
||||
|
||||
- [`NIX_STORE_DIR`]{#env-NIX_STORE_DIR}\
|
||||
- `NIX_STORE_DIR`\
|
||||
Overrides the location of the Nix store (default `prefix/store`).
|
||||
|
||||
- [`NIX_DATA_DIR`]{#env-NIX_DATA_DIR}\
|
||||
- `NIX_DATA_DIR`\
|
||||
Overrides the location of the Nix static data directory (default
|
||||
`prefix/share`).
|
||||
|
||||
- [`NIX_LOG_DIR`]{#env-NIX_LOG_DIR}\
|
||||
- `NIX_LOG_DIR`\
|
||||
Overrides the location of the Nix log directory (default
|
||||
`prefix/var/log/nix`).
|
||||
|
||||
- [`NIX_STATE_DIR`]{#env-NIX_STATE_DIR}\
|
||||
- `NIX_STATE_DIR`\
|
||||
Overrides the location of the Nix state directory (default
|
||||
`prefix/var/nix`).
|
||||
|
||||
- [`NIX_CONF_DIR`]{#env-NIX_CONF_DIR}\
|
||||
- `NIX_CONF_DIR`\
|
||||
Overrides the location of the system Nix configuration directory
|
||||
(default `prefix/etc/nix`).
|
||||
|
||||
- [`NIX_CONFIG`]{#env-NIX_CONFIG}\
|
||||
- `NIX_CONFIG`\
|
||||
Applies settings from Nix configuration from the environment.
|
||||
The content is treated as if it was read from a Nix configuration file.
|
||||
Settings are separated by the newline character.
|
||||
|
||||
- [`NIX_USER_CONF_FILES`]{#env-NIX_USER_CONF_FILES}\
|
||||
- `NIX_USER_CONF_FILES`\
|
||||
Overrides the location of the user Nix configuration files to load
|
||||
from (defaults to the XDG spec locations). The variable is treated
|
||||
as a list separated by the `:` token.
|
||||
|
||||
- [`TMPDIR`]{#env-TMPDIR}\
|
||||
- `TMPDIR`\
|
||||
Use the specified directory to store temporary files. In particular,
|
||||
this includes temporary build directories; these can take up
|
||||
substantial amounts of disk space. The default is `/tmp`.
|
||||
|
||||
- [`NIX_REMOTE`]{#env-NIX_REMOTE}\
|
||||
- `NIX_REMOTE`\
|
||||
This variable should be set to `daemon` if you want to use the Nix
|
||||
daemon to execute Nix operations. This is necessary in [multi-user
|
||||
Nix installations](../installation/multi-user.md). If the Nix
|
||||
@@ -108,16 +108,16 @@ Most Nix commands interpret the following environment variables:
|
||||
should be set to `unix://path/to/socket`. Otherwise, it should be
|
||||
left unset.
|
||||
|
||||
- [`NIX_SHOW_STATS`]{#env-NIX_SHOW_STATS}\
|
||||
- `NIX_SHOW_STATS`\
|
||||
If set to `1`, Nix will print some evaluation statistics, such as
|
||||
the number of values allocated.
|
||||
|
||||
- [`NIX_COUNT_CALLS`]{#env-NIX_COUNT_CALLS}\
|
||||
- `NIX_COUNT_CALLS`\
|
||||
If set to `1`, Nix will print how often functions were called during
|
||||
Nix expression evaluation. This is useful for profiling your Nix
|
||||
expressions.
|
||||
|
||||
- [`GC_INITIAL_HEAP_SIZE`]{#env-GC_INITIAL_HEAP_SIZE}\
|
||||
- `GC_INITIAL_HEAP_SIZE`\
|
||||
If Nix has been configured to use the Boehm garbage collector, this
|
||||
variable sets the initial size of the heap in bytes. It defaults to
|
||||
384 MiB. Setting it to a low value reduces memory consumption, but
|
||||
|
||||
@@ -47,16 +47,16 @@ All options not listed here are passed to `nix-store
|
||||
--realise`, except for `--arg` and `--attr` / `-A` which are passed to
|
||||
`nix-instantiate`.
|
||||
|
||||
- [`--no-out-link`]{#opt-no-out-link}\
|
||||
- `--no-out-link`\
|
||||
Do not create a symlink to the output path. Note that as a result
|
||||
the output does not become a root of the garbage collector, and so
|
||||
might be deleted by `nix-store
|
||||
--gc`.
|
||||
|
||||
- [`--dry-run`]{#opt-dry-run}\
|
||||
- `--dry-run`\
|
||||
Show what store paths would be built or downloaded.
|
||||
|
||||
- [`--out-link`]{#opt-out-link} / `-o` *outlink*\
|
||||
- `--out-link` / `-o` *outlink*\
|
||||
Change the name of the symlink to the output path created from
|
||||
`result` to *outlink*.
|
||||
|
||||
|
||||
@@ -101,8 +101,7 @@ The following common options are supported:
|
||||
|
||||
- `NIX_BUILD_SHELL`\
|
||||
Shell used to start the interactive environment. Defaults to the
|
||||
`bash` found in `<nixpkgs>`, falling back to the `bash` found in
|
||||
`PATH` if not found.
|
||||
`bash` found in `PATH`.
|
||||
|
||||
# Examples
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ This section lists the options that are common to all operations. These
|
||||
options are allowed for every subcommand, though they may not always
|
||||
have an effect.
|
||||
|
||||
- [`--add-root`]{#opt-add-root} *path*\
|
||||
- `--add-root` *path*\
|
||||
Causes the result of a realisation (`--realise` and
|
||||
`--force-realise`) to be registered as a root of the garbage
|
||||
collector. *path* will be created as a symlink to the resulting
|
||||
@@ -321,8 +321,8 @@ symlink.
|
||||
This query has one option:
|
||||
|
||||
- `--include-outputs`
|
||||
Also include the existing output paths of store derivations,
|
||||
and their closures.
|
||||
Also include the output path of store derivations, and their
|
||||
closures.
|
||||
|
||||
This query can be used to implement various kinds of deployment. A
|
||||
*source deployment* is obtained by distributing the closure of a
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
Most Nix commands accept the following command-line options:
|
||||
|
||||
- [`--help`]{#opt-help}\
|
||||
- `--help`\
|
||||
Prints out a summary of the command syntax and exits.
|
||||
|
||||
- [`--version`]{#opt-version}\
|
||||
- `--version`\
|
||||
Prints out the Nix version number on standard output and exits.
|
||||
|
||||
- [`--verbose`]{#opt-verbose} / `-v`\
|
||||
- `--verbose` / `-v`\
|
||||
Increases the level of verbosity of diagnostic messages printed on
|
||||
standard error. For each Nix operation, the information printed on
|
||||
standard output is well-defined; any diagnostic information is
|
||||
@@ -37,14 +37,14 @@ Most Nix commands accept the following command-line options:
|
||||
- 5\
|
||||
“Vomit”: print vast amounts of debug information.
|
||||
|
||||
- [`--quiet`]{#opt-quiet}\
|
||||
- `--quiet`\
|
||||
Decreases the level of verbosity of diagnostic messages printed on
|
||||
standard error. This is the inverse option to `-v` / `--verbose`.
|
||||
|
||||
This option may be specified repeatedly. See the previous verbosity
|
||||
levels list.
|
||||
|
||||
- [`--log-format`]{#opt-log-format} *format*\
|
||||
- `--log-format` *format*\
|
||||
This option can be used to change the output of the log format, with
|
||||
*format* being one of:
|
||||
|
||||
@@ -66,14 +66,14 @@ Most Nix commands accept the following command-line options:
|
||||
- bar-with-logs\
|
||||
Display the raw logs, with the progress bar at the bottom.
|
||||
|
||||
- [`--no-build-output`]{#opt-no-build-output} / `-Q`\
|
||||
- `--no-build-output` / `-Q`\
|
||||
By default, output written by builders to standard output and
|
||||
standard error is echoed to the Nix command's standard error. This
|
||||
option suppresses this behaviour. Note that the builder's standard
|
||||
output and error are always written to a log file in
|
||||
`prefix/nix/var/log/nix`.
|
||||
|
||||
- [`--max-jobs`]{#opt-max-jobs} / `-j` *number*\
|
||||
- `--max-jobs` / `-j` *number*\
|
||||
Sets the maximum number of build jobs that Nix will perform in
|
||||
parallel to the specified number. Specify `auto` to use the number
|
||||
of CPUs in the system. The default is specified by the `max-jobs`
|
||||
@@ -83,7 +83,7 @@ Most Nix commands accept the following command-line options:
|
||||
Setting it to `0` disallows building on the local machine, which is
|
||||
useful when you want builds to happen only on remote builders.
|
||||
|
||||
- [`--cores`]{#opt-cores}\
|
||||
- `--cores`\
|
||||
Sets the value of the `NIX_BUILD_CORES` environment variable in
|
||||
the invocation of builders. Builders can use this variable at
|
||||
their discretion to control the maximum amount of parallelism. For
|
||||
@@ -94,18 +94,18 @@ Most Nix commands accept the following command-line options:
|
||||
means that the builder should use all available CPU cores in the
|
||||
system.
|
||||
|
||||
- [`--max-silent-time`]{#opt-max-silent-time}\
|
||||
- `--max-silent-time`\
|
||||
Sets the maximum number of seconds that a builder can go without
|
||||
producing any data on standard output or standard error. The
|
||||
default is specified by the `max-silent-time` configuration
|
||||
setting. `0` means no time-out.
|
||||
|
||||
- [`--timeout`]{#opt-timeout}\
|
||||
- `--timeout`\
|
||||
Sets the maximum number of seconds that a builder can run. The
|
||||
default is specified by the `timeout` configuration setting. `0`
|
||||
means no timeout.
|
||||
|
||||
- [`--keep-going`]{#opt-keep-going} / `-k`\
|
||||
- `--keep-going` / `-k`\
|
||||
Keep going in case of failed builds, to the greatest extent
|
||||
possible. That is, if building an input of some derivation fails,
|
||||
Nix will still build the other inputs, but not the derivation
|
||||
@@ -113,13 +113,13 @@ Most Nix commands accept the following command-line options:
|
||||
for builds of substitutes), possibly killing builds in progress (in
|
||||
case of parallel or distributed builds).
|
||||
|
||||
- [`--keep-failed`]{#opt-keep-failed} / `-K`\
|
||||
- `--keep-failed` / `-K`\
|
||||
Specifies that in case of a build failure, the temporary directory
|
||||
(usually in `/tmp`) in which the build takes place should not be
|
||||
deleted. The path of the build directory is printed as an
|
||||
informational message.
|
||||
|
||||
- [`--fallback`]{#opt-fallback}\
|
||||
- `--fallback`\
|
||||
Whenever Nix attempts to build a derivation for which substitutes
|
||||
are known for each output path, but realising the output paths
|
||||
through the substitutes fails, fall back on building the derivation.
|
||||
@@ -134,12 +134,12 @@ Most Nix commands accept the following command-line options:
|
||||
failure in obtaining the substitutes to lead to a full build from
|
||||
source (with the related consumption of resources).
|
||||
|
||||
- [`--readonly-mode`]{#opt-readonly-mode}\
|
||||
- `--readonly-mode`\
|
||||
When this option is used, no attempt is made to open the Nix
|
||||
database. Most Nix operations do need database access, so those
|
||||
operations will fail.
|
||||
|
||||
- [`--arg`]{#opt-arg} *name* *value*\
|
||||
- `--arg` *name* *value*\
|
||||
This option is accepted by `nix-env`, `nix-instantiate`,
|
||||
`nix-shell` and `nix-build`. When evaluating Nix expressions, the
|
||||
expression evaluator will automatically try to call functions that
|
||||
@@ -170,13 +170,13 @@ Most Nix commands accept the following command-line options:
|
||||
since the argument is a Nix string literal, you have to escape the
|
||||
quotes.)
|
||||
|
||||
- [`--argstr`]{#opt-argstr} *name* *value*\
|
||||
- `--argstr` *name* *value*\
|
||||
This option is like `--arg`, only the value is not a Nix
|
||||
expression but a string. So instead of `--arg system
|
||||
\"i686-linux\"` (the outer quotes are to keep the shell happy) you
|
||||
can say `--argstr system i686-linux`.
|
||||
|
||||
- [`--attr`]{#opt-attr} / `-A` *attrPath*\
|
||||
- `--attr` / `-A` *attrPath*\
|
||||
Select an attribute from the top-level Nix expression being
|
||||
evaluated. (`nix-env`, `nix-instantiate`, `nix-build` and
|
||||
`nix-shell` only.) The *attribute path* *attrPath* is a sequence
|
||||
@@ -191,7 +191,7 @@ Most Nix commands accept the following command-line options:
|
||||
attribute of the fourth element of the array in the `foo` attribute
|
||||
of the top-level expression.
|
||||
|
||||
- [`--expr`]{#opt-expr} / `-E`\
|
||||
- `--expr` / `-E`\
|
||||
Interpret the command line arguments as a list of Nix expressions to
|
||||
be parsed and evaluated, rather than as a list of file names of Nix
|
||||
expressions. (`nix-instantiate`, `nix-build` and `nix-shell` only.)
|
||||
@@ -202,17 +202,17 @@ Most Nix commands accept the following command-line options:
|
||||
use, give your expression to the `nix-shell -p` convenience flag
|
||||
instead.
|
||||
|
||||
- [`-I`]{#opt-I} *path*\
|
||||
- `-I` *path*\
|
||||
Add a path to the Nix expression search path. This option may be
|
||||
given multiple times. See the `NIX_PATH` environment variable for
|
||||
information on the semantics of the Nix search path. Paths added
|
||||
through `-I` take precedence over `NIX_PATH`.
|
||||
|
||||
- [`--option`]{#opt-option} *name* *value*\
|
||||
- `--option` *name* *value*\
|
||||
Set the Nix configuration option *name* to *value*. This overrides
|
||||
settings in the Nix configuration file (see nix.conf5).
|
||||
|
||||
- [`--repair`]{#opt-repair}\
|
||||
- `--repair`\
|
||||
Fix corrupted or missing store paths by redownloading or rebuilding
|
||||
them. Note that this is slow because it requires computing a
|
||||
cryptographic hash of the contents of every path in the closure of
|
||||
|
||||
@@ -35,25 +35,6 @@ variables are set up so that those dependencies can be found:
|
||||
$ nix-shell
|
||||
```
|
||||
|
||||
or if you have a flake-enabled nix:
|
||||
|
||||
```console
|
||||
$ nix develop
|
||||
```
|
||||
|
||||
To get a shell with a different compilation environment (e.g. stdenv,
|
||||
gccStdenv, clangStdenv, clang11Stdenv):
|
||||
|
||||
```console
|
||||
$ nix-shell -A devShells.x86_64-linux.clang11StdenvPackages
|
||||
```
|
||||
|
||||
or if you have a flake-enabled nix:
|
||||
|
||||
```console
|
||||
$ nix develop .#clang11StdenvPackages
|
||||
```
|
||||
|
||||
To build Nix itself in this shell:
|
||||
|
||||
```console
|
||||
@@ -71,6 +52,18 @@ To install it in `$(pwd)/outputs` and test it:
|
||||
nix (Nix) 3.0
|
||||
```
|
||||
|
||||
To run a functional test:
|
||||
|
||||
```console
|
||||
make tests/test-name-should-auto-complete.sh.test
|
||||
```
|
||||
|
||||
To run the unit-tests for C++ code:
|
||||
|
||||
```
|
||||
make check
|
||||
```
|
||||
|
||||
If you have a flakes-enabled Nix you can replace:
|
||||
|
||||
```console
|
||||
@@ -82,29 +75,3 @@ by:
|
||||
```console
|
||||
$ nix develop
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Nix comes with three different flavors of tests: unit, functional and integration.
|
||||
|
||||
### Unit-tests
|
||||
|
||||
The unit-tests for each Nix library (`libexpr`, `libstore`, etc..) are defined
|
||||
under `src/{library_name}/tests` using the
|
||||
[googletest](https://google.github.io/googletest/) framework.
|
||||
|
||||
You can run the whole testsuite with `make check`, or the tests for a specific component with `make libfoo-tests_RUN`. Finer-grained filtering is also possible using the [--gtest_filter](https://google.github.io/googletest/advanced.html#running-a-subset-of-the-tests) command-line option.
|
||||
|
||||
### Functional tests
|
||||
|
||||
The functional tests reside under the `tests` directory and are listed in `tests/local.mk`.
|
||||
The whole testsuite can be run with `make install && make installcheck`.
|
||||
Individual tests can be run with `make tests/{testName}.sh.test`.
|
||||
|
||||
### Integration tests
|
||||
|
||||
The integration tests are defined in the Nix flake under the `hydraJobs.tests` attribute.
|
||||
These tests include everything that needs to interact with external services or run Nix in a non-trivial distributed setup.
|
||||
Because these tests are expensive and require more than what the standard github-actions setup provides, they only run on the master branch (on <https://hydra.nixos.org/jobset/nix/master>).
|
||||
|
||||
You can run them manually with `nix build .#hydraJobs.tests.{testName}` or `nix-build -A hydraJobs.tests.{testName}`
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Derivations can declare some infrequently used optional attributes.
|
||||
|
||||
- [`allowedReferences`]{#adv-attr-allowedReferences}\
|
||||
- `allowedReferences`\
|
||||
The optional attribute `allowedReferences` specifies a list of legal
|
||||
references (dependencies) of the output of the builder. For example,
|
||||
|
||||
@@ -17,7 +17,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
booting Linux don’t have accidental dependencies on other paths in
|
||||
the Nix store.
|
||||
|
||||
- [`allowedRequisites`]{#adv-attr-allowedRequisites}\
|
||||
- `allowedRequisites`\
|
||||
This attribute is similar to `allowedReferences`, but it specifies
|
||||
the legal requisites of the whole closure, so all the dependencies
|
||||
recursively. For example,
|
||||
@@ -30,7 +30,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
runtime dependency than `foobar`, and in addition it enforces that
|
||||
`foobar` itself doesn't introduce any other dependency itself.
|
||||
|
||||
- [`disallowedReferences`]{#adv-attr-disallowedReferences}\
|
||||
- `disallowedReferences`\
|
||||
The optional attribute `disallowedReferences` specifies a list of
|
||||
illegal references (dependencies) of the output of the builder. For
|
||||
example,
|
||||
@@ -42,7 +42,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
enforces that the output of a derivation cannot have a direct
|
||||
runtime dependencies on the derivation `foo`.
|
||||
|
||||
- [`disallowedRequisites`]{#adv-attr-disallowedRequisites}\
|
||||
- `disallowedRequisites`\
|
||||
This attribute is similar to `disallowedReferences`, but it
|
||||
specifies illegal requisites for the whole closure, so all the
|
||||
dependencies recursively. For example,
|
||||
@@ -55,7 +55,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
dependency on `foobar` or any other derivation depending recursively
|
||||
on `foobar`.
|
||||
|
||||
- [`exportReferencesGraph`]{#adv-attr-exportReferencesGraph}\
|
||||
- `exportReferencesGraph`\
|
||||
This attribute allows builders access to the references graph of
|
||||
their inputs. The attribute is a list of inputs in the Nix store
|
||||
whose references graph the builder needs to know. The value of
|
||||
@@ -84,7 +84,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
with a Nix store containing the closure of a bootable NixOS
|
||||
configuration).
|
||||
|
||||
- [`impureEnvVars`]{#adv-attr-impureEnvVars}\
|
||||
- `impureEnvVars`\
|
||||
This attribute allows you to specify a list of environment variables
|
||||
that should be passed from the environment of the calling user to
|
||||
the builder. Usually, the environment is cleared completely when the
|
||||
@@ -112,7 +112,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
> environmental variables come from the environment of the
|
||||
> `nix-build`.
|
||||
|
||||
- [`outputHash`]{#adv-attr-outputHash}; [`outputHashAlgo`]{#adv-attr-outputHashAlgo}; [`outputHashMode`]{#adv-attr-outputHashMode}\
|
||||
- `outputHash`; `outputHashAlgo`; `outputHashMode`\
|
||||
These attributes declare that the derivation is a so-called
|
||||
*fixed-output derivation*, which means that a cryptographic hash of
|
||||
the output is already known in advance. When the build of a
|
||||
@@ -208,7 +208,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
[`nix-hash` command](../command-ref/nix-hash.md) for information
|
||||
about converting to and from base-32 notation.)
|
||||
|
||||
- [`__contentAddressed`]{#adv-attr-__contentAddressed}
|
||||
- `__contentAddressed`
|
||||
If this **experimental** attribute is set to true, then the derivation
|
||||
outputs will be stored in a content-addressed location rather than the
|
||||
traditional input-addressed one.
|
||||
@@ -216,7 +216,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
|
||||
Setting this attribute also requires setting `outputHashMode` and `outputHashAlgo` like for *fixed-output derivations* (see above).
|
||||
|
||||
- [`passAsFile`]{#adv-attr-passAsFile}\
|
||||
- `passAsFile`\
|
||||
A list of names of attributes that should be passed via files rather
|
||||
than environment variables. For example, if you have
|
||||
|
||||
@@ -234,7 +234,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
builder, since most operating systems impose a limit on the size
|
||||
of the environment (typically, a few hundred kilobyte).
|
||||
|
||||
- [`preferLocalBuild`]{#adv-attr-preferLocalBuild}\
|
||||
- `preferLocalBuild`\
|
||||
If this attribute is set to `true` and [distributed building is
|
||||
enabled](../advanced-topics/distributed-builds.md), then, if
|
||||
possible, the derivation will be built locally instead of forwarded
|
||||
@@ -242,7 +242,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
where the cost of doing a download or remote build would exceed
|
||||
the cost of building locally.
|
||||
|
||||
- [`allowSubstitutes`]{#adv-attr-allowSubstitutes}\
|
||||
- `allowSubstitutes`\
|
||||
If this attribute is set to `false`, then Nix will always build this
|
||||
derivation; it will not try to substitute its outputs. This is
|
||||
useful for very trivial derivations (such as `writeText` in Nixpkgs)
|
||||
|
||||
@@ -14,7 +14,7 @@ Here are the constants built into the Nix expression evaluator:
|
||||
This allows a Nix expression to fall back gracefully on older Nix
|
||||
installations that don’t have the desired built-in function.
|
||||
|
||||
- [`builtins.currentSystem`]{#builtins-currentSystem}\
|
||||
- `builtins.currentSystem`\
|
||||
The built-in value `currentSystem` evaluates to the Nix platform
|
||||
identifier for the Nix installation on which the expression is being
|
||||
evaluated, such as `"i686-linux"` or `"x86_64-darwin"`.
|
||||
|
||||
@@ -4,7 +4,7 @@ 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,
|
||||
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` whose value must be a
|
||||
string specifying a Nix system type, such as `"i686-linux"` or
|
||||
`"x86_64-darwin"`. (To figure out your system type, run `nix -vv
|
||||
--version`.) The build can only be performed on a machine and
|
||||
|
||||
@@ -284,10 +284,6 @@ The points of interest are:
|
||||
function is called with the `localServer` argument set to `true` but
|
||||
the `db4` argument set to `null`, then the evaluation fails.
|
||||
|
||||
Note that `->` is the [logical
|
||||
implication](https://en.wikipedia.org/wiki/Truth_table#Logical_implication)
|
||||
Boolean operation.
|
||||
|
||||
2. This is a more subtle condition: if Subversion is built with Apache
|
||||
(`httpServer`) support, then the Expat library (an XML library) used
|
||||
by Subversion should be same as the one used by Apache. This is
|
||||
|
||||
@@ -1,62 +1,62 @@
|
||||
# Glossary
|
||||
|
||||
- [derivation]{#gloss-derivation}\
|
||||
- derivation\
|
||||
A description of a build action. The result of a derivation is a
|
||||
store object. Derivations are typically specified in Nix expressions
|
||||
using the [`derivation` primitive](expressions/derivations.md). These are
|
||||
translated into low-level *store derivations* (implicitly by
|
||||
`nix-env` and `nix-build`, or explicitly by `nix-instantiate`).
|
||||
|
||||
- [store]{#gloss-store}\
|
||||
- store\
|
||||
The location in the file system where store objects live. Typically
|
||||
`/nix/store`.
|
||||
|
||||
- [store path]{#gloss-store-path}\
|
||||
- store path\
|
||||
The location in the file system of a store object, i.e., an
|
||||
immediate child of the Nix store directory.
|
||||
|
||||
- [store object]{#gloss-store-object}\
|
||||
- store object\
|
||||
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 sources (objects copied from outside of the store),
|
||||
derivation outputs (objects produced by running a build action), or
|
||||
derivations (files describing a build action).
|
||||
|
||||
- [substitute]{#gloss-substitute}\
|
||||
- substitute\
|
||||
A substitute is a command invocation stored in the Nix database that
|
||||
describes how to build a store object, bypassing the normal build
|
||||
mechanism (i.e., derivations). Typically, the substitute builds the
|
||||
store object by downloading a pre-built version of the store object
|
||||
from some server.
|
||||
|
||||
- [purity]{#gloss-purity}\
|
||||
- purity\
|
||||
The assumption that equal Nix derivations when run always produce
|
||||
the same output. This cannot be guaranteed in general (e.g., a
|
||||
builder can rely on external inputs such as the network or the
|
||||
system time) but the Nix model assumes it.
|
||||
|
||||
- [Nix expression]{#gloss-nix-expression}\
|
||||
- Nix expression\
|
||||
A high-level description of software packages and compositions
|
||||
thereof. Deploying software using Nix entails writing Nix
|
||||
expressions for your packages. Nix expressions are translated to
|
||||
derivations that are stored in the Nix store. These derivations can
|
||||
then be built.
|
||||
|
||||
- [reference]{#gloss-reference}\
|
||||
- reference\
|
||||
A store path `P` is said to have a reference to a store path `Q` if
|
||||
the store object at `P` contains the path `Q` somewhere. The
|
||||
*references* of a store path are the set of store paths to which it
|
||||
has a reference.
|
||||
|
||||
|
||||
A derivation can reference other derivations and sources (but not
|
||||
output paths), whereas an output path only references other output
|
||||
paths.
|
||||
|
||||
- [reachable]{#gloss-reachable}\
|
||||
- reachable\
|
||||
A store path `Q` is reachable from another store path `P` if `Q`
|
||||
is in the *closure* of the *references* relation.
|
||||
|
||||
- [closure]{#gloss-closure}\
|
||||
- closure\
|
||||
The closure of a store path is the set of store paths that are
|
||||
directly or indirectly “reachable” from that store path; that is,
|
||||
it’s the closure of the path under the *references* relation. For
|
||||
@@ -66,39 +66,35 @@
|
||||
is necessary to deploy whole closures, since otherwise at runtime
|
||||
files could be missing. The command `nix-store -qR` prints out
|
||||
closures of store paths.
|
||||
|
||||
|
||||
As an example, if the store object at path `P` contains a reference
|
||||
to path `Q`, then `Q` is in the closure of `P`. Further, if `Q`
|
||||
references `R` then `R` is also in the closure of `P`.
|
||||
|
||||
- [output path]{#gloss-output-path}\
|
||||
- output path\
|
||||
A store path produced by a derivation.
|
||||
|
||||
- [deriver]{#gloss-deriver}\
|
||||
- deriver\
|
||||
The deriver of an *output path* is the store
|
||||
derivation that built it.
|
||||
|
||||
- [validity]{#gloss-validity}\
|
||||
- validity\
|
||||
A store path is considered *valid* if it exists in the file system,
|
||||
is listed in the Nix database as being valid, and if all paths in
|
||||
its closure are also valid.
|
||||
|
||||
- [user environment]{#gloss-user-env}\
|
||||
- user environment\
|
||||
An automatically generated store object that consists of a set of
|
||||
symlinks to “active” applications, i.e., other store paths. These
|
||||
are generated automatically by
|
||||
[`nix-env`](command-ref/nix-env.md). See *profiles*.
|
||||
|
||||
- [profile]{#gloss-profile}\
|
||||
- profile\
|
||||
A symlink to the current *user environment* of a user, e.g.,
|
||||
`/nix/var/nix/profiles/default`.
|
||||
|
||||
- [NAR]{#gloss-nar}\
|
||||
- NAR\
|
||||
A *N*ix *AR*chive. This is a serialisation of a path in the Nix
|
||||
store. It can contain regular files, directories and symbolic
|
||||
links. NARs are generated and unpacked using `nix-store --dump`
|
||||
and `nix-store --restore`.
|
||||
- [`∅`]{#gloss-emtpy-set}\
|
||||
The empty set symbol. In the context of profile history, this denotes a package is not present in a particular version of the profile.
|
||||
- [`ε`]{#gloss-epsilon}\
|
||||
The epsilon symbol. In the context of a package, this means the version is empty. More precisely, the derivation does not have a version attribute.
|
||||
|
||||
@@ -84,9 +84,7 @@ The installer will modify `/etc/bashrc`, and `/etc/zshrc` if they exist.
|
||||
The installer will first back up these files with a `.backup-before-nix`
|
||||
extension. The installer will also create `/etc/profile.d/nix.sh`.
|
||||
|
||||
## Uninstalling
|
||||
|
||||
### Linux
|
||||
You can uninstall Nix with the following commands:
|
||||
|
||||
```console
|
||||
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
|
||||
@@ -97,97 +95,16 @@ sudo systemctl stop nix-daemon.service
|
||||
sudo systemctl disable nix-daemon.socket
|
||||
sudo systemctl disable nix-daemon.service
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
# If you are on macOS, you will need to run:
|
||||
sudo launchctl unload /Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
sudo rm /Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
```
|
||||
|
||||
There may also be references to Nix in `/etc/profile`, `/etc/bashrc`,
|
||||
and `/etc/zshrc` which you may remove.
|
||||
|
||||
### macOS
|
||||
|
||||
1. Edit `/etc/zshrc` and `/etc/bashrc` to remove the lines sourcing
|
||||
`nix-daemon.sh`, which should look like this:
|
||||
|
||||
```bash
|
||||
# Nix
|
||||
if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
|
||||
. '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
|
||||
fi
|
||||
# End Nix
|
||||
```
|
||||
|
||||
If these files haven't been altered since installing Nix you can simply put
|
||||
the backups back in place:
|
||||
|
||||
```console
|
||||
sudo mv /etc/zshrc.backup-before-nix /etc/zshrc
|
||||
sudo mv /etc/bashrc.backup-before-nix /etc/bashrc
|
||||
```
|
||||
|
||||
This will stop shells from sourcing the file and bringing everything you
|
||||
installed using Nix in scope.
|
||||
|
||||
2. Stop and remove the Nix daemon services:
|
||||
|
||||
```console
|
||||
sudo launchctl unload /Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
sudo rm /Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
sudo launchctl unload /Library/LaunchDaemons/org.nixos.darwin-store.plist
|
||||
sudo rm /Library/LaunchDaemons/org.nixos.darwin-store.plist
|
||||
```
|
||||
|
||||
This stops the Nix daemon and prevents it from being started next time you
|
||||
boot the system.
|
||||
|
||||
3. Remove the `nixbld` group and the `_nixbuildN` users:
|
||||
|
||||
```console
|
||||
sudo dscl . -delete /Groups/nixbld
|
||||
for u in $(sudo dscl . -list /Users | grep _nixbld); do sudo dscl . -delete /Users/$u; done
|
||||
```
|
||||
|
||||
This will remove all the build users that no longer serve a purpose.
|
||||
|
||||
4. Edit fstab using `sudo vifs` to remove the line mounting the Nix Store
|
||||
volume on `/nix`, which looks like this,
|
||||
`LABEL=Nix\040Store /nix apfs rw,nobrowse`. This will prevent automatic
|
||||
mounting of the Nix Store volume.
|
||||
|
||||
5. Edit `/etc/synthetic.conf` to remove the `nix` line. If this is the only
|
||||
line in the file you can remove it entirely, `sudo rm /etc/synthetic.conf`.
|
||||
This will prevent the creation of the empty `/nix` directory to provide a
|
||||
mountpoint for the Nix Store volume.
|
||||
|
||||
6. Remove the files Nix added to your system:
|
||||
|
||||
```console
|
||||
sudo rm -rf /etc/nix /var/root/.nix-profile /var/root/.nix-defexpr /var/root/.nix-channels ~/.nix-profile ~/.nix-defexpr ~/.nix-channels
|
||||
```
|
||||
|
||||
This gets rid of any data Nix may have created except for the store which is
|
||||
removed next.
|
||||
|
||||
7. Remove the Nix Store volume:
|
||||
|
||||
```console
|
||||
sudo diskutil apfs deleteVolume /nix
|
||||
```
|
||||
|
||||
This will remove the Nix Store volume and everything that was added to the
|
||||
store.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> After you complete the steps here, you will still have an empty `/nix`
|
||||
> directory. This is an expected sign of a successful uninstall. The empty
|
||||
> `/nix` directory will disappear the next time you reboot.
|
||||
>
|
||||
> You do not have to reboot to finish uninstalling Nix. The uninstall is
|
||||
> complete. macOS (Catalina+) directly controls root directories and its
|
||||
> read-only root will prevent you from manually deleting the empty `/nix`
|
||||
> mountpoint.
|
||||
|
||||
# macOS Installation
|
||||
[]{#sect-macos-installation-change-store-prefix}[]{#sect-macos-installation-encrypted-volume}[]{#sect-macos-installation-symlink}[]{#sect-macos-installation-recommended-notes}
|
||||
# macOS Installation <a name="sect-macos-installation-change-store-prefix"></a><a name="sect-macos-installation-encrypted-volume"></a><a name="sect-macos-installation-symlink"></a><a name="sect-macos-installation-recommended-notes"></a>
|
||||
<!-- Note: anchors above to catch permalinks to old explanations -->
|
||||
|
||||
We believe we have ironed out how to cleanly support the read-only root
|
||||
@@ -202,30 +119,6 @@ this to run the installer, but it may help if you run into trouble:
|
||||
- update `/etc/synthetic.conf` to direct macOS to create a "synthetic"
|
||||
empty root directory to mount your volume
|
||||
- specify mount options for the volume in `/etc/fstab`
|
||||
- `rw`: read-write
|
||||
- `noauto`: prevent the system from auto-mounting the volume (so the
|
||||
LaunchDaemon mentioned below can control mounting it, and to avoid
|
||||
masking problems with that mounting service).
|
||||
- `nobrowse`: prevent the Nix Store volume from showing up on your
|
||||
desktop; also keeps Spotlight from spending resources to index
|
||||
this volume
|
||||
<!-- TODO:
|
||||
- `suid`: honor setuid? surely not? ...
|
||||
- `owners`: honor file ownership on the volume
|
||||
|
||||
For now I'll avoid pretending to understand suid/owners more
|
||||
than I do. There've been some vague reports of file-ownership
|
||||
and permission issues, particularly in cloud/VM/headless setups.
|
||||
My pet theory is that this has something to do with these setups
|
||||
not having a token that gets delegated to initial/admin accounts
|
||||
on macOS. See scripts/create-darwin-volume.sh for a little more.
|
||||
|
||||
In any case, by Dec 4 2021, it _seems_ like some combination of
|
||||
suid, owners, and calling diskutil enableOwnership have stopped
|
||||
new reports from coming in. But I hesitate to celebrate because we
|
||||
haven't really named and catalogued the behavior, understood what
|
||||
we're fixing, and validated that all 3 components are essential.
|
||||
-->
|
||||
- if you have FileVault enabled
|
||||
- generate an encryption password
|
||||
- put it in your system Keychain
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
To run the latest stable release of Nix with Docker run the following command:
|
||||
|
||||
```console
|
||||
$ docker run -ti nixos/nix
|
||||
$ docker -ti run nixos/nix
|
||||
Unable to find image 'nixos/nix:latest' locally
|
||||
latest: Pulling from nixos/nix
|
||||
5843afab3874: Pull complete
|
||||
@@ -16,7 +16,7 @@ nix (Nix) 2.3.12
|
||||
35ca4ada6e96:/# exit
|
||||
```
|
||||
|
||||
# What is included in Nix's Docker image?
|
||||
# What is included in Nix' Docker image?
|
||||
|
||||
The official Docker image is created using `pkgs.dockerTools.buildLayeredImage`
|
||||
(and not with `Dockerfile` as it is usual with Docker images). You can still
|
||||
@@ -54,6 +54,6 @@ You can also build a Docker image from source yourself:
|
||||
|
||||
```console
|
||||
$ nix build ./\#hydraJobs.dockerImage.x86_64-linux
|
||||
$ docker load -i ./result/image.tar.gz
|
||||
$ docker load -i ./result
|
||||
$ docker run -ti nix:2.5pre20211105
|
||||
```
|
||||
|
||||
@@ -44,11 +44,6 @@
|
||||
obtained from the its repository
|
||||
<https://github.com/troglobit/editline>.
|
||||
|
||||
- The `libsodium` library for verifying cryptographic signatures
|
||||
of contents fetched from binary caches.
|
||||
It can be obtained from the official web site
|
||||
<https://libsodium.org>.
|
||||
|
||||
- Recent versions of Bison and Flex to build the parser. (This is
|
||||
because Nix needs GLR support in Bison and reentrancy support in
|
||||
Flex.) For Bison, you need version 2.6, which can be obtained from
|
||||
@@ -63,11 +58,3 @@
|
||||
`--disable-seccomp-sandboxing` option to the `configure` script (Not
|
||||
recommended unless your system doesn't support `libseccomp`). To get
|
||||
the library, visit <https://github.com/seccomp/libseccomp>.
|
||||
|
||||
- On 64-bit x86 machines only, `libcpuid` library
|
||||
is used to determine which microarchitecture levels are supported
|
||||
(e.g., as whether to have `x86_64-v2-linux` among additional system types).
|
||||
The library is available from its homepage
|
||||
<http://libcpuid.sourceforge.net>.
|
||||
This is an optional dependency and can be disabled
|
||||
by providing a `--disable-cpuid` to the `configure` script.
|
||||
|
||||
@@ -4,4 +4,4 @@ Nix is currently supported on the following platforms:
|
||||
|
||||
- Linux (i686, x86\_64, aarch64).
|
||||
|
||||
- macOS (x86\_64, aarch64).
|
||||
- macOS (x86\_64).
|
||||
|
||||
@@ -40,7 +40,7 @@ $ nix-channel --update
|
||||
>
|
||||
> On NixOS, you’re automatically subscribed to a NixOS channel
|
||||
> corresponding to your NixOS major release (e.g.
|
||||
> <http://nixos.org/channels/nixos-21.11>). A NixOS channel is identical
|
||||
> <http://nixos.org/channels/nixos-14.12>). A NixOS channel is identical
|
||||
> to the Nixpkgs channel, except that it contains only Linux binaries
|
||||
> and is updated only if a set of regression tests succeed.
|
||||
|
||||
|
||||
@@ -276,9 +276,6 @@ more than 2800 commits from 195 contributors since release 2.3.
|
||||
|
||||
* Plugins can now register `nix` subcommands.
|
||||
|
||||
* The `--indirect` flag to `nix-store --add-root` has become a no-op.
|
||||
`--add-root` will always generate indirect GC roots from now on.
|
||||
|
||||
## Incompatible changes
|
||||
|
||||
* The `nix` command is now marked as an experimental feature. This
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# Release 2.5 (2021-12-13)
|
||||
|
||||
* The garbage collector no longer blocks new builds, so the message
|
||||
`waiting for the big garbage collector lock...` is a thing of the
|
||||
past.
|
||||
|
||||
* Binary cache stores now have a setting `compression-level`.
|
||||
|
||||
* `nix develop` now has a flag `--unpack` to run `unpackPhase`.
|
||||
|
||||
* Lists can now be compared lexicographically using the `<` operator.
|
||||
|
||||
* New built-in function: `builtins.groupBy`, with the same functionality as
|
||||
Nixpkgs' `lib.groupBy`, but faster.
|
||||
|
||||
* `nix repl` now has a `:log` command.
|
||||
@@ -1,21 +0,0 @@
|
||||
# Release 2.6 (2022-01-24)
|
||||
|
||||
* The Nix CLI now searches for a `flake.nix` up until the root of the current
|
||||
Git repository or a filesystem boundary rather than just in the current
|
||||
directory.
|
||||
* The TOML parser used by `builtins.fromTOML` has been replaced by [a
|
||||
more compliant one](https://github.com/ToruNiina/toml11).
|
||||
* Added `:st`/`:show-trace` commands to `nix repl`, which are used to
|
||||
set or toggle display of error traces.
|
||||
* New builtin function `builtins.zipAttrsWith` with the same
|
||||
functionality as `lib.zipAttrsWith` from Nixpkgs, but much more
|
||||
efficient.
|
||||
* New command `nix store copy-log` to copy build logs from one store
|
||||
to another.
|
||||
* The `commit-lockfile-summary` option can be set to a non-empty
|
||||
string to override the commit summary used when commiting an updated
|
||||
lockfile. This may be used in conjunction with the `nixConfig`
|
||||
attribute in `flake.nix` to better conform to repository
|
||||
conventions.
|
||||
* `docker run -ti nixos/nix:master` will place you in the Docker
|
||||
container with the latest version of Nix from the `master` branch.
|
||||
@@ -1,33 +0,0 @@
|
||||
# Release 2.7 (2022-03-07)
|
||||
|
||||
* Nix will now make some helpful suggestions when you mistype
|
||||
something on the command line. For instance, if you type `nix build
|
||||
nixpkgs#thunderbrd`, it will suggest `thunderbird`.
|
||||
|
||||
* A number of "default" flake output attributes have been
|
||||
renamed. These are:
|
||||
|
||||
* `defaultPackage.<system>` → `packages.<system>.default`
|
||||
* `defaultApps.<system>` → `apps.<system>.default`
|
||||
* `defaultTemplate` → `templates.default`
|
||||
* `defaultBundler.<system>` → `bundlers.<system>.default`
|
||||
* `overlay` → `overlays.default`
|
||||
* `devShell.<system>` → `devShells.<system>.default`
|
||||
|
||||
The old flake output attributes still work, but `nix flake check`
|
||||
will warn about them.
|
||||
|
||||
* Breaking API change: `nix bundle` now supports bundlers of the form
|
||||
`bundler.<system>.<name>= derivation: another-derivation;`. This
|
||||
supports additional functionality to inspect evaluation information
|
||||
during bundling. A new
|
||||
[repository](https://github.com/NixOS/bundlers) has various bundlers
|
||||
implemented.
|
||||
|
||||
* `nix store ping` now reports the version of the remote Nix daemon.
|
||||
|
||||
* `nix flake {init,new}` now display information about which files have been
|
||||
created.
|
||||
|
||||
* Templates can now define a `welcomeText` attribute, which is printed out by
|
||||
`nix flake {init,new} --template <template>`.
|
||||
@@ -1,53 +0,0 @@
|
||||
# Release 2.8 (2022-04-19)
|
||||
|
||||
* New experimental command: `nix fmt`, which applies a formatter
|
||||
defined by the `formatter.<system>` flake output to the Nix
|
||||
expressions in a flake.
|
||||
|
||||
* Various Nix commands can now read expressions from standard input
|
||||
using `--file -`.
|
||||
|
||||
* New experimental builtin function `builtins.fetchClosure` that
|
||||
copies a closure from a binary cache at evaluation time and rewrites
|
||||
it to content-addressed form (if it isn't already). Like
|
||||
`builtins.storePath`, this allows importing pre-built store paths;
|
||||
the difference is that it doesn't require the user to configure
|
||||
binary caches and trusted public keys.
|
||||
|
||||
This function is only available if you enable the experimental
|
||||
feature `fetch-closure`.
|
||||
|
||||
* New experimental feature: *impure derivations*. These are
|
||||
derivations that can produce a different result every time they're
|
||||
built. Here is an example:
|
||||
|
||||
```nix
|
||||
stdenv.mkDerivation {
|
||||
name = "impure";
|
||||
__impure = true; # marks this derivation as impure
|
||||
buildCommand = "date > $out";
|
||||
}
|
||||
```
|
||||
|
||||
Running `nix build` twice on this expression will build the
|
||||
derivation twice, producing two different content-addressed store
|
||||
paths. Like fixed-output derivations, impure derivations have access
|
||||
to the network. Only fixed-output derivations and impure derivations
|
||||
can depend on an impure derivation.
|
||||
|
||||
* `nix store make-content-addressable` has been renamed to `nix store
|
||||
make-content-addressed`.
|
||||
|
||||
* The `nixosModule` flake output attribute has been renamed consistent
|
||||
with the `.default` renames in Nix 2.7.
|
||||
|
||||
* `nixosModule` → `nixosModules.default`
|
||||
|
||||
As before, the old output will continue to work, but `nix flake check` will
|
||||
issue a warning about it.
|
||||
|
||||
* `nix run` is now stricter in what it accepts: members of the `apps`
|
||||
flake output are now required to be apps (as defined in [the
|
||||
manual](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-run.html#apps)),
|
||||
and members of `packages` or `legacyPackages` must be derivations
|
||||
(not apps).
|
||||
@@ -1,47 +0,0 @@
|
||||
# Release 2.9 (2022-05-30)
|
||||
|
||||
* Running Nix with the new `--debugger` flag will cause it to start a
|
||||
repl session if if an exception is thrown during evaluation, or if
|
||||
`builtins.break` is called. From there you can inspect the values
|
||||
of variables and evaluate Nix expressions. In debug mode, the
|
||||
following new repl commands are available:
|
||||
|
||||
```
|
||||
:env Show env stack
|
||||
:bt Show trace stack
|
||||
:st Show current trace
|
||||
:st <idx> Change to another trace in the stack
|
||||
:c Go until end of program, exception, or builtins.break().
|
||||
:s Go one step
|
||||
```
|
||||
|
||||
Read more about the debugger
|
||||
[here](https://www.zknotes.com/note/5970).
|
||||
|
||||
* Nix now provides better integration with zsh's `run-help`
|
||||
feature. It is now included in the Nix installation in the form of
|
||||
an autoloadable shell function, `run-help-nix`. It picks up Nix
|
||||
subcommands from the currently typed in command and directs the user
|
||||
to the associated man pages.
|
||||
|
||||
* `nix repl` has a new build-and-link (`:bl`) command that builds a
|
||||
derivation while creating GC root symlinks.
|
||||
|
||||
* The path produced by `builtins.toFile` is now allowed to be imported
|
||||
or read even with restricted evaluation. Note that this will not
|
||||
work with a read-only store.
|
||||
|
||||
* `nix build` has a new `--print-out-paths` flag to print the
|
||||
resulting output paths. This matches the default behaviour of
|
||||
`nix-build`.
|
||||
|
||||
* You can now specify which outputs of a derivation `nix` should
|
||||
operate on using the syntax `installable^outputs`,
|
||||
e.g. `nixpkgs#glibc^dev,static` or `nixpkgs#glibc^*`. By default,
|
||||
`nix` will use the outputs specified by the derivation's
|
||||
`meta.outputsToInstall` attribute if it exists, or all outputs
|
||||
otherwise.
|
||||
|
||||
* `builtins.fetchTree` (and flake inputs) can now be used to fetch
|
||||
plain files over the `http(s)` and `file` protocols in addition to
|
||||
directory tarballs.
|
||||
@@ -1 +1,7 @@
|
||||
# Release X.Y (202?-??-??)
|
||||
# Release 2.5 (2021-XX-XX)
|
||||
|
||||
* Binary cache stores now have a setting `compression-level`.
|
||||
|
||||
* `nix develop` now has a flag `--unpack` to run `unpackPhase`.
|
||||
|
||||
* Lists can now be compared lexicographically using the `<` operator.
|
||||
|
||||
24
docker.nix
24
docker.nix
@@ -20,9 +20,6 @@ let
|
||||
man
|
||||
cacert.out
|
||||
findutils
|
||||
iana-etc
|
||||
git
|
||||
openssh
|
||||
];
|
||||
|
||||
users = {
|
||||
@@ -140,8 +137,11 @@ let
|
||||
name = "root-profile-env";
|
||||
paths = defaultPkgs;
|
||||
};
|
||||
manifest = pkgs.buildPackages.runCommand "manifest.nix" { } ''
|
||||
cat > $out <<EOF
|
||||
profile = pkgs.buildPackages.runCommand "user-environment" { } ''
|
||||
mkdir $out
|
||||
cp -a ${rootEnv}/* $out/
|
||||
|
||||
cat > $out/manifest.nix <<EOF
|
||||
[
|
||||
${lib.concatStringsSep "\n" (builtins.map (drv: let
|
||||
outputs = drv.outputsToInstall or [ "out" ];
|
||||
@@ -161,11 +161,6 @@ let
|
||||
]
|
||||
EOF
|
||||
'';
|
||||
profile = pkgs.buildPackages.runCommand "user-environment" { } ''
|
||||
mkdir $out
|
||||
cp -a ${rootEnv}/* $out/
|
||||
ln -s ${manifest} $out/manifest.nix
|
||||
'';
|
||||
in
|
||||
pkgs.runCommand "base-system"
|
||||
{
|
||||
@@ -183,9 +178,6 @@ let
|
||||
set -x
|
||||
mkdir -p $out/etc
|
||||
|
||||
mkdir -p $out/etc/ssl/certs
|
||||
ln -s /nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt $out/etc/ssl/certs
|
||||
|
||||
cat $passwdContentsPath > $out/etc/passwd
|
||||
echo "" >> $out/etc/passwd
|
||||
|
||||
@@ -202,8 +194,6 @@ let
|
||||
|
||||
mkdir $out/tmp
|
||||
|
||||
mkdir -p $out/var/tmp
|
||||
|
||||
mkdir -p $out/etc/nix
|
||||
cat $nixConfContentsPath > $out/etc/nix/nix.conf
|
||||
|
||||
@@ -237,10 +227,6 @@ pkgs.dockerTools.buildLayeredImageWithNixDb {
|
||||
rm -rf nix-support
|
||||
ln -s /nix/var/nix/profiles nix/var/nix/gcroots/profiles
|
||||
'';
|
||||
fakeRootCommands = ''
|
||||
chmod 1777 tmp
|
||||
chmod 1777 var/tmp
|
||||
'';
|
||||
|
||||
config = {
|
||||
Cmd = [ "/root/.nix-profile/bin/bash" ];
|
||||
|
||||
24
flake.lock
generated
24
flake.lock
generated
@@ -18,11 +18,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1645296114,
|
||||
"narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=",
|
||||
"lastModified": 1632864508,
|
||||
"narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1",
|
||||
"rev": "82891b5e2c2359d7e58d08849e4c89511ab94234",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -31,26 +31,10 @@
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-regression": {
|
||||
"locked": {
|
||||
"lastModified": 1643052045,
|
||||
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"lowdown-src": "lowdown-src",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-regression": "nixpkgs-regression"
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
506
flake.nix
506
flake.nix
@@ -2,10 +2,9 @@
|
||||
description = "The purely functional package manager";
|
||||
|
||||
inputs.nixpkgs.url = "nixpkgs/nixos-21.05-small";
|
||||
inputs.nixpkgs-regression.url = "nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
|
||||
inputs.lowdown-src = { url = "github:kristapsdz/lowdown"; flake = false; };
|
||||
|
||||
outputs = { self, nixpkgs, nixpkgs-regression, lowdown-src }:
|
||||
outputs = { self, nixpkgs, lowdown-src }:
|
||||
|
||||
let
|
||||
|
||||
@@ -15,7 +14,7 @@
|
||||
then ""
|
||||
else "pre${builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}_${self.shortRev or "dirty"}";
|
||||
|
||||
officialRelease = true;
|
||||
officialRelease = false;
|
||||
|
||||
linux64BitSystems = [ "x86_64-linux" "aarch64-linux" ];
|
||||
linuxSystems = linux64BitSystems ++ [ "i686-linux" ];
|
||||
@@ -23,36 +22,15 @@
|
||||
|
||||
crossSystems = [ "armv6l-linux" "armv7l-linux" ];
|
||||
|
||||
stdenvs = [ "gccStdenv" "clangStdenv" "clang11Stdenv" "stdenv" "libcxxStdenv" ];
|
||||
|
||||
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system);
|
||||
forAllSystemsAndStdenvs = f: forAllSystems (system:
|
||||
nixpkgs.lib.listToAttrs
|
||||
(map
|
||||
(n:
|
||||
nixpkgs.lib.nameValuePair "${n}Packages" (
|
||||
f system n
|
||||
)) stdenvs
|
||||
)
|
||||
);
|
||||
|
||||
forAllStdenvs = stdenvs: f: nixpkgs.lib.genAttrs stdenvs (stdenv: f stdenv);
|
||||
|
||||
# Memoize nixpkgs for different platforms for efficiency.
|
||||
nixpkgsFor =
|
||||
let stdenvsPackages = forAllSystemsAndStdenvs
|
||||
(system: stdenv:
|
||||
import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [
|
||||
(overlayFor (p: p.${stdenv}))
|
||||
];
|
||||
}
|
||||
);
|
||||
in
|
||||
# Add the `stdenvPackages` at toplevel, both because these are the ones
|
||||
# we want most of the time and for backwards compatibility
|
||||
forAllSystems (system: stdenvsPackages.${system} // stdenvsPackages.${system}.stdenvPackages);
|
||||
nixpkgsFor = forAllSystems (system:
|
||||
import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ self.overlay ];
|
||||
}
|
||||
);
|
||||
|
||||
commonDeps = pkgs: with pkgs; rec {
|
||||
# Use "busybox-sandbox-shell" if present,
|
||||
@@ -97,12 +75,12 @@
|
||||
buildPackages.mdbook
|
||||
buildPackages.autoconf-archive
|
||||
buildPackages.autoreconfHook
|
||||
buildPackages.pkg-config
|
||||
buildPackages.pkgconfig
|
||||
|
||||
# Tests
|
||||
buildPackages.git
|
||||
buildPackages.mercurial # FIXME: remove? only needed for tests
|
||||
buildPackages.jq # Also for custom mdBook preprocessor.
|
||||
buildPackages.jq
|
||||
]
|
||||
++ lib.optionals stdenv.hostPlatform.isLinux [(buildPackages.util-linuxMinimal or buildPackages.utillinuxMinimal)];
|
||||
|
||||
@@ -133,12 +111,16 @@
|
||||
./boehmgc-coroutine-sp-fallback.diff
|
||||
];
|
||||
}))
|
||||
nlohmann_json
|
||||
];
|
||||
|
||||
perlDeps =
|
||||
[ perl
|
||||
perlPackages.DBDSQLite
|
||||
];
|
||||
};
|
||||
|
||||
installScriptFor = systems:
|
||||
with nixpkgsFor.x86_64-linux;
|
||||
installScriptFor = systems:
|
||||
with nixpkgsFor.x86_64-linux;
|
||||
runCommand "installer-script"
|
||||
{ buildInputs = [ nix ];
|
||||
}
|
||||
@@ -202,210 +184,191 @@
|
||||
installCheckPhase = "make installcheck -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES";
|
||||
};
|
||||
|
||||
binaryTarball = buildPackages: nix: pkgs:
|
||||
let
|
||||
inherit (pkgs) cacert;
|
||||
installerClosureInfo = buildPackages.closureInfo { rootPaths = [ nix cacert ]; };
|
||||
in
|
||||
binaryTarball = buildPackages: nix: pkgs: let
|
||||
inherit (pkgs) cacert;
|
||||
installerClosureInfo = buildPackages.closureInfo { rootPaths = [ nix cacert ]; };
|
||||
in
|
||||
|
||||
buildPackages.runCommand "nix-binary-tarball-${version}"
|
||||
{ #nativeBuildInputs = lib.optional (system != "aarch64-linux") shellcheck;
|
||||
meta.description = "Distribution-independent Nix bootstrap binaries for ${pkgs.system}";
|
||||
}
|
||||
''
|
||||
cp ${installerClosureInfo}/registration $TMPDIR/reginfo
|
||||
cp ${./scripts/create-darwin-volume.sh} $TMPDIR/create-darwin-volume.sh
|
||||
substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
buildPackages.runCommand "nix-binary-tarball-${version}"
|
||||
{ #nativeBuildInputs = lib.optional (system != "aarch64-linux") shellcheck;
|
||||
meta.description = "Distribution-independent Nix bootstrap binaries for ${pkgs.system}";
|
||||
}
|
||||
''
|
||||
cp ${installerClosureInfo}/registration $TMPDIR/reginfo
|
||||
cp ${./scripts/create-darwin-volume.sh} $TMPDIR/create-darwin-volume.sh
|
||||
substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
|
||||
substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user.sh \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${./scripts/install-systemd-multi-user.sh} $TMPDIR/install-systemd-multi-user.sh \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${./scripts/install-multi-user.sh} $TMPDIR/install-multi-user \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user.sh \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${./scripts/install-systemd-multi-user.sh} $TMPDIR/install-systemd-multi-user.sh \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${./scripts/install-multi-user.sh} $TMPDIR/install-multi-user \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
|
||||
if type -p shellcheck; then
|
||||
# SC1090: Don't worry about not being able to find
|
||||
# $nix/etc/profile.d/nix.sh
|
||||
shellcheck --exclude SC1090 $TMPDIR/install
|
||||
shellcheck $TMPDIR/create-darwin-volume.sh
|
||||
shellcheck $TMPDIR/install-darwin-multi-user.sh
|
||||
shellcheck $TMPDIR/install-systemd-multi-user.sh
|
||||
if type -p shellcheck; then
|
||||
# SC1090: Don't worry about not being able to find
|
||||
# $nix/etc/profile.d/nix.sh
|
||||
shellcheck --exclude SC1090 $TMPDIR/install
|
||||
shellcheck $TMPDIR/create-darwin-volume.sh
|
||||
shellcheck $TMPDIR/install-darwin-multi-user.sh
|
||||
shellcheck $TMPDIR/install-systemd-multi-user.sh
|
||||
|
||||
# SC1091: Don't panic about not being able to source
|
||||
# /etc/profile
|
||||
# SC2002: Ignore "useless cat" "error", when loading
|
||||
# .reginfo, as the cat is a much cleaner
|
||||
# implementation, even though it is "useless"
|
||||
# SC2116: Allow ROOT_HOME=$(echo ~root) for resolving
|
||||
# root's home directory
|
||||
shellcheck --external-sources \
|
||||
--exclude SC1091,SC2002,SC2116 $TMPDIR/install-multi-user
|
||||
fi
|
||||
# SC1091: Don't panic about not being able to source
|
||||
# /etc/profile
|
||||
# SC2002: Ignore "useless cat" "error", when loading
|
||||
# .reginfo, as the cat is a much cleaner
|
||||
# implementation, even though it is "useless"
|
||||
# SC2116: Allow ROOT_HOME=$(echo ~root) for resolving
|
||||
# root's home directory
|
||||
shellcheck --external-sources \
|
||||
--exclude SC1091,SC2002,SC2116 $TMPDIR/install-multi-user
|
||||
fi
|
||||
|
||||
chmod +x $TMPDIR/install
|
||||
chmod +x $TMPDIR/create-darwin-volume.sh
|
||||
chmod +x $TMPDIR/install-darwin-multi-user.sh
|
||||
chmod +x $TMPDIR/install-systemd-multi-user.sh
|
||||
chmod +x $TMPDIR/install-multi-user
|
||||
dir=nix-${version}-${pkgs.system}
|
||||
fn=$out/$dir.tar.xz
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products
|
||||
tar cvfJ $fn \
|
||||
--owner=0 --group=0 --mode=u+rw,uga+r \
|
||||
--absolute-names \
|
||||
--hard-dereference \
|
||||
--transform "s,$TMPDIR/install,$dir/install," \
|
||||
--transform "s,$TMPDIR/create-darwin-volume.sh,$dir/create-darwin-volume.sh," \
|
||||
--transform "s,$TMPDIR/reginfo,$dir/.reginfo," \
|
||||
--transform "s,$NIX_STORE,$dir/store,S" \
|
||||
$TMPDIR/install \
|
||||
$TMPDIR/create-darwin-volume.sh \
|
||||
$TMPDIR/install-darwin-multi-user.sh \
|
||||
$TMPDIR/install-systemd-multi-user.sh \
|
||||
$TMPDIR/install-multi-user \
|
||||
$TMPDIR/reginfo \
|
||||
$(cat ${installerClosureInfo}/store-paths)
|
||||
'';
|
||||
|
||||
overlayFor = getStdenv: final: prev:
|
||||
let currentStdenv = getStdenv final; in
|
||||
{
|
||||
nixStable = prev.nix;
|
||||
|
||||
# Forward from the previous stage as we don’t want it to pick the lowdown override
|
||||
nixUnstable = prev.nixUnstable;
|
||||
|
||||
nix = with final; with commonDeps pkgs; currentStdenv.mkDerivation {
|
||||
name = "nix-${version}";
|
||||
inherit version;
|
||||
|
||||
src = self;
|
||||
|
||||
VERSION_SUFFIX = versionSuffix;
|
||||
|
||||
outputs = [ "out" "dev" "doc" ];
|
||||
|
||||
nativeBuildInputs = nativeBuildDeps;
|
||||
buildInputs = buildDeps ++ awsDeps;
|
||||
|
||||
propagatedBuildInputs = propagatedDeps;
|
||||
|
||||
disallowedReferences = [ boost ];
|
||||
|
||||
preConfigure =
|
||||
''
|
||||
# Copy libboost_context so we don't get all of Boost in our closure.
|
||||
# https://github.com/NixOS/nixpkgs/issues/45462
|
||||
mkdir -p $out/lib
|
||||
cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib
|
||||
rm -f $out/lib/*.a
|
||||
${lib.optionalString currentStdenv.isLinux ''
|
||||
chmod u+w $out/lib/*.so.*
|
||||
patchelf --set-rpath $out/lib:${currentStdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.*
|
||||
''}
|
||||
${lib.optionalString currentStdenv.isDarwin ''
|
||||
for LIB in $out/lib/*.dylib; do
|
||||
chmod u+w $LIB
|
||||
install_name_tool -id $LIB $LIB
|
||||
done
|
||||
install_name_tool -change ${boost}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib
|
||||
''}
|
||||
'';
|
||||
|
||||
configureFlags = configureFlags ++
|
||||
[ "--sysconfdir=/etc" ];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1";
|
||||
|
||||
doCheck = true;
|
||||
|
||||
installFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p $doc/nix-support
|
||||
echo "doc manual $doc/share/doc/nix/manual" >> $doc/nix-support/hydra-build-products
|
||||
${lib.optionalString currentStdenv.isDarwin ''
|
||||
install_name_tool \
|
||||
-change ${boost}/lib/libboost_context.dylib \
|
||||
$out/lib/libboost_context.dylib \
|
||||
$out/lib/libnixutil.dylib
|
||||
''}
|
||||
'';
|
||||
|
||||
doInstallCheck = true;
|
||||
installCheckFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
separateDebugInfo = true;
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
passthru.perl-bindings = with final; perl.pkgs.toPerlModule (currentStdenv.mkDerivation {
|
||||
name = "nix-perl-${version}";
|
||||
|
||||
src = self;
|
||||
|
||||
nativeBuildInputs =
|
||||
[ buildPackages.autoconf-archive
|
||||
buildPackages.autoreconfHook
|
||||
buildPackages.pkg-config
|
||||
];
|
||||
|
||||
buildInputs =
|
||||
[ nix
|
||||
curl
|
||||
bzip2
|
||||
xz
|
||||
pkgs.perl
|
||||
boost
|
||||
]
|
||||
++ lib.optional (currentStdenv.isLinux || currentStdenv.isDarwin) libsodium
|
||||
++ lib.optional currentStdenv.isDarwin darwin.apple_sdk.frameworks.Security;
|
||||
|
||||
configureFlags = ''
|
||||
--with-dbi=${perlPackages.DBI}/${pkgs.perl.libPrefix}
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/${pkgs.perl.libPrefix}
|
||||
'';
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
postUnpack = "sourceRoot=$sourceRoot/perl";
|
||||
});
|
||||
|
||||
meta.platforms = systems;
|
||||
};
|
||||
|
||||
lowdown-nix = with final; currentStdenv.mkDerivation rec {
|
||||
name = "lowdown-0.9.0";
|
||||
|
||||
src = lowdown-src;
|
||||
|
||||
outputs = [ "out" "bin" "dev" ];
|
||||
|
||||
nativeBuildInputs = [ buildPackages.which ];
|
||||
|
||||
configurePhase = ''
|
||||
${if (currentStdenv.isDarwin && currentStdenv.isAarch64) then "echo \"HAVE_SANDBOX_INIT=false\" > configure.local" else ""}
|
||||
./configure \
|
||||
PREFIX=${placeholder "dev"} \
|
||||
BINDIR=${placeholder "bin"}/bin
|
||||
'';
|
||||
};
|
||||
};
|
||||
chmod +x $TMPDIR/install
|
||||
chmod +x $TMPDIR/create-darwin-volume.sh
|
||||
chmod +x $TMPDIR/install-darwin-multi-user.sh
|
||||
chmod +x $TMPDIR/install-systemd-multi-user.sh
|
||||
chmod +x $TMPDIR/install-multi-user
|
||||
dir=nix-${version}-${pkgs.system}
|
||||
fn=$out/$dir.tar.xz
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products
|
||||
tar cvfJ $fn \
|
||||
--owner=0 --group=0 --mode=u+rw,uga+r \
|
||||
--absolute-names \
|
||||
--hard-dereference \
|
||||
--transform "s,$TMPDIR/install,$dir/install," \
|
||||
--transform "s,$TMPDIR/create-darwin-volume.sh,$dir/create-darwin-volume.sh," \
|
||||
--transform "s,$TMPDIR/reginfo,$dir/.reginfo," \
|
||||
--transform "s,$NIX_STORE,$dir/store,S" \
|
||||
$TMPDIR/install \
|
||||
$TMPDIR/create-darwin-volume.sh \
|
||||
$TMPDIR/install-darwin-multi-user.sh \
|
||||
$TMPDIR/install-systemd-multi-user.sh \
|
||||
$TMPDIR/install-multi-user \
|
||||
$TMPDIR/reginfo \
|
||||
$(cat ${installerClosureInfo}/store-paths)
|
||||
'';
|
||||
|
||||
in {
|
||||
|
||||
# A Nixpkgs overlay that overrides the 'nix' and
|
||||
# 'nix.perl-bindings' packages.
|
||||
overlay = overlayFor (p: p.stdenv);
|
||||
overlay = final: prev: {
|
||||
|
||||
nixStable = prev.nix;
|
||||
|
||||
# Forward from the previous stage as we don’t want it to pick the lowdown override
|
||||
nixUnstable = prev.nixUnstable;
|
||||
|
||||
nix = with final; with commonDeps pkgs; stdenv.mkDerivation {
|
||||
name = "nix-${version}";
|
||||
inherit version;
|
||||
|
||||
src = self;
|
||||
|
||||
VERSION_SUFFIX = versionSuffix;
|
||||
|
||||
outputs = [ "out" "dev" "doc" ];
|
||||
|
||||
nativeBuildInputs = nativeBuildDeps;
|
||||
buildInputs = buildDeps ++ awsDeps;
|
||||
|
||||
propagatedBuildInputs = propagatedDeps;
|
||||
|
||||
preConfigure =
|
||||
''
|
||||
# Copy libboost_context so we don't get all of Boost in our closure.
|
||||
# https://github.com/NixOS/nixpkgs/issues/45462
|
||||
mkdir -p $out/lib
|
||||
cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib
|
||||
rm -f $out/lib/*.a
|
||||
${lib.optionalString stdenv.isLinux ''
|
||||
chmod u+w $out/lib/*.so.*
|
||||
patchelf --set-rpath $out/lib:${stdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.*
|
||||
''}
|
||||
'';
|
||||
|
||||
configureFlags = configureFlags ++
|
||||
[ "--sysconfdir=/etc" ];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1";
|
||||
|
||||
doCheck = true;
|
||||
|
||||
installFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p $doc/nix-support
|
||||
echo "doc manual $doc/share/doc/nix/manual" >> $doc/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
doInstallCheck = true;
|
||||
installCheckFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
separateDebugInfo = true;
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
passthru.perl-bindings = with final; stdenv.mkDerivation {
|
||||
name = "nix-perl-${version}";
|
||||
|
||||
src = self;
|
||||
|
||||
nativeBuildInputs =
|
||||
[ buildPackages.autoconf-archive
|
||||
buildPackages.autoreconfHook
|
||||
buildPackages.pkgconfig
|
||||
];
|
||||
|
||||
buildInputs =
|
||||
[ nix
|
||||
curl
|
||||
bzip2
|
||||
xz
|
||||
pkgs.perl
|
||||
boost
|
||||
]
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||
++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security;
|
||||
|
||||
configureFlags = ''
|
||||
--with-dbi=${perlPackages.DBI}/${pkgs.perl.libPrefix}
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/${pkgs.perl.libPrefix}
|
||||
'';
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
postUnpack = "sourceRoot=$sourceRoot/perl";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
lowdown-nix = with final; stdenv.mkDerivation rec {
|
||||
name = "lowdown-0.9.0";
|
||||
|
||||
src = lowdown-src;
|
||||
|
||||
outputs = [ "out" "bin" "dev" ];
|
||||
|
||||
nativeBuildInputs = [ buildPackages.which ];
|
||||
|
||||
configurePhase = ''
|
||||
${if (stdenv.isDarwin && stdenv.isAarch64) then "echo \"HAVE_SANDBOX_INIT=false\" > configure.local" else ""}
|
||||
./configure \
|
||||
PREFIX=${placeholder "dev"} \
|
||||
BINDIR=${placeholder "bin"}/bin
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
hydraJobs = {
|
||||
|
||||
@@ -443,7 +406,19 @@
|
||||
installerScriptForGHA = installScriptFor [ "x86_64-linux" "x86_64-darwin" "armv6l-linux" "armv7l-linux"];
|
||||
|
||||
# docker image with Nix inside
|
||||
dockerImage = nixpkgs.lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage);
|
||||
dockerImage = nixpkgs.lib.genAttrs linux64BitSystems (system:
|
||||
let
|
||||
pkgs = nixpkgsFor.${system};
|
||||
image = import ./docker.nix { inherit pkgs; tag = version; };
|
||||
in pkgs.runCommand "docker-image-tarball-${version}"
|
||||
{ meta.description = "Docker image with Nix for ${system}";
|
||||
}
|
||||
''
|
||||
mkdir -p $out/nix-support
|
||||
image=$out/image.tar.gz
|
||||
ln -s ${image} $image
|
||||
echo "file binary-dist $image" >> $out/nix-support/hydra-build-products
|
||||
'');
|
||||
|
||||
# Line coverage analysis.
|
||||
coverage =
|
||||
@@ -497,12 +472,6 @@
|
||||
inherit (self) overlay;
|
||||
});
|
||||
|
||||
tests.sourcehutFlakes = (import ./tests/sourcehut-flakes.nix rec {
|
||||
system = "x86_64-linux";
|
||||
inherit nixpkgs;
|
||||
inherit (self) overlay;
|
||||
});
|
||||
|
||||
tests.setuid = nixpkgs.lib.genAttrs
|
||||
["i686-linux" "x86_64-linux"]
|
||||
(system:
|
||||
@@ -511,23 +480,29 @@
|
||||
inherit (self) overlay;
|
||||
});
|
||||
|
||||
# Make sure that nix-env still produces the exact same result
|
||||
# on a particular version of Nixpkgs.
|
||||
/*
|
||||
# Check whether we can still evaluate all of Nixpkgs.
|
||||
tests.evalNixpkgs =
|
||||
import (nixpkgs + "/pkgs/top-level/make-tarball.nix") {
|
||||
# FIXME: fix pkgs/top-level/make-tarball.nix in NixOS to not require a revCount.
|
||||
inherit nixpkgs;
|
||||
pkgs = nixpkgsFor.x86_64-linux;
|
||||
officialRelease = false;
|
||||
};
|
||||
|
||||
# Check whether we can still evaluate NixOS.
|
||||
tests.evalNixOS =
|
||||
with nixpkgsFor.x86_64-linux;
|
||||
runCommand "eval-nixos" { buildInputs = [ nix ]; }
|
||||
''
|
||||
type -p nix-env
|
||||
# Note: we're filtering out nixos-install-tools because https://github.com/NixOS/nixpkgs/pull/153594#issuecomment-1020530593.
|
||||
time nix-env --store dummy:// -f ${nixpkgs-regression} -qaP --drv-path | sort | grep -v nixos-install-tools > packages
|
||||
[[ $(sha1sum < packages | cut -c1-40) = ff451c521e61e4fe72bdbe2d0ca5d1809affa733 ]]
|
||||
mkdir $out
|
||||
'';
|
||||
export NIX_STATE_DIR=$TMPDIR
|
||||
|
||||
metrics.nixpkgs = import "${nixpkgs-regression}/pkgs/top-level/metrics.nix" {
|
||||
pkgs = nixpkgsFor.x86_64-linux;
|
||||
nixpkgs = nixpkgs-regression;
|
||||
};
|
||||
nix-instantiate ${nixpkgs}/nixos/release-combined.nix -A tested --dry-run \
|
||||
--arg nixpkgs '{ outPath = ${nixpkgs}; revCount = 123; shortRev = "abcdefgh"; }'
|
||||
|
||||
touch $out
|
||||
'';
|
||||
*/
|
||||
|
||||
installTests = forAllSystems (system:
|
||||
let pkgs = nixpkgsFor.${system}; in
|
||||
@@ -549,9 +524,9 @@
|
||||
binaryTarball = self.hydraJobs.binaryTarball.${system};
|
||||
perlBindings = self.hydraJobs.perlBindings.${system};
|
||||
installTests = self.hydraJobs.installTests.${system};
|
||||
} // (nixpkgs.lib.optionalAttrs (builtins.elem system linux64BitSystems)) {
|
||||
} // (if system == "x86_64-linux" then {
|
||||
dockerImage = self.hydraJobs.dockerImage.${system};
|
||||
});
|
||||
} else {}));
|
||||
|
||||
packages = forAllSystems (system: {
|
||||
inherit (nixpkgsFor.${system}) nix;
|
||||
@@ -596,20 +571,6 @@
|
||||
|
||||
hardeningDisable = [ "pie" ];
|
||||
};
|
||||
dockerImage =
|
||||
let
|
||||
pkgs = nixpkgsFor.${system};
|
||||
image = import ./docker.nix { inherit pkgs; tag = version; };
|
||||
in
|
||||
pkgs.runCommand
|
||||
"docker-image-tarball-${version}"
|
||||
{ meta.description = "Docker image with Nix for ${system}"; }
|
||||
''
|
||||
mkdir -p $out/nix-support
|
||||
image=$out/image.tar.gz
|
||||
ln -s ${image} $image
|
||||
echo "file binary-dist $image" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
} // builtins.listToAttrs (map (crossSystem: {
|
||||
name = "nix-${crossSystem}";
|
||||
value = let
|
||||
@@ -649,27 +610,21 @@
|
||||
doInstallCheck = true;
|
||||
installCheckFlags = "sysconfdir=$(out)/etc";
|
||||
};
|
||||
}) crossSystems)) // (builtins.listToAttrs (map (stdenvName:
|
||||
nixpkgsFor.${system}.lib.nameValuePair
|
||||
"nix-${stdenvName}"
|
||||
nixpkgsFor.${system}."${stdenvName}Packages".nix
|
||||
) stdenvs)));
|
||||
}) crossSystems)));
|
||||
|
||||
defaultPackage = forAllSystems (system: self.packages.${system}.nix);
|
||||
|
||||
devShell = forAllSystems (system: self.devShells.${system}.stdenvPackages);
|
||||
|
||||
devShells = forAllSystemsAndStdenvs (system: stdenv:
|
||||
devShell = forAllSystems (system:
|
||||
with nixpkgsFor.${system};
|
||||
with commonDeps pkgs;
|
||||
|
||||
nixpkgsFor.${system}.${stdenv}.mkDerivation {
|
||||
stdenv.mkDerivation {
|
||||
name = "nix";
|
||||
|
||||
outputs = [ "out" "dev" "doc" ];
|
||||
|
||||
nativeBuildInputs = nativeBuildDeps;
|
||||
buildInputs = buildDeps ++ propagatedDeps ++ awsDeps;
|
||||
buildInputs = buildDeps ++ propagatedDeps ++ awsDeps ++ perlDeps;
|
||||
|
||||
inherit configureFlags;
|
||||
|
||||
@@ -682,9 +637,6 @@
|
||||
PATH=$prefix/bin:$PATH
|
||||
unset PYTHONPATH
|
||||
export MANPATH=$out/share/man:$MANPATH
|
||||
|
||||
# Make bash completion work.
|
||||
XDG_DATA_DIRS+=:$out/share
|
||||
'';
|
||||
});
|
||||
|
||||
|
||||
@@ -55,11 +55,6 @@ my $releaseDir = "nix/$releaseName";
|
||||
my $tmpDir = "$TMPDIR/nix-release/$releaseName";
|
||||
File::Path::make_path($tmpDir);
|
||||
|
||||
my $narCache = "$TMPDIR/nar-cache";
|
||||
File::Path::make_path($narCache);
|
||||
|
||||
my $binaryCache = "https://cache.nixos.org/?local-nar-cache=$narCache";
|
||||
|
||||
# S3 setup.
|
||||
my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'} or die "No AWS_ACCESS_KEY_ID given.";
|
||||
my $aws_secret_access_key = $ENV{'AWS_SECRET_ACCESS_KEY'} or die "No AWS_SECRET_ACCESS_KEY given.";
|
||||
@@ -85,7 +80,6 @@ sub downloadFile {
|
||||
my ($jobName, $productNr, $dstName) = @_;
|
||||
|
||||
my $buildInfo = decode_json(fetch("$evalUrl/job/$jobName", 'application/json'));
|
||||
#print STDERR "$jobName: ", Dumper($buildInfo), "\n";
|
||||
|
||||
my $srcFile = $buildInfo->{buildproducts}->{$productNr}->{path} or die "job '$jobName' lacks product $productNr\n";
|
||||
$dstName //= basename($srcFile);
|
||||
@@ -93,27 +87,19 @@ sub downloadFile {
|
||||
|
||||
if (!-e $tmpFile) {
|
||||
print STDERR "downloading $srcFile to $tmpFile...\n";
|
||||
|
||||
my $fileInfo = decode_json(`NIX_REMOTE=$binaryCache nix store ls --json '$srcFile'`);
|
||||
|
||||
$srcFile = $fileInfo->{target} if $fileInfo->{type} eq 'symlink';
|
||||
|
||||
#print STDERR $srcFile, " ", Dumper($fileInfo), "\n";
|
||||
|
||||
system("NIX_REMOTE=$binaryCache nix store cat '$srcFile' > '$tmpFile'.tmp") == 0
|
||||
system("NIX_REMOTE=https://cache.nixos.org/ nix store cat '$srcFile' > '$tmpFile'") == 0
|
||||
or die "unable to fetch $srcFile\n";
|
||||
rename("$tmpFile.tmp", $tmpFile) or die;
|
||||
}
|
||||
|
||||
my $sha256_expected = $buildInfo->{buildproducts}->{$productNr}->{sha256hash};
|
||||
my $sha256_expected = $buildInfo->{buildproducts}->{$productNr}->{sha256hash} or die;
|
||||
my $sha256_actual = `nix hash file --base16 --type sha256 '$tmpFile'`;
|
||||
chomp $sha256_actual;
|
||||
if (defined($sha256_expected) && $sha256_expected ne $sha256_actual) {
|
||||
if ($sha256_expected ne $sha256_actual) {
|
||||
print STDERR "file $tmpFile is corrupt, got $sha256_actual, expected $sha256_expected\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
write_file("$tmpFile.sha256", $sha256_actual);
|
||||
write_file("$tmpFile.sha256", $sha256_expected);
|
||||
|
||||
if (! -e "$tmpFile.asc") {
|
||||
system("gpg2 --detach-sign --armor $tmpFile") == 0 or die "unable to sign $tmpFile\n";
|
||||
@@ -131,60 +117,6 @@ downloadFile("binaryTarballCross.x86_64-linux.armv6l-linux", "1");
|
||||
downloadFile("binaryTarballCross.x86_64-linux.armv7l-linux", "1");
|
||||
downloadFile("installerScript", "1");
|
||||
|
||||
# Upload docker images to dockerhub.
|
||||
my $dockerManifest = "";
|
||||
my $dockerManifestLatest = "";
|
||||
|
||||
for my $platforms (["x86_64-linux", "amd64"], ["aarch64-linux", "arm64"]) {
|
||||
my $system = $platforms->[0];
|
||||
my $dockerPlatform = $platforms->[1];
|
||||
my $fn = "nix-$version-docker-image-$dockerPlatform.tar.gz";
|
||||
downloadFile("dockerImage.$system", "1", $fn);
|
||||
|
||||
print STDERR "loading docker image for $dockerPlatform...\n";
|
||||
system("docker load -i $tmpDir/$fn") == 0 or die;
|
||||
|
||||
my $tag = "nixos/nix:$version-$dockerPlatform";
|
||||
my $latestTag = "nixos/nix:latest-$dockerPlatform";
|
||||
|
||||
print STDERR "tagging $version docker image for $dockerPlatform...\n";
|
||||
system("docker tag nix:$version $tag") == 0 or die;
|
||||
|
||||
if ($isLatest) {
|
||||
print STDERR "tagging latest docker image for $dockerPlatform...\n";
|
||||
system("docker tag nix:$version $latestTag") == 0 or die;
|
||||
}
|
||||
|
||||
print STDERR "pushing $version docker image for $dockerPlatform...\n";
|
||||
system("docker push -q $tag") == 0 or die;
|
||||
|
||||
if ($isLatest) {
|
||||
print STDERR "pushing latest docker image for $dockerPlatform...\n";
|
||||
system("docker push -q $latestTag") == 0 or die;
|
||||
}
|
||||
|
||||
$dockerManifest .= " --amend $tag";
|
||||
$dockerManifestLatest .= " --amend $latestTag"
|
||||
}
|
||||
|
||||
print STDERR "creating multi-platform docker manifest...\n";
|
||||
system("docker manifest rm nixos/nix:$version");
|
||||
system("docker manifest create nixos/nix:$version $dockerManifest") == 0 or die;
|
||||
if ($isLatest) {
|
||||
print STDERR "creating latest multi-platform docker manifest...\n";
|
||||
system("docker manifest rm nixos/nix:latest");
|
||||
system("docker manifest create nixos/nix:latest $dockerManifestLatest") == 0 or die;
|
||||
}
|
||||
|
||||
print STDERR "pushing multi-platform docker manifest...\n";
|
||||
system("docker manifest push nixos/nix:$version") == 0 or die;
|
||||
|
||||
if ($isLatest) {
|
||||
print STDERR "pushing latest multi-platform docker manifest...\n";
|
||||
system("docker manifest push nixos/nix:latest") == 0 or die;
|
||||
}
|
||||
|
||||
# Upload release files to S3.
|
||||
for my $fn (glob "$tmpDir/*") {
|
||||
my $name = basename($fn);
|
||||
my $dstKey = "$releaseDir/" . $name;
|
||||
|
||||
@@ -7,15 +7,13 @@ function _complete_nix {
|
||||
local completion=${line%% *}
|
||||
if [[ -z $have_type ]]; then
|
||||
have_type=1
|
||||
if [[ $completion == filenames ]]; then
|
||||
if [[ $completion = filenames ]]; then
|
||||
compopt -o filenames
|
||||
elif [[ $completion == attrs ]]; then
|
||||
compopt -o nospace
|
||||
fi
|
||||
else
|
||||
COMPREPLY+=("$completion")
|
||||
fi
|
||||
done < <(NIX_GET_COMPLETIONS=$cword "${words[@]}" 2>/dev/null)
|
||||
done < <(NIX_GET_COMPLETIONS=$cword "${words[@]}")
|
||||
__ltrim_colon_completions "$cur"
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ end
|
||||
|
||||
function _nix_accepts_files
|
||||
set -l response (_nix_complete)
|
||||
# First line is either filenames or no-filenames.
|
||||
test $response[1] = 'filenames'
|
||||
end
|
||||
|
||||
|
||||
@@ -25,10 +25,5 @@
|
||||
<string>/var/log/nix-daemon.log</string>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/dev/null</string>
|
||||
<key>SoftResourceLimits</key>
|
||||
<dict>
|
||||
<key>NumberOfFiles</key>
|
||||
<integer>4096</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
ifdef HOST_LINUX
|
||||
|
||||
$(foreach n, nix-daemon.socket nix-daemon.service, $(eval $(call install-file-in, $(d)/$(n), $(prefix)/lib/systemd/system, 0644)))
|
||||
$(foreach n, nix-daemon.conf, $(eval $(call install-file-in, $(d)/$(n), $(prefix)/lib/tmpfiles.d, 0644)))
|
||||
|
||||
clean-files += $(d)/nix-daemon.socket $(d)/nix-daemon.service $(d)/nix-daemon.conf
|
||||
clean-files += $(d)/nix-daemon.socket $(d)/nix-daemon.service
|
||||
|
||||
endif
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
d @localstatedir@/nix/daemon-socket 0755 root root - -
|
||||
@@ -1,15 +1,12 @@
|
||||
[Unit]
|
||||
Description=Nix Daemon
|
||||
Documentation=man:nix-daemon https://nixos.org/manual
|
||||
RequiresMountsFor=@storedir@
|
||||
RequiresMountsFor=@localstatedir@
|
||||
RequiresMountsFor=@localstatedir@/nix/db
|
||||
ConditionPathIsReadWrite=@localstatedir@/nix/daemon-socket
|
||||
|
||||
[Service]
|
||||
ExecStart=@@bindir@/nix-daemon nix-daemon --daemon
|
||||
KillMode=process
|
||||
LimitNOFILE=4096
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -4,7 +4,7 @@ function _nix() {
|
||||
local ifs_bk="$IFS"
|
||||
local input=("${(Q)words[@]}")
|
||||
IFS=$'\n'
|
||||
local res=($(NIX_GET_COMPLETIONS=$((CURRENT - 1)) "$input[@]" 2>/dev/null))
|
||||
local res=($(NIX_GET_COMPLETIONS=$((CURRENT - 1)) "$input[@]"))
|
||||
IFS="$ifs_bk"
|
||||
local tpe="${${res[1]}%%> *}"
|
||||
local -a suggestions
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
$(eval $(call install-file-as, $(d)/completion.zsh, $(datarootdir)/zsh/site-functions/_nix, 0644))
|
||||
$(eval $(call install-file-as, $(d)/run-help-nix, $(datarootdir)/zsh/site-functions/run-help-nix, 0644))
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
emulate -L zsh
|
||||
|
||||
# run-help is a zsh widget that can be bound to a key. It mainly looks up the
|
||||
# man page for the currently typed in command.
|
||||
#
|
||||
# Although run-help works for any command without requiring special support,
|
||||
# it can only deduce the right man page based solely on the name of the
|
||||
# command. Programs like Nix provide better integration with run-help by
|
||||
# helping zsh identify Nix subcommands and their corresponding man pages. This
|
||||
# is what this function does.
|
||||
#
|
||||
# To actually use run-help on zsh, place the following lines in your .zshrc:
|
||||
#
|
||||
# (( $+aliases[run-help] )) && unalias run-help
|
||||
# autoload -Uz run-help run-help-nix
|
||||
#
|
||||
# Then also assign run-help to any key of choice:
|
||||
#
|
||||
# bindkey '^[h' run-help
|
||||
|
||||
while [[ "$#" != 0 && "$1" == -* ]]; do
|
||||
shift
|
||||
done
|
||||
|
||||
local -a subcommands; subcommands=( nix3 )
|
||||
|
||||
local arg
|
||||
for arg in "$@"; do
|
||||
if man -w "${(j:-:)subcommands}-$arg" >/dev/null 2>&1; then
|
||||
subcommands+="$arg"
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if (( $#subcommands > 1 )); then
|
||||
man "${(j:-:)subcommands}"
|
||||
else
|
||||
man nix
|
||||
fi
|
||||
|
||||
return $?
|
||||
@@ -14,27 +14,9 @@ if [ -t 1 ]; then
|
||||
yellow="[33;1m"
|
||||
normal="[m"
|
||||
fi
|
||||
|
||||
run_test () {
|
||||
(cd tests && env ${TESTS_ENVIRONMENT} init.sh 2>/dev/null > /dev/null)
|
||||
log="$(cd $(dirname $1) && env ${TESTS_ENVIRONMENT} $(basename $1) 2>&1)"
|
||||
status=$?
|
||||
}
|
||||
|
||||
run_test "$1"
|
||||
|
||||
# Hack: Retry the test if it fails with “unexpected EOF reading a line” as these
|
||||
# appear randomly without anyone knowing why.
|
||||
# See https://github.com/NixOS/nix/issues/3605 for more info
|
||||
if [[ $status -ne 0 && $status -ne 99 && \
|
||||
"$(uname)" == "Darwin" && \
|
||||
"$log" =~ "unexpected EOF reading a line" \
|
||||
]]; then
|
||||
echo "$post_run_msg [${yellow}FAIL$normal] (possibly flaky, so will be retried)"
|
||||
echo "$log" | sed 's/^/ /'
|
||||
run_test "$1"
|
||||
fi
|
||||
|
||||
(cd tests && env ${TESTS_ENVIRONMENT} init.sh 2>/dev/null > /dev/null)
|
||||
log="$(cd $(dirname $1) && env ${TESTS_ENVIRONMENT} $(basename $1) 2>&1)"
|
||||
status=$?
|
||||
if [ $status -eq 0 ]; then
|
||||
echo "$post_run_msg [${green}PASS$normal]"
|
||||
elif [ $status -eq 99 ]; then
|
||||
|
||||
399
nix-rust/Cargo.lock
generated
Normal file
399
nix-rust/Cargo.lock
generated
Normal file
@@ -0,0 +1,399 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "assert_matches"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "c2-chacha"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-cprng"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "nix-rust"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proptest"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rusty-fork 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_isaac"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_jitter"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_os"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusty-fork"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wait-timeout 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wait-timeout"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5"
|
||||
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
||||
"checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80"
|
||||
"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
|
||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||
"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
||||
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
|
||||
"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"
|
||||
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
||||
"checksum proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf147e022eacf0c8a054ab864914a7602618adba841d800a9a9868a5237a529f"
|
||||
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
||||
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||
"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
|
||||
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
||||
"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
|
||||
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
||||
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
||||
"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
|
||||
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
||||
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
||||
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
|
||||
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
|
||||
"checksum rusty-fork 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd93264e10c577503e926bd1430193eeb5d21b059148910082245309b424fae"
|
||||
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
|
||||
"checksum wait-timeout 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
||||
"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
|
||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
23
nix-rust/Cargo.toml
Normal file
23
nix-rust/Cargo.toml
Normal file
@@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "nix-rust"
|
||||
version = "0.1.0"
|
||||
authors = ["Eelco Dolstra <edolstra@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "nixrust"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
#futures-preview = { version = "=0.3.0-alpha.19" }
|
||||
#hyper = "0.13.0-alpha.4"
|
||||
#http = "0.1"
|
||||
#tokio = { version = "0.2.0-alpha.6", default-features = false, features = ["rt-full"] }
|
||||
lazy_static = "1.4"
|
||||
#byteorder = "1.3"
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "0.3"
|
||||
assert_matches = "1.3"
|
||||
proptest = "0.9"
|
||||
48
nix-rust/local.mk
Normal file
48
nix-rust/local.mk
Normal file
@@ -0,0 +1,48 @@
|
||||
ifeq ($(OPTIMIZE), 1)
|
||||
RUST_MODE = --release
|
||||
RUST_DIR = release
|
||||
else
|
||||
RUST_MODE =
|
||||
RUST_DIR = debug
|
||||
endif
|
||||
|
||||
libnixrust_PATH := $(d)/target/$(RUST_DIR)/libnixrust.$(SO_EXT)
|
||||
libnixrust_INSTALL_PATH := $(libdir)/libnixrust.$(SO_EXT)
|
||||
libnixrust_LDFLAGS_USE := -L$(d)/target/$(RUST_DIR) -lnixrust
|
||||
libnixrust_LDFLAGS_USE_INSTALLED := -L$(libdir) -lnixrust
|
||||
|
||||
ifdef HOST_LINUX
|
||||
libnixrust_LDFLAGS_USE += -ldl
|
||||
libnixrust_LDFLAGS_USE_INSTALLED += -ldl
|
||||
endif
|
||||
|
||||
ifdef HOST_DARWIN
|
||||
libnixrust_BUILD_FLAGS = NIX_LDFLAGS="-undefined dynamic_lookup"
|
||||
else
|
||||
libnixrust_LDFLAGS_USE += -Wl,-rpath,$(abspath $(d)/target/$(RUST_DIR))
|
||||
libnixrust_LDFLAGS_USE_INSTALLED += -Wl,-rpath,$(libdir)
|
||||
endif
|
||||
|
||||
$(libnixrust_PATH): $(call rwildcard, $(d)/src, *.rs) $(d)/Cargo.toml
|
||||
$(trace-gen) cd nix-rust && CARGO_HOME=$$(if [[ -d vendor ]]; then echo vendor; fi) \
|
||||
$(libnixrust_BUILD_FLAGS) \
|
||||
cargo build $(RUST_MODE) $$(if [[ -d vendor ]]; then echo --offline; fi) \
|
||||
&& touch target/$(RUST_DIR)/libnixrust.$(SO_EXT)
|
||||
|
||||
$(libnixrust_INSTALL_PATH): $(libnixrust_PATH)
|
||||
$(target-gen) cp $^ $@
|
||||
ifdef HOST_DARWIN
|
||||
install_name_tool -id $@ $@
|
||||
endif
|
||||
|
||||
clean: clean-rust
|
||||
|
||||
clean-rust:
|
||||
$(suppress) rm -rfv nix-rust/target
|
||||
|
||||
ifndef HOST_DARWIN
|
||||
check: rust-tests
|
||||
|
||||
rust-tests:
|
||||
$(trace-test) cd nix-rust && CARGO_HOME=$$(if [[ -d vendor ]]; then echo vendor; fi) cargo test --release $$(if [[ -d vendor ]]; then echo --offline; fi)
|
||||
endif
|
||||
77
nix-rust/src/c.rs
Normal file
77
nix-rust/src/c.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
use super::{error, store::path, store::StorePath, util};
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ffi_String_new(s: &str, out: *mut String) {
|
||||
// FIXME: check whether 's' is valid UTF-8?
|
||||
out.write(s.to_string())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ffi_String_drop(self_: *mut String) {
|
||||
std::ptr::drop_in_place(self_);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ffi_StorePath_new(
|
||||
path: &str,
|
||||
store_dir: &str,
|
||||
) -> Result<StorePath, error::CppException> {
|
||||
StorePath::new(std::path::Path::new(path), std::path::Path::new(store_dir))
|
||||
.map_err(|err| err.into())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ffi_StorePath_new2(
|
||||
hash: &[u8; crate::store::path::STORE_PATH_HASH_BYTES],
|
||||
name: &str,
|
||||
) -> Result<StorePath, error::CppException> {
|
||||
StorePath::from_parts(*hash, name).map_err(|err| err.into())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ffi_StorePath_fromBaseName(
|
||||
base_name: &str,
|
||||
) -> Result<StorePath, error::CppException> {
|
||||
StorePath::new_from_base_name(base_name).map_err(|err| err.into())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ffi_StorePath_drop(self_: *mut StorePath) {
|
||||
std::ptr::drop_in_place(self_);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ffi_StorePath_to_string(self_: &StorePath) -> Vec<u8> {
|
||||
let mut buf = vec![0; path::STORE_PATH_HASH_CHARS + 1 + self_.name.name().len()];
|
||||
util::base32::encode_into(self_.hash.hash(), &mut buf[0..path::STORE_PATH_HASH_CHARS]);
|
||||
buf[path::STORE_PATH_HASH_CHARS] = b'-';
|
||||
buf[path::STORE_PATH_HASH_CHARS + 1..].clone_from_slice(self_.name.name().as_bytes());
|
||||
buf
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ffi_StorePath_less_than(a: &StorePath, b: &StorePath) -> bool {
|
||||
a < b
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ffi_StorePath_eq(a: &StorePath, b: &StorePath) -> bool {
|
||||
a == b
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ffi_StorePath_clone(self_: &StorePath) -> StorePath {
|
||||
self_.clone()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ffi_StorePath_name(self_: &StorePath) -> &str {
|
||||
self_.name.name()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ffi_StorePath_hash_data(
|
||||
self_: &StorePath,
|
||||
) -> &[u8; crate::store::path::STORE_PATH_HASH_BYTES] {
|
||||
self_.hash.hash()
|
||||
}
|
||||
118
nix-rust/src/error.rs
Normal file
118
nix-rust/src/error.rs
Normal file
@@ -0,0 +1,118 @@
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
InvalidPath(crate::store::StorePath),
|
||||
BadStorePath(std::path::PathBuf),
|
||||
NotInStore(std::path::PathBuf),
|
||||
BadNarInfo,
|
||||
BadBase32,
|
||||
StorePathNameEmpty,
|
||||
StorePathNameTooLong,
|
||||
BadStorePathName,
|
||||
NarSizeFieldTooBig,
|
||||
BadNarString,
|
||||
BadNarPadding,
|
||||
BadNarVersionMagic,
|
||||
MissingNarOpenTag,
|
||||
MissingNarCloseTag,
|
||||
MissingNarField,
|
||||
BadNarField(String),
|
||||
BadExecutableField,
|
||||
IOError(std::io::Error),
|
||||
#[cfg(unused)]
|
||||
HttpError(hyper::error::Error),
|
||||
Misc(String),
|
||||
#[cfg(not(test))]
|
||||
Foreign(CppException),
|
||||
BadTarFileMemberName(String),
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
Error::IOError(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unused)]
|
||||
impl From<hyper::error::Error> for Error {
|
||||
fn from(err: hyper::error::Error) -> Self {
|
||||
Error::HttpError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Error::InvalidPath(_) => write!(f, "invalid path"),
|
||||
Error::BadNarInfo => write!(f, ".narinfo file is corrupt"),
|
||||
Error::BadStorePath(path) => write!(f, "path '{}' is not a store path", path.display()),
|
||||
Error::NotInStore(path) => {
|
||||
write!(f, "path '{}' is not in the Nix store", path.display())
|
||||
}
|
||||
Error::BadBase32 => write!(f, "invalid base32 string"),
|
||||
Error::StorePathNameEmpty => write!(f, "store path name is empty"),
|
||||
Error::StorePathNameTooLong => {
|
||||
write!(f, "store path name is longer than 211 characters")
|
||||
}
|
||||
Error::BadStorePathName => write!(f, "store path name contains forbidden character"),
|
||||
Error::NarSizeFieldTooBig => write!(f, "size field in NAR is too big"),
|
||||
Error::BadNarString => write!(f, "NAR string is not valid UTF-8"),
|
||||
Error::BadNarPadding => write!(f, "NAR padding is not zero"),
|
||||
Error::BadNarVersionMagic => write!(f, "unsupported NAR version"),
|
||||
Error::MissingNarOpenTag => write!(f, "NAR open tag is missing"),
|
||||
Error::MissingNarCloseTag => write!(f, "NAR close tag is missing"),
|
||||
Error::MissingNarField => write!(f, "expected NAR field is missing"),
|
||||
Error::BadNarField(s) => write!(f, "unrecognized NAR field '{}'", s),
|
||||
Error::BadExecutableField => write!(f, "bad 'executable' field in NAR"),
|
||||
Error::IOError(err) => write!(f, "I/O error: {}", err),
|
||||
#[cfg(unused)]
|
||||
Error::HttpError(err) => write!(f, "HTTP error: {}", err),
|
||||
#[cfg(not(test))]
|
||||
Error::Foreign(_) => write!(f, "<C++ exception>"), // FIXME
|
||||
Error::Misc(s) => write!(f, "{}", s),
|
||||
Error::BadTarFileMemberName(s) => {
|
||||
write!(f, "tar archive contains illegal file name '{}'", s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl From<Error> for CppException {
|
||||
fn from(err: Error) -> Self {
|
||||
match err {
|
||||
Error::Foreign(ex) => ex,
|
||||
_ => CppException::new(&err.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct CppException(*const libc::c_void); // == std::exception_ptr*
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl CppException {
|
||||
fn new(s: &str) -> Self {
|
||||
Self(unsafe { make_error(s) })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl Drop for CppException {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
destroy_error(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
extern "C" {
|
||||
#[allow(improper_ctypes)] // YOLO
|
||||
fn make_error(s: &str) -> *const libc::c_void;
|
||||
|
||||
fn destroy_error(exc: *const libc::c_void);
|
||||
}
|
||||
10
nix-rust/src/lib.rs
Normal file
10
nix-rust/src/lib.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
#[cfg(not(test))]
|
||||
mod c;
|
||||
mod error;
|
||||
#[cfg(unused)]
|
||||
mod nar;
|
||||
mod store;
|
||||
mod util;
|
||||
|
||||
pub use error::Error;
|
||||
126
nix-rust/src/nar.rs
Normal file
126
nix-rust/src/nar.rs
Normal file
@@ -0,0 +1,126 @@
|
||||
use crate::Error;
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use std::convert::TryFrom;
|
||||
use std::io::Read;
|
||||
|
||||
pub fn parse<R: Read>(input: &mut R) -> Result<(), Error> {
|
||||
if String::read(input)? != NAR_VERSION_MAGIC {
|
||||
return Err(Error::BadNarVersionMagic);
|
||||
}
|
||||
|
||||
parse_file(input)
|
||||
}
|
||||
|
||||
const NAR_VERSION_MAGIC: &str = "nix-archive-1";
|
||||
|
||||
fn parse_file<R: Read>(input: &mut R) -> Result<(), Error> {
|
||||
if String::read(input)? != "(" {
|
||||
return Err(Error::MissingNarOpenTag);
|
||||
}
|
||||
|
||||
if String::read(input)? != "type" {
|
||||
return Err(Error::MissingNarField);
|
||||
}
|
||||
|
||||
match String::read(input)?.as_ref() {
|
||||
"regular" => {
|
||||
let mut _executable = false;
|
||||
let mut tag = String::read(input)?;
|
||||
if tag == "executable" {
|
||||
_executable = true;
|
||||
if String::read(input)? != "" {
|
||||
return Err(Error::BadExecutableField);
|
||||
}
|
||||
tag = String::read(input)?;
|
||||
}
|
||||
if tag != "contents" {
|
||||
return Err(Error::MissingNarField);
|
||||
}
|
||||
let _contents = Vec::<u8>::read(input)?;
|
||||
if String::read(input)? != ")" {
|
||||
return Err(Error::MissingNarCloseTag);
|
||||
}
|
||||
}
|
||||
"directory" => loop {
|
||||
match String::read(input)?.as_ref() {
|
||||
"entry" => {
|
||||
if String::read(input)? != "(" {
|
||||
return Err(Error::MissingNarOpenTag);
|
||||
}
|
||||
if String::read(input)? != "name" {
|
||||
return Err(Error::MissingNarField);
|
||||
}
|
||||
let _name = String::read(input)?;
|
||||
if String::read(input)? != "node" {
|
||||
return Err(Error::MissingNarField);
|
||||
}
|
||||
parse_file(input)?;
|
||||
let tag = String::read(input)?;
|
||||
if tag != ")" {
|
||||
return Err(Error::MissingNarCloseTag);
|
||||
}
|
||||
}
|
||||
")" => break,
|
||||
s => return Err(Error::BadNarField(s.into())),
|
||||
}
|
||||
},
|
||||
"symlink" => {
|
||||
if String::read(input)? != "target" {
|
||||
return Err(Error::MissingNarField);
|
||||
}
|
||||
let _target = String::read(input)?;
|
||||
if String::read(input)? != ")" {
|
||||
return Err(Error::MissingNarCloseTag);
|
||||
}
|
||||
}
|
||||
s => return Err(Error::BadNarField(s.into())),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
trait Deserialize: Sized {
|
||||
fn read<R: Read>(input: &mut R) -> Result<Self, Error>;
|
||||
}
|
||||
|
||||
impl Deserialize for String {
|
||||
fn read<R: Read>(input: &mut R) -> Result<Self, Error> {
|
||||
let buf = Deserialize::read(input)?;
|
||||
Ok(String::from_utf8(buf).map_err(|_| Error::BadNarString)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for Vec<u8> {
|
||||
fn read<R: Read>(input: &mut R) -> Result<Self, Error> {
|
||||
let n: usize = Deserialize::read(input)?;
|
||||
let mut buf = vec![0; n];
|
||||
input.read_exact(&mut buf)?;
|
||||
skip_padding(input, n)?;
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
|
||||
fn skip_padding<R: Read>(input: &mut R, len: usize) -> Result<(), Error> {
|
||||
if len % 8 != 0 {
|
||||
let mut buf = [0; 8];
|
||||
let buf = &mut buf[0..8 - (len % 8)];
|
||||
input.read_exact(buf)?;
|
||||
if !buf.iter().all(|b| *b == 0) {
|
||||
return Err(Error::BadNarPadding);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Deserialize for u64 {
|
||||
fn read<R: Read>(input: &mut R) -> Result<Self, Error> {
|
||||
Ok(input.read_u64::<LittleEndian>()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for usize {
|
||||
fn read<R: Read>(input: &mut R) -> Result<Self, Error> {
|
||||
let n: u64 = Deserialize::read(input)?;
|
||||
Ok(usize::try_from(n).map_err(|_| Error::NarSizeFieldTooBig)?)
|
||||
}
|
||||
}
|
||||
48
nix-rust/src/store/binary_cache_store.rs
Normal file
48
nix-rust/src/store/binary_cache_store.rs
Normal file
@@ -0,0 +1,48 @@
|
||||
use super::{PathInfo, Store, StorePath};
|
||||
use crate::Error;
|
||||
use hyper::client::Client;
|
||||
|
||||
pub struct BinaryCacheStore {
|
||||
base_uri: String,
|
||||
client: Client<hyper::client::HttpConnector, hyper::Body>,
|
||||
}
|
||||
|
||||
impl BinaryCacheStore {
|
||||
pub fn new(base_uri: String) -> Self {
|
||||
Self {
|
||||
base_uri,
|
||||
client: Client::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Store for BinaryCacheStore {
|
||||
fn query_path_info(
|
||||
&self,
|
||||
path: &StorePath,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<PathInfo, Error>> + Send>> {
|
||||
let uri = format!("{}/{}.narinfo", self.base_uri.clone(), path.hash);
|
||||
let path = path.clone();
|
||||
let client = self.client.clone();
|
||||
let store_dir = self.store_dir().to_string();
|
||||
|
||||
Box::pin(async move {
|
||||
let response = client.get(uri.parse::<hyper::Uri>().unwrap()).await?;
|
||||
|
||||
if response.status() == hyper::StatusCode::NOT_FOUND
|
||||
|| response.status() == hyper::StatusCode::FORBIDDEN
|
||||
{
|
||||
return Err(Error::InvalidPath(path));
|
||||
}
|
||||
|
||||
let mut body = response.into_body();
|
||||
|
||||
let mut bytes = Vec::new();
|
||||
while let Some(next) = body.next().await {
|
||||
bytes.extend(next?);
|
||||
}
|
||||
|
||||
PathInfo::parse_nar_info(std::str::from_utf8(&bytes).unwrap(), &store_dir)
|
||||
})
|
||||
}
|
||||
}
|
||||
17
nix-rust/src/store/mod.rs
Normal file
17
nix-rust/src/store/mod.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
pub mod path;
|
||||
|
||||
#[cfg(unused)]
|
||||
mod binary_cache_store;
|
||||
#[cfg(unused)]
|
||||
mod path_info;
|
||||
#[cfg(unused)]
|
||||
mod store;
|
||||
|
||||
pub use path::{StorePath, StorePathHash, StorePathName};
|
||||
|
||||
#[cfg(unused)]
|
||||
pub use binary_cache_store::BinaryCacheStore;
|
||||
#[cfg(unused)]
|
||||
pub use path_info::PathInfo;
|
||||
#[cfg(unused)]
|
||||
pub use store::Store;
|
||||
224
nix-rust/src/store/path.rs
Normal file
224
nix-rust/src/store/path.rs
Normal file
@@ -0,0 +1,224 @@
|
||||
use crate::error::Error;
|
||||
use crate::util::base32;
|
||||
use std::fmt;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
pub struct StorePath {
|
||||
pub hash: StorePathHash,
|
||||
pub name: StorePathName,
|
||||
}
|
||||
|
||||
pub const STORE_PATH_HASH_BYTES: usize = 20;
|
||||
pub const STORE_PATH_HASH_CHARS: usize = 32;
|
||||
|
||||
impl StorePath {
|
||||
pub fn new(path: &Path, store_dir: &Path) -> Result<Self, Error> {
|
||||
if path.parent() != Some(store_dir) {
|
||||
return Err(Error::NotInStore(path.into()));
|
||||
}
|
||||
Self::new_from_base_name(
|
||||
path.file_name()
|
||||
.ok_or_else(|| Error::BadStorePath(path.into()))?
|
||||
.to_str()
|
||||
.ok_or_else(|| Error::BadStorePath(path.into()))?,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn from_parts(hash: [u8; STORE_PATH_HASH_BYTES], name: &str) -> Result<Self, Error> {
|
||||
Ok(StorePath {
|
||||
hash: StorePathHash(hash),
|
||||
name: StorePathName::new(name)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_from_base_name(base_name: &str) -> Result<Self, Error> {
|
||||
if base_name.len() < STORE_PATH_HASH_CHARS + 1
|
||||
|| base_name.as_bytes()[STORE_PATH_HASH_CHARS] != b'-'
|
||||
{
|
||||
return Err(Error::BadStorePath(base_name.into()));
|
||||
}
|
||||
|
||||
Ok(StorePath {
|
||||
hash: StorePathHash::new(&base_name[0..STORE_PATH_HASH_CHARS])?,
|
||||
name: StorePathName::new(&base_name[STORE_PATH_HASH_CHARS + 1..])?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for StorePath {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}-{}", self.hash, self.name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct StorePathHash([u8; STORE_PATH_HASH_BYTES]);
|
||||
|
||||
impl StorePathHash {
|
||||
pub fn new(s: &str) -> Result<Self, Error> {
|
||||
assert_eq!(s.len(), STORE_PATH_HASH_CHARS);
|
||||
let v = base32::decode(s)?;
|
||||
assert_eq!(v.len(), STORE_PATH_HASH_BYTES);
|
||||
let mut bytes: [u8; 20] = Default::default();
|
||||
bytes.copy_from_slice(&v[0..STORE_PATH_HASH_BYTES]);
|
||||
Ok(Self(bytes))
|
||||
}
|
||||
|
||||
pub fn hash(&self) -> &[u8; STORE_PATH_HASH_BYTES] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for StorePathHash {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut buf = vec![0; STORE_PATH_HASH_CHARS];
|
||||
base32::encode_into(&self.0, &mut buf);
|
||||
f.write_str(std::str::from_utf8(&buf).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for StorePathHash {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
// Historically we've sorted store paths by their base32
|
||||
// serialization, but our base32 encodes bytes in reverse
|
||||
// order. So compare them in reverse order as well.
|
||||
self.0.iter().rev().cmp(other.0.iter().rev())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for StorePathHash {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
pub struct StorePathName(String);
|
||||
|
||||
impl StorePathName {
|
||||
pub fn new(s: &str) -> Result<Self, Error> {
|
||||
if s.is_empty() {
|
||||
return Err(Error::StorePathNameEmpty);
|
||||
}
|
||||
|
||||
if s.len() > 211 {
|
||||
return Err(Error::StorePathNameTooLong);
|
||||
}
|
||||
|
||||
let is_good_path_name = s.chars().all(|c| {
|
||||
c.is_ascii_alphabetic()
|
||||
|| c.is_ascii_digit()
|
||||
|| c == '+'
|
||||
|| c == '-'
|
||||
|| c == '.'
|
||||
|| c == '_'
|
||||
|| c == '?'
|
||||
|| c == '='
|
||||
});
|
||||
if s.starts_with('.') || !is_good_path_name {
|
||||
return Err(Error::BadStorePathName);
|
||||
}
|
||||
|
||||
Ok(Self(s.to_string()))
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for StorePathName {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use assert_matches::assert_matches;
|
||||
|
||||
#[test]
|
||||
fn test_parse() {
|
||||
let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-konsole-18.12.3";
|
||||
let p = StorePath::new_from_base_name(&s).unwrap();
|
||||
assert_eq!(p.name.0, "konsole-18.12.3");
|
||||
assert_eq!(
|
||||
p.hash.0,
|
||||
[
|
||||
0x9f, 0x76, 0x49, 0x20, 0xf6, 0x5d, 0xe9, 0x71, 0xc4, 0xca, 0x46, 0x21, 0xab, 0xff,
|
||||
0x9b, 0x44, 0xef, 0x87, 0x0f, 0x3c
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_name() {
|
||||
let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-";
|
||||
assert_matches!(
|
||||
StorePath::new_from_base_name(&s),
|
||||
Err(Error::StorePathNameEmpty)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_dash() {
|
||||
let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz";
|
||||
assert_matches!(
|
||||
StorePath::new_from_base_name(&s),
|
||||
Err(Error::BadStorePath(_))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_short_hash() {
|
||||
let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxl-konsole-18.12.3";
|
||||
assert_matches!(
|
||||
StorePath::new_from_base_name(&s),
|
||||
Err(Error::BadStorePath(_))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_hash() {
|
||||
let s = "7h7qgvs4kgzsn8e6rb273saxyqh4jxlz-konsole-18.12.3";
|
||||
assert_matches!(StorePath::new_from_base_name(&s), Err(Error::BadBase32));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_long_name() {
|
||||
let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
assert_matches!(StorePath::new_from_base_name(&s), Ok(_));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_too_long_name() {
|
||||
let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
assert_matches!(
|
||||
StorePath::new_from_base_name(&s),
|
||||
Err(Error::StorePathNameTooLong)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bad_name() {
|
||||
let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-foo bar";
|
||||
assert_matches!(
|
||||
StorePath::new_from_base_name(&s),
|
||||
Err(Error::BadStorePathName)
|
||||
);
|
||||
|
||||
let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-kónsole";
|
||||
assert_matches!(
|
||||
StorePath::new_from_base_name(&s),
|
||||
Err(Error::BadStorePathName)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_roundtrip() {
|
||||
let s = "7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-konsole-18.12.3";
|
||||
assert_eq!(StorePath::new_from_base_name(&s).unwrap().to_string(), s);
|
||||
}
|
||||
}
|
||||
70
nix-rust/src/store/path_info.rs
Normal file
70
nix-rust/src/store/path_info.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use crate::store::StorePath;
|
||||
use crate::Error;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PathInfo {
|
||||
pub path: StorePath,
|
||||
pub references: BTreeSet<StorePath>,
|
||||
pub nar_size: u64,
|
||||
pub deriver: Option<StorePath>,
|
||||
|
||||
// Additional binary cache info.
|
||||
pub url: Option<String>,
|
||||
pub compression: Option<String>,
|
||||
pub file_size: Option<u64>,
|
||||
}
|
||||
|
||||
impl PathInfo {
|
||||
pub fn parse_nar_info(nar_info: &str, store_dir: &str) -> Result<Self, Error> {
|
||||
let mut path = None;
|
||||
let mut references = BTreeSet::new();
|
||||
let mut nar_size = None;
|
||||
let mut deriver = None;
|
||||
let mut url = None;
|
||||
let mut compression = None;
|
||||
let mut file_size = None;
|
||||
|
||||
for line in nar_info.lines() {
|
||||
let colon = line.find(':').ok_or(Error::BadNarInfo)?;
|
||||
|
||||
let (name, value) = line.split_at(colon);
|
||||
|
||||
if !value.starts_with(": ") {
|
||||
return Err(Error::BadNarInfo);
|
||||
}
|
||||
|
||||
let value = &value[2..];
|
||||
|
||||
if name == "StorePath" {
|
||||
path = Some(StorePath::new(std::path::Path::new(value), store_dir)?);
|
||||
} else if name == "NarSize" {
|
||||
nar_size = Some(u64::from_str_radix(value, 10).map_err(|_| Error::BadNarInfo)?);
|
||||
} else if name == "References" {
|
||||
if !value.is_empty() {
|
||||
for r in value.split(' ') {
|
||||
references.insert(StorePath::new_from_base_name(r)?);
|
||||
}
|
||||
}
|
||||
} else if name == "Deriver" {
|
||||
deriver = Some(StorePath::new_from_base_name(value)?);
|
||||
} else if name == "URL" {
|
||||
url = Some(value.into());
|
||||
} else if name == "Compression" {
|
||||
compression = Some(value.into());
|
||||
} else if name == "FileSize" {
|
||||
file_size = Some(u64::from_str_radix(value, 10).map_err(|_| Error::BadNarInfo)?);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(PathInfo {
|
||||
path: path.ok_or(Error::BadNarInfo)?,
|
||||
references,
|
||||
nar_size: nar_size.ok_or(Error::BadNarInfo)?,
|
||||
deriver,
|
||||
url: Some(url.ok_or(Error::BadNarInfo)?),
|
||||
compression,
|
||||
file_size,
|
||||
})
|
||||
}
|
||||
}
|
||||
53
nix-rust/src/store/store.rs
Normal file
53
nix-rust/src/store/store.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use super::{PathInfo, StorePath};
|
||||
use crate::Error;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::path::Path;
|
||||
|
||||
pub trait Store: Send + Sync {
|
||||
fn store_dir(&self) -> &str {
|
||||
"/nix/store"
|
||||
}
|
||||
|
||||
fn query_path_info(
|
||||
&self,
|
||||
store_path: &StorePath,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<PathInfo, Error>> + Send>>;
|
||||
}
|
||||
|
||||
impl dyn Store {
|
||||
pub fn parse_store_path(&self, path: &Path) -> Result<StorePath, Error> {
|
||||
StorePath::new(path, self.store_dir())
|
||||
}
|
||||
|
||||
pub async fn compute_path_closure(
|
||||
&self,
|
||||
roots: BTreeSet<StorePath>,
|
||||
) -> Result<BTreeMap<StorePath, PathInfo>, Error> {
|
||||
let mut done = BTreeSet::new();
|
||||
let mut result = BTreeMap::new();
|
||||
let mut pending = vec![];
|
||||
|
||||
for root in roots {
|
||||
pending.push(self.query_path_info(&root));
|
||||
done.insert(root);
|
||||
}
|
||||
|
||||
while !pending.is_empty() {
|
||||
let (info, _, remaining) = futures::future::select_all(pending).await;
|
||||
pending = remaining;
|
||||
|
||||
let info = info?;
|
||||
|
||||
for path in &info.references {
|
||||
if !done.contains(path) {
|
||||
pending.push(self.query_path_info(&path));
|
||||
done.insert(path.clone());
|
||||
}
|
||||
}
|
||||
|
||||
result.insert(info.path.clone(), info);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
160
nix-rust/src/util/base32.rs
Normal file
160
nix-rust/src/util/base32.rs
Normal file
@@ -0,0 +1,160 @@
|
||||
use crate::error::Error;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
pub fn encoded_len(input_len: usize) -> usize {
|
||||
if input_len == 0 {
|
||||
0
|
||||
} else {
|
||||
(input_len * 8 - 1) / 5 + 1
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decoded_len(input_len: usize) -> usize {
|
||||
input_len * 5 / 8
|
||||
}
|
||||
|
||||
static BASE32_CHARS: &[u8; 32] = &b"0123456789abcdfghijklmnpqrsvwxyz";
|
||||
|
||||
lazy_static! {
|
||||
static ref BASE32_CHARS_REVERSE: Box<[u8; 256]> = {
|
||||
let mut xs = [0xffu8; 256];
|
||||
for (n, c) in BASE32_CHARS.iter().enumerate() {
|
||||
xs[*c as usize] = n as u8;
|
||||
}
|
||||
Box::new(xs)
|
||||
};
|
||||
}
|
||||
|
||||
pub fn encode(input: &[u8]) -> String {
|
||||
let mut buf = vec![0; encoded_len(input.len())];
|
||||
encode_into(input, &mut buf);
|
||||
std::str::from_utf8(&buf).unwrap().to_string()
|
||||
}
|
||||
|
||||
pub fn encode_into(input: &[u8], output: &mut [u8]) {
|
||||
let len = encoded_len(input.len());
|
||||
assert_eq!(len, output.len());
|
||||
|
||||
let mut nr_bits_left: usize = 0;
|
||||
let mut bits_left: u16 = 0;
|
||||
let mut pos = len;
|
||||
|
||||
for b in input {
|
||||
bits_left |= (*b as u16) << nr_bits_left;
|
||||
nr_bits_left += 8;
|
||||
while nr_bits_left > 5 {
|
||||
output[pos - 1] = BASE32_CHARS[(bits_left & 0x1f) as usize];
|
||||
pos -= 1;
|
||||
bits_left >>= 5;
|
||||
nr_bits_left -= 5;
|
||||
}
|
||||
}
|
||||
|
||||
if nr_bits_left > 0 {
|
||||
output[pos - 1] = BASE32_CHARS[(bits_left & 0x1f) as usize];
|
||||
pos -= 1;
|
||||
}
|
||||
|
||||
assert_eq!(pos, 0);
|
||||
}
|
||||
|
||||
pub fn decode(input: &str) -> Result<Vec<u8>, crate::Error> {
|
||||
let mut res = Vec::with_capacity(decoded_len(input.len()));
|
||||
|
||||
let mut nr_bits_left: usize = 0;
|
||||
let mut bits_left: u16 = 0;
|
||||
|
||||
for c in input.chars().rev() {
|
||||
let b = BASE32_CHARS_REVERSE[c as usize];
|
||||
if b == 0xff {
|
||||
return Err(Error::BadBase32);
|
||||
}
|
||||
bits_left |= (b as u16) << nr_bits_left;
|
||||
nr_bits_left += 5;
|
||||
if nr_bits_left >= 8 {
|
||||
res.push((bits_left & 0xff) as u8);
|
||||
bits_left >>= 8;
|
||||
nr_bits_left -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
if nr_bits_left > 0 && bits_left != 0 {
|
||||
return Err(Error::BadBase32);
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use assert_matches::assert_matches;
|
||||
use hex;
|
||||
use proptest::proptest;
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
assert_eq!(encode(&[]), "");
|
||||
|
||||
assert_eq!(
|
||||
encode(&hex::decode("0839703786356bca59b0f4a32987eb2e6de43ae8").unwrap()),
|
||||
"x0xf8v9fxf3jk8zln1cwlsrmhqvp0f88"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
encode(
|
||||
&hex::decode("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
|
||||
.unwrap()
|
||||
),
|
||||
"1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
encode(
|
||||
&hex::decode("ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f")
|
||||
.unwrap()
|
||||
),
|
||||
"2gs8k559z4rlahfx0y688s49m2vvszylcikrfinm30ly9rak69236nkam5ydvly1ai7xac99vxfc4ii84hawjbk876blyk1jfhkbbyx"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
assert_eq!(hex::encode(decode("").unwrap()), "");
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(decode("x0xf8v9fxf3jk8zln1cwlsrmhqvp0f88").unwrap()),
|
||||
"0839703786356bca59b0f4a32987eb2e6de43ae8"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(decode("1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s").unwrap()),
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(decode("2gs8k559z4rlahfx0y688s49m2vvszylcikrfinm30ly9rak69236nkam5ydvly1ai7xac99vxfc4ii84hawjbk876blyk1jfhkbbyx").unwrap()),
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
|
||||
);
|
||||
|
||||
assert_matches!(
|
||||
decode("xoxf8v9fxf3jk8zln1cwlsrmhqvp0f88"),
|
||||
Err(Error::BadBase32)
|
||||
);
|
||||
assert_matches!(
|
||||
decode("2b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s"),
|
||||
Err(Error::BadBase32)
|
||||
);
|
||||
assert_matches!(decode("2"), Err(Error::BadBase32));
|
||||
assert_matches!(decode("2gs"), Err(Error::BadBase32));
|
||||
assert_matches!(decode("2gs8"), Err(Error::BadBase32));
|
||||
}
|
||||
|
||||
proptest! {
|
||||
|
||||
#[test]
|
||||
fn roundtrip(s: Vec<u8>) {
|
||||
assert_eq!(s, decode(&encode(&s)).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
1
nix-rust/src/util/mod.rs
Normal file
1
nix-rust/src/util/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod base32;
|
||||
@@ -41,7 +41,7 @@ perlarchname=$($perl -e 'use Config; print $Config{archname};')
|
||||
AC_SUBST(perllibdir, [${libdir}/perl5/site_perl/$perlversion/$perlarchname])
|
||||
AC_MSG_RESULT($perllibdir)
|
||||
|
||||
# Look for libsodium.
|
||||
# Look for libsodium, an optional dependency.
|
||||
PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"])
|
||||
|
||||
# Check for the required Perl dependencies (DBI and DBD::SQLite).
|
||||
|
||||
@@ -240,7 +240,7 @@ SV * convertHash(char * algo, char * s, int toBase32)
|
||||
PPCODE:
|
||||
try {
|
||||
auto h = Hash::parseAny(s, parseHashType(algo));
|
||||
auto s = h.to_string(toBase32 ? Base32 : Base16, false);
|
||||
string s = h.to_string(toBase32 ? Base32 : Base16, false);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
# set -x
|
||||
|
||||
|
||||
# mapfile BUILDS_FOR_LATEST_EVAL < <(
|
||||
# curl -H 'Accept: application/json' https://hydra.nixos.org/jobset/nix/master/evals | \
|
||||
# jq -r '.evals[0].builds[] | @sh')
|
||||
BUILDS_FOR_LATEST_EVAL=$(
|
||||
curl -sS -H 'Accept: application/json' https://hydra.nixos.org/jobset/nix/master/evals | \
|
||||
jq -r '.evals[0].builds[]')
|
||||
|
||||
someBuildFailed=0
|
||||
|
||||
for buildId in $BUILDS_FOR_LATEST_EVAL; do
|
||||
buildInfo=$(curl --fail -sS -H 'Accept: application/json' "https://hydra.nixos.org/build/$buildId")
|
||||
|
||||
finished=$(echo "$buildInfo" | jq -r '.finished')
|
||||
|
||||
if [[ $finished = 0 ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
buildStatus=$(echo "$buildInfo" | jq -r '.buildstatus')
|
||||
|
||||
if [[ $buildStatus != 0 ]]; then
|
||||
someBuildFailed=1
|
||||
echo "Job “$(echo "$buildInfo" | jq -r '.job')” failed on hydra: $buildInfo"
|
||||
fi
|
||||
done
|
||||
|
||||
exit "$someBuildFailed"
|
||||
@@ -246,8 +246,7 @@ get_volume_pass() {
|
||||
verify_volume_pass() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
local volume_uuid="$2"
|
||||
_sudo "to confirm the password actually unlocks the volume" \
|
||||
/usr/sbin/diskutil apfs unlockVolume "$volume_special" -verify -stdinpassphrase -user "$volume_uuid"
|
||||
/usr/sbin/diskutil apfs unlockVolume "$volume_special" -verify -stdinpassphrase -user "$volume_uuid"
|
||||
}
|
||||
|
||||
volume_pass_works() {
|
||||
@@ -441,26 +440,7 @@ add_nix_vol_fstab_line() {
|
||||
# shellcheck disable=SC1003,SC2026
|
||||
local escaped_mountpoint="${NIX_ROOT/ /'\\\'040}"
|
||||
shift
|
||||
|
||||
# wrap `ex` to work around a problem with vim plugins breaking exit codes
|
||||
# (see github.com/NixOS/nix/issues/5468)
|
||||
#
|
||||
# the first draft used `--noplugin`, but github.com/NixOS/nix/issues/6462
|
||||
# suggests we need the less-semantic `-u NONE`
|
||||
#
|
||||
# we'd prefer EDITOR="/usr/bin/ex -u NONE" but vifs doesn't word-split
|
||||
# the EDITOR env.
|
||||
#
|
||||
# TODO: at some point we should switch to `--clean`, but it wasn't added
|
||||
# until https://github.com/vim/vim/releases/tag/v8.0.1554 while the macOS
|
||||
# minver 10.12.6 seems to have released with vim 7.4
|
||||
cat > "$SCRATCH/ex_cleanroom_wrapper" <<EOF
|
||||
#!/bin/sh
|
||||
/usr/bin/ex -u NONE "\$@"
|
||||
EOF
|
||||
chmod 755 "$SCRATCH/ex_cleanroom_wrapper"
|
||||
|
||||
EDITOR="$SCRATCH/ex_cleanroom_wrapper" _sudo "to add nix to fstab" "$@" <<EOF
|
||||
EDITOR="/usr/bin/ex" _sudo "to add nix to fstab" "$@" <<EOF
|
||||
:a
|
||||
UUID=$uuid $escaped_mountpoint apfs rw,noauto,nobrowse,suid,owners
|
||||
.
|
||||
@@ -650,9 +630,8 @@ EOF
|
||||
task "Configuring /etc/synthetic.conf to make a mount-point at $NIX_ROOT" >&2
|
||||
# technically /etc/synthetic.d/nix is supported in Big Sur+
|
||||
# but handling both takes even more code...
|
||||
# Note: `-u NONE` disables vim plugins/rc; see note on --clean earlier
|
||||
_sudo "to add Nix to /etc/synthetic.conf" \
|
||||
/usr/bin/ex -u NONE /etc/synthetic.conf <<EOF
|
||||
/usr/bin/ex /etc/synthetic.conf <<EOF
|
||||
:a
|
||||
${NIX_ROOT:1}
|
||||
.
|
||||
@@ -691,27 +670,22 @@ encrypt_volume() {
|
||||
local volume_uuid="$1"
|
||||
local volume_label="$2"
|
||||
local password
|
||||
|
||||
task "Encrypt the Nix volume" >&2
|
||||
|
||||
# Note: mount/unmount are late additions to support the right order
|
||||
# of operations for creating the volume and then baking its uuid into
|
||||
# other artifacts; not as well-trod wrt to potential errors, race
|
||||
# conditions, etc.
|
||||
|
||||
_sudo "to mount your Nix volume for encrypting" \
|
||||
/usr/sbin/diskutil mount "$volume_label"
|
||||
/usr/sbin/diskutil mount "$volume_label"
|
||||
|
||||
password="$(/usr/bin/xxd -l 32 -p -c 256 /dev/random)"
|
||||
_sudo "to add your Nix volume's password to Keychain" \
|
||||
/usr/bin/security -i <<EOF
|
||||
add-generic-password -a "$volume_label" -s "$volume_uuid" -l "$volume_label encryption password" -D "Encrypted volume password" -j "Added automatically by the Nix installer for use by $NIX_VOLUME_MOUNTD_DEST" -w "$password" -T /System/Library/CoreServices/APFSUserAgent -T /System/Library/CoreServices/CSUserAgent -T /usr/bin/security "/Library/Keychains/System.keychain"
|
||||
EOF
|
||||
builtin printf "%s" "$password" | _sudo "to actually encrypt your Nix volume" \
|
||||
builtin printf "%s" "$password" | _sudo "to encrypt your Nix volume" \
|
||||
/usr/sbin/diskutil apfs encryptVolume "$volume_label" -user disk -stdinpassphrase
|
||||
|
||||
_sudo "to unmount the encrypted volume" \
|
||||
/usr/sbin/diskutil unmount force "$volume_label"
|
||||
/usr/sbin/diskutil unmount force "$volume_label"
|
||||
}
|
||||
|
||||
create_volume() {
|
||||
@@ -820,8 +794,7 @@ setup_volume_daemon() {
|
||||
local volume_uuid="$2"
|
||||
if ! test_voldaemon; then
|
||||
task "Configuring LaunchDaemon to mount '$NIX_VOLUME_LABEL'" >&2
|
||||
# Note: `-u NONE` disables vim plugins/rc; see note on --clean earlier
|
||||
_sudo "to install the Nix volume mounter" /usr/bin/ex -u NONE "$NIX_VOLUME_MOUNTD_DEST" <<EOF
|
||||
_sudo "to install the Nix volume mounter" /usr/bin/ex "$NIX_VOLUME_MOUNTD_DEST" <<EOF
|
||||
:a
|
||||
$(generate_mount_daemon "$cmd_type" "$volume_uuid")
|
||||
.
|
||||
|
||||
@@ -218,7 +218,7 @@ EOF
|
||||
setup_darwin_volume
|
||||
fi
|
||||
|
||||
if [ "$(/usr/sbin/diskutil info -plist /nix | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]" -)" = "<false/>" ]; then
|
||||
failure "This script needs a /nix volume with global permissions! This may require running sudo /usr/sbin/diskutil enableOwnership /nix."
|
||||
if [ "$(diskutil info -plist /nix | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]" -)" = "<false/>" ]; then
|
||||
failure "This script needs a /nix volume with global permissions! This may require running sudo diskutil enableOwnership /nix."
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -23,10 +23,10 @@ readonly RED='\033[31m'
|
||||
# installer allows overriding build user count to speed up installation
|
||||
# as creating each user takes non-trivial amount of time on macos
|
||||
readonly NIX_USER_COUNT=${NIX_USER_COUNT:-32}
|
||||
readonly NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-30000}"
|
||||
readonly NIX_BUILD_GROUP_ID="30000"
|
||||
readonly NIX_BUILD_GROUP_NAME="nixbld"
|
||||
# darwin installer needs to override these
|
||||
NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-30001}"
|
||||
NIX_FIRST_BUILD_UID="30001"
|
||||
NIX_BUILD_USER_NAME_TEMPLATE="nixbld%d"
|
||||
# Please don't change this. We don't support it, because the
|
||||
# default shell profile that comes with Nix doesn't support it.
|
||||
@@ -377,11 +377,6 @@ cure_artifacts() {
|
||||
}
|
||||
|
||||
validate_starting_assumptions() {
|
||||
task "Checking for artifacts of previous installs"
|
||||
cat <<EOF
|
||||
Before I try to install, I'll check for signs Nix already is or has
|
||||
been installed on this system.
|
||||
EOF
|
||||
if type nix-env 2> /dev/null >&2; then
|
||||
warning <<EOF
|
||||
Nix already appears to be installed. This installer may run into issues.
|
||||
@@ -391,11 +386,6 @@ $(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
|
||||
# TODO: I think it would be good for this step to accumulate more
|
||||
# knowledge of older obsolete artifacts, if there are any.
|
||||
# We could issue a "reminder" here that the user might want
|
||||
# to clean them up?
|
||||
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
# TODO: I think it would be good to accumulate a list of all
|
||||
# of the copies so that people don't hit this 2 or 3x in
|
||||
@@ -423,18 +413,6 @@ EOF
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$(uname -s)" = "Linux" ] && [ ! -e /run/systemd/system ]; then
|
||||
warning <<EOF
|
||||
We did not detect systemd on your system. With a multi-user install
|
||||
without systemd you will have to manually configure your init system to
|
||||
launch the Nix daemon after installation.
|
||||
EOF
|
||||
if ! ui_confirm "Do you want to proceed with a multi-user installation?"; then
|
||||
failure <<EOF
|
||||
You have aborted the installation.
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
setup_report() {
|
||||
@@ -588,40 +566,21 @@ create_directories() {
|
||||
# since this bit is cross-platform:
|
||||
# - first try with `command -vp` to try and find
|
||||
# chown in the usual places
|
||||
# * to work around some sort of deficiency in
|
||||
# `command -p` in macOS bash 3.2, we also add
|
||||
# PATH="$(getconf PATH 2>/dev/null)". As long as
|
||||
# getconf is found, this should set a sane PATH
|
||||
# which `command -p` in bash 3.2 appears to use.
|
||||
# A bash with a properly-working `command -p`
|
||||
# should ignore this hard-set PATH in favor of
|
||||
# whatever it obtains internally. See
|
||||
# github.com/NixOS/nix/issues/5768
|
||||
# - fall back on `command -v` which would find
|
||||
# any chown on path
|
||||
# if we don't find one, the command is already
|
||||
# hiding behind || true, and the general state
|
||||
# should be one the user can repair once they
|
||||
# figure out where chown is...
|
||||
local get_chr_own="$(PATH="$(getconf PATH 2>/dev/null)" command -vp chown)"
|
||||
local get_chr_own="$(command -vp chown)"
|
||||
if [[ -z "$get_chr_own" ]]; then
|
||||
get_chr_own="$(command -v chown)"
|
||||
fi
|
||||
|
||||
if [[ -z "$get_chr_own" ]]; then
|
||||
reminder <<EOF
|
||||
I wanted to take root ownership of existing Nix store files,
|
||||
but I couldn't locate 'chown'. (You may need to fix your PATH.)
|
||||
To manually change file ownership, you can run:
|
||||
sudo chown -R 'root:$NIX_BUILD_GROUP_NAME' '$NIX_ROOT'
|
||||
EOF
|
||||
else
|
||||
_sudo "to take root ownership of existing Nix store files" \
|
||||
"$get_chr_own" -R "root:$NIX_BUILD_GROUP_NAME" "$NIX_ROOT" || true
|
||||
fi
|
||||
_sudo "to take root ownership of existing Nix store files" \
|
||||
"$get_chr_own" -R "root:$NIX_BUILD_GROUP_NAME" "$NIX_ROOT" || true
|
||||
fi
|
||||
_sudo "to make the basic directory structure of Nix (part 1)" \
|
||||
install -dv -m 0755 /nix /nix/var /nix/var/log /nix/var/log/nix /nix/var/log/nix/drvs /nix/var/nix{,/db,/gcroots,/profiles,/temproots,/userpool,/daemon-socket} /nix/var/nix/{gcroots,profiles}/per-user
|
||||
install -dv -m 0755 /nix /nix/var /nix/var/log /nix/var/log/nix /nix/var/log/nix/drvs /nix/var/nix{,/db,/gcroots,/profiles,/temproots,/userpool} /nix/var/nix/{gcroots,profiles}/per-user
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 2)" \
|
||||
install -dv -g "$NIX_BUILD_GROUP_NAME" -m 1775 /nix/store
|
||||
@@ -751,7 +710,7 @@ install_from_extracted_nix() {
|
||||
cd "$EXTRACTED_NIX_PATH"
|
||||
|
||||
_sudo "to copy the basic Nix files to the new store at $NIX_ROOT/store" \
|
||||
cp -RPp ./store/* "$NIX_ROOT/store/"
|
||||
cp -RLp ./store/* "$NIX_ROOT/store/"
|
||||
|
||||
_sudo "to make the new store non-writable at $NIX_ROOT/store" \
|
||||
chmod -R ugo-w "$NIX_ROOT/store/"
|
||||
|
||||
@@ -38,7 +38,7 @@ fi
|
||||
|
||||
# Determine if we could use the multi-user installer or not
|
||||
if [ "$(uname -s)" = "Linux" ]; then
|
||||
echo "Note: a multi-user installation is possible. See https://nixos.org/manual/nix/stable/installation/installing-binary.html#multi-user-installation" >&2
|
||||
echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2
|
||||
fi
|
||||
|
||||
case "$(uname -s)" in
|
||||
@@ -98,7 +98,7 @@ while [ $# -gt 0 ]; do
|
||||
echo " providing multi-user support and better isolation for local builds."
|
||||
echo " Both for security and reproducibility, this method is recommended if"
|
||||
echo " supported on your platform."
|
||||
echo " See https://nixos.org/manual/nix/stable/installation/installing-binary.html#multi-user-installation"
|
||||
echo " See https://nixos.org/nix/manual/#sect-multi-user-installation"
|
||||
echo ""
|
||||
echo " --no-daemon: Simple, single-user installation that does not require root and is"
|
||||
echo " trivial to uninstall."
|
||||
@@ -144,7 +144,7 @@ if ! [ -e "$dest" ]; then
|
||||
fi
|
||||
|
||||
if ! [ -w "$dest" ]; then
|
||||
echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see https://nixos.org/manual/nix/stable/installation/multi-user.html. If you wish to continue with a single-user install for $USER please run 'chown -R $USER $dest' as root." >&2
|
||||
echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see https://nixos.org/nix/manual/#ssec-multi-user. If you wish to continue with a single-user install for $USER please run 'chown -R $USER $dest' as root." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@ readonly SERVICE_DEST=/etc/systemd/system/nix-daemon.service
|
||||
readonly SOCKET_SRC=/lib/systemd/system/nix-daemon.socket
|
||||
readonly SOCKET_DEST=/etc/systemd/system/nix-daemon.socket
|
||||
|
||||
readonly TMPFILES_SRC=/lib/tmpfiles.d/nix-daemon.conf
|
||||
readonly TMPFILES_DEST=/etc/tmpfiles.d/nix-daemon.conf
|
||||
|
||||
# Path for the systemd override unit file to contain the proxy settings
|
||||
readonly SERVICE_OVERRIDE=${SERVICE_DEST}.d/override.conf
|
||||
@@ -85,13 +83,6 @@ EOF
|
||||
poly_configure_nix_daemon_service() {
|
||||
if [ -e /run/systemd/system ]; then
|
||||
task "Setting up the nix-daemon systemd service"
|
||||
|
||||
_sudo "to create the nix-daemon tmpfiles config" \
|
||||
ln -sfn /nix/var/nix/profiles/default/$TMPFILES_SRC $TMPFILES_DEST
|
||||
|
||||
_sudo "to run systemd-tmpfiles once to pick that path up" \
|
||||
systemd-tmpfiles --create --prefix=/nix/var/nix
|
||||
|
||||
_sudo "to set up the nix-daemon service" \
|
||||
systemctl link "/nix/var/nix/profiles/default$SERVICE_SRC"
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ if [ "$(uname -s)" != "Darwin" ]; then
|
||||
fi
|
||||
|
||||
if command -v curl > /dev/null 2>&1; then
|
||||
fetch() { curl --fail -L "$1" -o "$2"; }
|
||||
fetch() { curl -L "$1" -o "$2"; }
|
||||
elif command -v wget > /dev/null 2>&1; then
|
||||
fetch() { wget "$1" -O "$2"; }
|
||||
else
|
||||
|
||||
@@ -24,9 +24,6 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then
|
||||
export NIX_SSL_CERT_FILE="$NIX_LINK/etc/ca-bundle.crt"
|
||||
fi
|
||||
|
||||
# Only use MANPATH if it is already set. In general `man` will just simply
|
||||
# pick up `.nix-profile/share/man` because is it close to `.nix-profile/bin`
|
||||
# which is in the $PATH. For more info, run `manpath -d`.
|
||||
if [ -n "${MANPATH-}" ]; then
|
||||
export MANPATH="$NIX_LINK/share/man:$MANPATH"
|
||||
fi
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
(import (fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz") {
|
||||
(import (fetchTarball https://github.com/edolstra/flake-compat/archive/master.tar.gz) {
|
||||
src = ./.;
|
||||
}).shellNix
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "pathlocks.hh"
|
||||
#include "globals.hh"
|
||||
#include "serialise.hh"
|
||||
#include "build-result.hh"
|
||||
#include "store-api.hh"
|
||||
#include "derivations.hh"
|
||||
#include "local-store.hh"
|
||||
@@ -33,7 +32,7 @@ std::string escapeUri(std::string uri)
|
||||
return uri;
|
||||
}
|
||||
|
||||
static std::string currentLoad;
|
||||
static string currentLoad;
|
||||
|
||||
static AutoCloseFD openSlotLock(const Machine & m, uint64_t slot)
|
||||
{
|
||||
@@ -98,7 +97,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
}
|
||||
|
||||
std::optional<StorePath> drvPath;
|
||||
std::string storeUri;
|
||||
string storeUri;
|
||||
|
||||
while (true) {
|
||||
|
||||
@@ -184,7 +183,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
else
|
||||
{
|
||||
// build the hint template.
|
||||
std::string errorText =
|
||||
string errorText =
|
||||
"Failed to find a machine for remote build!\n"
|
||||
"derivation: %s\nrequired (system, features): (%s, %s)";
|
||||
errorText += "\n%s available machines:";
|
||||
@@ -194,7 +193,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
errorText += "\n(%s, %s, %s, %s)";
|
||||
|
||||
// add the template values.
|
||||
std::string drvstr;
|
||||
string drvstr;
|
||||
if (drvPath.has_value())
|
||||
drvstr = drvPath->to_string();
|
||||
else
|
||||
@@ -209,7 +208,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
|
||||
for (auto & m : machines)
|
||||
error
|
||||
% concatStringsSep<std::vector<std::string>>(", ", m.systemTypes)
|
||||
% concatStringsSep<vector<string>>(", ", m.systemTypes)
|
||||
% m.maxJobs
|
||||
% concatStringsSep<StringSet>(", ", m.supportedFeatures)
|
||||
% concatStringsSep<StringSet>(", ", m.mandatoryFeatures);
|
||||
@@ -300,7 +299,7 @@ connected:
|
||||
|
||||
std::set<Realisation> missingRealisations;
|
||||
StorePathSet missingPaths;
|
||||
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations) && !drv.type().hasKnownOutputPaths()) {
|
||||
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations) && !derivationHasKnownOutputPaths(drv.type())) {
|
||||
for (auto & outputName : wantedOutputs) {
|
||||
auto thisOutputHash = outputHashes.at(outputName);
|
||||
auto thisOutputId = DrvOutput{ thisOutputHash, outputName };
|
||||
|
||||
18
src/cpptoml/LICENSE
Normal file
18
src/cpptoml/LICENSE
Normal file
@@ -0,0 +1,18 @@
|
||||
Copyright (c) 2014 Chase Geigle
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
3668
src/cpptoml/cpptoml.h
Normal file
3668
src/cpptoml/cpptoml.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -54,43 +54,8 @@ void StoreCommand::run()
|
||||
run(getStore());
|
||||
}
|
||||
|
||||
CopyCommand::CopyCommand()
|
||||
{
|
||||
addFlag({
|
||||
.longName = "from",
|
||||
.description = "URL of the source Nix store.",
|
||||
.labels = {"store-uri"},
|
||||
.handler = {&srcUri},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "to",
|
||||
.description = "URL of the destination Nix store.",
|
||||
.labels = {"store-uri"},
|
||||
.handler = {&dstUri},
|
||||
});
|
||||
}
|
||||
|
||||
ref<Store> CopyCommand::createStore()
|
||||
{
|
||||
return srcUri.empty() ? StoreCommand::createStore() : openStore(srcUri);
|
||||
}
|
||||
|
||||
ref<Store> CopyCommand::getDstStore()
|
||||
{
|
||||
if (srcUri.empty() && dstUri.empty())
|
||||
throw UsageError("you must pass '--from' and/or '--to'");
|
||||
|
||||
return dstUri.empty() ? openStore() : openStore(dstUri);
|
||||
}
|
||||
|
||||
EvalCommand::EvalCommand()
|
||||
{
|
||||
addFlag({
|
||||
.longName = "debugger",
|
||||
.description = "start an interactive environment if evaluation fails",
|
||||
.handler = {&startReplOnEvalErrors, true},
|
||||
});
|
||||
}
|
||||
|
||||
EvalCommand::~EvalCommand()
|
||||
@@ -108,21 +73,8 @@ ref<Store> EvalCommand::getEvalStore()
|
||||
|
||||
ref<EvalState> EvalCommand::getEvalState()
|
||||
{
|
||||
if (!evalState) {
|
||||
evalState =
|
||||
#if HAVE_BOEHMGC
|
||||
std::allocate_shared<EvalState>(traceable_allocator<EvalState>(),
|
||||
searchPath, getEvalStore(), getStore())
|
||||
#else
|
||||
std::make_shared<EvalState>(
|
||||
searchPath, getEvalStore(), getStore())
|
||||
#endif
|
||||
;
|
||||
|
||||
if (startReplOnEvalErrors) {
|
||||
evalState->debugRepl = &runRepl;
|
||||
};
|
||||
}
|
||||
if (!evalState)
|
||||
evalState = std::make_shared<EvalState>(searchPath, getEvalStore(), getStore());
|
||||
return ref<EvalState>(evalState);
|
||||
}
|
||||
|
||||
@@ -163,7 +115,7 @@ void BuiltPathsCommand::run(ref<Store> store)
|
||||
for (auto & p : store->queryAllValidPaths())
|
||||
paths.push_back(BuiltPath::Opaque{p});
|
||||
} else {
|
||||
paths = Installable::toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables);
|
||||
paths = toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables);
|
||||
if (recursive) {
|
||||
// XXX: This only computes the store path closure, ignoring
|
||||
// intermediate realisations
|
||||
@@ -207,17 +159,16 @@ void StorePathCommand::run(ref<Store> store, std::vector<StorePath> && storePath
|
||||
run(store, *storePaths.begin());
|
||||
}
|
||||
|
||||
Strings editorFor(const Path & file, uint32_t line)
|
||||
Strings editorFor(const Pos & pos)
|
||||
{
|
||||
auto editor = getEnv("EDITOR").value_or("cat");
|
||||
auto args = tokenizeString<Strings>(editor);
|
||||
if (line > 0 && (
|
||||
if (pos.line > 0 && (
|
||||
editor.find("emacs") != std::string::npos ||
|
||||
editor.find("nano") != std::string::npos ||
|
||||
editor.find("vim") != std::string::npos ||
|
||||
editor.find("kak") != std::string::npos))
|
||||
args.push_back(fmt("+%d", line));
|
||||
args.push_back(file);
|
||||
editor.find("vim") != std::string::npos))
|
||||
args.push_back(fmt("+%d", pos.line));
|
||||
args.push_back(pos.file);
|
||||
return args;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "common-eval-args.hh"
|
||||
#include "path.hh"
|
||||
#include "flake/lockfile.hh"
|
||||
#include "store-api.hh"
|
||||
|
||||
#include <optional>
|
||||
|
||||
@@ -42,23 +43,8 @@ private:
|
||||
std::shared_ptr<Store> _store;
|
||||
};
|
||||
|
||||
/* A command that copies something between `--from` and `--to`
|
||||
stores. */
|
||||
struct CopyCommand : virtual StoreCommand
|
||||
{
|
||||
std::string srcUri, dstUri;
|
||||
|
||||
CopyCommand();
|
||||
|
||||
ref<Store> createStore() override;
|
||||
|
||||
ref<Store> getDstStore();
|
||||
};
|
||||
|
||||
struct EvalCommand : virtual StoreCommand, MixEvalArgs
|
||||
{
|
||||
bool startReplOnEvalErrors = false;
|
||||
|
||||
EvalCommand();
|
||||
|
||||
~EvalCommand();
|
||||
@@ -83,16 +69,23 @@ struct MixFlakeOptions : virtual Args, EvalCommand
|
||||
{ return {}; }
|
||||
};
|
||||
|
||||
/* How to handle derivations in commands that operate on store paths. */
|
||||
enum class OperateOn {
|
||||
/* Operate on the output path. */
|
||||
Output,
|
||||
/* Operate on the .drv path. */
|
||||
Derivation
|
||||
};
|
||||
|
||||
struct SourceExprCommand : virtual Args, MixFlakeOptions
|
||||
{
|
||||
std::optional<Path> file;
|
||||
std::optional<std::string> expr;
|
||||
bool readOnlyMode = false;
|
||||
|
||||
// FIXME: move this; not all commands (e.g. 'nix run') use it.
|
||||
OperateOn operateOn = OperateOn::Output;
|
||||
|
||||
SourceExprCommand(bool supportReadOnlyMode = false);
|
||||
SourceExprCommand();
|
||||
|
||||
std::vector<std::shared_ptr<Installable>> parseInstallables(
|
||||
ref<Store> store, std::vector<std::string> ss);
|
||||
@@ -107,6 +100,19 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions
|
||||
void completeInstallable(std::string_view prefix);
|
||||
};
|
||||
|
||||
enum class Realise {
|
||||
/* Build the derivation. Postcondition: the
|
||||
derivation outputs exist. */
|
||||
Outputs,
|
||||
/* Don't build the derivation. Postcondition: the store derivation
|
||||
exists. */
|
||||
Derivation,
|
||||
/* Evaluate in dry-run mode. Postcondition: nothing. */
|
||||
// FIXME: currently unused, but could be revived if we can
|
||||
// evaluate derivations in-memory.
|
||||
Nothing
|
||||
};
|
||||
|
||||
/* A command that operates on a list of "installables", which can be
|
||||
store paths, attribute paths, Nix expressions, etc. */
|
||||
struct InstallablesCommand : virtual Args, SourceExprCommand
|
||||
@@ -131,13 +137,13 @@ struct InstallableCommand : virtual Args, SourceExprCommand
|
||||
{
|
||||
std::shared_ptr<Installable> installable;
|
||||
|
||||
InstallableCommand(bool supportReadOnlyMode = false);
|
||||
InstallableCommand();
|
||||
|
||||
void prepare() override;
|
||||
|
||||
std::optional<FlakeRef> getFlakeRefForCompletion() override
|
||||
{
|
||||
return parseFlakeRefWithFragment(_installable, absPath(".")).first;
|
||||
return parseFlakeRef(_installable, absPath("."));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -219,9 +225,41 @@ static RegisterCommand registerCommand2(std::vector<std::string> && name)
|
||||
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
|
||||
}
|
||||
|
||||
BuiltPaths build(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store, Realise mode,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||
BuildMode bMode = bmNormal);
|
||||
|
||||
std::set<StorePath> toStorePaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables);
|
||||
|
||||
StorePath toStorePath(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
std::shared_ptr<Installable> installable);
|
||||
|
||||
std::set<StorePath> toDerivations(
|
||||
ref<Store> store,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||
bool useDeriver = false);
|
||||
|
||||
BuiltPaths toBuiltPaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables);
|
||||
|
||||
/* Helper function to generate args that invoke $EDITOR on
|
||||
filename:lineno. */
|
||||
Strings editorFor(const Path & file, uint32_t line);
|
||||
Strings editorFor(const Pos & pos);
|
||||
|
||||
struct MixProfile : virtual StoreCommand
|
||||
{
|
||||
@@ -272,8 +310,4 @@ void printClosureDiff(
|
||||
const StorePath & afterPath,
|
||||
std::string_view indent);
|
||||
|
||||
|
||||
void runRepl(
|
||||
ref<EvalState> evalState,
|
||||
const ValMap & extraEnv);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include "globals.hh"
|
||||
#include "installables.hh"
|
||||
#include "util.hh"
|
||||
#include "command.hh"
|
||||
#include "attr-path.hh"
|
||||
#include "common-eval-args.hh"
|
||||
@@ -14,7 +12,6 @@
|
||||
#include "eval-cache.hh"
|
||||
#include "url.hh"
|
||||
#include "registry.hh"
|
||||
#include "build-result.hh"
|
||||
|
||||
#include <regex>
|
||||
#include <queue>
|
||||
@@ -100,15 +97,7 @@ MixFlakeOptions::MixFlakeOptions()
|
||||
lockFlags.writeLockFile = false;
|
||||
lockFlags.inputOverrides.insert_or_assign(
|
||||
flake::parseInputPath(inputPath),
|
||||
parseFlakeRef(flakeRef, absPath("."), true));
|
||||
}},
|
||||
.completer = {[&](size_t n, std::string_view prefix) {
|
||||
if (n == 0) {
|
||||
if (auto flakeRef = getFlakeRefForCompletion())
|
||||
completeFlakeInputPath(getEvalState(), *flakeRef, prefix);
|
||||
} else if (n == 1) {
|
||||
completeFlakeRef(getEvalState()->store, prefix);
|
||||
}
|
||||
parseFlakeRef(flakeRef, absPath(".")));
|
||||
}}
|
||||
});
|
||||
|
||||
@@ -139,14 +128,12 @@ MixFlakeOptions::MixFlakeOptions()
|
||||
});
|
||||
}
|
||||
|
||||
SourceExprCommand::SourceExprCommand(bool supportReadOnlyMode)
|
||||
SourceExprCommand::SourceExprCommand()
|
||||
{
|
||||
addFlag({
|
||||
.longName = "file",
|
||||
.shortName = 'f',
|
||||
.description =
|
||||
"Interpret installables as attribute paths relative to the Nix expression stored in *file*. "
|
||||
"If *file* is the character -, then a Nix expression will be read from standard input.",
|
||||
.description = "Interpret installables as attribute paths relative to the Nix expression stored in *file*.",
|
||||
.category = installablesCategory,
|
||||
.labels = {"file"},
|
||||
.handler = {&file},
|
||||
@@ -167,25 +154,11 @@ SourceExprCommand::SourceExprCommand(bool supportReadOnlyMode)
|
||||
.category = installablesCategory,
|
||||
.handler = {&operateOn, OperateOn::Derivation},
|
||||
});
|
||||
|
||||
if (supportReadOnlyMode) {
|
||||
addFlag({
|
||||
.longName = "read-only",
|
||||
.description =
|
||||
"Do not instantiate each evaluated derivation. "
|
||||
"This improves performance, but can cause errors when accessing "
|
||||
"store paths of derivations during evaluation.",
|
||||
.handler = {&readOnlyMode, true},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Strings SourceExprCommand::getDefaultFlakeAttrPaths()
|
||||
{
|
||||
return {
|
||||
"packages." + settings.thisSystem.get() + ".default",
|
||||
"defaultPackage." + settings.thisSystem.get()
|
||||
};
|
||||
return {"defaultPackage." + settings.thisSystem.get()};
|
||||
}
|
||||
|
||||
Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
|
||||
@@ -203,8 +176,6 @@ Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
|
||||
void SourceExprCommand::completeInstallable(std::string_view prefix)
|
||||
{
|
||||
if (file) {
|
||||
completionType = ctAttrs;
|
||||
|
||||
evalSettings.pureEval = false;
|
||||
auto state = getEvalState();
|
||||
Expr *e = state->parseExprFromFile(
|
||||
@@ -220,27 +191,23 @@ void SourceExprCommand::completeInstallable(std::string_view prefix)
|
||||
auto sep = prefix_.rfind('.');
|
||||
std::string searchWord;
|
||||
if (sep != std::string::npos) {
|
||||
searchWord = prefix_.substr(sep + 1, std::string::npos);
|
||||
searchWord = prefix_.substr(sep, std::string::npos);
|
||||
prefix_ = prefix_.substr(0, sep);
|
||||
} else {
|
||||
searchWord = prefix_;
|
||||
prefix_ = "";
|
||||
}
|
||||
|
||||
auto [v, pos] = findAlongAttrPath(*state, prefix_, *autoArgs, root);
|
||||
Value &v1(*v);
|
||||
state->forceValue(v1, pos);
|
||||
Value &v1(*findAlongAttrPath(*state, prefix_, *autoArgs, root).first);
|
||||
state->forceValue(v1);
|
||||
Value v2;
|
||||
state->autoCallFunction(*autoArgs, v1, v2);
|
||||
|
||||
if (v2.type() == nAttrs) {
|
||||
for (auto & i : *v2.attrs) {
|
||||
std::string name = state->symbols[i.name];
|
||||
std::string name = i.name;
|
||||
if (name.find(searchWord) == 0) {
|
||||
if (prefix_ == "")
|
||||
completions->add(name);
|
||||
else
|
||||
completions->add(prefix_ + "." + name);
|
||||
completions->add(i.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,14 +232,11 @@ void completeFlakeRefWithFragment(
|
||||
prefix. */
|
||||
try {
|
||||
auto hash = prefix.find('#');
|
||||
if (hash == std::string::npos) {
|
||||
completeFlakeRef(evalState->store, prefix);
|
||||
} else {
|
||||
completionType = ctAttrs;
|
||||
|
||||
if (hash != std::string::npos) {
|
||||
auto fragment = prefix.substr(hash + 1);
|
||||
auto flakeRefS = std::string(prefix.substr(0, hash));
|
||||
auto flakeRef = parseFlakeRef(expandTilde(flakeRefS), absPath("."));
|
||||
// FIXME: do tilde expansion.
|
||||
auto flakeRef = parseFlakeRef(flakeRefS, absPath("."));
|
||||
|
||||
auto evalCache = openEvalCache(*evalState,
|
||||
std::make_shared<flake::LockedFlake>(lockFlake(*evalState, flakeRef, lockFlags)));
|
||||
@@ -291,19 +255,19 @@ void completeFlakeRefWithFragment(
|
||||
|
||||
std::string lastAttr;
|
||||
if (!attrPath.empty() && !hasSuffix(attrPathS, ".")) {
|
||||
lastAttr = evalState->symbols[attrPath.back()];
|
||||
lastAttr = attrPath.back();
|
||||
attrPath.pop_back();
|
||||
}
|
||||
|
||||
auto attr = root->findAlongAttrPath(attrPath);
|
||||
if (!attr) continue;
|
||||
|
||||
for (auto & attr2 : (*attr)->getAttrs()) {
|
||||
if (hasPrefix(evalState->symbols[attr2], lastAttr)) {
|
||||
auto attrPath2 = (*attr)->getAttrPath(attr2);
|
||||
for (auto & attr2 : attr->getAttrs()) {
|
||||
if (hasPrefix(attr2, lastAttr)) {
|
||||
auto attrPath2 = attr->getAttrPath(attr2);
|
||||
/* Strip the attrpath prefix. */
|
||||
attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size());
|
||||
completions->add(flakeRefS + "#" + concatStringsSep(".", evalState->symbols.resolve(attrPath2)));
|
||||
completions->add(flakeRefS + "#" + concatStringsSep(".", attrPath2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -321,13 +285,12 @@ void completeFlakeRefWithFragment(
|
||||
} catch (Error & e) {
|
||||
warn(e.msg());
|
||||
}
|
||||
|
||||
completeFlakeRef(evalState->store, prefix);
|
||||
}
|
||||
|
||||
void completeFlakeRef(ref<Store> store, std::string_view prefix)
|
||||
{
|
||||
if (!settings.isExperimentalFeatureEnabled(Xp::Flakes))
|
||||
return;
|
||||
|
||||
if (prefix == "")
|
||||
completions->add(".");
|
||||
|
||||
@@ -357,16 +320,16 @@ DerivedPath Installable::toDerivedPath()
|
||||
return std::move(buildables[0]);
|
||||
}
|
||||
|
||||
std::vector<ref<eval_cache::AttrCursor>>
|
||||
std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>>
|
||||
Installable::getCursors(EvalState & state)
|
||||
{
|
||||
auto evalCache =
|
||||
std::make_shared<nix::eval_cache::EvalCache>(std::nullopt, state,
|
||||
[&]() { return toValue(state).first; });
|
||||
return {evalCache->getRoot()};
|
||||
return {{evalCache->getRoot(), ""}};
|
||||
}
|
||||
|
||||
ref<eval_cache::AttrCursor>
|
||||
std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>
|
||||
Installable::getCursor(EvalState & state)
|
||||
{
|
||||
auto cursors = getCursors(state);
|
||||
@@ -375,18 +338,6 @@ Installable::getCursor(EvalState & state)
|
||||
return cursors[0];
|
||||
}
|
||||
|
||||
static StorePath getDeriver(
|
||||
ref<Store> store,
|
||||
const Installable & i,
|
||||
const StorePath & drvPath)
|
||||
{
|
||||
auto derivers = store->queryValidDerivers(drvPath);
|
||||
if (derivers.empty())
|
||||
throw Error("'%s' does not have a known deriver", i.what());
|
||||
// FIXME: use all derivers?
|
||||
return *derivers.begin();
|
||||
}
|
||||
|
||||
struct InstallableStorePath : Installable
|
||||
{
|
||||
ref<Store> store;
|
||||
@@ -395,7 +346,7 @@ struct InstallableStorePath : Installable
|
||||
InstallableStorePath(ref<Store> store, StorePath && storePath)
|
||||
: store(store), storePath(std::move(storePath)) { }
|
||||
|
||||
std::string what() const override { return store->printStorePath(storePath); }
|
||||
std::string what() override { return store->printStorePath(storePath); }
|
||||
|
||||
DerivedPaths toDerivedPaths() override
|
||||
{
|
||||
@@ -416,15 +367,6 @@ struct InstallableStorePath : Installable
|
||||
}
|
||||
}
|
||||
|
||||
StorePathSet toDrvPaths(ref<Store> store) override
|
||||
{
|
||||
if (storePath.isDerivation()) {
|
||||
return {storePath};
|
||||
} else {
|
||||
return {getDeriver(store, *this, storePath)};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<StorePath> getStorePath() override
|
||||
{
|
||||
return storePath;
|
||||
@@ -440,8 +382,10 @@ DerivedPaths InstallableValue::toDerivedPaths()
|
||||
|
||||
// Group by derivation, helps with .all in particular
|
||||
for (auto & drv : toDerivations()) {
|
||||
for (auto & outputName : drv.outputsToInstall)
|
||||
drvsToOutputs[drv.drvPath].insert(outputName);
|
||||
auto outputName = drv.outputName;
|
||||
if (outputName == "")
|
||||
throw Error("derivation '%s' lacks an 'outputName' attribute", state->store->printStorePath(drv.drvPath));
|
||||
drvsToOutputs[drv.drvPath].insert(outputName);
|
||||
drvsToCopy.insert(drv.drvPath);
|
||||
}
|
||||
|
||||
@@ -451,40 +395,22 @@ DerivedPaths InstallableValue::toDerivedPaths()
|
||||
return res;
|
||||
}
|
||||
|
||||
StorePathSet InstallableValue::toDrvPaths(ref<Store> store)
|
||||
{
|
||||
StorePathSet res;
|
||||
for (auto & drv : toDerivations())
|
||||
res.insert(drv.drvPath);
|
||||
return res;
|
||||
}
|
||||
|
||||
struct InstallableAttrPath : InstallableValue
|
||||
{
|
||||
SourceExprCommand & cmd;
|
||||
RootValue v;
|
||||
std::string attrPath;
|
||||
OutputsSpec outputsSpec;
|
||||
|
||||
InstallableAttrPath(
|
||||
ref<EvalState> state,
|
||||
SourceExprCommand & cmd,
|
||||
Value * v,
|
||||
const std::string & attrPath,
|
||||
OutputsSpec outputsSpec)
|
||||
: InstallableValue(state)
|
||||
, cmd(cmd)
|
||||
, v(allocRootValue(v))
|
||||
, attrPath(attrPath)
|
||||
, outputsSpec(std::move(outputsSpec))
|
||||
InstallableAttrPath(ref<EvalState> state, SourceExprCommand & cmd, Value * v, const std::string & attrPath)
|
||||
: InstallableValue(state), cmd(cmd), v(allocRootValue(v)), attrPath(attrPath)
|
||||
{ }
|
||||
|
||||
std::string what() const override { return attrPath; }
|
||||
std::string what() override { return attrPath; }
|
||||
|
||||
std::pair<Value *, PosIdx> toValue(EvalState & state) override
|
||||
std::pair<Value *, Pos> toValue(EvalState & state) override
|
||||
{
|
||||
auto [vRes, pos] = findAlongAttrPath(state, attrPath, *cmd.getAutoArgs(state), **v);
|
||||
state.forceValue(*vRes, pos);
|
||||
state.forceValue(*vRes);
|
||||
return {vRes, pos};
|
||||
}
|
||||
|
||||
@@ -502,21 +428,10 @@ std::vector<InstallableValue::DerivationInfo> InstallableAttrPath::toDerivations
|
||||
|
||||
std::vector<DerivationInfo> res;
|
||||
for (auto & drvInfo : drvInfos) {
|
||||
auto drvPath = drvInfo.queryDrvPath();
|
||||
if (!drvPath)
|
||||
throw Error("'%s' is not a derivation", what());
|
||||
|
||||
std::set<std::string> outputsToInstall;
|
||||
|
||||
if (auto outputNames = std::get_if<OutputNames>(&outputsSpec))
|
||||
outputsToInstall = *outputNames;
|
||||
else
|
||||
for (auto & output : drvInfo.queryOutputs(false, std::get_if<DefaultOutputs>(&outputsSpec)))
|
||||
outputsToInstall.insert(output.first);
|
||||
|
||||
res.push_back(DerivationInfo {
|
||||
.drvPath = *drvPath,
|
||||
.outputsToInstall = std::move(outputsToInstall)
|
||||
res.push_back({
|
||||
state->store->parseStorePath(drvInfo.queryDrvPath()),
|
||||
state->store->maybeParseStorePath(drvInfo.queryOutPath()),
|
||||
drvInfo.queryOutputName()
|
||||
});
|
||||
}
|
||||
|
||||
@@ -545,7 +460,7 @@ Value * InstallableFlake::getFlakeOutputs(EvalState & state, const flake::Locked
|
||||
auto aOutputs = vFlake->attrs->get(state.symbols.create("outputs"));
|
||||
assert(aOutputs);
|
||||
|
||||
state.forceValue(*aOutputs->value, [&]() { return aOutputs->value->determinePos(noPos); });
|
||||
state.forceValue(*aOutputs->value);
|
||||
|
||||
return aOutputs->value;
|
||||
}
|
||||
@@ -570,7 +485,7 @@ ref<eval_cache::EvalCache> openEvalCache(
|
||||
auto vFlake = state.allocValue();
|
||||
flake::callFlake(state, *lockedFlake, *vFlake);
|
||||
|
||||
state.forceAttrs(*vFlake, noPos);
|
||||
state.forceAttrs(*vFlake);
|
||||
|
||||
auto aOutputs = vFlake->attrs->get(state.symbols.create("outputs"));
|
||||
assert(aOutputs);
|
||||
@@ -593,16 +508,13 @@ InstallableFlake::InstallableFlake(
|
||||
SourceExprCommand * cmd,
|
||||
ref<EvalState> state,
|
||||
FlakeRef && flakeRef,
|
||||
std::string_view fragment,
|
||||
OutputsSpec outputsSpec,
|
||||
Strings attrPaths,
|
||||
Strings prefixes,
|
||||
Strings && attrPaths,
|
||||
Strings && prefixes,
|
||||
const flake::LockFlags & lockFlags)
|
||||
: InstallableValue(state),
|
||||
flakeRef(flakeRef),
|
||||
attrPaths(fragment == "" ? attrPaths : Strings{(std::string) fragment}),
|
||||
prefixes(fragment == "" ? Strings{} : prefixes),
|
||||
outputsSpec(std::move(outputsSpec)),
|
||||
attrPaths(attrPaths),
|
||||
prefixes(prefixes),
|
||||
lockFlags(lockFlags)
|
||||
{
|
||||
if (cmd && cmd->getAutoArgs(*state)->size())
|
||||
@@ -611,53 +523,35 @@ InstallableFlake::InstallableFlake(
|
||||
|
||||
std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableFlake::toDerivation()
|
||||
{
|
||||
auto attr = getCursor(*state);
|
||||
auto lockedFlake = getLockedFlake();
|
||||
|
||||
auto attrPath = attr->getAttrPathStr();
|
||||
auto cache = openEvalCache(*state, lockedFlake);
|
||||
auto root = cache->getRoot();
|
||||
|
||||
if (!attr->isDerivation())
|
||||
throw Error("flake output attribute '%s' is not a derivation", attrPath);
|
||||
for (auto & attrPath : getActualAttrPaths()) {
|
||||
auto attr = root->findAlongAttrPath(
|
||||
parseAttrPath(*state, attrPath),
|
||||
true
|
||||
);
|
||||
|
||||
auto drvPath = attr->forceDerivation();
|
||||
if (!attr) continue;
|
||||
|
||||
std::set<std::string> outputsToInstall;
|
||||
std::optional<NixInt> priority;
|
||||
if (!attr->isDerivation())
|
||||
throw Error("flake output attribute '%s' is not a derivation", attrPath);
|
||||
|
||||
if (auto aOutputSpecified = attr->maybeGetAttr(state->sOutputSpecified)) {
|
||||
if (aOutputSpecified->getBool()) {
|
||||
if (auto aOutputName = attr->maybeGetAttr("outputName"))
|
||||
outputsToInstall = { aOutputName->getString() };
|
||||
}
|
||||
auto drvPath = attr->forceDerivation();
|
||||
|
||||
auto drvInfo = DerivationInfo{
|
||||
std::move(drvPath),
|
||||
state->store->maybeParseStorePath(attr->getAttr(state->sOutPath)->getString()),
|
||||
attr->getAttr(state->sOutputName)->getString()
|
||||
};
|
||||
|
||||
return {attrPath, lockedFlake->flake.lockedRef, std::move(drvInfo)};
|
||||
}
|
||||
|
||||
else if (auto aMeta = attr->maybeGetAttr(state->sMeta)) {
|
||||
if (auto aOutputsToInstall = aMeta->maybeGetAttr("outputsToInstall"))
|
||||
for (auto & s : aOutputsToInstall->getListOfStrings())
|
||||
outputsToInstall.insert(s);
|
||||
if (auto aPriority = aMeta->maybeGetAttr("priority"))
|
||||
priority = aPriority->getInt();
|
||||
}
|
||||
|
||||
if (outputsToInstall.empty() || std::get_if<AllOutputs>(&outputsSpec)) {
|
||||
outputsToInstall.clear();
|
||||
if (auto aOutputs = attr->maybeGetAttr(state->sOutputs))
|
||||
for (auto & s : aOutputs->getListOfStrings())
|
||||
outputsToInstall.insert(s);
|
||||
}
|
||||
|
||||
if (outputsToInstall.empty())
|
||||
outputsToInstall.insert("out");
|
||||
|
||||
if (auto outputNames = std::get_if<OutputNames>(&outputsSpec))
|
||||
outputsToInstall = *outputNames;
|
||||
|
||||
auto drvInfo = DerivationInfo {
|
||||
.drvPath = std::move(drvPath),
|
||||
.outputsToInstall = std::move(outputsToInstall),
|
||||
.priority = priority,
|
||||
};
|
||||
|
||||
return {attrPath, getLockedFlake()->flake.lockedRef, std::move(drvInfo)};
|
||||
throw Error("flake '%s' does not provide attribute %s",
|
||||
flakeRef, showAttrPaths(getActualAttrPaths()));
|
||||
}
|
||||
|
||||
std::vector<InstallableValue::DerivationInfo> InstallableFlake::toDerivations()
|
||||
@@ -667,12 +561,28 @@ std::vector<InstallableValue::DerivationInfo> InstallableFlake::toDerivations()
|
||||
return res;
|
||||
}
|
||||
|
||||
std::pair<Value *, PosIdx> InstallableFlake::toValue(EvalState & state)
|
||||
std::pair<Value *, Pos> InstallableFlake::toValue(EvalState & state)
|
||||
{
|
||||
return {&getCursor(state)->forceValue(), noPos};
|
||||
auto lockedFlake = getLockedFlake();
|
||||
|
||||
auto vOutputs = getFlakeOutputs(state, *lockedFlake);
|
||||
|
||||
auto emptyArgs = state.allocBindings(0);
|
||||
|
||||
for (auto & attrPath : getActualAttrPaths()) {
|
||||
try {
|
||||
auto [v, pos] = findAlongAttrPath(state, attrPath, *emptyArgs, *vOutputs);
|
||||
state.forceValue(*v);
|
||||
return {v, pos};
|
||||
} catch (AttrPathNotFound & e) {
|
||||
}
|
||||
}
|
||||
|
||||
throw Error("flake '%s' does not provide attribute %s",
|
||||
flakeRef, showAttrPaths(getActualAttrPaths()));
|
||||
}
|
||||
|
||||
std::vector<ref<eval_cache::AttrCursor>>
|
||||
std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>>
|
||||
InstallableFlake::getCursors(EvalState & state)
|
||||
{
|
||||
auto evalCache = openEvalCache(state,
|
||||
@@ -680,55 +590,21 @@ InstallableFlake::getCursors(EvalState & state)
|
||||
|
||||
auto root = evalCache->getRoot();
|
||||
|
||||
std::vector<ref<eval_cache::AttrCursor>> res;
|
||||
std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>> res;
|
||||
|
||||
for (auto & attrPath : getActualAttrPaths()) {
|
||||
auto attr = root->findAlongAttrPath(parseAttrPath(state, attrPath));
|
||||
if (attr) res.push_back(ref(*attr));
|
||||
if (attr) res.push_back({attr, attrPath});
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ref<eval_cache::AttrCursor> InstallableFlake::getCursor(EvalState & state)
|
||||
{
|
||||
auto lockedFlake = getLockedFlake();
|
||||
|
||||
auto cache = openEvalCache(state, lockedFlake);
|
||||
auto root = cache->getRoot();
|
||||
|
||||
Suggestions suggestions;
|
||||
|
||||
auto attrPaths = getActualAttrPaths();
|
||||
|
||||
for (auto & attrPath : attrPaths) {
|
||||
debug("trying flake output attribute '%s'", attrPath);
|
||||
|
||||
auto attrOrSuggestions = root->findAlongAttrPath(
|
||||
parseAttrPath(state, attrPath),
|
||||
true
|
||||
);
|
||||
|
||||
if (!attrOrSuggestions) {
|
||||
suggestions += attrOrSuggestions.getSuggestions();
|
||||
continue;
|
||||
}
|
||||
|
||||
return *attrOrSuggestions;
|
||||
}
|
||||
|
||||
throw Error(
|
||||
suggestions,
|
||||
"flake '%s' does not provide attribute %s",
|
||||
flakeRef,
|
||||
showAttrPaths(attrPaths));
|
||||
}
|
||||
|
||||
std::shared_ptr<flake::LockedFlake> InstallableFlake::getLockedFlake() const
|
||||
{
|
||||
flake::LockFlags lockFlagsApplyConfig = lockFlags;
|
||||
lockFlagsApplyConfig.applyNixConfig = true;
|
||||
if (!_lockedFlake) {
|
||||
flake::LockFlags lockFlagsApplyConfig = lockFlags;
|
||||
lockFlagsApplyConfig.applyNixConfig = true;
|
||||
_lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(*state, flakeRef, lockFlagsApplyConfig));
|
||||
}
|
||||
return _lockedFlake;
|
||||
@@ -753,10 +629,6 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
||||
{
|
||||
std::vector<std::shared_ptr<Installable>> result;
|
||||
|
||||
if (readOnlyMode) {
|
||||
settings.readOnlyMode = true;
|
||||
}
|
||||
|
||||
if (file || expr) {
|
||||
if (file && expr)
|
||||
throw UsageError("'--file' and '--expr' are exclusive");
|
||||
@@ -767,24 +639,15 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
||||
auto state = getEvalState();
|
||||
auto vFile = state->allocValue();
|
||||
|
||||
if (file == "-") {
|
||||
auto e = state->parseStdin();
|
||||
state->eval(e, *vFile);
|
||||
} else if (file)
|
||||
if (file)
|
||||
state->evalFile(lookupFileArg(*state, *file), *vFile);
|
||||
else {
|
||||
auto e = state->parseExprFromString(*expr, absPath("."));
|
||||
state->eval(e, *vFile);
|
||||
}
|
||||
|
||||
for (auto & s : ss) {
|
||||
auto [prefix, outputsSpec] = parseOutputsSpec(s);
|
||||
result.push_back(
|
||||
std::make_shared<InstallableAttrPath>(
|
||||
state, *this, vFile,
|
||||
prefix == "." ? "" : prefix,
|
||||
outputsSpec));
|
||||
}
|
||||
for (auto & s : ss)
|
||||
result.push_back(std::make_shared<InstallableAttrPath>(state, *this, vFile, s == "." ? "" : s));
|
||||
|
||||
} else {
|
||||
|
||||
@@ -803,14 +666,12 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
||||
}
|
||||
|
||||
try {
|
||||
auto [flakeRef, fragment, outputsSpec] = parseFlakeRefWithFragmentAndOutputsSpec(s, absPath("."));
|
||||
auto [flakeRef, fragment] = parseFlakeRefWithFragment(s, absPath("."));
|
||||
result.push_back(std::make_shared<InstallableFlake>(
|
||||
this,
|
||||
getEvalState(),
|
||||
std::move(flakeRef),
|
||||
fragment,
|
||||
outputsSpec,
|
||||
getDefaultFlakeAttrPaths(),
|
||||
fragment == "" ? getDefaultFlakeAttrPaths() : Strings{fragment},
|
||||
getDefaultFlakeAttrPathPrefixes(),
|
||||
lockFlags));
|
||||
continue;
|
||||
@@ -833,20 +694,56 @@ std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
|
||||
return installables.front();
|
||||
}
|
||||
|
||||
BuiltPaths Installable::build(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||
BuildMode bMode)
|
||||
BuiltPaths getBuiltPaths(ref<Store> evalStore, ref<Store> store, const DerivedPaths & hopefullyBuiltPaths)
|
||||
{
|
||||
BuiltPaths res;
|
||||
for (auto & [_, builtPath] : build2(evalStore, store, mode, installables, bMode))
|
||||
res.push_back(builtPath);
|
||||
for (const auto & b : hopefullyBuiltPaths)
|
||||
std::visit(
|
||||
overloaded{
|
||||
[&](const DerivedPath::Opaque & bo) {
|
||||
res.push_back(BuiltPath::Opaque{bo.path});
|
||||
},
|
||||
[&](const DerivedPath::Built & bfd) {
|
||||
OutputPathMap outputs;
|
||||
auto drv = evalStore->readDerivation(bfd.drvPath);
|
||||
auto outputHashes = staticOutputHashes(*evalStore, drv); // FIXME: expensive
|
||||
auto drvOutputs = drv.outputsAndOptPaths(*store);
|
||||
for (auto & output : bfd.outputs) {
|
||||
if (!outputHashes.count(output))
|
||||
throw Error(
|
||||
"the derivation '%s' doesn't have an output named '%s'",
|
||||
store->printStorePath(bfd.drvPath), output);
|
||||
if (settings.isExperimentalFeatureEnabled(
|
||||
Xp::CaDerivations)) {
|
||||
auto outputId =
|
||||
DrvOutput{outputHashes.at(output), output};
|
||||
auto realisation =
|
||||
store->queryRealisation(outputId);
|
||||
if (!realisation)
|
||||
throw Error(
|
||||
"cannot operate on an output of unbuilt "
|
||||
"content-addressed derivation '%s'",
|
||||
outputId.to_string());
|
||||
outputs.insert_or_assign(
|
||||
output, realisation->outPath);
|
||||
} else {
|
||||
// If ca-derivations isn't enabled, assume that
|
||||
// the output path is statically known.
|
||||
assert(drvOutputs.count(output));
|
||||
assert(drvOutputs.at(output).second);
|
||||
outputs.insert_or_assign(
|
||||
output, *drvOutputs.at(output).second);
|
||||
}
|
||||
}
|
||||
res.push_back(BuiltPath::Built{bfd.drvPath, outputs});
|
||||
},
|
||||
},
|
||||
b.raw());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::build2(
|
||||
BuiltPaths build(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
@@ -857,98 +754,21 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::bui
|
||||
settings.readOnlyMode = true;
|
||||
|
||||
std::vector<DerivedPath> pathsToBuild;
|
||||
std::map<DerivedPath, std::vector<std::shared_ptr<Installable>>> backmap;
|
||||
|
||||
for (auto & i : installables) {
|
||||
for (auto b : i->toDerivedPaths()) {
|
||||
pathsToBuild.push_back(b);
|
||||
backmap[b].push_back(i);
|
||||
}
|
||||
auto b = i->toDerivedPaths();
|
||||
pathsToBuild.insert(pathsToBuild.end(), b.begin(), b.end());
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> res;
|
||||
|
||||
switch (mode) {
|
||||
|
||||
case Realise::Nothing:
|
||||
case Realise::Derivation:
|
||||
if (mode == Realise::Nothing || mode == Realise::Derivation)
|
||||
printMissing(store, pathsToBuild, lvlError);
|
||||
else if (mode == Realise::Outputs)
|
||||
store->buildPaths(pathsToBuild, bMode, evalStore);
|
||||
|
||||
for (auto & path : pathsToBuild) {
|
||||
for (auto & installable : backmap[path]) {
|
||||
std::visit(overloaded {
|
||||
[&](const DerivedPath::Built & bfd) {
|
||||
OutputPathMap outputs;
|
||||
auto drv = evalStore->readDerivation(bfd.drvPath);
|
||||
auto outputHashes = staticOutputHashes(*evalStore, drv); // FIXME: expensive
|
||||
auto drvOutputs = drv.outputsAndOptPaths(*store);
|
||||
for (auto & output : bfd.outputs) {
|
||||
auto outputHash = get(outputHashes, output);
|
||||
if (!outputHash)
|
||||
throw Error(
|
||||
"the derivation '%s' doesn't have an output named '%s'",
|
||||
store->printStorePath(bfd.drvPath), output);
|
||||
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
|
||||
DrvOutput outputId { *outputHash, output };
|
||||
auto realisation = store->queryRealisation(outputId);
|
||||
if (!realisation)
|
||||
throw Error(
|
||||
"cannot operate on an output of the "
|
||||
"unbuilt derivation '%s'",
|
||||
outputId.to_string());
|
||||
outputs.insert_or_assign(output, realisation->outPath);
|
||||
} else {
|
||||
// If ca-derivations isn't enabled, assume that
|
||||
// the output path is statically known.
|
||||
auto drvOutput = get(drvOutputs, output);
|
||||
assert(drvOutput);
|
||||
assert(drvOutput->second);
|
||||
outputs.insert_or_assign(
|
||||
output, *drvOutput->second);
|
||||
}
|
||||
}
|
||||
res.push_back({installable, BuiltPath::Built { bfd.drvPath, outputs }});
|
||||
},
|
||||
[&](const DerivedPath::Opaque & bo) {
|
||||
res.push_back({installable, BuiltPath::Opaque { bo.path }});
|
||||
},
|
||||
}, path.raw());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Realise::Outputs: {
|
||||
for (auto & buildResult : store->buildPathsWithResults(pathsToBuild, bMode, evalStore)) {
|
||||
if (!buildResult.success())
|
||||
buildResult.rethrow();
|
||||
|
||||
for (auto & installable : backmap[buildResult.path]) {
|
||||
std::visit(overloaded {
|
||||
[&](const DerivedPath::Built & bfd) {
|
||||
std::map<std::string, StorePath> outputs;
|
||||
for (auto & path : buildResult.builtOutputs)
|
||||
outputs.emplace(path.first.outputName, path.second.outPath);
|
||||
res.push_back({installable, BuiltPath::Built { bfd.drvPath, outputs }});
|
||||
},
|
||||
[&](const DerivedPath::Opaque & bo) {
|
||||
res.push_back({installable, BuiltPath::Opaque { bo.path }});
|
||||
},
|
||||
}, buildResult.path.raw());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return res;
|
||||
return getBuiltPaths(evalStore, store, pathsToBuild);
|
||||
}
|
||||
|
||||
BuiltPaths Installable::toBuiltPaths(
|
||||
BuiltPaths toBuiltPaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
@@ -956,19 +776,19 @@ BuiltPaths Installable::toBuiltPaths(
|
||||
const std::vector<std::shared_ptr<Installable>> & installables)
|
||||
{
|
||||
if (operateOn == OperateOn::Output)
|
||||
return Installable::build(evalStore, store, mode, installables);
|
||||
return build(evalStore, store, mode, installables);
|
||||
else {
|
||||
if (mode == Realise::Nothing)
|
||||
settings.readOnlyMode = true;
|
||||
|
||||
BuiltPaths res;
|
||||
for (auto & drvPath : Installable::toDerivations(store, installables, true))
|
||||
for (auto & drvPath : toDerivations(store, installables, true))
|
||||
res.push_back(BuiltPath::Opaque{drvPath});
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
StorePathSet Installable::toStorePaths(
|
||||
StorePathSet toStorePaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
@@ -982,7 +802,7 @@ StorePathSet Installable::toStorePaths(
|
||||
return outPaths;
|
||||
}
|
||||
|
||||
StorePath Installable::toStorePath(
|
||||
StorePath toStorePath(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
@@ -996,7 +816,7 @@ StorePath Installable::toStorePath(
|
||||
return *paths.begin();
|
||||
}
|
||||
|
||||
StorePathSet Installable::toDerivations(
|
||||
StorePathSet toDerivations(
|
||||
ref<Store> store,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||
bool useDeriver)
|
||||
@@ -1009,7 +829,11 @@ StorePathSet Installable::toDerivations(
|
||||
[&](const DerivedPath::Opaque & bo) {
|
||||
if (!useDeriver)
|
||||
throw Error("argument '%s' did not evaluate to a derivation", i->what());
|
||||
drvPaths.insert(getDeriver(store, *i, bo.path));
|
||||
auto derivers = store->queryValidDerivers(bo.path);
|
||||
if (derivers.empty())
|
||||
throw Error("'%s' does not have a known deriver", i->what());
|
||||
// FIXME: use all derivers?
|
||||
drvPaths.insert(*derivers.begin());
|
||||
},
|
||||
[&](const DerivedPath::Built & bfd) {
|
||||
drvPaths.insert(bfd.drvPath);
|
||||
@@ -1033,7 +857,7 @@ InstallablesCommand::InstallablesCommand()
|
||||
void InstallablesCommand::prepare()
|
||||
{
|
||||
if (_installables.empty() && useDefaultInstallables())
|
||||
// FIXME: commands like "nix profile install" should not have a
|
||||
// FIXME: commands like "nix install" should not have a
|
||||
// default, probably.
|
||||
_installables.push_back(".");
|
||||
installables = parseInstallables(getStore(), _installables);
|
||||
@@ -1043,14 +867,13 @@ std::optional<FlakeRef> InstallablesCommand::getFlakeRefForCompletion()
|
||||
{
|
||||
if (_installables.empty()) {
|
||||
if (useDefaultInstallables())
|
||||
return parseFlakeRefWithFragment(".", absPath(".")).first;
|
||||
return parseFlakeRef(".", absPath("."));
|
||||
return {};
|
||||
}
|
||||
return parseFlakeRefWithFragment(_installables.front(), absPath(".")).first;
|
||||
return parseFlakeRef(_installables.front(), absPath("."));
|
||||
}
|
||||
|
||||
InstallableCommand::InstallableCommand(bool supportReadOnlyMode)
|
||||
: SourceExprCommand(supportReadOnlyMode)
|
||||
InstallableCommand::InstallableCommand()
|
||||
{
|
||||
expectArgs({
|
||||
.label = "installable",
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "path-with-outputs.hh"
|
||||
#include "derived-path.hh"
|
||||
#include "eval.hh"
|
||||
#include "store-api.hh"
|
||||
#include "flake/flake.hh"
|
||||
|
||||
#include <optional>
|
||||
@@ -30,45 +29,19 @@ struct UnresolvedApp
|
||||
App resolve(ref<Store> evalStore, ref<Store> store);
|
||||
};
|
||||
|
||||
enum class Realise {
|
||||
/* Build the derivation. Postcondition: the
|
||||
derivation outputs exist. */
|
||||
Outputs,
|
||||
/* Don't build the derivation. Postcondition: the store derivation
|
||||
exists. */
|
||||
Derivation,
|
||||
/* Evaluate in dry-run mode. Postcondition: nothing. */
|
||||
// FIXME: currently unused, but could be revived if we can
|
||||
// evaluate derivations in-memory.
|
||||
Nothing
|
||||
};
|
||||
|
||||
/* How to handle derivations in commands that operate on store paths. */
|
||||
enum class OperateOn {
|
||||
/* Operate on the output path. */
|
||||
Output,
|
||||
/* Operate on the .drv path. */
|
||||
Derivation
|
||||
};
|
||||
|
||||
struct Installable
|
||||
{
|
||||
virtual ~Installable() { }
|
||||
|
||||
virtual std::string what() const = 0;
|
||||
virtual std::string what() = 0;
|
||||
|
||||
virtual DerivedPaths toDerivedPaths() = 0;
|
||||
|
||||
virtual StorePathSet toDrvPaths(ref<Store> store)
|
||||
{
|
||||
throw Error("'%s' cannot be converted to a derivation path", what());
|
||||
}
|
||||
|
||||
DerivedPath toDerivedPath();
|
||||
|
||||
UnresolvedApp toApp(EvalState & state);
|
||||
|
||||
virtual std::pair<Value *, PosIdx> toValue(EvalState & state)
|
||||
virtual std::pair<Value *, Pos> toValue(EvalState & state)
|
||||
{
|
||||
throw Error("argument '%s' cannot be evaluated", what());
|
||||
}
|
||||
@@ -80,56 +53,16 @@ struct Installable
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual std::vector<ref<eval_cache::AttrCursor>>
|
||||
virtual std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>>
|
||||
getCursors(EvalState & state);
|
||||
|
||||
virtual ref<eval_cache::AttrCursor>
|
||||
std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>
|
||||
getCursor(EvalState & state);
|
||||
|
||||
virtual FlakeRef nixpkgsFlakeRef() const
|
||||
{
|
||||
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
|
||||
}
|
||||
|
||||
static BuiltPaths build(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||
BuildMode bMode = bmNormal);
|
||||
|
||||
static std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> build2(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||
BuildMode bMode = bmNormal);
|
||||
|
||||
static std::set<StorePath> toStorePaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables);
|
||||
|
||||
static StorePath toStorePath(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
std::shared_ptr<Installable> installable);
|
||||
|
||||
static std::set<StorePath> toDerivations(
|
||||
ref<Store> store,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||
bool useDeriver = false);
|
||||
|
||||
static BuiltPaths toBuiltPaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables);
|
||||
};
|
||||
|
||||
struct InstallableValue : Installable
|
||||
@@ -141,15 +74,13 @@ struct InstallableValue : Installable
|
||||
struct DerivationInfo
|
||||
{
|
||||
StorePath drvPath;
|
||||
std::set<std::string> outputsToInstall;
|
||||
std::optional<NixInt> priority;
|
||||
std::optional<StorePath> outPath;
|
||||
std::string outputName;
|
||||
};
|
||||
|
||||
virtual std::vector<DerivationInfo> toDerivations() = 0;
|
||||
|
||||
DerivedPaths toDerivedPaths() override;
|
||||
|
||||
StorePathSet toDrvPaths(ref<Store> store) override;
|
||||
};
|
||||
|
||||
struct InstallableFlake : InstallableValue
|
||||
@@ -157,7 +88,6 @@ struct InstallableFlake : InstallableValue
|
||||
FlakeRef flakeRef;
|
||||
Strings attrPaths;
|
||||
Strings prefixes;
|
||||
OutputsSpec outputsSpec;
|
||||
const flake::LockFlags & lockFlags;
|
||||
mutable std::shared_ptr<flake::LockedFlake> _lockedFlake;
|
||||
|
||||
@@ -165,13 +95,11 @@ struct InstallableFlake : InstallableValue
|
||||
SourceExprCommand * cmd,
|
||||
ref<EvalState> state,
|
||||
FlakeRef && flakeRef,
|
||||
std::string_view fragment,
|
||||
OutputsSpec outputsSpec,
|
||||
Strings attrPaths,
|
||||
Strings prefixes,
|
||||
Strings && attrPaths,
|
||||
Strings && prefixes,
|
||||
const flake::LockFlags & lockFlags);
|
||||
|
||||
std::string what() const override { return flakeRef.to_string() + "#" + *attrPaths.begin(); }
|
||||
std::string what() override { return flakeRef.to_string() + "#" + *attrPaths.begin(); }
|
||||
|
||||
std::vector<std::string> getActualAttrPaths();
|
||||
|
||||
@@ -181,17 +109,11 @@ struct InstallableFlake : InstallableValue
|
||||
|
||||
std::vector<DerivationInfo> toDerivations() override;
|
||||
|
||||
std::pair<Value *, PosIdx> toValue(EvalState & state) override;
|
||||
std::pair<Value *, Pos> toValue(EvalState & state) override;
|
||||
|
||||
/* Get a cursor to every attrpath in getActualAttrPaths() that
|
||||
exists. */
|
||||
std::vector<ref<eval_cache::AttrCursor>>
|
||||
std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>>
|
||||
getCursors(EvalState & state) override;
|
||||
|
||||
/* Get a cursor to the first attrpath in getActualAttrPaths() that
|
||||
exists, or throw an exception with suggestions if none exists. */
|
||||
ref<eval_cache::AttrCursor> getCursor(EvalState & state) override;
|
||||
|
||||
std::shared_ptr<flake::LockedFlake> getLockedFlake() const;
|
||||
|
||||
FlakeRef nixpkgsFlakeRef() const override;
|
||||
|
||||
@@ -6,9 +6,9 @@ libcmd_DIR := $(d)
|
||||
|
||||
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
|
||||
|
||||
libcmd_LDFLAGS = $(EDITLINE_LIBS) -llowdown -pthread
|
||||
libcmd_LDFLAGS += -llowdown -pthread
|
||||
|
||||
libcmd_LIBS = libstore libutil libexpr libmain libfetchers
|
||||
|
||||
|
||||
@@ -9,12 +9,10 @@ namespace nix {
|
||||
|
||||
std::string renderMarkdownToTerminal(std::string_view markdown)
|
||||
{
|
||||
int windowWidth = getWindowSize().second;
|
||||
|
||||
struct lowdown_opts opts {
|
||||
.type = LOWDOWN_TERM,
|
||||
.maxdepth = 20,
|
||||
.cols = (size_t) std::max(windowWidth - 5, 60),
|
||||
.cols = std::max(getWindowSize().second, (unsigned short) 80),
|
||||
.hmargin = 0,
|
||||
.vmargin = 0,
|
||||
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace nix {
|
||||
static Strings parseAttrPath(std::string_view s)
|
||||
{
|
||||
Strings res;
|
||||
std::string cur;
|
||||
string cur;
|
||||
auto i = s.begin();
|
||||
while (i != s.end()) {
|
||||
if (*i == '.') {
|
||||
@@ -41,13 +41,13 @@ std::vector<Symbol> parseAttrPath(EvalState & state, std::string_view s)
|
||||
}
|
||||
|
||||
|
||||
std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::string & attrPath,
|
||||
std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const string & attrPath,
|
||||
Bindings & autoArgs, Value & vIn)
|
||||
{
|
||||
Strings tokens = parseAttrPath(attrPath);
|
||||
|
||||
Value * v = &vIn;
|
||||
PosIdx pos = noPos;
|
||||
Pos pos = noPos;
|
||||
|
||||
for (auto & attr : tokens) {
|
||||
|
||||
@@ -58,7 +58,7 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
||||
Value * vNew = state.allocValue();
|
||||
state.autoCallFunction(autoArgs, *v, *vNew);
|
||||
v = vNew;
|
||||
state.forceValue(*v, noPos);
|
||||
state.forceValue(*v);
|
||||
|
||||
/* It should evaluate to either a set or an expression,
|
||||
according to what is specified in the attrPath. */
|
||||
@@ -74,16 +74,10 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
||||
throw Error("empty attribute name in selection path '%1%'", attrPath);
|
||||
|
||||
Bindings::iterator a = v->attrs->find(state.symbols.create(attr));
|
||||
if (a == v->attrs->end()) {
|
||||
std::set<std::string> attrNames;
|
||||
for (auto & attr : *v->attrs)
|
||||
attrNames.insert(state.symbols[attr.name]);
|
||||
|
||||
auto suggestions = Suggestions::bestMatches(attrNames, attr);
|
||||
throw AttrPathNotFound(suggestions, "attribute '%1%' in selection path '%2%' not found", attr, attrPath);
|
||||
}
|
||||
if (a == v->attrs->end())
|
||||
throw AttrPathNotFound("attribute '%1%' in selection path '%2%' not found", attr, attrPath);
|
||||
v = &*a->value;
|
||||
pos = a->pos;
|
||||
pos = *a->pos;
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -106,7 +100,7 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
||||
}
|
||||
|
||||
|
||||
std::pair<std::string, uint32_t> findPackageFilename(EvalState & state, Value & v, std::string what)
|
||||
Pos findPackageFilename(EvalState & state, Value & v, std::string what)
|
||||
{
|
||||
Value * v2;
|
||||
try {
|
||||
@@ -127,12 +121,14 @@ std::pair<std::string, uint32_t> findPackageFilename(EvalState & state, Value &
|
||||
std::string filename(pos, 0, colon);
|
||||
unsigned int lineno;
|
||||
try {
|
||||
lineno = std::stoi(std::string(pos, colon + 1, std::string::npos));
|
||||
lineno = std::stoi(std::string(pos, colon + 1));
|
||||
} catch (std::invalid_argument & e) {
|
||||
throw ParseError("cannot parse line number '%s'", pos);
|
||||
}
|
||||
|
||||
return { std::move(filename), lineno };
|
||||
Symbol file = state.symbols.create(filename);
|
||||
|
||||
return { foFile, file, lineno, 0 };
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,14 +10,11 @@ namespace nix {
|
||||
MakeError(AttrPathNotFound, Error);
|
||||
MakeError(NoPositionInfo, Error);
|
||||
|
||||
std::pair<Value *, PosIdx> findAlongAttrPath(
|
||||
EvalState & state,
|
||||
const std::string & attrPath,
|
||||
Bindings & autoArgs,
|
||||
Value & vIn);
|
||||
std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const string & attrPath,
|
||||
Bindings & autoArgs, Value & vIn);
|
||||
|
||||
/* Heuristic to find the filename and lineno or a nix value. */
|
||||
std::pair<std::string, uint32_t> findPackageFilename(EvalState & state, Value & v, std::string what);
|
||||
Pos findPackageFilename(EvalState & state, Value & v, std::string what);
|
||||
|
||||
std::vector<Symbol> parseAttrPath(EvalState & state, std::string_view s);
|
||||
|
||||
|
||||
@@ -7,26 +7,33 @@
|
||||
namespace nix {
|
||||
|
||||
|
||||
|
||||
/* Allocate a new array of attributes for an attribute set with a specific
|
||||
capacity. The space is implicitly reserved after the Bindings
|
||||
structure. */
|
||||
Bindings * EvalState::allocBindings(size_t capacity)
|
||||
{
|
||||
if (capacity == 0)
|
||||
return &emptyBindings;
|
||||
if (capacity > std::numeric_limits<Bindings::size_t>::max())
|
||||
throw Error("attribute set of size %d is too big", capacity);
|
||||
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity);
|
||||
}
|
||||
|
||||
|
||||
void EvalState::mkAttrs(Value & v, size_t capacity)
|
||||
{
|
||||
if (capacity == 0) {
|
||||
v = vEmptySet;
|
||||
return;
|
||||
}
|
||||
v.mkAttrs(allocBindings(capacity));
|
||||
nrAttrsets++;
|
||||
nrAttrsInAttrsets += capacity;
|
||||
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity);
|
||||
}
|
||||
|
||||
|
||||
/* Create a new attribute named 'name' on an existing attribute set stored
|
||||
in 'vAttrs' and return the newly allocated Value which is associated with
|
||||
this attribute. */
|
||||
Value * EvalState::allocAttr(Value & vAttrs, Symbol name)
|
||||
Value * EvalState::allocAttr(Value & vAttrs, const Symbol & name)
|
||||
{
|
||||
Value * v = allocValue();
|
||||
vAttrs.attrs->push_back(Attr(name, v));
|
||||
@@ -34,36 +41,15 @@ Value * EvalState::allocAttr(Value & vAttrs, Symbol name)
|
||||
}
|
||||
|
||||
|
||||
Value * EvalState::allocAttr(Value & vAttrs, std::string_view name)
|
||||
Value * EvalState::allocAttr(Value & vAttrs, const std::string & name)
|
||||
{
|
||||
return allocAttr(vAttrs, symbols.create(name));
|
||||
}
|
||||
|
||||
|
||||
Value & BindingsBuilder::alloc(Symbol name, PosIdx pos)
|
||||
{
|
||||
auto value = state.allocValue();
|
||||
bindings->push_back(Attr(name, value, pos));
|
||||
return *value;
|
||||
}
|
||||
|
||||
|
||||
Value & BindingsBuilder::alloc(std::string_view name, PosIdx pos)
|
||||
{
|
||||
return alloc(state.symbols.create(name), pos);
|
||||
}
|
||||
|
||||
|
||||
void Bindings::sort()
|
||||
{
|
||||
if (size_) std::sort(begin(), end());
|
||||
}
|
||||
|
||||
|
||||
Value & Value::mkAttrs(BindingsBuilder & bindings)
|
||||
{
|
||||
mkAttrs(bindings.finish());
|
||||
return *this;
|
||||
std::sort(begin(), end());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,27 +15,18 @@ struct Value;
|
||||
/* Map one attribute name to its value. */
|
||||
struct Attr
|
||||
{
|
||||
/* the placement of `name` and `pos` in this struct is important.
|
||||
both of them are uint32 wrappers, they are next to each other
|
||||
to make sure that Attr has no padding on 64 bit machines. that
|
||||
way we keep Attr size at two words with no wasted space. */
|
||||
Symbol name;
|
||||
PosIdx pos;
|
||||
Value * value;
|
||||
Attr(Symbol name, Value * value, PosIdx pos = noPos)
|
||||
: name(name), pos(pos), value(value) { };
|
||||
Attr() { };
|
||||
ptr<Pos> pos;
|
||||
Attr(Symbol name, Value * value, ptr<Pos> pos = ptr(&noPos))
|
||||
: name(name), value(value), pos(pos) { };
|
||||
Attr() : pos(&noPos) { };
|
||||
bool operator < (const Attr & a) const
|
||||
{
|
||||
return name < a.name;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(Attr) == 2 * sizeof(uint32_t) + sizeof(Value *),
|
||||
"performance of the evaluator is highly sensitive to the size of Attr. "
|
||||
"avoid introducing any padding into Attr if at all possible, and do not "
|
||||
"introduce new fields that need not be present for almost every instance.");
|
||||
|
||||
/* Bindings contains all the attributes of an attribute set. It is defined
|
||||
by its size and its capacity, the capacity being the number of Attr
|
||||
elements allocated after this structure, while the size corresponds to
|
||||
@@ -44,13 +35,13 @@ class Bindings
|
||||
{
|
||||
public:
|
||||
typedef uint32_t size_t;
|
||||
PosIdx pos;
|
||||
ptr<Pos> pos;
|
||||
|
||||
private:
|
||||
size_t size_, capacity_;
|
||||
Attr attrs[0];
|
||||
|
||||
Bindings(size_t capacity) : size_(0), capacity_(capacity) { }
|
||||
Bindings(size_t capacity) : pos(&noPos), size_(0), capacity_(capacity) { }
|
||||
Bindings(const Bindings & bindings) = delete;
|
||||
|
||||
public:
|
||||
@@ -66,7 +57,7 @@ public:
|
||||
attrs[size_++] = attr;
|
||||
}
|
||||
|
||||
iterator find(Symbol name)
|
||||
iterator find(const Symbol & name)
|
||||
{
|
||||
Attr key(name, 0);
|
||||
iterator i = std::lower_bound(begin(), end(), key);
|
||||
@@ -74,7 +65,7 @@ public:
|
||||
return end();
|
||||
}
|
||||
|
||||
Attr * get(Symbol name)
|
||||
Attr * get(const Symbol & name)
|
||||
{
|
||||
Attr key(name, 0);
|
||||
iterator i = std::lower_bound(begin(), end(), key);
|
||||
@@ -82,6 +73,18 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Attr & need(const Symbol & name, const Pos & pos = noPos)
|
||||
{
|
||||
auto a = get(name);
|
||||
if (!a)
|
||||
throw Error({
|
||||
.msg = hintfmt("attribute '%s' missing", name),
|
||||
.errPos = pos
|
||||
});
|
||||
|
||||
return *a;
|
||||
}
|
||||
|
||||
iterator begin() { return &attrs[0]; }
|
||||
iterator end() { return &attrs[size_]; }
|
||||
|
||||
@@ -95,15 +98,14 @@ public:
|
||||
size_t capacity() { return capacity_; }
|
||||
|
||||
/* Returns the attributes in lexicographically sorted order. */
|
||||
std::vector<const Attr *> lexicographicOrder(const SymbolTable & symbols) const
|
||||
std::vector<const Attr *> lexicographicOrder() const
|
||||
{
|
||||
std::vector<const Attr *> res;
|
||||
res.reserve(size_);
|
||||
for (size_t n = 0; n < size_; n++)
|
||||
res.emplace_back(&attrs[n]);
|
||||
std::sort(res.begin(), res.end(), [&](const Attr * a, const Attr * b) {
|
||||
std::string_view sa = symbols[a->name], sb = symbols[b->name];
|
||||
return sa < sb;
|
||||
std::sort(res.begin(), res.end(), [](const Attr * a, const Attr * b) {
|
||||
return (const string &) a->name < (const string &) b->name;
|
||||
});
|
||||
return res;
|
||||
}
|
||||
@@ -111,52 +113,5 @@ public:
|
||||
friend class EvalState;
|
||||
};
|
||||
|
||||
/* A wrapper around Bindings that ensures that its always in sorted
|
||||
order at the end. The only way to consume a BindingsBuilder is to
|
||||
call finish(), which sorts the bindings. */
|
||||
class BindingsBuilder
|
||||
{
|
||||
Bindings * bindings;
|
||||
|
||||
public:
|
||||
// needed by std::back_inserter
|
||||
using value_type = Attr;
|
||||
|
||||
EvalState & state;
|
||||
|
||||
BindingsBuilder(EvalState & state, Bindings * bindings)
|
||||
: bindings(bindings), state(state)
|
||||
{ }
|
||||
|
||||
void insert(Symbol name, Value * value, PosIdx pos = noPos)
|
||||
{
|
||||
insert(Attr(name, value, pos));
|
||||
}
|
||||
|
||||
void insert(const Attr & attr)
|
||||
{
|
||||
push_back(attr);
|
||||
}
|
||||
|
||||
void push_back(const Attr & attr)
|
||||
{
|
||||
bindings->push_back(attr);
|
||||
}
|
||||
|
||||
Value & alloc(Symbol name, PosIdx pos = noPos);
|
||||
|
||||
Value & alloc(std::string_view name, PosIdx pos = noPos);
|
||||
|
||||
Bindings * finish()
|
||||
{
|
||||
bindings->sort();
|
||||
return bindings;
|
||||
}
|
||||
|
||||
Bindings * alreadySorted()
|
||||
{
|
||||
return bindings;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "registry.hh"
|
||||
#include "flake/flakeref.hh"
|
||||
#include "store-api.hh"
|
||||
#include "command.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
@@ -60,9 +59,6 @@ MixEvalArgs::MixEvalArgs()
|
||||
fetchers::Attrs extraAttrs;
|
||||
if (to.subdir != "") extraAttrs["dir"] = to.subdir;
|
||||
fetchers::overrideRegistry(from.input, to.input, extraAttrs);
|
||||
}},
|
||||
.completer = {[&](size_t, std::string_view prefix) {
|
||||
completeFlakeRef(openStore(), prefix);
|
||||
}}
|
||||
});
|
||||
|
||||
@@ -77,29 +73,30 @@ MixEvalArgs::MixEvalArgs()
|
||||
|
||||
Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
|
||||
{
|
||||
auto res = state.buildBindings(autoArgs.size());
|
||||
Bindings * res = state.allocBindings(autoArgs.size());
|
||||
for (auto & i : autoArgs) {
|
||||
auto v = state.allocValue();
|
||||
Value * v = state.allocValue();
|
||||
if (i.second[0] == 'E')
|
||||
state.mkThunk_(*v, state.parseExprFromString(i.second.substr(1), absPath(".")));
|
||||
state.mkThunk_(*v, state.parseExprFromString(string(i.second, 1), absPath(".")));
|
||||
else
|
||||
v->mkString(((std::string_view) i.second).substr(1));
|
||||
res.insert(state.symbols.create(i.first), v);
|
||||
mkString(*v, string(i.second, 1));
|
||||
res->push_back(Attr(state.symbols.create(i.first), v));
|
||||
}
|
||||
return res.finish();
|
||||
res->sort();
|
||||
return res;
|
||||
}
|
||||
|
||||
Path lookupFileArg(EvalState & state, std::string_view s)
|
||||
Path lookupFileArg(EvalState & state, string s)
|
||||
{
|
||||
if (isUri(s)) {
|
||||
return state.store->toRealPath(
|
||||
fetchers::downloadTarball(
|
||||
state.store, resolveUri(s), "source", false).first.storePath);
|
||||
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
||||
Path p(s.substr(1, s.size() - 2));
|
||||
Path p = s.substr(1, s.size() - 2);
|
||||
return state.findFile(p);
|
||||
} else
|
||||
return absPath(std::string(s));
|
||||
return absPath(s);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,6 @@ private:
|
||||
std::map<std::string, std::string> autoArgs;
|
||||
};
|
||||
|
||||
Path lookupFileArg(EvalState & state, std::string_view s);
|
||||
Path lookupFileArg(EvalState & state, string s);
|
||||
|
||||
}
|
||||
@@ -21,8 +21,6 @@ struct AttrDb
|
||||
{
|
||||
std::atomic_bool failed{false};
|
||||
|
||||
const Store & cfg;
|
||||
|
||||
struct State
|
||||
{
|
||||
SQLite db;
|
||||
@@ -35,19 +33,12 @@ struct AttrDb
|
||||
|
||||
std::unique_ptr<Sync<State>> _state;
|
||||
|
||||
SymbolTable & symbols;
|
||||
|
||||
AttrDb(
|
||||
const Store & cfg,
|
||||
const Hash & fingerprint,
|
||||
SymbolTable & symbols)
|
||||
: cfg(cfg)
|
||||
, _state(std::make_unique<Sync<State>>())
|
||||
, symbols(symbols)
|
||||
AttrDb(const Hash & fingerprint)
|
||||
: _state(std::make_unique<Sync<State>>())
|
||||
{
|
||||
auto state(_state->lock());
|
||||
|
||||
Path cacheDir = getCacheDir() + "/nix/eval-cache-v4";
|
||||
Path cacheDir = getCacheDir() + "/nix/eval-cache-v2";
|
||||
createDirs(cacheDir);
|
||||
|
||||
Path dbPath = cacheDir + "/" + fingerprint.to_string(Base16, false) + ".sqlite";
|
||||
@@ -106,7 +97,7 @@ struct AttrDb
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(key.second)
|
||||
(AttrType::FullAttrs)
|
||||
(0, false).exec();
|
||||
|
||||
@@ -116,7 +107,7 @@ struct AttrDb
|
||||
for (auto & attr : attrs)
|
||||
state->insertAttribute.use()
|
||||
(rowId)
|
||||
(symbols[attr])
|
||||
(attr)
|
||||
(AttrType::Placeholder)
|
||||
(0, false).exec();
|
||||
|
||||
@@ -141,14 +132,14 @@ struct AttrDb
|
||||
}
|
||||
state->insertAttributeWithContext.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(key.second)
|
||||
(AttrType::String)
|
||||
(s)
|
||||
(ctx).exec();
|
||||
} else {
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(key.second)
|
||||
(AttrType::String)
|
||||
(s).exec();
|
||||
}
|
||||
@@ -167,7 +158,7 @@ struct AttrDb
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(key.second)
|
||||
(AttrType::Bool)
|
||||
(b ? 1 : 0).exec();
|
||||
|
||||
@@ -175,42 +166,6 @@ struct AttrDb
|
||||
});
|
||||
}
|
||||
|
||||
AttrId setInt(
|
||||
AttrKey key,
|
||||
int n)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
{
|
||||
auto state(_state->lock());
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::Int)
|
||||
(n).exec();
|
||||
|
||||
return state->db.getLastInsertedRowId();
|
||||
});
|
||||
}
|
||||
|
||||
AttrId setListOfStrings(
|
||||
AttrKey key,
|
||||
const std::vector<std::string> & l)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
{
|
||||
auto state(_state->lock());
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(AttrType::ListOfStrings)
|
||||
(concatStringsSep("\t", l)).exec();
|
||||
|
||||
return state->db.getLastInsertedRowId();
|
||||
});
|
||||
}
|
||||
|
||||
AttrId setPlaceholder(AttrKey key)
|
||||
{
|
||||
return doSQLite([&]()
|
||||
@@ -219,7 +174,7 @@ struct AttrDb
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(key.second)
|
||||
(AttrType::Placeholder)
|
||||
(0, false).exec();
|
||||
|
||||
@@ -235,7 +190,7 @@ struct AttrDb
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(key.second)
|
||||
(AttrType::Missing)
|
||||
(0, false).exec();
|
||||
|
||||
@@ -251,7 +206,7 @@ struct AttrDb
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(key.second)
|
||||
(AttrType::Misc)
|
||||
(0, false).exec();
|
||||
|
||||
@@ -267,7 +222,7 @@ struct AttrDb
|
||||
|
||||
state->insertAttribute.use()
|
||||
(key.first)
|
||||
(symbols[key.second])
|
||||
(key.second)
|
||||
(AttrType::Failed)
|
||||
(0, false).exec();
|
||||
|
||||
@@ -275,11 +230,13 @@ struct AttrDb
|
||||
});
|
||||
}
|
||||
|
||||
std::optional<std::pair<AttrId, AttrValue>> getAttr(AttrKey key)
|
||||
std::optional<std::pair<AttrId, AttrValue>> getAttr(
|
||||
AttrKey key,
|
||||
SymbolTable & symbols)
|
||||
{
|
||||
auto state(_state->lock());
|
||||
|
||||
auto queryAttribute(state->queryAttribute.use()(key.first)(symbols[key.second]));
|
||||
auto queryAttribute(state->queryAttribute.use()(key.first)(key.second));
|
||||
if (!queryAttribute.next()) return {};
|
||||
|
||||
auto rowId = (AttrType) queryAttribute.getInt(0);
|
||||
@@ -293,22 +250,18 @@ struct AttrDb
|
||||
std::vector<Symbol> attrs;
|
||||
auto queryAttributes(state->queryAttributes.use()(rowId));
|
||||
while (queryAttributes.next())
|
||||
attrs.emplace_back(symbols.create(queryAttributes.getStr(0)));
|
||||
attrs.push_back(symbols.create(queryAttributes.getStr(0)));
|
||||
return {{rowId, attrs}};
|
||||
}
|
||||
case AttrType::String: {
|
||||
NixStringContext context;
|
||||
std::vector<std::pair<Path, std::string>> context;
|
||||
if (!queryAttribute.isNull(3))
|
||||
for (auto & s : tokenizeString<std::vector<std::string>>(queryAttribute.getStr(3), ";"))
|
||||
context.push_back(decodeContext(cfg, s));
|
||||
context.push_back(decodeContext(s));
|
||||
return {{rowId, string_t{queryAttribute.getStr(2), context}}};
|
||||
}
|
||||
case AttrType::Bool:
|
||||
return {{rowId, queryAttribute.getInt(2) != 0}};
|
||||
case AttrType::Int:
|
||||
return {{rowId, int_t{queryAttribute.getInt(2)}}};
|
||||
case AttrType::ListOfStrings:
|
||||
return {{rowId, tokenizeString<std::vector<std::string>>(queryAttribute.getStr(2), "\t")}};
|
||||
case AttrType::Missing:
|
||||
return {{rowId, missing_t()}};
|
||||
case AttrType::Misc:
|
||||
@@ -321,13 +274,10 @@ struct AttrDb
|
||||
}
|
||||
};
|
||||
|
||||
static std::shared_ptr<AttrDb> makeAttrDb(
|
||||
const Store & cfg,
|
||||
const Hash & fingerprint,
|
||||
SymbolTable & symbols)
|
||||
static std::shared_ptr<AttrDb> makeAttrDb(const Hash & fingerprint)
|
||||
{
|
||||
try {
|
||||
return std::make_shared<AttrDb>(cfg, fingerprint, symbols);
|
||||
return std::make_shared<AttrDb>(fingerprint);
|
||||
} catch (SQLiteError &) {
|
||||
ignoreException();
|
||||
return nullptr;
|
||||
@@ -338,7 +288,7 @@ EvalCache::EvalCache(
|
||||
std::optional<std::reference_wrapper<const Hash>> useCache,
|
||||
EvalState & state,
|
||||
RootLoader rootLoader)
|
||||
: db(useCache ? makeAttrDb(*state.store, *useCache, state.symbols) : nullptr)
|
||||
: db(useCache ? makeAttrDb(*useCache) : nullptr)
|
||||
, state(state)
|
||||
, rootLoader(rootLoader)
|
||||
{
|
||||
@@ -353,9 +303,9 @@ Value * EvalCache::getRootValue()
|
||||
return *value;
|
||||
}
|
||||
|
||||
ref<AttrCursor> EvalCache::getRoot()
|
||||
std::shared_ptr<AttrCursor> EvalCache::getRoot()
|
||||
{
|
||||
return make_ref<AttrCursor>(ref(shared_from_this()), std::nullopt);
|
||||
return std::make_shared<AttrCursor>(ref(shared_from_this()), std::nullopt);
|
||||
}
|
||||
|
||||
AttrCursor::AttrCursor(
|
||||
@@ -374,7 +324,8 @@ AttrKey AttrCursor::getKey()
|
||||
if (!parent)
|
||||
return {0, root->state.sEpsilon};
|
||||
if (!parent->first->cachedValue) {
|
||||
parent->first->cachedValue = root->db->getAttr(parent->first->getKey());
|
||||
parent->first->cachedValue = root->db->getAttr(
|
||||
parent->first->getKey(), root->state.symbols);
|
||||
assert(parent->first->cachedValue);
|
||||
}
|
||||
return {parent->first->cachedValue->first, parent->second};
|
||||
@@ -385,7 +336,7 @@ Value & AttrCursor::getValue()
|
||||
if (!_value) {
|
||||
if (parent) {
|
||||
auto & vParent = parent->first->getValue();
|
||||
root->state.forceAttrs(vParent, noPos);
|
||||
root->state.forceAttrs(vParent);
|
||||
auto attr = vParent.attrs->get(parent->second);
|
||||
if (!attr)
|
||||
throw Error("attribute '%s' is unexpectedly missing", getAttrPathStr());
|
||||
@@ -415,22 +366,22 @@ std::vector<Symbol> AttrCursor::getAttrPath(Symbol name) const
|
||||
|
||||
std::string AttrCursor::getAttrPathStr() const
|
||||
{
|
||||
return concatStringsSep(".", root->state.symbols.resolve(getAttrPath()));
|
||||
return concatStringsSep(".", getAttrPath());
|
||||
}
|
||||
|
||||
std::string AttrCursor::getAttrPathStr(Symbol name) const
|
||||
{
|
||||
return concatStringsSep(".", root->state.symbols.resolve(getAttrPath(name)));
|
||||
return concatStringsSep(".", getAttrPath(name));
|
||||
}
|
||||
|
||||
Value & AttrCursor::forceValue()
|
||||
{
|
||||
debug("evaluating uncached attribute '%s'", getAttrPathStr());
|
||||
debug("evaluating uncached attribute %s", getAttrPathStr());
|
||||
|
||||
auto & v = getValue();
|
||||
|
||||
try {
|
||||
root->state.forceValue(v, noPos);
|
||||
root->state.forceValue(v);
|
||||
} catch (EvalError &) {
|
||||
debug("setting '%s' to failed", getAttrPathStr());
|
||||
if (root->db)
|
||||
@@ -446,8 +397,6 @@ Value & AttrCursor::forceValue()
|
||||
cachedValue = {root->db->setString(getKey(), v.path), string_t{v.path, {}}};
|
||||
else if (v.type() == nBool)
|
||||
cachedValue = {root->db->setBool(getKey(), v.boolean), v.boolean};
|
||||
else if (v.type() == nInt)
|
||||
cachedValue = {root->db->setInt(getKey(), v.integer), int_t{v.integer}};
|
||||
else if (v.type() == nAttrs)
|
||||
; // FIXME: do something?
|
||||
else
|
||||
@@ -457,30 +406,20 @@ Value & AttrCursor::forceValue()
|
||||
return v;
|
||||
}
|
||||
|
||||
Suggestions AttrCursor::getSuggestionsForAttr(Symbol name)
|
||||
{
|
||||
auto attrNames = getAttrs();
|
||||
std::set<std::string> strAttrNames;
|
||||
for (auto & name : attrNames)
|
||||
strAttrNames.insert(root->state.symbols[name]);
|
||||
|
||||
return Suggestions::bestMatches(strAttrNames, root->state.symbols[name]);
|
||||
}
|
||||
|
||||
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErrors)
|
||||
{
|
||||
if (root->db) {
|
||||
if (!cachedValue)
|
||||
cachedValue = root->db->getAttr(getKey());
|
||||
cachedValue = root->db->getAttr(getKey(), root->state.symbols);
|
||||
|
||||
if (cachedValue) {
|
||||
if (auto attrs = std::get_if<std::vector<Symbol>>(&cachedValue->second)) {
|
||||
for (auto & attr : *attrs)
|
||||
if (attr == name)
|
||||
return std::make_shared<AttrCursor>(root, std::make_pair(shared_from_this(), attr));
|
||||
return std::make_shared<AttrCursor>(root, std::make_pair(shared_from_this(), name));
|
||||
return nullptr;
|
||||
} else if (std::get_if<placeholder_t>(&cachedValue->second)) {
|
||||
auto attr = root->db->getAttr({cachedValue->first, name});
|
||||
auto attr = root->db->getAttr({cachedValue->first, name}, root->state.symbols);
|
||||
if (attr) {
|
||||
if (std::get_if<missing_t>(&attr->second))
|
||||
return nullptr;
|
||||
@@ -507,11 +446,6 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
|
||||
return nullptr;
|
||||
//throw TypeError("'%s' is not an attribute set", getAttrPathStr());
|
||||
|
||||
for (auto & attr : *v.attrs) {
|
||||
if (root->db)
|
||||
root->db->setPlaceholder({cachedValue->first, attr.name});
|
||||
}
|
||||
|
||||
auto attr = v.attrs->get(name);
|
||||
|
||||
if (!attr) {
|
||||
@@ -530,7 +464,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
|
||||
cachedValue2 = {root->db->setPlaceholder({cachedValue->first, name}), placeholder_t()};
|
||||
}
|
||||
|
||||
return make_ref<AttrCursor>(
|
||||
return std::make_shared<AttrCursor>(
|
||||
root, std::make_pair(shared_from_this(), name), attr->value, std::move(cachedValue2));
|
||||
}
|
||||
|
||||
@@ -539,51 +473,47 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name)
|
||||
return maybeGetAttr(root->state.symbols.create(name));
|
||||
}
|
||||
|
||||
ref<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
|
||||
std::shared_ptr<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
|
||||
{
|
||||
auto p = maybeGetAttr(name, forceErrors);
|
||||
if (!p)
|
||||
throw Error("attribute '%s' does not exist", getAttrPathStr(name));
|
||||
return ref(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
ref<AttrCursor> AttrCursor::getAttr(std::string_view name)
|
||||
std::shared_ptr<AttrCursor> AttrCursor::getAttr(std::string_view name)
|
||||
{
|
||||
return getAttr(root->state.symbols.create(name));
|
||||
}
|
||||
|
||||
OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force)
|
||||
std::shared_ptr<AttrCursor> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force)
|
||||
{
|
||||
auto res = shared_from_this();
|
||||
for (auto & attr : attrPath) {
|
||||
auto child = res->maybeGetAttr(attr, force);
|
||||
if (!child) {
|
||||
auto suggestions = res->getSuggestionsForAttr(attr);
|
||||
return OrSuggestions<ref<AttrCursor>>::failed(suggestions);
|
||||
}
|
||||
res = child;
|
||||
res = res->maybeGetAttr(attr, force);
|
||||
if (!res) return {};
|
||||
}
|
||||
return ref(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string AttrCursor::getString()
|
||||
{
|
||||
if (root->db) {
|
||||
if (!cachedValue)
|
||||
cachedValue = root->db->getAttr(getKey());
|
||||
cachedValue = root->db->getAttr(getKey(), root->state.symbols);
|
||||
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
|
||||
if (auto s = std::get_if<string_t>(&cachedValue->second)) {
|
||||
debug("using cached string attribute '%s'", getAttrPathStr());
|
||||
return s->first;
|
||||
} else
|
||||
root->state.debugThrowLastTrace(TypeError("'%s' is not a string", getAttrPathStr()));
|
||||
throw TypeError("'%s' is not a string", getAttrPathStr());
|
||||
}
|
||||
}
|
||||
|
||||
auto & v = forceValue();
|
||||
|
||||
if (v.type() != nString && v.type() != nPath)
|
||||
root->state.debugThrowLastTrace(TypeError("'%s' is not a string but %s", getAttrPathStr(), showType(v.type())));
|
||||
throw TypeError("'%s' is not a string but %s", getAttrPathStr(), showType(v.type()));
|
||||
|
||||
return v.type() == nString ? v.string.s : v.path;
|
||||
}
|
||||
@@ -592,12 +522,12 @@ string_t AttrCursor::getStringWithContext()
|
||||
{
|
||||
if (root->db) {
|
||||
if (!cachedValue)
|
||||
cachedValue = root->db->getAttr(getKey());
|
||||
cachedValue = root->db->getAttr(getKey(), root->state.symbols);
|
||||
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
|
||||
if (auto s = std::get_if<string_t>(&cachedValue->second)) {
|
||||
bool valid = true;
|
||||
for (auto & c : s->second) {
|
||||
if (!root->state.store->isValidPath(c.first)) {
|
||||
if (!root->state.store->isValidPath(root->state.store->parseStorePath(c.first))) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
@@ -607,122 +537,66 @@ string_t AttrCursor::getStringWithContext()
|
||||
return *s;
|
||||
}
|
||||
} else
|
||||
root->state.debugThrowLastTrace(TypeError("'%s' is not a string", getAttrPathStr()));
|
||||
throw TypeError("'%s' is not a string", getAttrPathStr());
|
||||
}
|
||||
}
|
||||
|
||||
auto & v = forceValue();
|
||||
|
||||
if (v.type() == nString)
|
||||
return {v.string.s, v.getContext(*root->state.store)};
|
||||
return {v.string.s, v.getContext()};
|
||||
else if (v.type() == nPath)
|
||||
return {v.path, {}};
|
||||
else
|
||||
root->state.debugThrowLastTrace(TypeError("'%s' is not a string but %s", getAttrPathStr(), showType(v.type())));
|
||||
throw TypeError("'%s' is not a string but %s", getAttrPathStr(), showType(v.type()));
|
||||
}
|
||||
|
||||
bool AttrCursor::getBool()
|
||||
{
|
||||
if (root->db) {
|
||||
if (!cachedValue)
|
||||
cachedValue = root->db->getAttr(getKey());
|
||||
cachedValue = root->db->getAttr(getKey(), root->state.symbols);
|
||||
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
|
||||
if (auto b = std::get_if<bool>(&cachedValue->second)) {
|
||||
debug("using cached Boolean attribute '%s'", getAttrPathStr());
|
||||
return *b;
|
||||
} else
|
||||
root->state.debugThrowLastTrace(TypeError("'%s' is not a Boolean", getAttrPathStr()));
|
||||
throw TypeError("'%s' is not a Boolean", getAttrPathStr());
|
||||
}
|
||||
}
|
||||
|
||||
auto & v = forceValue();
|
||||
|
||||
if (v.type() != nBool)
|
||||
root->state.debugThrowLastTrace(TypeError("'%s' is not a Boolean", getAttrPathStr()));
|
||||
throw TypeError("'%s' is not a Boolean", getAttrPathStr());
|
||||
|
||||
return v.boolean;
|
||||
}
|
||||
|
||||
NixInt AttrCursor::getInt()
|
||||
{
|
||||
if (root->db) {
|
||||
if (!cachedValue)
|
||||
cachedValue = root->db->getAttr(getKey());
|
||||
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
|
||||
if (auto i = std::get_if<int_t>(&cachedValue->second)) {
|
||||
debug("using cached Integer attribute '%s'", getAttrPathStr());
|
||||
return i->x;
|
||||
} else
|
||||
throw TypeError("'%s' is not an Integer", getAttrPathStr());
|
||||
}
|
||||
}
|
||||
|
||||
auto & v = forceValue();
|
||||
|
||||
if (v.type() != nInt)
|
||||
throw TypeError("'%s' is not an Integer", getAttrPathStr());
|
||||
|
||||
return v.integer;
|
||||
}
|
||||
|
||||
std::vector<std::string> AttrCursor::getListOfStrings()
|
||||
{
|
||||
if (root->db) {
|
||||
if (!cachedValue)
|
||||
cachedValue = root->db->getAttr(getKey());
|
||||
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
|
||||
if (auto l = std::get_if<std::vector<std::string>>(&cachedValue->second)) {
|
||||
debug("using cached list of strings attribute '%s'", getAttrPathStr());
|
||||
return *l;
|
||||
} else
|
||||
throw TypeError("'%s' is not a list of strings", getAttrPathStr());
|
||||
}
|
||||
}
|
||||
|
||||
debug("evaluating uncached attribute '%s'", getAttrPathStr());
|
||||
|
||||
auto & v = getValue();
|
||||
root->state.forceValue(v, noPos);
|
||||
|
||||
if (v.type() != nList)
|
||||
throw TypeError("'%s' is not a list", getAttrPathStr());
|
||||
|
||||
std::vector<std::string> res;
|
||||
|
||||
for (auto & elem : v.listItems())
|
||||
res.push_back(std::string(root->state.forceStringNoCtx(*elem)));
|
||||
|
||||
if (root->db)
|
||||
cachedValue = {root->db->setListOfStrings(getKey(), res), res};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<Symbol> AttrCursor::getAttrs()
|
||||
{
|
||||
if (root->db) {
|
||||
if (!cachedValue)
|
||||
cachedValue = root->db->getAttr(getKey());
|
||||
cachedValue = root->db->getAttr(getKey(), root->state.symbols);
|
||||
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
|
||||
if (auto attrs = std::get_if<std::vector<Symbol>>(&cachedValue->second)) {
|
||||
debug("using cached attrset attribute '%s'", getAttrPathStr());
|
||||
return *attrs;
|
||||
} else
|
||||
root->state.debugThrowLastTrace(TypeError("'%s' is not an attribute set", getAttrPathStr()));
|
||||
throw TypeError("'%s' is not an attribute set", getAttrPathStr());
|
||||
}
|
||||
}
|
||||
|
||||
auto & v = forceValue();
|
||||
|
||||
if (v.type() != nAttrs)
|
||||
root->state.debugThrowLastTrace(TypeError("'%s' is not an attribute set", getAttrPathStr()));
|
||||
throw TypeError("'%s' is not an attribute set", getAttrPathStr());
|
||||
|
||||
std::vector<Symbol> attrs;
|
||||
for (auto & attr : *getValue().attrs)
|
||||
attrs.push_back(attr.name);
|
||||
std::sort(attrs.begin(), attrs.end(), [&](Symbol a, Symbol b) {
|
||||
std::string_view sa = root->state.symbols[a], sb = root->state.symbols[b];
|
||||
return sa < sb;
|
||||
std::sort(attrs.begin(), attrs.end(), [](const Symbol & a, const Symbol & b) {
|
||||
return (const string &) a < (const string &) b;
|
||||
});
|
||||
|
||||
if (root->db)
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
EvalState & state,
|
||||
RootLoader rootLoader);
|
||||
|
||||
ref<AttrCursor> getRoot();
|
||||
std::shared_ptr<AttrCursor> getRoot();
|
||||
};
|
||||
|
||||
enum AttrType {
|
||||
@@ -44,18 +44,15 @@ enum AttrType {
|
||||
Misc = 4,
|
||||
Failed = 5,
|
||||
Bool = 6,
|
||||
ListOfStrings = 7,
|
||||
Int = 8,
|
||||
};
|
||||
|
||||
struct placeholder_t {};
|
||||
struct missing_t {};
|
||||
struct misc_t {};
|
||||
struct failed_t {};
|
||||
struct int_t { NixInt x; };
|
||||
typedef uint64_t AttrId;
|
||||
typedef std::pair<AttrId, Symbol> AttrKey;
|
||||
typedef std::pair<std::string, NixStringContext> string_t;
|
||||
typedef std::pair<std::string, std::vector<std::pair<Path, std::string>>> string_t;
|
||||
|
||||
typedef std::variant<
|
||||
std::vector<Symbol>,
|
||||
@@ -64,9 +61,7 @@ typedef std::variant<
|
||||
missing_t,
|
||||
misc_t,
|
||||
failed_t,
|
||||
bool,
|
||||
int_t,
|
||||
std::vector<std::string>
|
||||
bool
|
||||
> AttrValue;
|
||||
|
||||
class AttrCursor : public std::enable_shared_from_this<AttrCursor>
|
||||
@@ -99,19 +94,15 @@ public:
|
||||
|
||||
std::string getAttrPathStr(Symbol name) const;
|
||||
|
||||
Suggestions getSuggestionsForAttr(Symbol name);
|
||||
|
||||
std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name, bool forceErrors = false);
|
||||
|
||||
std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name);
|
||||
|
||||
ref<AttrCursor> getAttr(Symbol name, bool forceErrors = false);
|
||||
std::shared_ptr<AttrCursor> getAttr(Symbol name, bool forceErrors = false);
|
||||
|
||||
ref<AttrCursor> getAttr(std::string_view name);
|
||||
std::shared_ptr<AttrCursor> getAttr(std::string_view name);
|
||||
|
||||
/* Get an attribute along a chain of attrsets. Note that this does
|
||||
not auto-call functors or functions. */
|
||||
OrSuggestions<ref<AttrCursor>> findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force = false);
|
||||
std::shared_ptr<AttrCursor> findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force = false);
|
||||
|
||||
std::string getString();
|
||||
|
||||
@@ -119,10 +110,6 @@ public:
|
||||
|
||||
bool getBool();
|
||||
|
||||
NixInt getInt();
|
||||
|
||||
std::vector<std::string> getListOfStrings();
|
||||
|
||||
std::vector<Symbol> getAttrs();
|
||||
|
||||
bool isDerivation();
|
||||
|
||||
@@ -2,91 +2,35 @@
|
||||
|
||||
#include "eval.hh"
|
||||
|
||||
#define LocalNoInline(f) static f __attribute__((noinline)); f
|
||||
#define LocalNoInlineNoReturn(f) static f __attribute__((noinline, noreturn)); f
|
||||
|
||||
namespace nix {
|
||||
|
||||
/* Note: Various places expect the allocated memory to be zeroed. */
|
||||
[[gnu::always_inline]]
|
||||
inline void * allocBytes(size_t n)
|
||||
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s))
|
||||
{
|
||||
void * p;
|
||||
#if HAVE_BOEHMGC
|
||||
p = GC_MALLOC(n);
|
||||
#else
|
||||
p = calloc(n, 1);
|
||||
#endif
|
||||
if (!p) throw std::bad_alloc();
|
||||
return p;
|
||||
throw EvalError({
|
||||
.msg = hintfmt(s),
|
||||
.errPos = pos
|
||||
});
|
||||
}
|
||||
|
||||
LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v))
|
||||
{
|
||||
throw TypeError(s, showType(v));
|
||||
}
|
||||
|
||||
|
||||
[[gnu::always_inline]]
|
||||
Value * EvalState::allocValue()
|
||||
LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const Value & v))
|
||||
{
|
||||
#if HAVE_BOEHMGC
|
||||
/* We use the boehm batch allocator to speed up allocations of Values (of which there are many).
|
||||
GC_malloc_many returns a linked list of objects of the given size, where the first word
|
||||
of each object is also the pointer to the next object in the list. This also means that we
|
||||
have to explicitly clear the first word of every object we take. */
|
||||
if (!*valueAllocCache) {
|
||||
*valueAllocCache = GC_malloc_many(sizeof(Value));
|
||||
if (!*valueAllocCache) throw std::bad_alloc();
|
||||
}
|
||||
|
||||
/* GC_NEXT is a convenience macro for accessing the first word of an object.
|
||||
Take the first list item, advance the list to the next item, and clear the next pointer. */
|
||||
void * p = *valueAllocCache;
|
||||
*valueAllocCache = GC_NEXT(p);
|
||||
GC_NEXT(p) = nullptr;
|
||||
#else
|
||||
void * p = allocBytes(sizeof(Value));
|
||||
#endif
|
||||
|
||||
nrValues++;
|
||||
return (Value *) p;
|
||||
throw TypeError({
|
||||
.msg = hintfmt(s, showType(v)),
|
||||
.errPos = pos
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
[[gnu::always_inline]]
|
||||
Env & EvalState::allocEnv(size_t size)
|
||||
{
|
||||
nrEnvs++;
|
||||
nrValuesInEnvs += size;
|
||||
|
||||
Env * env;
|
||||
|
||||
#if HAVE_BOEHMGC
|
||||
if (size == 1) {
|
||||
/* see allocValue for explanations. */
|
||||
if (!*env1AllocCache) {
|
||||
*env1AllocCache = GC_malloc_many(sizeof(Env) + sizeof(Value *));
|
||||
if (!*env1AllocCache) throw std::bad_alloc();
|
||||
}
|
||||
|
||||
void * p = *env1AllocCache;
|
||||
*env1AllocCache = GC_NEXT(p);
|
||||
GC_NEXT(p) = nullptr;
|
||||
env = (Env *) p;
|
||||
} else
|
||||
#endif
|
||||
env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *));
|
||||
|
||||
env->type = Env::Plain;
|
||||
|
||||
/* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */
|
||||
|
||||
return *env;
|
||||
}
|
||||
|
||||
|
||||
[[gnu::always_inline]]
|
||||
void EvalState::forceValue(Value & v, const PosIdx pos)
|
||||
{
|
||||
forceValue(v, [&]() { return pos; });
|
||||
}
|
||||
|
||||
|
||||
template<typename Callable>
|
||||
void EvalState::forceValue(Value & v, Callable getPos)
|
||||
void EvalState::forceValue(Value & v, const Pos & pos)
|
||||
{
|
||||
if (v.isThunk()) {
|
||||
Env * env = v.thunk.env;
|
||||
@@ -103,34 +47,53 @@ void EvalState::forceValue(Value & v, Callable getPos)
|
||||
else if (v.isApp())
|
||||
callFunction(*v.app.left, *v.app.right, v, noPos);
|
||||
else if (v.isBlackhole())
|
||||
throwEvalError(getPos(), "infinite recursion encountered");
|
||||
throwEvalError(pos, "infinite recursion encountered");
|
||||
}
|
||||
|
||||
|
||||
[[gnu::always_inline]]
|
||||
inline void EvalState::forceAttrs(Value & v, const PosIdx pos)
|
||||
inline void EvalState::forceAttrs(Value & v)
|
||||
{
|
||||
forceAttrs(v, [&]() { return pos; });
|
||||
}
|
||||
|
||||
|
||||
template <typename Callable>
|
||||
[[gnu::always_inline]]
|
||||
inline void EvalState::forceAttrs(Value & v, Callable getPos)
|
||||
{
|
||||
forceValue(v, getPos);
|
||||
forceValue(v);
|
||||
if (v.type() != nAttrs)
|
||||
throwTypeError(getPos(), "value is %1% while a set was expected", v);
|
||||
throwTypeError("value is %1% while a set was expected", v);
|
||||
}
|
||||
|
||||
|
||||
[[gnu::always_inline]]
|
||||
inline void EvalState::forceList(Value & v, const PosIdx pos)
|
||||
inline void EvalState::forceAttrs(Value & v, const Pos & pos)
|
||||
{
|
||||
forceValue(v, pos);
|
||||
if (v.type() != nAttrs)
|
||||
throwTypeError(pos, "value is %1% while a set was expected", v);
|
||||
}
|
||||
|
||||
|
||||
inline void EvalState::forceList(Value & v)
|
||||
{
|
||||
forceValue(v);
|
||||
if (!v.isList())
|
||||
throwTypeError("value is %1% while a list was expected", v);
|
||||
}
|
||||
|
||||
|
||||
inline void EvalState::forceList(Value & v, const Pos & pos)
|
||||
{
|
||||
forceValue(v, pos);
|
||||
if (!v.isList())
|
||||
throwTypeError(pos, "value is %1% while a list was expected", v);
|
||||
}
|
||||
|
||||
/* Note: Various places expect the allocated memory to be zeroed. */
|
||||
inline void * allocBytes(size_t n)
|
||||
{
|
||||
void * p;
|
||||
#if HAVE_BOEHMGC
|
||||
p = GC_MALLOC(n);
|
||||
#else
|
||||
p = calloc(n, 1);
|
||||
#endif
|
||||
if (!p) throw std::bad_alloc();
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user