mirror of
https://github.com/NixOS/nix.git
synced 2025-11-21 09:49:36 +01:00
Merge remote-tracking branch 'origin/master' into progress-bar
This commit is contained in:
commit
c4f0508ef5
417 changed files with 42697 additions and 9071 deletions
35
.github/STALE-BOT.md
vendored
Normal file
35
.github/STALE-BOT.md
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Stale bot information
|
||||
|
||||
- Thanks for your contribution!
|
||||
- To remove the stale label, just leave a new comment.
|
||||
- _How to find the right people to ping?_ → [`git blame`](https://git-scm.com/docs/git-blame) to the rescue! (or GitHub's history and blame buttons.)
|
||||
- You can always ask for help on [our Discourse Forum](https://discourse.nixos.org/) or on [Matrix - #nix:nixos.org](https://matrix.to/#/#nix:nixos.org).
|
||||
|
||||
## Suggestions for PRs
|
||||
|
||||
1. GitHub sometimes doesn't notify people who commented / reviewed a PR previously, when you (force) push commits. If you have addressed the reviews you can [officially ask for a review](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/requesting-a-pull-request-review) from those who commented to you or anyone else.
|
||||
2. If it is unfinished but you plan to finish it, please mark it as a draft.
|
||||
3. If you don't expect to work on it any time soon, closing it with a short comment may encourage someone else to pick up your work.
|
||||
4. To get things rolling again, rebase the PR against the target branch and address valid comments.
|
||||
5. If you need a review to move forward, ask in [the Discourse thread for PRs that need help](https://discourse.nixos.org/t/prs-in-distress/3604).
|
||||
6. If all you need is a merge, check the git history to find and [request reviews](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/requesting-a-pull-request-review) from people who usually merge related contributions.
|
||||
|
||||
## Suggestions for issues
|
||||
|
||||
1. If it is resolved (either for you personally, or in general), please consider closing it.
|
||||
2. If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough.
|
||||
3. If you still have interest in resolving it, try to ping somebody who you believe might have an interest in the topic. Consider discussing the problem in [our Discourse Forum](https://discourse.nixos.org/).
|
||||
4. As with all open source projects, your best option is to submit a Pull Request that addresses this issue. We :heart: this attitude!
|
||||
|
||||
**Memorandum on closing issues**
|
||||
|
||||
Don't be afraid to close an issue that holds valuable information. Closed issues stay in the system for people to search, read, cross-reference, or even reopen--nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.
|
||||
|
||||
## Useful GitHub search queries
|
||||
|
||||
- [Open PRs with any stale-bot interaction](https://github.com/NixOS/nix/pulls?q=is%3Apr+is%3Aopen+commenter%3Aapp%2Fstale+)
|
||||
- [Open PRs with any stale-bot interaction and `stale`](https://github.com/NixOS/nix/pulls?q=is%3Apr+is%3Aopen+commenter%3Aapp%2Fstale+label%3A%22stale%22)
|
||||
- [Open PRs with any stale-bot interaction and NOT `stale`](https://github.com/NixOS/nix/pulls?q=is%3Apr+is%3Aopen+commenter%3Aapp%2Fstale+-label%3A%22stale%22+)
|
||||
- [Open Issues with any stale-bot interaction](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+commenter%3Aapp%2Fstale+)
|
||||
- [Open Issues with any stale-bot interaction and `stale`](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+commenter%3Aapp%2Fstale+label%3A%22stale%22+)
|
||||
- [Open Issues with any stale-bot interaction and NOT `stale`](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+commenter%3Aapp%2Fstale+-label%3A%22stale%22+)
|
||||
10
.github/stale.yml
vendored
Normal file
10
.github/stale.yml
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
daysUntilStale: 180
|
||||
daysUntilClose: 365
|
||||
exemptLabels:
|
||||
- "critical"
|
||||
staleLabel: "stale"
|
||||
markComment: |
|
||||
I marked this as stale due to inactivity. → [More info](https://github.com/NixOS/nix/blob/master/.github/STALE-BOT.md)
|
||||
closeComment: |
|
||||
I closed this issue due to inactivity. → [More info](https://github.com/NixOS/nix/blob/master/.github/STALE-BOT.md)
|
||||
69
.github/workflows/test.yml
vendored
69
.github/workflows/test.yml
vendored
|
|
@ -1,17 +1,76 @@
|
|||
name: "Test"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
|
||||
tests:
|
||||
needs: [check_cachix]
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: cachix/install-nix-action@v14.1
|
||||
- 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'
|
||||
with:
|
||||
name: '${{ env.CACHIX_NAME }}'
|
||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
- run: nix-build -A checks.$(nix-instantiate --eval -E '(builtins.currentSystem)')
|
||||
|
||||
check_cachix:
|
||||
name: Cachix secret present for installer tests
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
secret: ${{ steps.secret.outputs.secret }}
|
||||
steps:
|
||||
- name: Check for Cachix secret
|
||||
id: secret
|
||||
env:
|
||||
_CACHIX_SECRETS: ${{ secrets.CACHIX_SIGNING_KEY }}${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
run: echo "::set-output name=secret::${{ env._CACHIX_SECRETS != '' }}"
|
||||
|
||||
installer:
|
||||
needs: [tests, check_cachix]
|
||||
if: github.event_name == 'push' && needs.check_cachix.outputs.secret == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
installerURL: ${{ steps.prepare-installer.outputs.installerURL }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.5
|
||||
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@v14.1
|
||||
- uses: cachix/cachix-action@v10
|
||||
with:
|
||||
name: '${{ env.CACHIX_NAME }}'
|
||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
- id: prepare-installer
|
||||
run: scripts/prepare-installer-for-github-actions
|
||||
|
||||
installer_test:
|
||||
needs: [installer, check_cachix]
|
||||
if: github.event_name == 'push' && needs.check_cachix.outputs.secret == 'true'
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v2.3.5
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- uses: cachix/install-nix-action@v14.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: cachix/install-nix-action@v12
|
||||
#- run: nix flake check
|
||||
- run: nix-build -A checks.$(if [[ `uname` = Linux ]]; then echo x86_64-linux; else echo x86_64-darwin; fi)
|
||||
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
|
||||
|
|
|
|||
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -15,6 +15,7 @@ perl/Makefile.config
|
|||
/doc/manual/*.1
|
||||
/doc/manual/*.5
|
||||
/doc/manual/*.8
|
||||
/doc/manual/generated/*
|
||||
/doc/manual/nix.json
|
||||
/doc/manual/conf-file.json
|
||||
/doc/manual/builtins.json
|
||||
|
|
@ -39,6 +40,7 @@ perl/Makefile.config
|
|||
|
||||
# /src/libstore/
|
||||
*.gen.*
|
||||
/src/libstore/tests/libstore-tests
|
||||
|
||||
# /src/libutil/
|
||||
/src/libutil/tests/libutil-tests
|
||||
|
|
@ -56,9 +58,6 @@ perl/Makefile.config
|
|||
|
||||
/src/nix-prefetch-url/nix-prefetch-url
|
||||
|
||||
# /src/nix-daemon/
|
||||
/src/nix-daemon/nix-daemon
|
||||
|
||||
/src/nix-collect-garbage/nix-collect-garbage
|
||||
|
||||
# /src/nix-channel/
|
||||
|
|
@ -76,12 +75,12 @@ perl/Makefile.config
|
|||
# /tests/
|
||||
/tests/test-tmp
|
||||
/tests/common.sh
|
||||
/tests/dummy
|
||||
/tests/result*
|
||||
/tests/restricted-innocent
|
||||
/tests/shell
|
||||
/tests/shell.drv
|
||||
/tests/config.nix
|
||||
/tests/ca/config.nix
|
||||
|
||||
# /tests/lang/
|
||||
/tests/lang/*.out
|
||||
|
|
|
|||
2
.version
2
.version
|
|
@ -1 +1 @@
|
|||
2.4
|
||||
2.5
|
||||
6
Makefile
6
Makefile
|
|
@ -4,13 +4,17 @@ makefiles = \
|
|||
src/libutil/local.mk \
|
||||
src/libutil/tests/local.mk \
|
||||
src/libstore/local.mk \
|
||||
src/libstore/tests/local.mk \
|
||||
src/libfetchers/local.mk \
|
||||
src/libmain/local.mk \
|
||||
src/libexpr/local.mk \
|
||||
src/libcmd/local.mk \
|
||||
src/nix/local.mk \
|
||||
src/resolve-system-dependencies/local.mk \
|
||||
scripts/local.mk \
|
||||
misc/bash/local.mk \
|
||||
misc/fish/local.mk \
|
||||
misc/zsh/local.mk \
|
||||
misc/systemd/local.mk \
|
||||
misc/launchd/local.mk \
|
||||
misc/upstart/local.mk \
|
||||
|
|
@ -30,4 +34,4 @@ endif
|
|||
|
||||
include mk/lib.mk
|
||||
|
||||
GLOBAL_CXXFLAGS += -g -Wall -include config.h -std=c++17
|
||||
GLOBAL_CXXFLAGS += -g -Wall -include config.h -std=c++17 -I src
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
HOST_OS = @host_os@
|
||||
AR = @AR@
|
||||
BDW_GC_LIBS = @BDW_GC_LIBS@
|
||||
BOOST_LDFLAGS = @BOOST_LDFLAGS@
|
||||
|
|
@ -9,14 +10,14 @@ CXXFLAGS = @CXXFLAGS@
|
|||
EDITLINE_LIBS = @EDITLINE_LIBS@
|
||||
ENABLE_S3 = @ENABLE_S3@
|
||||
GTEST_LIBS = @GTEST_LIBS@
|
||||
HAVE_LIBCPUID = @HAVE_LIBCPUID@
|
||||
HAVE_SECCOMP = @HAVE_SECCOMP@
|
||||
HAVE_SODIUM = @HAVE_SODIUM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBARCHIVE_LIBS = @LIBARCHIVE_LIBS@
|
||||
LIBBROTLI_LIBS = @LIBBROTLI_LIBS@
|
||||
LIBCURL_LIBS = @LIBCURL_LIBS@
|
||||
LIBLZMA_LIBS = @LIBLZMA_LIBS@
|
||||
OPENSSL_LIBS = @OPENSSL_LIBS@
|
||||
LIBSECCOMP_LIBS = @LIBSECCOMP_LIBS@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
SHELL = @bash@
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ build nix from source with nix-build or how to get a development environment.
|
|||
- [Nix manual](https://nixos.org/nix/manual)
|
||||
- [Nix jobsets on hydra.nixos.org](https://hydra.nixos.org/project/nix)
|
||||
- [NixOS Discourse](https://discourse.nixos.org/)
|
||||
- [IRC - #nixos on freenode.net](irc://irc.freenode.net/#nixos)
|
||||
- [Matrix - #nix:nixos.org](https://matrix.to/#/#nix:nixos.org)
|
||||
- [IRC - #nixos on libera.chat](irc://irc.libera.chat/#nixos)
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
42
boehmgc-coroutine-sp-fallback.diff
Normal file
42
boehmgc-coroutine-sp-fallback.diff
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
diff --git a/pthread_stop_world.c b/pthread_stop_world.c
|
||||
index 1cee6a0b..46c3acd9 100644
|
||||
--- a/pthread_stop_world.c
|
||||
+++ b/pthread_stop_world.c
|
||||
@@ -674,6 +674,8 @@ GC_INNER void GC_push_all_stacks(void)
|
||||
struct GC_traced_stack_sect_s *traced_stack_sect;
|
||||
pthread_t self = pthread_self();
|
||||
word total_size = 0;
|
||||
+ size_t stack_limit;
|
||||
+ pthread_attr_t pattr;
|
||||
|
||||
if (!EXPECT(GC_thr_initialized, TRUE))
|
||||
GC_thr_init();
|
||||
@@ -723,6 +725,28 @@ GC_INNER void GC_push_all_stacks(void)
|
||||
hi = p->altstack + p->altstack_size;
|
||||
/* FIXME: Need to scan the normal stack too, but how ? */
|
||||
/* FIXME: Assume stack grows down */
|
||||
+ } else {
|
||||
+ if (pthread_getattr_np(p->id, &pattr)) {
|
||||
+ ABORT("GC_push_all_stacks: pthread_getattr_np failed!");
|
||||
+ }
|
||||
+ if (pthread_attr_getstacksize(&pattr, &stack_limit)) {
|
||||
+ ABORT("GC_push_all_stacks: pthread_attr_getstacksize failed!");
|
||||
+ }
|
||||
+ // When a thread goes into a coroutine, we lose its original sp until
|
||||
+ // control flow returns to the thread.
|
||||
+ // While in the coroutine, the sp points outside the thread stack,
|
||||
+ // so we can detect this and push the entire thread stack instead,
|
||||
+ // as an approximation.
|
||||
+ // We assume that the coroutine has similarly added its entire stack.
|
||||
+ // This could be made accurate by cooperating with the application
|
||||
+ // via new functions and/or callbacks.
|
||||
+ #ifndef STACK_GROWS_UP
|
||||
+ if (lo >= hi || lo < hi - stack_limit) { // sp outside stack
|
||||
+ lo = hi - stack_limit;
|
||||
+ }
|
||||
+ #else
|
||||
+ #error "STACK_GROWS_UP not supported in boost_coroutine2 (as of june 2021), so we don't support it in Nix."
|
||||
+ #endif
|
||||
}
|
||||
GC_push_all_stack_sections(lo, hi, traced_stack_sect);
|
||||
# ifdef STACK_GROWS_UP
|
||||
20
config/config.guess
vendored
20
config/config.guess
vendored
|
|
@ -1,8 +1,8 @@
|
|||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright 1992-2020 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2021 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2020-11-19'
|
||||
timestamp='2021-01-25'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
|
|
@ -50,7 +50,7 @@ version="\
|
|||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright 1992-2020 Free Software Foundation, Inc.
|
||||
Copyright 1992-2021 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
|
|
@ -188,10 +188,9 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
|||
#
|
||||
# Note: NetBSD doesn't particularly care about the vendor
|
||||
# portion of the name. We always set it to "unknown".
|
||||
sysctl="sysctl -n hw.machine_arch"
|
||||
UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \
|
||||
"/sbin/$sysctl" 2>/dev/null || \
|
||||
"/usr/sbin/$sysctl" 2>/dev/null || \
|
||||
/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
|
||||
/usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
|
||||
echo unknown))
|
||||
case "$UNAME_MACHINE_ARCH" in
|
||||
aarch64eb) machine=aarch64_be-unknown ;;
|
||||
|
|
@ -996,6 +995,9 @@ EOF
|
|||
k1om:Linux:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
m32r*:Linux:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
|
|
@ -1084,7 +1086,7 @@ EOF
|
|||
ppcle:Linux:*:*)
|
||||
echo powerpcle-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
riscv32:Linux:*:* | riscv64:Linux:*:*)
|
||||
riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
s390:Linux:*:* | s390x:Linux:*:*)
|
||||
|
|
@ -1480,8 +1482,8 @@ EOF
|
|||
i*86:rdos:*:*)
|
||||
echo "$UNAME_MACHINE"-pc-rdos
|
||||
exit ;;
|
||||
i*86:AROS:*:*)
|
||||
echo "$UNAME_MACHINE"-pc-aros
|
||||
*:AROS:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-aros
|
||||
exit ;;
|
||||
x86_64:VMkernel:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-esx
|
||||
|
|
|
|||
20
config/config.sub
vendored
20
config/config.sub
vendored
|
|
@ -1,8 +1,8 @@
|
|||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright 1992-2020 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2021 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2020-12-02'
|
||||
timestamp='2021-01-08'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
|
|
@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
|
|||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright 1992-2020 Free Software Foundation, Inc.
|
||||
Copyright 1992-2021 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
|
|
@ -1185,6 +1185,7 @@ case $cpu-$vendor in
|
|||
| k1om \
|
||||
| le32 | le64 \
|
||||
| lm32 \
|
||||
| loongarch32 | loongarch64 | loongarchx32 \
|
||||
| m32c | m32r | m32rle \
|
||||
| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
|
||||
| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
|
||||
|
|
@ -1229,7 +1230,7 @@ case $cpu-$vendor in
|
|||
| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
|
||||
| pru \
|
||||
| pyramid \
|
||||
| riscv | riscv32 | riscv64 \
|
||||
| riscv | riscv32 | riscv32be | riscv64 | riscv64be \
|
||||
| rl78 | romp | rs6000 | rx \
|
||||
| s390 | s390x \
|
||||
| score \
|
||||
|
|
@ -1682,11 +1683,14 @@ fi
|
|||
|
||||
# Now, validate our (potentially fixed-up) OS.
|
||||
case $os in
|
||||
# Sometimes we do "kernel-abi", so those need to count as OSes.
|
||||
# Sometimes we do "kernel-libc", so those need to count as OSes.
|
||||
musl* | newlib* | uclibc*)
|
||||
;;
|
||||
# Likewise for "kernel-libc"
|
||||
eabi | eabihf | gnueabi | gnueabihf)
|
||||
# Likewise for "kernel-abi"
|
||||
eabi* | gnueabi*)
|
||||
;;
|
||||
# VxWorks passes extra cpu info in the 4th filed.
|
||||
simlinux | simwindows | spe)
|
||||
;;
|
||||
# Now accept the basic system types.
|
||||
# The portable systems comes first.
|
||||
|
|
@ -1750,6 +1754,8 @@ case $kernel-$os in
|
|||
;;
|
||||
kfreebsd*-gnu* | kopensolaris*-gnu*)
|
||||
;;
|
||||
vxworks-simlinux | vxworks-simwindows | vxworks-spe)
|
||||
;;
|
||||
nto-qnx*)
|
||||
;;
|
||||
os2-emx)
|
||||
|
|
|
|||
124
configure.ac
124
configure.ac
|
|
@ -1,4 +1,4 @@
|
|||
AC_INIT(nix, m4_esyscmd([bash -c "echo -n $(cat ./.version)$VERSION_SUFFIX"]))
|
||||
AC_INIT([nix],[m4_esyscmd(bash -c "echo -n $(cat ./.version)$VERSION_SUFFIX")])
|
||||
AC_CONFIG_MACRO_DIRS([m4])
|
||||
AC_CONFIG_SRCDIR(README.md)
|
||||
AC_CONFIG_AUX_DIR(config)
|
||||
|
|
@ -9,8 +9,7 @@ AC_PROG_SED
|
|||
AC_CANONICAL_HOST
|
||||
AC_MSG_CHECKING([for the canonical Nix system name])
|
||||
|
||||
AC_ARG_WITH(system, AC_HELP_STRING([--with-system=SYSTEM],
|
||||
[Platform identifier (e.g., `i686-linux').]),
|
||||
AC_ARG_WITH(system, AS_HELP_STRING([--with-system=SYSTEM],[Platform identifier (e.g., `i686-linux').]),
|
||||
[system=$withval],
|
||||
[case "$host_cpu" in
|
||||
i*86)
|
||||
|
|
@ -33,14 +32,6 @@ AC_ARG_WITH(system, AC_HELP_STRING([--with-system=SYSTEM],
|
|||
system="$machine_name-`echo $host_os | "$SED" -e's/@<:@0-9.@:>@*$//g'`";;
|
||||
esac])
|
||||
|
||||
sys_name=$(uname -s | tr 'A-Z ' 'a-z_')
|
||||
|
||||
case $sys_name in
|
||||
cygwin*)
|
||||
sys_name=cygwin
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_MSG_RESULT($system)
|
||||
AC_SUBST(system)
|
||||
AC_DEFINE_UNQUOTED(SYSTEM, ["$system"], [platform identifier ('cpu-os')])
|
||||
|
|
@ -64,10 +55,12 @@ AC_SYS_LARGEFILE
|
|||
|
||||
# Solaris-specific stuff.
|
||||
AC_STRUCT_DIRENT_D_TYPE
|
||||
if test "$sys_name" = sunos; then
|
||||
case "$host_os" in
|
||||
solaris*)
|
||||
# Solaris requires -lsocket -lnsl for network functions
|
||||
LIBS="-lsocket -lnsl $LIBS"
|
||||
fi
|
||||
LDFLAGS="-lsocket -lnsl $LDFLAGS"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# Check for pubsetbuf.
|
||||
|
|
@ -127,8 +120,7 @@ NEED_PROG(jq, jq)
|
|||
AC_SUBST(coreutils, [$(dirname $(type -p cat))])
|
||||
|
||||
|
||||
AC_ARG_WITH(store-dir, AC_HELP_STRING([--with-store-dir=PATH],
|
||||
[path of the Nix store (defaults to /nix/store)]),
|
||||
AC_ARG_WITH(store-dir, AS_HELP_STRING([--with-store-dir=PATH],[path of the Nix store (defaults to /nix/store)]),
|
||||
storedir=$withval, storedir='/nix/store')
|
||||
AC_SUBST(storedir)
|
||||
|
||||
|
|
@ -152,13 +144,12 @@ int main() {
|
|||
}]])], GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC=no, GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC=yes)
|
||||
AC_MSG_RESULT($GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC)
|
||||
if test "x$GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC" = xyes; then
|
||||
LIBS="-latomic $LIBS"
|
||||
LDFLAGS="-latomic $LDFLAGS"
|
||||
fi
|
||||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
AC_ARG_ENABLE(shared, AC_HELP_STRING([--enable-shared],
|
||||
[Build shared libraries for Nix [default=yes]]),
|
||||
AC_ARG_ENABLE(shared, AS_HELP_STRING([--enable-shared],[Build shared libraries for Nix [default=yes]]),
|
||||
shared=$enableval, shared=yes)
|
||||
if test "$shared" = yes; then
|
||||
AC_SUBST(BUILD_SHARED_LIBS, 1, [Whether to build shared libraries.])
|
||||
|
|
@ -172,11 +163,6 @@ fi
|
|||
PKG_CHECK_MODULES([OPENSSL], [libcrypto], [CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"])
|
||||
|
||||
|
||||
# Look for libbz2, a required dependency.
|
||||
AC_CHECK_LIB([bz2], [BZ2_bzWriteOpen], [true],
|
||||
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See https://sourceware.org/bzip2/.])])
|
||||
AC_CHECK_HEADERS([bzlib.h], [true],
|
||||
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See https://sourceware.org/bzip2/.])])
|
||||
# Checks for libarchive
|
||||
PKG_CHECK_MODULES([LIBARCHIVE], [libarchive >= 3.1.2], [CXXFLAGS="$LIBARCHIVE_CFLAGS $CXXFLAGS"])
|
||||
# Workaround until https://github.com/libarchive/libarchive/issues/1446 is fixed
|
||||
|
|
@ -203,51 +189,47 @@ PKG_CHECK_MODULES([EDITLINE], [libeditline], [CXXFLAGS="$EDITLINE_CFLAGS $CXXFLA
|
|||
])
|
||||
|
||||
# Look for libsodium, an optional dependency.
|
||||
PKG_CHECK_MODULES([SODIUM], [libsodium],
|
||||
[AC_DEFINE([HAVE_SODIUM], [1], [Whether to use libsodium for cryptography.])
|
||||
CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"
|
||||
have_sodium=1], [have_sodium=])
|
||||
AC_SUBST(HAVE_SODIUM, [$have_sodium])
|
||||
|
||||
# Look for liblzma, a required dependency.
|
||||
PKG_CHECK_MODULES([LIBLZMA], [liblzma], [CXXFLAGS="$LIBLZMA_CFLAGS $CXXFLAGS"])
|
||||
AC_CHECK_LIB([lzma], [lzma_stream_encoder_mt],
|
||||
[AC_DEFINE([HAVE_LZMA_MT], [1], [xz multithreaded compression support])])
|
||||
|
||||
# Look for zlib, a required dependency.
|
||||
PKG_CHECK_MODULES([ZLIB], [zlib], [CXXFLAGS="$ZLIB_CFLAGS $CXXFLAGS"])
|
||||
AC_CHECK_HEADER([zlib.h],[:],[AC_MSG_ERROR([could not find the zlib.h header])])
|
||||
LDFLAGS="-lz $LDFLAGS"
|
||||
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.
|
||||
if test "$machine_name" = "x86_64"; then
|
||||
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])
|
||||
|
||||
|
||||
# Look for libseccomp, required for Linux sandboxing.
|
||||
if test "$sys_name" = linux; then
|
||||
AC_ARG_ENABLE([seccomp-sandboxing],
|
||||
AC_HELP_STRING([--disable-seccomp-sandboxing],
|
||||
[Don't build support for seccomp sandboxing (only recommended if your arch doesn't support libseccomp yet!)]
|
||||
))
|
||||
if test "x$enable_seccomp_sandboxing" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBSECCOMP], [libseccomp],
|
||||
[CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS"])
|
||||
have_seccomp=1
|
||||
AC_DEFINE([HAVE_SECCOMP], [1], [Whether seccomp is available and should be used for sandboxing.])
|
||||
else
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
AC_ARG_ENABLE([seccomp-sandboxing],
|
||||
AS_HELP_STRING([--disable-seccomp-sandboxing],[Don't build support for seccomp sandboxing (only recommended if your arch doesn't support libseccomp yet!)
|
||||
]))
|
||||
if test "x$enable_seccomp_sandboxing" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBSECCOMP], [libseccomp],
|
||||
[CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS"])
|
||||
have_seccomp=1
|
||||
AC_DEFINE([HAVE_SECCOMP], [1], [Whether seccomp is available and should be used for sandboxing.])
|
||||
else
|
||||
have_seccomp=
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
have_seccomp=
|
||||
fi
|
||||
else
|
||||
have_seccomp=
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(HAVE_SECCOMP, [$have_seccomp])
|
||||
|
||||
|
||||
# Look for aws-cpp-sdk-s3.
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_CHECK_HEADERS([aws/s3/S3Client.h],
|
||||
[AC_DEFINE([ENABLE_S3], [1], [Whether to enable S3 support via aws-sdk-cpp.])
|
||||
enable_s3=1], [enable_s3=])
|
||||
[AC_DEFINE([ENABLE_S3], [1], [Whether to enable S3 support via aws-sdk-cpp.]) enable_s3=1],
|
||||
[AC_DEFINE([ENABLE_S3], [0], [Whether to enable S3 support via aws-sdk-cpp.]) enable_s3=])
|
||||
AC_SUBST(ENABLE_S3, [$enable_s3])
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
|
|
@ -260,8 +242,7 @@ fi
|
|||
|
||||
|
||||
# Whether to use the Boehm garbage collector.
|
||||
AC_ARG_ENABLE(gc, AC_HELP_STRING([--enable-gc],
|
||||
[enable garbage collection in the Nix expression evaluator (requires Boehm GC) [default=yes]]),
|
||||
AC_ARG_ENABLE(gc, AS_HELP_STRING([--enable-gc],[enable garbage collection in the Nix expression evaluator (requires Boehm GC) [default=yes]]),
|
||||
gc=$enableval, gc=yes)
|
||||
if test "$gc" = yes; then
|
||||
PKG_CHECK_MODULES([BDW_GC], [bdw-gc])
|
||||
|
|
@ -275,11 +256,12 @@ PKG_CHECK_MODULES([GTEST], [gtest_main])
|
|||
|
||||
|
||||
# documentation generation switch
|
||||
AC_ARG_ENABLE(doc-gen, AC_HELP_STRING([--disable-doc-gen],
|
||||
[disable documentation generation]),
|
||||
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.8.0], [CXXFLAGS="$LOWDOWN_CFLAGS $CXXFLAGS"])
|
||||
|
||||
# Setuid installations.
|
||||
AC_CHECK_FUNCS([setresuid setreuid lchown])
|
||||
|
|
@ -291,24 +273,14 @@ AC_CHECK_FUNCS([strsignal posix_fallocate sysconf])
|
|||
|
||||
# This is needed if bzip2 is a static library, and the Nix libraries
|
||||
# are dynamic.
|
||||
if test "$(uname)" = "Darwin"; then
|
||||
case "${host_os}" in
|
||||
darwin*)
|
||||
LDFLAGS="-all_load $LDFLAGS"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# Do we have GNU tar?
|
||||
AC_MSG_CHECKING([if you have a recent GNU tar])
|
||||
if $tar --version 2> /dev/null | grep -q GNU && tar cvf /dev/null --warning=no-timestamp ./config.log > /dev/null; then
|
||||
AC_MSG_RESULT(yes)
|
||||
tarFlags="--warning=no-timestamp"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_SUBST(tarFlags)
|
||||
|
||||
|
||||
AC_ARG_WITH(sandbox-shell, AC_HELP_STRING([--with-sandbox-shell=PATH],
|
||||
[path of a statically-linked shell to use as /bin/sh in sandboxes]),
|
||||
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)
|
||||
|
||||
|
|
@ -323,6 +295,6 @@ done
|
|||
|
||||
rm -f Makefile.config
|
||||
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([])
|
||||
AC_OUTPUT
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ builtins:
|
|||
concatStrings (map
|
||||
(name:
|
||||
let builtin = builtins.${name}; in
|
||||
" - `builtins.${name}` " + concatStringsSep " " (map (s: "*${s}*") builtin.args)
|
||||
+ " \n\n"
|
||||
+ concatStrings (map (s: " ${s}\n") (splitLines builtin.doc)) + "\n\n"
|
||||
"<dt><code>${name} "
|
||||
+ concatStringsSep " " (map (s: "<var>${s}</var>") builtin.args)
|
||||
+ "</code></dt>"
|
||||
+ "<dd>\n\n"
|
||||
+ builtin.doc
|
||||
+ "\n\n</dd>"
|
||||
)
|
||||
(attrNames builtins))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
command:
|
||||
{ command, renderLinks ? false }:
|
||||
|
||||
with builtins;
|
||||
with import ./utils.nix;
|
||||
|
|
@ -7,47 +7,77 @@ let
|
|||
|
||||
showCommand =
|
||||
{ command, def, filename }:
|
||||
"# Name\n\n"
|
||||
''
|
||||
**Warning**: This program is **experimental** and its interface is subject to change.
|
||||
''
|
||||
+ "# Name\n\n"
|
||||
+ "`${command}` - ${def.description}\n\n"
|
||||
+ "# Synopsis\n\n"
|
||||
+ showSynopsis { inherit command; args = def.args; }
|
||||
+ (if def.commands or {} != {}
|
||||
then
|
||||
let
|
||||
categories = sort (x: y: x.id < y.id) (unique (map (cmd: cmd.category) (attrValues def.commands)));
|
||||
listCommands = cmds:
|
||||
concatStrings (map (name:
|
||||
"* "
|
||||
+ (if renderLinks
|
||||
then "[`${command} ${name}`](./${appendName filename name}.md)"
|
||||
else "`${command} ${name}`")
|
||||
+ " - ${cmds.${name}.description}\n")
|
||||
(attrNames cmds));
|
||||
in
|
||||
"where *subcommand* is one of the following:\n\n"
|
||||
# FIXME: group by category
|
||||
+ concatStrings (map (name:
|
||||
"* [`${command} ${name}`](./${appendName filename name}.md) - ${def.commands.${name}.description}\n")
|
||||
(attrNames def.commands))
|
||||
+ "\n"
|
||||
+ (if length categories > 1
|
||||
then
|
||||
concatStrings (map
|
||||
(cat:
|
||||
"**${toString cat.description}:**\n\n"
|
||||
+ listCommands (filterAttrs (n: v: v.category == cat) def.commands)
|
||||
+ "\n"
|
||||
) categories)
|
||||
+ "\n"
|
||||
else
|
||||
listCommands def.commands
|
||||
+ "\n")
|
||||
else "")
|
||||
+ (if def ? doc
|
||||
then def.doc + "\n\n"
|
||||
else "")
|
||||
+ (let s = showFlags def.flags; in
|
||||
+ (let s = showOptions def.flags; in
|
||||
if s != ""
|
||||
then "# Flags\n\n${s}"
|
||||
then "# Options\n\n${s}"
|
||||
else "")
|
||||
;
|
||||
|
||||
appendName = filename: name: (if filename == "nix" then "nix3" else filename) + "-" + name;
|
||||
|
||||
showFlags = flags:
|
||||
concatStrings
|
||||
(map (longName:
|
||||
let flag = flags.${longName}; in
|
||||
if flag.category or "" != "config"
|
||||
then
|
||||
" - `--${longName}`"
|
||||
+ (if flag ? shortName then " / `-${flag.shortName}`" else "")
|
||||
+ (if flag ? labels then " " + (concatStringsSep " " (map (s: "*${s}*") flag.labels)) else "")
|
||||
+ " \n"
|
||||
+ " " + flag.description + "\n\n"
|
||||
else "")
|
||||
(attrNames flags));
|
||||
showOptions = flags:
|
||||
let
|
||||
categories = sort builtins.lessThan (unique (map (cmd: cmd.category) (attrValues flags)));
|
||||
in
|
||||
concatStrings (map
|
||||
(cat:
|
||||
(if cat != ""
|
||||
then "**${cat}:**\n\n"
|
||||
else "")
|
||||
+ concatStrings
|
||||
(map (longName:
|
||||
let
|
||||
flag = flags.${longName};
|
||||
in
|
||||
" - `--${longName}`"
|
||||
+ (if flag ? shortName then " / `-${flag.shortName}`" else "")
|
||||
+ (if flag ? labels then " " + (concatStringsSep " " (map (s: "*${s}*") flag.labels)) else "")
|
||||
+ " \n"
|
||||
+ " " + flag.description + "\n\n"
|
||||
) (attrNames (filterAttrs (n: v: v.category == cat) flags))))
|
||||
categories);
|
||||
|
||||
showSynopsis =
|
||||
{ command, args }:
|
||||
"`${command}` [*flags*...] ${concatStringsSep " "
|
||||
"`${command}` [*option*...] ${concatStringsSep " "
|
||||
(map (arg: "*${arg.label}*" + (if arg ? arity then "" else "...")) args)}\n\n";
|
||||
|
||||
processCommand = { command, def, filename }:
|
||||
|
|
@ -63,7 +93,7 @@ let
|
|||
in
|
||||
|
||||
let
|
||||
manpages = processCommand { filename = "nix"; command = "nix"; def = command; };
|
||||
manpages = processCommand { filename = "nix"; command = "nix"; def = builtins.fromJSON command; };
|
||||
summary = concatStrings (map (manpage: " - [${manpage.command}](command-ref/new-cli/${manpage.name})\n") manpages);
|
||||
in
|
||||
(listToAttrs manpages) // { "SUMMARY.md" = summary; }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
ifeq ($(doc_generate),yes)
|
||||
|
||||
MANUAL_SRCS := $(call rwildcard, $(d)/src, *.md)
|
||||
|
||||
# Generate man pages.
|
||||
man-pages := $(foreach n, \
|
||||
nix-env.1 nix-build.1 nix-shell.1 nix-store.1 nix-instantiate.1 \
|
||||
|
|
@ -25,19 +23,19 @@ nix-eval = $(dummy-env) $(bindir)/nix eval --experimental-features nix-command -
|
|||
$(d)/%.1: $(d)/src/command-ref/%.md
|
||||
@printf "Title: %s\n\n" "$$(basename $@ .1)" > $^.tmp
|
||||
@cat $^ >> $^.tmp
|
||||
$(trace-gen) lowdown -sT man $^.tmp -o $@
|
||||
$(trace-gen) lowdown -sT man -M section=1 $^.tmp -o $@
|
||||
@rm $^.tmp
|
||||
|
||||
$(d)/%.8: $(d)/src/command-ref/%.md
|
||||
@printf "Title: %s\n\n" "$$(basename $@ .8)" > $^.tmp
|
||||
@cat $^ >> $^.tmp
|
||||
$(trace-gen) lowdown -sT man $^.tmp -o $@
|
||||
$(trace-gen) lowdown -sT man -M section=8 $^.tmp -o $@
|
||||
@rm $^.tmp
|
||||
|
||||
$(d)/nix.conf.5: $(d)/src/command-ref/conf-file.md
|
||||
@printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp
|
||||
@cat $^ >> $^.tmp
|
||||
$(trace-gen) lowdown -sT man $^.tmp -o $@
|
||||
$(trace-gen) lowdown -sT man -M section=5 $^.tmp -o $@
|
||||
@rm $^.tmp
|
||||
|
||||
$(d)/src/SUMMARY.md: $(d)/src/SUMMARY.md.in $(d)/src/command-ref/new-cli
|
||||
|
|
@ -46,7 +44,7 @@ $(d)/src/SUMMARY.md: $(d)/src/SUMMARY.md.in $(d)/src/command-ref/new-cli
|
|||
|
||||
$(d)/src/command-ref/new-cli: $(d)/nix.json $(d)/generate-manpage.nix $(bindir)/nix
|
||||
@rm -rf $@
|
||||
$(trace-gen) $(nix-eval) --write-to $@ --expr 'import doc/manual/generate-manpage.nix (builtins.fromJSON (builtins.readFile $<))'
|
||||
$(trace-gen) $(nix-eval) --write-to $@ --expr 'import doc/manual/generate-manpage.nix { command = builtins.readFile $<; renderLinks = true; }'
|
||||
|
||||
$(d)/src/command-ref/conf-file.md: $(d)/conf-file.json $(d)/generate-options.nix $(d)/src/command-ref/conf-file-prefix.md $(bindir)/nix
|
||||
@cat doc/manual/src/command-ref/conf-file-prefix.md > $@.tmp
|
||||
|
|
@ -64,6 +62,7 @@ $(d)/conf-file.json: $(bindir)/nix
|
|||
$(d)/src/expressions/builtins.md: $(d)/builtins.json $(d)/generate-builtins.nix $(d)/src/expressions/builtins-prefix.md $(bindir)/nix
|
||||
@cat doc/manual/src/expressions/builtins-prefix.md > $@.tmp
|
||||
$(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-builtins.nix (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp
|
||||
@cat doc/manual/src/expressions/builtins-suffix.md >> $@.tmp
|
||||
@mv $@.tmp $@
|
||||
|
||||
$(d)/builtins.json: $(bindir)/nix
|
||||
|
|
@ -74,17 +73,28 @@ $(d)/builtins.json: $(bindir)/nix
|
|||
install: $(docdir)/manual/index.html
|
||||
|
||||
# Generate 'nix' manpages.
|
||||
install: $(d)/src/command-ref/new-cli
|
||||
install: $(mandir)/man1/nix3-manpages
|
||||
man: doc/manual/generated/man1/nix3-manpages
|
||||
all: doc/manual/generated/man1/nix3-manpages
|
||||
|
||||
$(mandir)/man1/nix3-manpages: doc/manual/generated/man1/nix3-manpages
|
||||
@mkdir -p $(DESTDIR)$$(dirname $@)
|
||||
$(trace-install) install -m 0644 $$(dirname $<)/* $(DESTDIR)$$(dirname $@)
|
||||
|
||||
doc/manual/generated/man1/nix3-manpages: $(d)/src/command-ref/new-cli
|
||||
@mkdir -p $(DESTDIR)$$(dirname $@)
|
||||
$(trace-gen) for i in doc/manual/src/command-ref/new-cli/*.md; do \
|
||||
name=$$(basename $$i .md); \
|
||||
tmpFile=$$(mktemp); \
|
||||
if [[ $$name = SUMMARY ]]; then continue; fi; \
|
||||
printf "Title: %s\n\n" "$$name" > $$i.tmp; \
|
||||
cat $$i >> $$i.tmp; \
|
||||
lowdown -sT man $$i.tmp -o $(mandir)/man1/$$name.1; \
|
||||
printf "Title: %s\n\n" "$$name" > $$tmpFile; \
|
||||
cat $$i >> $$tmpFile; \
|
||||
lowdown -sT man -M section=1 $$tmpFile -o $(DESTDIR)$$(dirname $@)/$$name.1; \
|
||||
rm $$tmpFile; \
|
||||
done
|
||||
@touch $@
|
||||
|
||||
$(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
|
||||
$(trace-gen) RUST_LOG=warn mdbook build doc/manual -d $(docdir)/manual
|
||||
@cp doc/manual/highlight.pack.js $(docdir)/manual/highlight.js
|
||||
$(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
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@
|
|||
- [Hacking](contributing/hacking.md)
|
||||
- [CLI guideline](contributing/cli-guideline.md)
|
||||
- [Release Notes](release-notes/release-notes.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)
|
||||
- [Release 2.1 (2018-09-02)](release-notes/rl-2.1.md)
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ Nix has two relevant settings with regards to how your CPU cores will
|
|||
be utilized: `cores` and `max-jobs`. This chapter will talk about what
|
||||
they are, how they interact, and their configuration trade-offs.
|
||||
|
||||
- `max-jobs`
|
||||
- `max-jobs`\
|
||||
Dictates how many separate derivations will be built at the same
|
||||
time. If you set this to zero, the local machine will do no
|
||||
builds. Nix will still substitute from binary caches, and build
|
||||
remotely if remote builders are configured.
|
||||
|
||||
- `cores`
|
||||
- `cores`\
|
||||
Suggests how many cores each derivation should use. Similar to
|
||||
`make -j`.
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ then you need to ensure that the `PATH` of non-interactive login shells
|
|||
contains Nix.
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
>
|
||||
> If you are building via the Nix daemon, it is the Nix daemon user
|
||||
> account (that is, `root`) that should have SSH access to the remote
|
||||
> machine. If you can’t or don’t want to configure `root` to be able to
|
||||
|
|
@ -52,7 +52,7 @@ example, the following command allows you to build a derivation for
|
|||
```console
|
||||
$ uname
|
||||
Linux
|
||||
|
||||
|
||||
$ nix build \
|
||||
'(with import <nixpkgs> { system = "x86_64-darwin"; }; runCommand "foo" {} "uname > $out")' \
|
||||
--builders 'ssh://mac x86_64-darwin'
|
||||
|
|
@ -103,7 +103,7 @@ default, set it to `-`.
|
|||
```nix
|
||||
requiredSystemFeatures = [ "kvm" ];
|
||||
```
|
||||
|
||||
|
||||
will cause the build to be performed on a machine that has the `kvm`
|
||||
feature.
|
||||
|
||||
|
|
@ -112,6 +112,10 @@ default, set it to `-`.
|
|||
features appear in the derivation’s `requiredSystemFeatures`
|
||||
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
|
||||
via `base64 -w0 /etc/ssh/ssh_host_ed25519_key.pub`.
|
||||
|
||||
For example, the machine specification
|
||||
|
||||
nix@scratchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 1 kvm
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ set -f # disable globbing
|
|||
export IFS=' '
|
||||
|
||||
echo "Signing paths" $OUT_PATHS
|
||||
nix sign-paths --key-file /etc/nix/key.private $OUT_PATHS
|
||||
nix store sign --key-file /etc/nix/key.private $OUT_PATHS
|
||||
echo "Uploading paths" $OUT_PATHS
|
||||
exec nix copy --to 's3://example-nix-cache' $OUT_PATHS
|
||||
```
|
||||
|
|
@ -63,7 +63,7 @@ exec nix copy --to 's3://example-nix-cache' $OUT_PATHS
|
|||
> The `$OUT_PATHS` variable is a space-separated list of Nix store
|
||||
> paths. In this case, we expect and want the shell to perform word
|
||||
> splitting to make each output path its own argument to `nix
|
||||
> sign-paths`. Nix guarantees the paths will not contain any spaces,
|
||||
> store sign`. Nix guarantees the paths will not contain any spaces,
|
||||
> however a store path might contain glob characters. The `set -f`
|
||||
> disables globbing in the shell.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,45 +2,49 @@
|
|||
|
||||
Most Nix commands interpret the following environment variables:
|
||||
|
||||
- `IN_NIX_SHELL`
|
||||
- `IN_NIX_SHELL`\
|
||||
Indicator that tells if the current environment was set up by
|
||||
`nix-shell`. Since Nix 2.0 the values are `"pure"` and `"impure"`
|
||||
|
||||
- `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
|
||||
|
||||
|
||||
/home/eelco/Dev:/etc/nixos
|
||||
|
||||
|
||||
will cause Nix to look for paths relative to `/home/eelco/Dev` and
|
||||
`/etc/nixos`, in this order. It is also possible to match paths
|
||||
against a prefix. For example, the value
|
||||
|
||||
|
||||
nixpkgs=/home/eelco/Dev/nixpkgs-branch:/etc/nixos
|
||||
|
||||
|
||||
will cause Nix to search for `<nixpkgs/path>` in
|
||||
`/home/eelco/Dev/nixpkgs-branch/path` and `/etc/nixos/nixpkgs/path`.
|
||||
|
||||
|
||||
If a path in the Nix search path starts with `http://` or
|
||||
`https://`, it is interpreted as the URL of a tarball that will be
|
||||
downloaded and unpacked to a temporary location. The tarball must
|
||||
consist of a single top-level directory. For example, setting
|
||||
`NIX_PATH` to
|
||||
|
||||
nixpkgs=https://github.com/NixOS/nixpkgs/archive/nixos-15.09.tar.gz
|
||||
|
||||
tells Nix to download the latest revision in the Nixpkgs/NixOS 15.09
|
||||
channel.
|
||||
|
||||
A following shorthand can be used to refer to the official channels:
|
||||
|
||||
nixpkgs=channel:nixos-15.09
|
||||
|
||||
The search path can be extended using the `-I` option, which takes
|
||||
precedence over `NIX_PATH`.
|
||||
|
||||
- `NIX_IGNORE_SYMLINK_STORE`
|
||||
nixpkgs=https://github.com/NixOS/nixpkgs/archive/master.tar.gz
|
||||
|
||||
tells Nix to download and use the current contents of the
|
||||
`master` branch in the `nixpkgs` repository.
|
||||
|
||||
The URLs of the tarballs from the official nixos.org channels (see
|
||||
[the manual for `nix-channel`](nix-channel.md)) can be abbreviated
|
||||
as `channel:<channel-name>`. For instance, the following two
|
||||
values of `NIX_PATH` are equivalent:
|
||||
|
||||
nixpkgs=channel:nixos-21.05
|
||||
nixpkgs=https://nixos.org/channels/nixos-21.05/nixexprs.tar.xz
|
||||
|
||||
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`\
|
||||
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
|
||||
|
|
@ -50,7 +54,7 @@ Most Nix commands interpret the following environment variables:
|
|||
builds are deployed to machines where `/nix/store` resolves
|
||||
differently. If you are sure that you’re not going to do that, you
|
||||
can set `NIX_IGNORE_SYMLINK_STORE` to `1`.
|
||||
|
||||
|
||||
Note that if you’re symlinking the Nix store so that you can put it
|
||||
on another file system than the root file system, on Linux you’re
|
||||
better off using `bind` mount points, e.g.,
|
||||
|
|
@ -59,44 +63,44 @@ Most Nix commands interpret the following environment variables:
|
|||
$ mkdir /nix
|
||||
$ mount -o bind /mnt/otherdisk/nix /nix
|
||||
```
|
||||
|
||||
|
||||
Consult the mount 8 manual page for details.
|
||||
|
||||
- `NIX_STORE_DIR`
|
||||
- `NIX_STORE_DIR`\
|
||||
Overrides the location of the Nix store (default `prefix/store`).
|
||||
|
||||
- `NIX_DATA_DIR`
|
||||
- `NIX_DATA_DIR`\
|
||||
Overrides the location of the Nix static data directory (default
|
||||
`prefix/share`).
|
||||
|
||||
- `NIX_LOG_DIR`
|
||||
- `NIX_LOG_DIR`\
|
||||
Overrides the location of the Nix log directory (default
|
||||
`prefix/var/log/nix`).
|
||||
|
||||
- `NIX_STATE_DIR`
|
||||
- `NIX_STATE_DIR`\
|
||||
Overrides the location of the Nix state directory (default
|
||||
`prefix/var/nix`).
|
||||
|
||||
- `NIX_CONF_DIR`
|
||||
- `NIX_CONF_DIR`\
|
||||
Overrides the location of the system Nix configuration directory
|
||||
(default `prefix/etc/nix`).
|
||||
|
||||
- `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`
|
||||
- `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`
|
||||
- `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`
|
||||
- `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
|
||||
|
|
@ -104,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`
|
||||
- `NIX_SHOW_STATS`\
|
||||
If set to `1`, Nix will print some evaluation statistics, such as
|
||||
the number of values allocated.
|
||||
|
||||
- `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`
|
||||
- `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`
|
||||
- `--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`
|
||||
- `--dry-run`\
|
||||
Show what store paths would be built or downloaded.
|
||||
|
||||
- `--out-link` / `-o` *outlink*
|
||||
- `--out-link` / `-o` *outlink*\
|
||||
Change the name of the symlink to the output path created from
|
||||
`result` to *outlink*.
|
||||
|
||||
|
|
|
|||
|
|
@ -17,26 +17,26 @@ To see the list of official NixOS channels, visit
|
|||
|
||||
This command has the following operations:
|
||||
|
||||
- `--add` *url* \[*name*\]
|
||||
- `--add` *url* \[*name*\]\
|
||||
Adds a channel named *name* with URL *url* to the list of subscribed
|
||||
channels. If *name* is omitted, it defaults to the last component of
|
||||
*url*, with the suffixes `-stable` or `-unstable` removed.
|
||||
|
||||
- `--remove` *name*
|
||||
- `--remove` *name*\
|
||||
Removes the channel named *name* from the list of subscribed
|
||||
channels.
|
||||
|
||||
- `--list`
|
||||
- `--list`\
|
||||
Prints the names and URLs of all subscribed channels on standard
|
||||
output.
|
||||
|
||||
- `--update` \[*names*…\]
|
||||
- `--update` \[*names*…\]\
|
||||
Downloads the Nix expressions of all subscribed channels (or only
|
||||
those included in *names* if specified) and makes them the default
|
||||
for `nix-env` operations (by symlinking them from the directory
|
||||
`~/.nix-defexpr`).
|
||||
|
||||
- `--rollback` \[*generation*\]
|
||||
- `--rollback` \[*generation*\]\
|
||||
Reverts the previous call to `nix-channel
|
||||
--update`. Optionally, you can specify a specific channel generation
|
||||
number to restore.
|
||||
|
|
@ -70,14 +70,14 @@ $ nix-instantiate --eval -E '(import <nixpkgs> {}).lib.version'
|
|||
|
||||
# Files
|
||||
|
||||
- `/nix/var/nix/profiles/per-user/username/channels`
|
||||
- `/nix/var/nix/profiles/per-user/username/channels`\
|
||||
`nix-channel` uses a `nix-env` profile to keep track of previous
|
||||
versions of the subscribed channels. Every time you run `nix-channel
|
||||
--update`, a new channel generation (that is, a symlink to the
|
||||
channel Nix expressions in the Nix store) is created. This enables
|
||||
`nix-channel --rollback` to revert to previous versions.
|
||||
|
||||
- `~/.nix-defexpr/channels`
|
||||
- `~/.nix-defexpr/channels`\
|
||||
This is a symlink to
|
||||
`/nix/var/nix/profiles/per-user/username/channels`. It ensures that
|
||||
`nix-env` can find your channels. In a multi-user installation, you
|
||||
|
|
@ -89,7 +89,7 @@ $ nix-instantiate --eval -E '(import <nixpkgs> {}).lib.version'
|
|||
A channel URL should point to a directory containing the following
|
||||
files:
|
||||
|
||||
- `nixexprs.tar.xz`
|
||||
- `nixexprs.tar.xz`\
|
||||
A tarball containing Nix expressions and files referenced by them
|
||||
(such as build scripts and patches). At the top level, the tarball
|
||||
should contain a single directory. That directory must contain a
|
||||
|
|
|
|||
|
|
@ -35,21 +35,21 @@ and second to send the dump of those paths. If this bothers you, use
|
|||
|
||||
# Options
|
||||
|
||||
- `--to`
|
||||
- `--to`\
|
||||
Copy the closure of _paths_ from the local Nix store to the Nix
|
||||
store on _machine_. This is the default.
|
||||
|
||||
- `--from`
|
||||
- `--from`\
|
||||
Copy the closure of _paths_ from the Nix store on _machine_ to the
|
||||
local Nix store.
|
||||
|
||||
- `--gzip`
|
||||
- `--gzip`\
|
||||
Enable compression of the SSH connection.
|
||||
|
||||
- `--include-outputs`
|
||||
- `--include-outputs`\
|
||||
Also copy the outputs of store derivations included in the closure.
|
||||
|
||||
- `--use-substitutes` / `-s`
|
||||
- `--use-substitutes` / `-s`\
|
||||
Attempt to download missing paths on the target machine using Nix’s
|
||||
substitute mechanism. Any paths that cannot be substituted on the
|
||||
target are still copied normally from the source. This is useful,
|
||||
|
|
@ -58,12 +58,12 @@ and second to send the dump of those paths. If this bothers you, use
|
|||
`nixos.org` (the default binary cache server) is
|
||||
fast.
|
||||
|
||||
- `-v`
|
||||
- `-v`\
|
||||
Show verbose output.
|
||||
|
||||
# Environment variables
|
||||
|
||||
- `NIX_SSHOPTS`
|
||||
- `NIX_SSHOPTS`\
|
||||
Additional options to be passed to `ssh` on the command
|
||||
line.
|
||||
|
||||
|
|
|
|||
|
|
@ -36,27 +36,27 @@ case-sensitive. The regular expression can optionally be followed by a
|
|||
dash and a version number; if omitted, any version of the package will
|
||||
match. Here are some examples:
|
||||
|
||||
- `firefox`
|
||||
- `firefox`\
|
||||
Matches the package name `firefox` and any version.
|
||||
|
||||
- `firefox-32.0`
|
||||
- `firefox-32.0`\
|
||||
Matches the package name `firefox` and version `32.0`.
|
||||
|
||||
- `gtk\\+`
|
||||
- `gtk\\+`\
|
||||
Matches the package name `gtk+`. The `+` character must be escaped
|
||||
using a backslash to prevent it from being interpreted as a
|
||||
quantifier, and the backslash must be escaped in turn with another
|
||||
backslash to ensure that the shell passes it on.
|
||||
|
||||
- `.\*`
|
||||
- `.\*`\
|
||||
Matches any package name. This is the default for most commands.
|
||||
|
||||
- `'.*zip.*'`
|
||||
- `'.*zip.*'`\
|
||||
Matches any package name containing the string `zip`. Note the dots:
|
||||
`'*zip*'` does not work, because in a regular expression, the
|
||||
character `*` is interpreted as a quantifier.
|
||||
|
||||
- `'.*(firefox|chromium).*'`
|
||||
- `'.*(firefox|chromium).*'`\
|
||||
Matches any package name containing the strings `firefox` or
|
||||
`chromium`.
|
||||
|
||||
|
|
@ -66,7 +66,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.
|
||||
|
||||
- `--file` / `-f` *path*
|
||||
- `--file` / `-f` *path*\
|
||||
Specifies the Nix expression (designated below as the *active Nix
|
||||
expression*) used by the `--install`, `--upgrade`, and `--query
|
||||
--available` operations to obtain derivations. The default is
|
||||
|
|
@ -77,13 +77,13 @@ have an effect.
|
|||
unpacked to a temporary location. The tarball must include a single
|
||||
top-level directory containing at least a file named `default.nix`.
|
||||
|
||||
- `--profile` / `-p` *path*
|
||||
- `--profile` / `-p` *path*\
|
||||
Specifies the profile to be used by those operations that operate on
|
||||
a profile (designated below as the *active profile*). A profile is a
|
||||
sequence of user environments called *generations*, one of which is
|
||||
the *current generation*.
|
||||
|
||||
- `--dry-run`
|
||||
- `--dry-run`\
|
||||
For the `--install`, `--upgrade`, `--uninstall`,
|
||||
`--switch-generation`, `--delete-generations` and `--rollback`
|
||||
operations, this flag will cause `nix-env` to print what *would* be
|
||||
|
|
@ -93,7 +93,7 @@ have an effect.
|
|||
[substituted](../glossary.md) (i.e., downloaded) and which paths
|
||||
will be built from source (because no substitute is available).
|
||||
|
||||
- `--system-filter` *system*
|
||||
- `--system-filter` *system*\
|
||||
By default, operations such as `--query
|
||||
--available` show derivations matching any platform. This option
|
||||
allows you to use derivations for the specified platform *system*.
|
||||
|
|
@ -102,7 +102,7 @@ have an effect.
|
|||
|
||||
# Files
|
||||
|
||||
- `~/.nix-defexpr`
|
||||
- `~/.nix-defexpr`\
|
||||
The source for the default Nix expressions used by the
|
||||
`--install`, `--upgrade`, and `--query --available` operations to
|
||||
obtain derivations. The `--file` option may be used to override
|
||||
|
|
@ -140,7 +140,7 @@ have an effect.
|
|||
The command `nix-channel` places symlinks to the downloaded Nix
|
||||
expressions from each subscribed channel in this directory.
|
||||
|
||||
- `~/.nix-profile`
|
||||
- `~/.nix-profile`\
|
||||
A symbolic link to the user's current profile. By default, this
|
||||
symlink points to `prefix/var/nix/profiles/default`. The `PATH`
|
||||
environment variable should include `~/.nix-profile/bin` for the
|
||||
|
|
@ -217,13 +217,13 @@ a number of possible ways:
|
|||
|
||||
## Flags
|
||||
|
||||
- `--prebuilt-only` / `-b`
|
||||
- `--prebuilt-only` / `-b`\
|
||||
Use only derivations for which a substitute is registered, i.e.,
|
||||
there is a pre-built binary available that can be downloaded in lieu
|
||||
of building the derivation. Thus, no packages will be built from
|
||||
source.
|
||||
|
||||
- `--preserve-installed`; `-P`
|
||||
- `--preserve-installed`; `-P`\
|
||||
Do not remove derivations with a name matching one of the
|
||||
derivations being installed. Usually, trying to have two versions of
|
||||
the same package installed in the same generation of a profile will
|
||||
|
|
@ -231,7 +231,7 @@ a number of possible ways:
|
|||
clashes between the two versions. However, this is not the case for
|
||||
all packages.
|
||||
|
||||
- `--remove-all`; `-r`
|
||||
- `--remove-all`; `-r`\
|
||||
Remove all previously installed packages first. This is equivalent
|
||||
to running `nix-env -e '.*'` first, except that everything happens
|
||||
in a single transaction.
|
||||
|
|
@ -346,24 +346,24 @@ version is installed.
|
|||
|
||||
## Flags
|
||||
|
||||
- `--lt`
|
||||
- `--lt`\
|
||||
Only upgrade a derivation to newer versions. This is the default.
|
||||
|
||||
- `--leq`
|
||||
- `--leq`\
|
||||
In addition to upgrading to newer versions, also “upgrade” to
|
||||
derivations that have the same version. Version are not a unique
|
||||
identification of a derivation, so there may be many derivations
|
||||
that have the same version. This flag may be useful to force
|
||||
“synchronisation” between the installed and available derivations.
|
||||
|
||||
- `--eq`
|
||||
- `--eq`\
|
||||
*Only* “upgrade” to derivations that have the same version. This may
|
||||
not seem very useful, but it actually is, e.g., when there is a new
|
||||
release of Nixpkgs and you want to replace installed applications
|
||||
with the same versions built against newer dependencies (to reduce
|
||||
the number of dependencies floating around on your system).
|
||||
|
||||
- `--always`
|
||||
- `--always`\
|
||||
In addition to upgrading to newer versions, also “upgrade” to
|
||||
derivations that have the same or a lower version. I.e., derivations
|
||||
may actually be downgraded depending on what is available in the
|
||||
|
|
@ -578,11 +578,11 @@ The derivations are sorted by their `name` attributes.
|
|||
The following flags specify the set of things on which the query
|
||||
operates.
|
||||
|
||||
- `--installed`
|
||||
- `--installed`\
|
||||
The query operates on the store paths that are installed in the
|
||||
current generation of the active profile. This is the default.
|
||||
|
||||
- `--available`; `-a`
|
||||
- `--available`; `-a`\
|
||||
The query operates on the derivations that are available in the
|
||||
active Nix expression.
|
||||
|
||||
|
|
@ -593,24 +593,24 @@ selected derivations. Multiple flags may be specified, in which case the
|
|||
information is shown in the order given here. Note that the name of the
|
||||
derivation is shown unless `--no-name` is specified.
|
||||
|
||||
- `--xml`
|
||||
- `--xml`\
|
||||
Print the result in an XML representation suitable for automatic
|
||||
processing by other tools. The root element is called `items`, which
|
||||
contains a `item` element for each available or installed
|
||||
derivation. The fields discussed below are all stored in attributes
|
||||
of the `item` elements.
|
||||
|
||||
- `--json`
|
||||
- `--json`\
|
||||
Print the result in a JSON representation suitable for automatic
|
||||
processing by other tools.
|
||||
|
||||
- `--prebuilt-only` / `-b`
|
||||
- `--prebuilt-only` / `-b`\
|
||||
Show only derivations for which a substitute is registered, i.e.,
|
||||
there is a pre-built binary available that can be downloaded in lieu
|
||||
of building the derivation. Thus, this shows all packages that
|
||||
probably can be installed quickly.
|
||||
|
||||
- `--status`; `-s`
|
||||
- `--status`; `-s`\
|
||||
Print the *status* of the derivation. The status consists of three
|
||||
characters. The first is `I` or `-`, indicating whether the
|
||||
derivation is currently installed in the current generation of the
|
||||
|
|
@ -621,49 +621,49 @@ derivation is shown unless `--no-name` is specified.
|
|||
derivation to be built. The third is `S` or `-`, indicating whether
|
||||
a substitute is available for the derivation.
|
||||
|
||||
- `--attr-path`; `-P`
|
||||
- `--attr-path`; `-P`\
|
||||
Print the *attribute path* of the derivation, which can be used to
|
||||
unambiguously select it using the `--attr` option available in
|
||||
commands that install derivations like `nix-env --install`. This
|
||||
option only works together with `--available`
|
||||
|
||||
- `--no-name`
|
||||
- `--no-name`\
|
||||
Suppress printing of the `name` attribute of each derivation.
|
||||
|
||||
- `--compare-versions` / `-c`
|
||||
- `--compare-versions` / `-c`\
|
||||
Compare installed versions to available versions, or vice versa (if
|
||||
`--available` is given). This is useful for quickly seeing whether
|
||||
upgrades for installed packages are available in a Nix expression. A
|
||||
column is added with the following meaning:
|
||||
|
||||
- `<` *version*
|
||||
- `<` *version*\
|
||||
A newer version of the package is available or installed.
|
||||
|
||||
- `=` *version*
|
||||
- `=` *version*\
|
||||
At most the same version of the package is available or
|
||||
installed.
|
||||
|
||||
- `>` *version*
|
||||
- `>` *version*\
|
||||
Only older versions of the package are available or installed.
|
||||
|
||||
- `- ?`
|
||||
- `- ?`\
|
||||
No version of the package is available or installed.
|
||||
|
||||
- `--system`
|
||||
- `--system`\
|
||||
Print the `system` attribute of the derivation.
|
||||
|
||||
- `--drv-path`
|
||||
- `--drv-path`\
|
||||
Print the path of the store derivation.
|
||||
|
||||
- `--out-path`
|
||||
- `--out-path`\
|
||||
Print the output path of the derivation.
|
||||
|
||||
- `--description`
|
||||
- `--description`\
|
||||
Print a short (one-line) description of the derivation, if
|
||||
available. The description is taken from the `meta.description`
|
||||
attribute of the derivation.
|
||||
|
||||
- `--meta`
|
||||
- `--meta`\
|
||||
Print all of the meta-attributes of the derivation. This option is
|
||||
only available with `--xml` or `--json`.
|
||||
|
||||
|
|
@ -874,7 +874,7 @@ error: no generation older than the current (91) exists
|
|||
|
||||
# Environment variables
|
||||
|
||||
- `NIX_PROFILE`
|
||||
- `NIX_PROFILE`\
|
||||
Location of the Nix profile. Defaults to the target of the symlink
|
||||
`~/.nix-profile`, if it exists, or `/nix/var/nix/profiles/default`
|
||||
otherwise.
|
||||
|
|
|
|||
|
|
@ -29,29 +29,29 @@ md5sum`.
|
|||
|
||||
# Options
|
||||
|
||||
- `--flat`
|
||||
- `--flat`\
|
||||
Print the cryptographic hash of the contents of each regular file
|
||||
*path*. That is, do not compute the hash over the dump of *path*.
|
||||
The result is identical to that produced by the GNU commands
|
||||
`md5sum` and `sha1sum`.
|
||||
|
||||
- `--base32`
|
||||
- `--base32`\
|
||||
Print the hash in a base-32 representation rather than hexadecimal.
|
||||
This base-32 representation is more compact and can be used in Nix
|
||||
expressions (such as in calls to `fetchurl`).
|
||||
|
||||
- `--truncate`
|
||||
- `--truncate`\
|
||||
Truncate hashes longer than 160 bits (such as SHA-256) to 160 bits.
|
||||
|
||||
- `--type` *hashAlgo*
|
||||
- `--type` *hashAlgo*\
|
||||
Use the specified cryptographic hash algorithm, which can be one of
|
||||
`md5`, `sha1`, `sha256`, and `sha512`.
|
||||
|
||||
- `--to-base16`
|
||||
- `--to-base16`\
|
||||
Don’t hash anything, but convert the base-32 hash representation
|
||||
*hash* to hexadecimal.
|
||||
|
||||
- `--to-base32`
|
||||
- `--to-base32`\
|
||||
Don’t hash anything, but convert the hexadecimal hash representation
|
||||
*hash* to base-32.
|
||||
|
||||
|
|
|
|||
|
|
@ -29,26 +29,26 @@ standard input.
|
|||
|
||||
# Options
|
||||
|
||||
- `--add-root` *path*
|
||||
- `--add-root` *path*\
|
||||
See the [corresponding option](nix-store.md) in `nix-store`.
|
||||
|
||||
- `--parse`
|
||||
- `--parse`\
|
||||
Just parse the input files, and print their abstract syntax trees on
|
||||
standard output in ATerm format.
|
||||
|
||||
- `--eval`
|
||||
- `--eval`\
|
||||
Just parse and evaluate the input files, and print the resulting
|
||||
values on standard output. No instantiation of store derivations
|
||||
takes place.
|
||||
|
||||
- `--find-file`
|
||||
- `--find-file`\
|
||||
Look up the given files in Nix’s search path (as specified by the
|
||||
`NIX_PATH` environment variable). If found, print the corresponding
|
||||
absolute paths on standard output. For instance, if `NIX_PATH` is
|
||||
`nixpkgs=/home/alice/nixpkgs`, then `nix-instantiate --find-file
|
||||
nixpkgs/default.nix` will print `/home/alice/nixpkgs/default.nix`.
|
||||
|
||||
- `--strict`
|
||||
- `--strict`\
|
||||
When used with `--eval`, recursively evaluate list elements and
|
||||
attributes. Normally, such sub-expressions are left unevaluated
|
||||
(since the Nix expression language is lazy).
|
||||
|
|
@ -58,17 +58,17 @@ standard input.
|
|||
> This option can cause non-termination, because lazy data
|
||||
> structures can be infinitely large.
|
||||
|
||||
- `--json`
|
||||
- `--json`\
|
||||
When used with `--eval`, print the resulting value as an JSON
|
||||
representation of the abstract syntax tree rather than as an ATerm.
|
||||
|
||||
- `--xml`
|
||||
- `--xml`\
|
||||
When used with `--eval`, print the resulting value as an XML
|
||||
representation of the abstract syntax tree rather than as an ATerm.
|
||||
The schema is the same as that used by the [`toXML`
|
||||
built-in](../expressions/builtins.md).
|
||||
|
||||
- `--read-write-mode`
|
||||
- `--read-write-mode`\
|
||||
When used with `--eval`, perform evaluation in read/write mode so
|
||||
nix language features that require it will still work (at the cost
|
||||
of needing to do instantiation of every evaluated derivation). If
|
||||
|
|
|
|||
|
|
@ -37,22 +37,22 @@ Nix store is also printed.
|
|||
|
||||
# Options
|
||||
|
||||
- `--type` *hashAlgo*
|
||||
- `--type` *hashAlgo*\
|
||||
Use the specified cryptographic hash algorithm, which can be one of
|
||||
`md5`, `sha1`, `sha256`, and `sha512`.
|
||||
|
||||
- `--print-path`
|
||||
- `--print-path`\
|
||||
Print the store path of the downloaded file on standard output.
|
||||
|
||||
- `--unpack`
|
||||
- `--unpack`\
|
||||
Unpack the archive (which must be a tarball or zip file) and add the
|
||||
result to the Nix store. The resulting hash can be used with
|
||||
functions such as Nixpkgs’s `fetchzip` or `fetchFromGitHub`.
|
||||
|
||||
- `--executable`
|
||||
- `--executable`\
|
||||
Set the executable bit on the downloaded file.
|
||||
|
||||
- `--name` *name*
|
||||
- `--name` *name*\
|
||||
Override the name of the file in the Nix store. By default, this is
|
||||
`hash-basename`, where *basename* is the last component of *url*.
|
||||
Overriding the name is necessary when *basename* contains characters
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
[`--command` *cmd*]
|
||||
[`--run` *cmd*]
|
||||
[`--exclude` *regexp*]
|
||||
[--pure]
|
||||
[--keep *name*]
|
||||
[`--pure`]
|
||||
[`--keep` *name*]
|
||||
{{`--packages` | `-p`} {*packages* | *expressions*} … | [*path*]}
|
||||
|
||||
# Description
|
||||
|
|
@ -54,7 +54,7 @@ All options not listed here are passed to `nix-store
|
|||
--realise`, except for `--arg` and `--attr` / `-A` which are passed to
|
||||
`nix-instantiate`.
|
||||
|
||||
- `--command` *cmd*
|
||||
- `--command` *cmd*\
|
||||
In the environment of the derivation, run the shell command *cmd*.
|
||||
This command is executed in an interactive shell. (Use `--run` to
|
||||
use a non-interactive shell instead.) However, a call to `exit` is
|
||||
|
|
@ -64,36 +64,34 @@ All options not listed here are passed to `nix-store
|
|||
drop you into the interactive shell. This can be useful for doing
|
||||
any additional initialisation.
|
||||
|
||||
- `--run` *cmd*
|
||||
- `--run` *cmd*\
|
||||
Like `--command`, but executes the command in a non-interactive
|
||||
shell. This means (among other things) that if you hit Ctrl-C while
|
||||
the command is running, the shell exits.
|
||||
|
||||
- `--exclude` *regexp*
|
||||
- `--exclude` *regexp*\
|
||||
Do not build any dependencies whose store path matches the regular
|
||||
expression *regexp*. This option may be specified multiple times.
|
||||
|
||||
- `--pure`
|
||||
- `--pure`\
|
||||
If this flag is specified, the environment is almost entirely
|
||||
cleared before the interactive shell is started, so you get an
|
||||
environment that more closely corresponds to the “real” Nix build. A
|
||||
few variables, in particular `HOME`, `USER` and `DISPLAY`, are
|
||||
retained. Note that (depending on your Bash
|
||||
installation) `/etc/bashrc` is still sourced, so any variables set
|
||||
there will affect the interactive shell.
|
||||
retained.
|
||||
|
||||
- `--packages` / `-p` *packages*…
|
||||
- `--packages` / `-p` *packages*…\
|
||||
Set up an environment in which the specified packages are present.
|
||||
The command line arguments are interpreted as attribute names inside
|
||||
the Nix Packages collection. Thus, `nix-shell -p libjpeg openjdk`
|
||||
will start a shell in which the packages denoted by the attribute
|
||||
names `libjpeg` and `openjdk` are present.
|
||||
|
||||
- `-i` *interpreter*
|
||||
- `-i` *interpreter*\
|
||||
The chained script interpreter to be invoked by `nix-shell`. Only
|
||||
applicable in `#!`-scripts (described below).
|
||||
|
||||
- `--keep` *name*
|
||||
- `--keep` *name*\
|
||||
When a `--pure` shell is started, keep the listed environment
|
||||
variables.
|
||||
|
||||
|
|
@ -101,7 +99,7 @@ The following common options are supported:
|
|||
|
||||
# Environment variables
|
||||
|
||||
- `NIX_BUILD_SHELL`
|
||||
- `NIX_BUILD_SHELL`\
|
||||
Shell used to start the interactive environment. Defaults to the
|
||||
`bash` found in `PATH`.
|
||||
|
||||
|
|
@ -112,13 +110,19 @@ shell in which to build it:
|
|||
|
||||
```console
|
||||
$ nix-shell '<nixpkgs>' -A pan
|
||||
[nix-shell]$ unpackPhase
|
||||
[nix-shell]$ eval ${unpackPhase:-unpackPhase}
|
||||
[nix-shell]$ cd pan-*
|
||||
[nix-shell]$ configurePhase
|
||||
[nix-shell]$ buildPhase
|
||||
[nix-shell]$ eval ${configurePhase:-configurePhase}
|
||||
[nix-shell]$ eval ${buildPhase:-buildPhase}
|
||||
[nix-shell]$ ./pan/gui/pan
|
||||
```
|
||||
|
||||
The reason we use form `eval ${configurePhase:-configurePhase}` here is because
|
||||
those packages that override these phases do so by exporting the overridden
|
||||
values in the environment variable of the same name.
|
||||
Here bash is being told to either evaluate the contents of 'configurePhase',
|
||||
if it exists as a variable, otherwise evaluate the configurePhase function.
|
||||
|
||||
To clear the environment first, and do some additional automatic
|
||||
initialisation of the interactive shell:
|
||||
|
||||
|
|
@ -232,22 +236,23 @@ terraform apply
|
|||
> in a nix-shell shebang.
|
||||
|
||||
Finally, using the merging of multiple nix-shell shebangs the following
|
||||
Haskell script uses a specific branch of Nixpkgs/NixOS (the 18.03 stable
|
||||
Haskell script uses a specific branch of Nixpkgs/NixOS (the 20.03 stable
|
||||
branch):
|
||||
|
||||
```haskell
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i runghc -p "haskellPackages.ghcWithPackages (ps: [ps.HTTP ps.tagsoup])"
|
||||
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/nixos-18.03.tar.gz
|
||||
#! nix-shell -i runghc -p "haskellPackages.ghcWithPackages (ps: [ps.download-curl ps.tagsoup])"
|
||||
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/nixos-20.03.tar.gz
|
||||
|
||||
import Network.HTTP
|
||||
import Network.Curl.Download
|
||||
import Text.HTML.TagSoup
|
||||
import Data.Either
|
||||
import Data.ByteString.Char8 (unpack)
|
||||
|
||||
-- Fetch nixos.org and print all hrefs.
|
||||
main = do
|
||||
resp <- Network.HTTP.simpleHTTP (getRequest "http://nixos.org/")
|
||||
body <- getResponseBody resp
|
||||
let tags = filter (isTagOpenName "a") $ parseTags body
|
||||
resp <- openURI "https://nixos.org/"
|
||||
let tags = filter (isTagOpenName "a") $ parseTags $ unpack $ fromRight undefined resp
|
||||
let tags' = map (fromAttrib "href") tags
|
||||
mapM_ putStrLn $ filter (/= "") tags'
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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` *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
|
||||
|
|
@ -79,22 +79,22 @@ paths. Realisation is a somewhat overloaded term:
|
|||
system). If the path is already valid, we are done immediately.
|
||||
Otherwise, the path and any missing paths in its closure may be
|
||||
produced through substitutes. If there are no (successful)
|
||||
subsitutes, realisation fails.
|
||||
substitutes, realisation fails.
|
||||
|
||||
The output path of each derivation is printed on standard output. (For
|
||||
non-derivations argument, the argument itself is printed.)
|
||||
|
||||
The following flags are available:
|
||||
|
||||
- `--dry-run`
|
||||
- `--dry-run`\
|
||||
Print on standard error a description of what packages would be
|
||||
built or downloaded, without actually performing the operation.
|
||||
|
||||
- `--ignore-unknown`
|
||||
- `--ignore-unknown`\
|
||||
If a non-derivation path does not have a substitute, then silently
|
||||
ignore it.
|
||||
|
||||
- `--check`
|
||||
- `--check`\
|
||||
This option allows you to check whether a derivation is
|
||||
deterministic. It rebuilds the specified derivation and checks
|
||||
whether the result is bitwise-identical with the existing outputs,
|
||||
|
|
@ -110,20 +110,20 @@ The following flags are available:
|
|||
|
||||
Special exit codes:
|
||||
|
||||
- `100`
|
||||
- `100`\
|
||||
Generic build failure, the builder process returned with a non-zero
|
||||
exit code.
|
||||
|
||||
- `101`
|
||||
- `101`\
|
||||
Build timeout, the build was aborted because it did not complete
|
||||
within the specified `timeout`.
|
||||
|
||||
- `102`
|
||||
- `102`\
|
||||
Hash mismatch, the build output was rejected because it does not
|
||||
match the [`outputHash` attribute of the
|
||||
derivation](../expressions/advanced-attributes.md).
|
||||
|
||||
- `104`
|
||||
- `104`\
|
||||
Not deterministic, the build succeeded in check mode but the
|
||||
resulting output is not binary reproducable.
|
||||
|
||||
|
|
@ -170,7 +170,7 @@ access to a restricted ssh user.
|
|||
|
||||
The following flags are available:
|
||||
|
||||
- `--write`
|
||||
- `--write`\
|
||||
Allow the connected client to request the realization of
|
||||
derivations. In effect, this can be used to make the host act as a
|
||||
remote builder.
|
||||
|
|
@ -200,18 +200,18 @@ reachable via file system references from a set of “roots”, are deleted.
|
|||
|
||||
The following suboperations may be specified:
|
||||
|
||||
- `--print-roots`
|
||||
- `--print-roots`\
|
||||
This operation prints on standard output the set of roots used by
|
||||
the garbage collector.
|
||||
|
||||
- `--print-live`
|
||||
- `--print-live`\
|
||||
This operation prints on standard output the set of “live” store
|
||||
paths, which are all the store paths reachable from the roots. Live
|
||||
paths should never be deleted, since that would break consistency —
|
||||
it would become possible that applications are installed that
|
||||
reference things that are no longer present in the store.
|
||||
|
||||
- `--print-dead`
|
||||
- `--print-dead`\
|
||||
This operation prints out on standard output the set of “dead” store
|
||||
paths, which is just the opposite of the set of live paths: any path
|
||||
in the store that is not live (with respect to the roots) is dead.
|
||||
|
|
@ -219,14 +219,14 @@ The following suboperations may be specified:
|
|||
By default, all unreachable paths are deleted. The following options
|
||||
control what gets deleted and in what order:
|
||||
|
||||
- `--max-freed` *bytes*
|
||||
- `--max-freed` *bytes*\
|
||||
Keep deleting paths until at least *bytes* bytes have been deleted,
|
||||
then stop. The argument *bytes* can be followed by the
|
||||
multiplicative suffix `K`, `M`, `G` or `T`, denoting KiB, MiB, GiB
|
||||
or TiB units.
|
||||
|
||||
The behaviour of the collector is also influenced by the
|
||||
`keep-outputs` and `keep-derivations` variables in the Nix
|
||||
`keep-outputs` and `keep-derivations` settings in the Nix
|
||||
configuration file.
|
||||
|
||||
By default, the collector prints the total number of freed bytes when it
|
||||
|
|
@ -300,22 +300,22 @@ symlink.
|
|||
|
||||
## Common query options
|
||||
|
||||
- `--use-output`; `-u`
|
||||
- `--use-output`; `-u`\
|
||||
For each argument to the query that is a store derivation, apply the
|
||||
query to the output path of the derivation instead.
|
||||
|
||||
- `--force-realise`; `-f`
|
||||
- `--force-realise`; `-f`\
|
||||
Realise each argument to the query first (see [`nix-store
|
||||
--realise`](#operation---realise)).
|
||||
|
||||
## Queries
|
||||
|
||||
- `--outputs`
|
||||
- `--outputs`\
|
||||
Prints out the [output paths](../glossary.md) of the store
|
||||
derivations *paths*. These are the paths that will be produced when
|
||||
the derivation is built.
|
||||
|
||||
- `--requisites`; `-R`
|
||||
- `--requisites`; `-R`\
|
||||
Prints out the [closure](../glossary.md) of the store path *paths*.
|
||||
|
||||
This query has one option:
|
||||
|
|
@ -332,31 +332,31 @@ symlink.
|
|||
dependencies) is obtained by distributing the closure of a store
|
||||
derivation and specifying the option `--include-outputs`.
|
||||
|
||||
- `--references`
|
||||
- `--references`\
|
||||
Prints the set of [references](../glossary.md) of the store paths
|
||||
*paths*, that is, their immediate dependencies. (For *all*
|
||||
dependencies, use `--requisites`.)
|
||||
|
||||
- `--referrers`
|
||||
- `--referrers`\
|
||||
Prints the set of *referrers* of the store paths *paths*, that is,
|
||||
the store paths currently existing in the Nix store that refer to
|
||||
one of *paths*. Note that contrary to the references, the set of
|
||||
referrers is not constant; it can change as store paths are added or
|
||||
removed.
|
||||
|
||||
- `--referrers-closure`
|
||||
- `--referrers-closure`\
|
||||
Prints the closure of the set of store paths *paths* under the
|
||||
referrers relation; that is, all store paths that directly or
|
||||
indirectly refer to one of *paths*. These are all the path currently
|
||||
in the Nix store that are dependent on *paths*.
|
||||
|
||||
- `--deriver`; `-d`
|
||||
- `--deriver`; `-d`\
|
||||
Prints the [deriver](../glossary.md) of the store paths *paths*. If
|
||||
the path has no deriver (e.g., if it is a source file), or if the
|
||||
deriver is not known (e.g., in the case of a binary-only
|
||||
deployment), the string `unknown-deriver` is printed.
|
||||
|
||||
- `--graph`
|
||||
- `--graph`\
|
||||
Prints the references graph of the store paths *paths* in the format
|
||||
of the `dot` tool of AT\&T's [Graphviz
|
||||
package](http://www.graphviz.org/). This can be used to visualise
|
||||
|
|
@ -364,39 +364,39 @@ symlink.
|
|||
this to a store derivation. To obtain a runtime dependency graph,
|
||||
apply it to an output path.
|
||||
|
||||
- `--tree`
|
||||
- `--tree`\
|
||||
Prints the references graph of the store paths *paths* as a nested
|
||||
ASCII tree. References are ordered by descending closure size; this
|
||||
tends to flatten the tree, making it more readable. The query only
|
||||
recurses into a store path when it is first encountered; this
|
||||
prevents a blowup of the tree representation of the graph.
|
||||
|
||||
- `--graphml`
|
||||
- `--graphml`\
|
||||
Prints the references graph of the store paths *paths* in the
|
||||
[GraphML](http://graphml.graphdrawing.org/) file format. This can be
|
||||
used to visualise dependency graphs. To obtain a build-time
|
||||
dependency graph, apply this to a store derivation. To obtain a
|
||||
runtime dependency graph, apply it to an output path.
|
||||
|
||||
- `--binding` *name*; `-b` *name*
|
||||
- `--binding` *name*; `-b` *name*\
|
||||
Prints the value of the attribute *name* (i.e., environment
|
||||
variable) of the store derivations *paths*. It is an error for a
|
||||
derivation to not have the specified attribute.
|
||||
|
||||
- `--hash`
|
||||
- `--hash`\
|
||||
Prints the SHA-256 hash of the contents of the store paths *paths*
|
||||
(that is, the hash of the output of `nix-store --dump` on the given
|
||||
paths). Since the hash is stored in the Nix database, this is a fast
|
||||
operation.
|
||||
|
||||
- `--size`
|
||||
- `--size`\
|
||||
Prints the size in bytes of the contents of the store paths *paths*
|
||||
— to be precise, the size of the output of `nix-store --dump` on
|
||||
the given paths. Note that the actual disk space required by the
|
||||
store paths may be higher, especially on filesystems with large
|
||||
cluster sizes.
|
||||
|
||||
- `--roots`
|
||||
- `--roots`\
|
||||
Prints the garbage collector roots that point, directly or
|
||||
indirectly, at the store paths *paths*.
|
||||
|
||||
|
|
@ -513,7 +513,7 @@ public url or broke since the download expression was written.
|
|||
|
||||
This operation has the following options:
|
||||
|
||||
- `--recursive`
|
||||
- `--recursive`\
|
||||
Use recursive instead of flat hashing mode, used when adding
|
||||
directories to the store.
|
||||
|
||||
|
|
@ -540,14 +540,14 @@ being modified by non-Nix tools, or of bugs in Nix itself.
|
|||
|
||||
This operation has the following options:
|
||||
|
||||
- `--check-contents`
|
||||
- `--check-contents`\
|
||||
Checks that the contents of every valid store path has not been
|
||||
altered by computing a SHA-256 hash of the contents and comparing it
|
||||
with the hash stored in the Nix database at build time. Paths that
|
||||
have been modified are printed out. For large stores,
|
||||
`--check-contents` is obviously quite slow.
|
||||
|
||||
- `--repair`
|
||||
- `--repair`\
|
||||
If any valid path is missing from the store, or (if
|
||||
`--check-contents` is given) the contents of a valid path has been
|
||||
modified, then try to repair the path by redownloading it. See
|
||||
|
|
|
|||
|
|
@ -2,56 +2,56 @@
|
|||
|
||||
Most Nix commands accept the following command-line options:
|
||||
|
||||
- `--help`
|
||||
- `--help`\
|
||||
Prints out a summary of the command syntax and exits.
|
||||
|
||||
- `--version`
|
||||
- `--version`\
|
||||
Prints out the Nix version number on standard output and exits.
|
||||
|
||||
- `--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
|
||||
printed on standard error, never on standard output.
|
||||
|
||||
|
||||
This option may be specified repeatedly. Currently, the following
|
||||
verbosity levels exist:
|
||||
|
||||
- 0
|
||||
|
||||
- 0\
|
||||
“Errors only”: only print messages explaining why the Nix
|
||||
invocation failed.
|
||||
|
||||
- 1
|
||||
|
||||
- 1\
|
||||
“Informational”: print *useful* messages about what Nix is
|
||||
doing. This is the default.
|
||||
|
||||
- 2
|
||||
|
||||
- 2\
|
||||
“Talkative”: print more informational messages.
|
||||
|
||||
- 3
|
||||
|
||||
- 3\
|
||||
“Chatty”: print even more informational messages.
|
||||
|
||||
- 4
|
||||
|
||||
- 4\
|
||||
“Debug”: print debug information.
|
||||
|
||||
- 5
|
||||
|
||||
- 5\
|
||||
“Vomit”: print vast amounts of debug information.
|
||||
|
||||
- `--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` *format*
|
||||
- `--log-format` *format*\
|
||||
This option can be used to change the output of the log format, with
|
||||
*format* being one of:
|
||||
|
||||
- raw
|
||||
|
||||
- raw\
|
||||
This is the raw format, as outputted by nix-build.
|
||||
|
||||
- internal-json
|
||||
|
||||
- internal-json\
|
||||
Outputs the logs in a structured manner.
|
||||
|
||||
> **Warning**
|
||||
|
|
@ -60,30 +60,30 @@ Most Nix commands accept the following command-line options:
|
|||
> the error-messages (namely of the `msg`-field) can change
|
||||
> between releases.
|
||||
|
||||
- bar
|
||||
- bar\
|
||||
Only display a progress bar during the builds.
|
||||
|
||||
- bar-with-logs
|
||||
|
||||
- bar-with-logs\
|
||||
Display the raw logs, with the progress bar at the bottom.
|
||||
|
||||
- `--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` / `-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`
|
||||
configuration setting, which itself defaults to `1`. A higher
|
||||
value is useful on SMP systems or to exploit I/O latency.
|
||||
|
||||
|
||||
Setting it to `0` disallows building on the local machine, which is
|
||||
useful when you want builds to happen only on remote builders.
|
||||
|
||||
- `--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`
|
||||
- `--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`
|
||||
- `--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` / `-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,17 +113,17 @@ 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` / `-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`
|
||||
- `--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.
|
||||
|
||||
|
||||
The most common scenario in which this is useful is when we have
|
||||
registered substitutes in order to perform binary distribution from,
|
||||
say, a network repository. If the repository is down, the
|
||||
|
|
@ -134,21 +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).
|
||||
|
||||
- `--no-build-hook`
|
||||
Disables the build hook mechanism. This allows to ignore remote
|
||||
builders if they are setup on the machine.
|
||||
|
||||
It's useful in cases where the bandwidth between the client and the
|
||||
remote builder is too low. In that case it can take more time to
|
||||
upload the sources to the remote builder and fetch back the result
|
||||
than to do the computation locally.
|
||||
|
||||
- `--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` *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
|
||||
|
|
@ -160,7 +151,7 @@ Most Nix commands accept the following command-line options:
|
|||
override a default value). That is, if the evaluator encounters a
|
||||
function with an argument named *name*, it will call it with value
|
||||
*value*.
|
||||
|
||||
|
||||
For instance, the top-level `default.nix` in Nixpkgs is actually a
|
||||
function:
|
||||
|
||||
|
|
@ -170,7 +161,7 @@ Most Nix commands accept the following command-line options:
|
|||
...
|
||||
}: ...
|
||||
```
|
||||
|
||||
|
||||
So if you call this Nix expression (e.g., when you do `nix-env -i
|
||||
pkgname`), the function will be called automatically using the
|
||||
value [`builtins.currentSystem`](../expressions/builtins.md) for
|
||||
|
|
@ -179,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` *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` / `-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
|
||||
|
|
@ -194,34 +185,34 @@ Most Nix commands accept the following command-line options:
|
|||
would cause the expression `e.xorg.xorgserver` to be used. See
|
||||
[`nix-env --install`](nix-env.md#operation---install) for some
|
||||
concrete examples.
|
||||
|
||||
|
||||
In addition to attribute names, you can also specify array indices.
|
||||
For instance, the attribute path `foo.3.bar` selects the `bar`
|
||||
attribute of the fourth element of the array in the `foo` attribute
|
||||
of the top-level expression.
|
||||
|
||||
- `--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.)
|
||||
|
||||
|
||||
For `nix-shell`, this option is commonly used to give you a shell in
|
||||
which you can build the packages returned by the expression. If you
|
||||
want to get a shell which contain the *built* packages ready for
|
||||
use, give your expression to the `nix-shell -p` convenience flag
|
||||
instead.
|
||||
|
||||
- `-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` *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`
|
||||
- `--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
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
Derivations can declare some infrequently used optional attributes.
|
||||
|
||||
- `allowedReferences`
|
||||
- `allowedReferences`\
|
||||
The optional attribute `allowedReferences` specifies a list of legal
|
||||
references (dependencies) of the output of the builder. For example,
|
||||
|
||||
|
||||
```nix
|
||||
allowedReferences = [];
|
||||
```
|
||||
|
||||
|
||||
enforces that the output of a derivation cannot have any runtime
|
||||
dependencies on its inputs. To allow an output to have a runtime
|
||||
dependency on itself, use `"out"` as a list item. This is used in
|
||||
|
|
@ -17,45 +17,45 @@ Derivations can declare some infrequently used optional attributes.
|
|||
booting Linux don’t have accidental dependencies on other paths in
|
||||
the Nix store.
|
||||
|
||||
- `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,
|
||||
|
||||
|
||||
```nix
|
||||
allowedRequisites = [ foobar ];
|
||||
```
|
||||
|
||||
|
||||
enforces that the output of a derivation cannot have any other
|
||||
runtime dependency than `foobar`, and in addition it enforces that
|
||||
`foobar` itself doesn't introduce any other dependency itself.
|
||||
|
||||
- `disallowedReferences`
|
||||
- `disallowedReferences`\
|
||||
The optional attribute `disallowedReferences` specifies a list of
|
||||
illegal references (dependencies) of the output of the builder. For
|
||||
example,
|
||||
|
||||
|
||||
```nix
|
||||
disallowedReferences = [ foo ];
|
||||
```
|
||||
|
||||
|
||||
enforces that the output of a derivation cannot have a direct
|
||||
runtime dependencies on the derivation `foo`.
|
||||
|
||||
- `disallowedRequisites`
|
||||
- `disallowedRequisites`\
|
||||
This attribute is similar to `disallowedReferences`, but it
|
||||
specifies illegal requisites for the whole closure, so all the
|
||||
dependencies recursively. For example,
|
||||
|
||||
|
||||
```nix
|
||||
disallowedRequisites = [ foobar ];
|
||||
```
|
||||
|
||||
|
||||
enforces that the output of a derivation cannot have any runtime
|
||||
dependency on `foobar` or any other derivation depending recursively
|
||||
on `foobar`.
|
||||
|
||||
- `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
|
||||
|
|
@ -65,17 +65,17 @@ Derivations can declare some infrequently used optional attributes.
|
|||
files have the format used by `nix-store --register-validity`
|
||||
(with the deriver fields left empty). For example, when the
|
||||
following derivation is built:
|
||||
|
||||
|
||||
```nix
|
||||
derivation {
|
||||
...
|
||||
exportReferencesGraph = [ "libfoo-graph" libfoo ];
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
the references graph of `libfoo` is placed in the file
|
||||
`libfoo-graph` in the temporary build directory.
|
||||
|
||||
|
||||
`exportReferencesGraph` is useful for builders that want to do
|
||||
something with the closure of a store path. Examples include the
|
||||
builders in NixOS that generate the initial ramdisk for booting
|
||||
|
|
@ -84,66 +84,66 @@ Derivations can declare some infrequently used optional attributes.
|
|||
with a Nix store containing the closure of a bootable NixOS
|
||||
configuration).
|
||||
|
||||
- `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
|
||||
builder is executed, but with this attribute you can allow specific
|
||||
environment variables to be passed unmodified. For example,
|
||||
`fetchurl` in Nixpkgs has the line
|
||||
|
||||
|
||||
```nix
|
||||
impureEnvVars = [ "http_proxy" "https_proxy" ... ];
|
||||
```
|
||||
|
||||
|
||||
to make it use the proxy server configuration specified by the user
|
||||
in the environment variables `http_proxy` and friends.
|
||||
|
||||
|
||||
This attribute is only allowed in *fixed-output derivations* (see
|
||||
below), where impurities such as these are okay since (the hash
|
||||
of) the output is known in advance. It is ignored for all other
|
||||
derivations.
|
||||
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
>
|
||||
> `impureEnvVars` implementation takes environment variables from
|
||||
> the current builder process. When a daemon is building its
|
||||
> environmental variables are used. Without the daemon, the
|
||||
> environmental variables come from the environment of the
|
||||
> `nix-build`.
|
||||
|
||||
- `outputHash`; `outputHashAlgo`; `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
|
||||
fixed-output derivation finishes, Nix computes the cryptographic
|
||||
hash of the output and compares it to the hash declared with these
|
||||
attributes. If there is a mismatch, the build fails.
|
||||
|
||||
|
||||
The rationale for fixed-output derivations is derivations such as
|
||||
those produced by the `fetchurl` function. This function downloads a
|
||||
file from a given URL. To ensure that the downloaded file has not
|
||||
been modified, the caller must also specify a cryptographic hash of
|
||||
the file. For example,
|
||||
|
||||
|
||||
```nix
|
||||
fetchurl {
|
||||
url = "http://ftp.gnu.org/pub/gnu/hello/hello-2.1.1.tar.gz";
|
||||
sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
It sometimes happens that the URL of the file changes, e.g., because
|
||||
servers are reorganised or no longer available. We then must update
|
||||
the call to `fetchurl`, e.g.,
|
||||
|
||||
|
||||
```nix
|
||||
fetchurl {
|
||||
url = "ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz";
|
||||
sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
If a `fetchurl` derivation was treated like a normal derivation, the
|
||||
output paths of the derivation and *all derivations depending on it*
|
||||
would change. For instance, if we were to change the URL of the
|
||||
|
|
@ -151,16 +151,16 @@ Derivations can declare some infrequently used optional attributes.
|
|||
other packages depend) massive rebuilds would be needed. This is
|
||||
unfortunate for a change which we know cannot have a real effect as
|
||||
it propagates upwards through the dependency graph.
|
||||
|
||||
|
||||
For fixed-output derivations, on the other hand, the name of the
|
||||
output path only depends on the `outputHash*` and `name` attributes,
|
||||
while all other attributes are ignored for the purpose of computing
|
||||
the output path. (The `name` attribute is included because it is
|
||||
part of the path.)
|
||||
|
||||
|
||||
As an example, here is the (simplified) Nix expression for
|
||||
`fetchurl`:
|
||||
|
||||
|
||||
```nix
|
||||
{ stdenv, curl }: # The curl program is used for downloading.
|
||||
|
||||
|
|
@ -180,43 +180,51 @@ Derivations can declare some infrequently used optional attributes.
|
|||
inherit url;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
The `outputHashAlgo` attribute specifies the hash algorithm used to
|
||||
compute the hash. It can currently be `"sha1"`, `"sha256"` or
|
||||
`"sha512"`.
|
||||
|
||||
|
||||
The `outputHashMode` attribute determines how the hash is computed.
|
||||
It must be one of the following two values:
|
||||
|
||||
- `"flat"`
|
||||
|
||||
- `"flat"`\
|
||||
The output must be a non-executable regular file. If it isn’t,
|
||||
the build fails. The hash is simply computed over the contents
|
||||
of that file (so it’s equal to what Unix commands like
|
||||
`sha256sum` or `sha1sum` produce).
|
||||
|
||||
|
||||
This is the default.
|
||||
|
||||
- `"recursive"`
|
||||
|
||||
- `"recursive"`\
|
||||
The hash is computed over the NAR archive dump of the output
|
||||
(i.e., the result of [`nix-store
|
||||
--dump`](../command-ref/nix-store.md#operation---dump)). In
|
||||
this case, the output can be anything, including a directory
|
||||
tree.
|
||||
|
||||
|
||||
The `outputHash` attribute, finally, must be a string containing
|
||||
the hash in either hexadecimal or base-32 notation. (See the
|
||||
[`nix-hash` command](../command-ref/nix-hash.md) for information
|
||||
about converting to and from base-32 notation.)
|
||||
|
||||
- `__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.
|
||||
This only has an effect if the `ca-derivation` experimental feature is enabled.
|
||||
|
||||
Setting this attribute also requires setting `outputHashMode` and `outputHashAlgo` like for *fixed-output derivations* (see above).
|
||||
|
||||
- `passAsFile`
|
||||
- `passAsFile`\
|
||||
A list of names of attributes that should be passed via files rather
|
||||
than environment variables. For example, if you have
|
||||
|
||||
|
||||
```nix
|
||||
passAsFile = ["big"];
|
||||
big = "a very long string";
|
||||
```
|
||||
|
||||
|
||||
then when the builder runs, the environment variable `bigPath`
|
||||
will contain the absolute path to a temporary file containing `a
|
||||
very long string`. That is, for any attribute *x* listed in
|
||||
|
|
@ -226,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`
|
||||
- `preferLocalBuild`\
|
||||
If this attribute is set to `true` and [distributed building is
|
||||
enabled](../advanced-topics/distributed-builds.md), then, if
|
||||
possible, the derivaton will be built locally instead of forwarded
|
||||
|
|
@ -234,14 +242,14 @@ 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`
|
||||
- `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)
|
||||
that are cheaper to build than to substitute from a binary cache.
|
||||
|
||||
|
||||
> **Note**
|
||||
>
|
||||
>
|
||||
> You need to have a builder configured which satisfies the
|
||||
> derivation’s `system` attribute, since the derivation cannot be
|
||||
> substituted. Thus it is usually a good idea to align `system` with
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Here are the constants built into the Nix expression evaluator:
|
||||
|
||||
- `builtins`
|
||||
- `builtins`\
|
||||
The set `builtins` contains all the built-in functions and values.
|
||||
You can use `builtins` to test for the availability of features in
|
||||
the Nix installation, e.g.,
|
||||
|
|
@ -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`\
|
||||
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"`.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ scope. Instead, you can access them through the `builtins` built-in
|
|||
value, which is a set that contains all built-in functions and values.
|
||||
For instance, `derivation` is also available as `builtins.derivation`.
|
||||
|
||||
- `derivation` *attrs*; `builtins.derivation` *attrs*
|
||||
|
||||
`derivation` is described in [its own section](derivations.md).
|
||||
|
||||
<dl>
|
||||
<dt><code>derivation <var>attrs</var></code>;
|
||||
<code>builtins.derivation <var>attrs</var></code></dt>
|
||||
<dd><p><var>derivation</var> in described in
|
||||
<a href="derivations.md">its own section</a>.</p></dd>
|
||||
|
|
|
|||
1
doc/manual/src/expressions/builtins-suffix.md
Normal file
1
doc/manual/src/expressions/builtins-suffix.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
</dl>
|
||||
|
|
@ -25,5 +25,4 @@ order of precedence (from strongest to weakest binding).
|
|||
| Inequality | *e1* `!=` *e2* | none | Inequality. | 11 |
|
||||
| Logical AND | *e1* `&&` *e2* | left | Logical AND. | 12 |
|
||||
| Logical OR | *e1* `\|\|` *e2* | left | Logical OR. | 13 |
|
||||
| Logical Implication | *e1* `->` *e2* | none | Logical implication (equivalent to `!e1 \|\|
|
||||
e2`). | 14 |
|
||||
| Logical Implication | *e1* `->` *e2* | none | Logical implication (equivalent to `!e1 \|\| e2`). | 14 |
|
||||
|
|
|
|||
|
|
@ -139,6 +139,13 @@ Nix has the following basic data types:
|
|||
environment variable `NIX_PATH` will be searched for the given file
|
||||
or directory name.
|
||||
|
||||
Antiquotation is supported in any paths except those in angle brackets.
|
||||
`./${foo}-${bar}.nix` is a more convenient way of writing
|
||||
`./. + "/" + foo + "-" + bar + ".nix"` or `./. + "/${foo}-${bar}.nix"`. At
|
||||
least one slash must appear *before* any antiquotations for this to be
|
||||
recognized as a path. `a.${foo}/b.${bar}` is a syntactically valid division
|
||||
operation. `./a.${foo}/b.${bar}` is a path.
|
||||
|
||||
- *Booleans* with values `true` and `false`.
|
||||
|
||||
- The null value, denoted as `null`.
|
||||
|
|
|
|||
|
|
@ -1,48 +1,48 @@
|
|||
# Glossary
|
||||
|
||||
- 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
|
||||
- store\
|
||||
The location in the file system where store objects live. Typically
|
||||
`/nix/store`.
|
||||
|
||||
- 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
|
||||
- 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
|
||||
- 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
|
||||
- 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
|
||||
- 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
|
||||
- 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
|
||||
|
|
@ -52,11 +52,11 @@
|
|||
output paths), whereas an output path only references other output
|
||||
paths.
|
||||
|
||||
- reachable
|
||||
- reachable\
|
||||
A store path `Q` is reachable from another store path `P` if `Q`
|
||||
is in the *closure* of the *references* relation.
|
||||
|
||||
- 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
|
||||
|
|
@ -71,29 +71,29 @@
|
|||
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
|
||||
- output path\
|
||||
A store path produced by a derivation.
|
||||
|
||||
- deriver
|
||||
- deriver\
|
||||
The deriver of an *output path* is the store
|
||||
derivation that built it.
|
||||
|
||||
- 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
|
||||
- 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
|
||||
- profile\
|
||||
A symlink to the current *user environment* of a user, e.g.,
|
||||
`/nix/var/nix/profiles/default`.
|
||||
|
||||
- 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`
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
# Building Nix from Source
|
||||
|
||||
After unpacking or checking out the Nix sources, issue the following
|
||||
commands:
|
||||
After cloning Nix's Git repository, issue the following commands:
|
||||
|
||||
```console
|
||||
$ ./bootstrap.sh
|
||||
$ ./configure options...
|
||||
$ make
|
||||
$ make install
|
||||
|
|
@ -11,13 +11,6 @@ $ make install
|
|||
|
||||
Nix requires GNU Make so you may need to invoke `gmake` instead.
|
||||
|
||||
When building from the Git repository, these should be preceded by the
|
||||
command:
|
||||
|
||||
```console
|
||||
$ ./bootstrap.sh
|
||||
```
|
||||
|
||||
The installation path can be specified by passing the `--prefix=prefix`
|
||||
to `configure`. The default installation directory is `/usr/local`. You
|
||||
can change this to any location you like. You must have write permission
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crt
|
|||
> **Note**
|
||||
>
|
||||
> You must not add the export and then do the install, as the Nix
|
||||
> installer will detect the presense of Nix configuration, and abort.
|
||||
> installer will detect the presence of Nix configuration, and abort.
|
||||
|
||||
## `NIX_SSL_CERT_FILE` with macOS and the Nix daemon
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,26 @@
|
|||
# Installing a Binary Distribution
|
||||
|
||||
If you are using Linux or macOS versions up to 10.14 (Mojave), the
|
||||
easiest way to install Nix is to run the following command:
|
||||
The easiest way to install Nix is to run the following command:
|
||||
|
||||
```console
|
||||
$ sh <(curl -L https://nixos.org/nix/install)
|
||||
```
|
||||
|
||||
If you're using macOS 10.15 (Catalina) or newer, consult [the macOS
|
||||
installation instructions](#macos-installation) before installing.
|
||||
This will run the installer interactively (causing it to explain what
|
||||
it is doing more explicitly), and perform the default "type" of install
|
||||
for your platform:
|
||||
- single-user on Linux
|
||||
- multi-user on macOS
|
||||
|
||||
As of Nix 2.1.0, the Nix installer will always default to creating a
|
||||
single-user installation, however opting in to the multi-user
|
||||
installation is highly recommended.
|
||||
> **Notes on read-only filesystem root in macOS 10.15 Catalina +**
|
||||
>
|
||||
> - It took some time to support this cleanly. You may see posts,
|
||||
> examples, and tutorials using obsolete workarounds.
|
||||
> - Supporting it cleanly made macOS installs too complex to qualify
|
||||
> as single-user, so this type is no longer supported on macOS.
|
||||
|
||||
We recommend the multi-user install if it supports your platform and
|
||||
you can authenticate with `sudo`.
|
||||
|
||||
# Single User Installation
|
||||
|
||||
|
|
@ -50,9 +58,9 @@ $ rm -rf /nix
|
|||
The multi-user Nix installation creates system users, and a system
|
||||
service for the Nix daemon.
|
||||
|
||||
- Linux running systemd, with SELinux disabled
|
||||
|
||||
- macOS
|
||||
**Supported Systems**
|
||||
- Linux running systemd, with SELinux disabled
|
||||
- macOS
|
||||
|
||||
You can instruct the installer to perform a multi-user installation on
|
||||
your system:
|
||||
|
|
@ -96,165 +104,28 @@ 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 Installation
|
||||
# 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 -->
|
||||
|
||||
Starting with macOS 10.15 (Catalina), the root filesystem is read-only.
|
||||
This means `/nix` can no longer live on your system volume, and that
|
||||
you'll need a workaround to install Nix.
|
||||
We believe we have ironed out how to cleanly support the read-only root
|
||||
on modern macOS. New installs will do this automatically, and you can
|
||||
also re-run a new installer to convert your existing setup.
|
||||
|
||||
The recommended approach, which creates an unencrypted APFS volume for
|
||||
your Nix store and a "synthetic" empty directory to mount it over at
|
||||
`/nix`, is least likely to impair Nix or your system.
|
||||
This section previously detailed the situation, options, and trade-offs,
|
||||
but it now only outlines what the installer does. You don't need to know
|
||||
this to run the installer, but it may help if you run into trouble:
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> With all separate-volume approaches, it's possible something on your
|
||||
> system (particularly daemons/services and restored apps) may need
|
||||
> access to your Nix store before the volume is mounted. Adding
|
||||
> additional encryption makes this more likely.
|
||||
|
||||
If you're using a recent Mac with a [T2
|
||||
chip](https://www.apple.com/euro/mac/shared/docs/Apple_T2_Security_Chip_Overview.pdf),
|
||||
your drive will still be encrypted at rest (in which case "unencrypted"
|
||||
is a bit of a misnomer). To use this approach, just install Nix with:
|
||||
|
||||
```console
|
||||
$ sh <(curl -L https://nixos.org/nix/install) --darwin-use-unencrypted-nix-store-volume
|
||||
```
|
||||
|
||||
If you don't like the sound of this, you'll want to weigh the other
|
||||
approaches and tradeoffs detailed in this section.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> All of the known workarounds have drawbacks, but we hope better
|
||||
> solutions will be available in the future. Some that we have our eye
|
||||
> on are:
|
||||
>
|
||||
> 1. A true firmlink would enable the Nix store to live on the primary
|
||||
> data volume without the build problems caused by the symlink
|
||||
> approach. End users cannot currently create true firmlinks.
|
||||
>
|
||||
> 2. If the Nix store volume shared FileVault encryption with the
|
||||
> primary data volume (probably by using the same volume group and
|
||||
> role), FileVault encryption could be easily supported by the
|
||||
> installer without requiring manual setup by each user.
|
||||
|
||||
## Change the Nix store path prefix
|
||||
|
||||
Changing the default prefix for the Nix store is a simple approach which
|
||||
enables you to leave it on your root volume, where it can take full
|
||||
advantage of FileVault encryption if enabled. Unfortunately, this
|
||||
approach also opts your device out of some benefits that are enabled by
|
||||
using the same prefix across systems:
|
||||
|
||||
- Your system won't be able to take advantage of the binary cache
|
||||
(unless someone is able to stand up and support duplicate caching
|
||||
infrastructure), which means you'll spend more time waiting for
|
||||
builds.
|
||||
|
||||
- It's harder to build and deploy packages to Linux systems.
|
||||
|
||||
It would also possible (and often requested) to just apply this change
|
||||
ecosystem-wide, but it's an intrusive process that has side effects we
|
||||
want to avoid for now.
|
||||
|
||||
## Use a separate encrypted volume
|
||||
|
||||
If you like, you can also add encryption to the recommended approach
|
||||
taken by the installer. You can do this by pre-creating an encrypted
|
||||
volume before you run the installer--or you can run the installer and
|
||||
encrypt the volume it creates later.
|
||||
|
||||
In either case, adding encryption to a second volume isn't quite as
|
||||
simple as enabling FileVault for your boot volume. Before you dive in,
|
||||
there are a few things to weigh:
|
||||
|
||||
1. The additional volume won't be encrypted with your existing
|
||||
FileVault key, so you'll need another mechanism to decrypt the
|
||||
volume.
|
||||
|
||||
2. You can store the password in Keychain to automatically decrypt the
|
||||
volume on boot--but it'll have to wait on Keychain and may not mount
|
||||
before your GUI apps restore. If any of your launchd agents or apps
|
||||
depend on Nix-installed software (for example, if you use a
|
||||
Nix-installed login shell), the restore may fail or break.
|
||||
|
||||
On a case-by-case basis, you may be able to work around this problem
|
||||
by using `wait4path` to block execution until your executable is
|
||||
available.
|
||||
|
||||
It's also possible to decrypt and mount the volume earlier with a
|
||||
login hook--but this mechanism appears to be deprecated and its
|
||||
future is unclear.
|
||||
|
||||
3. You can hard-code the password in the clear, so that your store
|
||||
volume can be decrypted before Keychain is available.
|
||||
|
||||
If you are comfortable navigating these tradeoffs, you can encrypt the
|
||||
volume with something along the lines of:
|
||||
|
||||
```console
|
||||
$ diskutil apfs enableFileVault /nix -user disk
|
||||
```
|
||||
|
||||
## Symlink the Nix store to a custom location
|
||||
|
||||
Another simple approach is using `/etc/synthetic.conf` to symlink the
|
||||
Nix store to the data volume. This option also enables your store to
|
||||
share any configured FileVault encryption. Unfortunately, builds that
|
||||
resolve the symlink may leak the canonical path or even fail.
|
||||
|
||||
Because of these downsides, we can't recommend this approach.
|
||||
|
||||
## Notes on the recommended approach
|
||||
|
||||
This section goes into a little more detail on the recommended approach.
|
||||
You don't need to understand it to run the installer, but it can serve
|
||||
as a helpful reference if you run into trouble.
|
||||
|
||||
1. In order to compose user-writable locations into the new read-only
|
||||
system root, Apple introduced a new concept called `firmlinks`,
|
||||
which it describes as a "bi-directional wormhole" between two
|
||||
filesystems. You can see the current firmlinks in
|
||||
`/usr/share/firmlinks`. Unfortunately, firmlinks aren't (currently?)
|
||||
user-configurable.
|
||||
|
||||
For special cases like NFS mount points or package manager roots,
|
||||
[synthetic.conf(5)](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man5/synthetic.conf.5.html)
|
||||
supports limited user-controlled file-creation (of symlinks, and
|
||||
synthetic empty directories) at `/`. To create a synthetic empty
|
||||
directory for mounting at `/nix`, add the following line to
|
||||
`/etc/synthetic.conf` (create it if necessary):
|
||||
|
||||
nix
|
||||
|
||||
2. This configuration is applied at boot time, but you can use
|
||||
`apfs.util` to trigger creation (not deletion) of new entries
|
||||
without a reboot:
|
||||
|
||||
```console
|
||||
$ /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B
|
||||
```
|
||||
|
||||
3. Create the new APFS volume with diskutil:
|
||||
|
||||
```console
|
||||
$ sudo diskutil apfs addVolume diskX APFS 'Nix Store' -mountpoint /nix
|
||||
```
|
||||
|
||||
4. Using `vifs`, add the new mount to `/etc/fstab`. If it doesn't
|
||||
already have other entries, it should look something like:
|
||||
|
||||
#
|
||||
# Warning - this file should only be modified with vifs(8)
|
||||
#
|
||||
# Failure to do so is unsupported and may be destructive.
|
||||
#
|
||||
LABEL=Nix\040Store /nix apfs rw,nobrowse
|
||||
|
||||
The nobrowse setting will keep Spotlight from indexing this volume,
|
||||
and keep it from showing up on your desktop.
|
||||
- create a new APFS volume for your Nix store
|
||||
- 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`
|
||||
- if you have FileVault enabled
|
||||
- generate an encryption password
|
||||
- put it in your system Keychain
|
||||
- use it to encrypt the volume
|
||||
- create a system LaunchDaemon to mount this volume early enough in the
|
||||
boot process to avoid problems loading or restoring any programs that
|
||||
need access to your Nix store
|
||||
|
||||
# Installing a pinned Nix version from a URL
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Installing Nix from Source
|
||||
|
||||
If no binary package is available, you can download and compile a source
|
||||
distribution.
|
||||
If no binary package is available or if you want to hack on Nix, you
|
||||
can build Nix from its Git repository.
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
# Obtaining a Source Distribution
|
||||
# Obtaining the Source
|
||||
|
||||
The source tarball of the most recent stable release can be downloaded
|
||||
from the [Nix homepage](http://nixos.org/nix/download.html). You can
|
||||
also grab the [most recent development
|
||||
release](http://hydra.nixos.org/job/nix/master/release/latest-finished#tabs-constituents).
|
||||
|
||||
Alternatively, the most recent sources of Nix can be obtained from its
|
||||
[Git repository](https://github.com/NixOS/nix). For example, the
|
||||
following command will check out the latest revision into a directory
|
||||
called `nix`:
|
||||
The most recent sources of Nix can be obtained from its [Git
|
||||
repository](https://github.com/NixOS/nix). For example, the following
|
||||
command will check out the latest revision into a directory called
|
||||
`nix`:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/NixOS/nix
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@
|
|||
|
||||
- GNU Autoconf (<https://www.gnu.org/software/autoconf/>) and the
|
||||
autoconf-archive macro collection
|
||||
(<https://www.gnu.org/software/autoconf-archive/>). These are only
|
||||
needed to run the bootstrap script, and are not necessary if your
|
||||
source distribution came with a pre-built `./configure` script.
|
||||
(<https://www.gnu.org/software/autoconf-archive/>). These are
|
||||
needed to run the bootstrap script.
|
||||
|
||||
- GNU Make.
|
||||
|
||||
|
|
@ -26,15 +25,6 @@
|
|||
available for download from the official repository
|
||||
<https://github.com/google/brotli>.
|
||||
|
||||
- The bzip2 compressor program and the `libbz2` library. Thus you must
|
||||
have bzip2 installed, including development headers and libraries.
|
||||
If your distribution does not provide these, you can obtain bzip2
|
||||
from
|
||||
<https://sourceware.org/bzip2/>.
|
||||
|
||||
- `liblzma`, which is provided by XZ Utils. If your distribution does
|
||||
not provide this, you can get it from <https://tukaani.org/xz/>.
|
||||
|
||||
- cURL and its library. If your distribution does not provide it, you
|
||||
can get it from <https://curl.haxx.se/>.
|
||||
|
||||
|
|
@ -61,8 +51,7 @@
|
|||
you need version 2.5.35, which is available on
|
||||
[SourceForge](http://lex.sourceforge.net/). Slightly older versions
|
||||
may also work, but ancient versions like the ubiquitous 2.5.4a
|
||||
won't. Note that these are only required if you modify the parser or
|
||||
when you are building from the Git repository.
|
||||
won't.
|
||||
|
||||
- The `libseccomp` is used to provide syscall filtering on Linux. This
|
||||
is an optional dependency and can be disabled passing a
|
||||
|
|
|
|||
|
|
@ -7,17 +7,17 @@ cache mechanism that Nix usually uses to fetch prebuilt binaries from
|
|||
|
||||
The following options can be specified as URL parameters to the S3 URL:
|
||||
|
||||
- `profile`
|
||||
- `profile`\
|
||||
The name of the AWS configuration profile to use. By default Nix
|
||||
will use the `default` profile.
|
||||
|
||||
- `region`
|
||||
- `region`\
|
||||
The region of the S3 bucket. `us–east-1` by default.
|
||||
|
||||
If your bucket is not in `us–east-1`, you should always explicitly
|
||||
specify the region parameter.
|
||||
|
||||
- `endpoint`
|
||||
- `endpoint`\
|
||||
The URL to your S3-compatible service, for when not using Amazon S3.
|
||||
Do not specify this value if you're using Amazon S3.
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ The following options can be specified as URL parameters to the S3 URL:
|
|||
> This endpoint must support HTTPS and will use path-based
|
||||
> addressing instead of virtual host based addressing.
|
||||
|
||||
- `scheme`
|
||||
- `scheme`\
|
||||
The scheme used for S3 requests, `https` (default) or `http`. This
|
||||
option allows you to disable HTTPS for binary caches which don't
|
||||
support it.
|
||||
|
|
|
|||
539
doc/manual/src/release-notes/rl-2.4.md
Normal file
539
doc/manual/src/release-notes/rl-2.4.md
Normal file
|
|
@ -0,0 +1,539 @@
|
|||
# Release 2.4 (2021-11-01)
|
||||
|
||||
This is the first release in more than two years and is the result of
|
||||
more than 2800 commits from 195 contributors since release 2.3.
|
||||
|
||||
## Highlights
|
||||
|
||||
* Nix's **error messages** have been improved a lot. For instance,
|
||||
evaluation errors now point out the location of the error:
|
||||
|
||||
```
|
||||
$ nix build
|
||||
error: undefined variable 'bzip3'
|
||||
|
||||
at /nix/store/449lv242z0zsgwv95a8124xi11sp419f-source/flake.nix:88:13:
|
||||
|
||||
87| [ curl
|
||||
88| bzip3 xz brotli editline
|
||||
| ^
|
||||
89| openssl sqlite
|
||||
```
|
||||
|
||||
* The **`nix` command** has seen a lot of work and is now almost at
|
||||
feature parity with the old command-line interface (the `nix-*`
|
||||
commands). It aims to be [more modern, consistent and pleasant to
|
||||
use](../contributing/cli-guideline.md) than the old CLI. It is still
|
||||
marked as experimental but its interface should not change much
|
||||
anymore in future releases.
|
||||
|
||||
* **Flakes** are a new format to package Nix-based projects in a more
|
||||
discoverable, composable, consistent and reproducible way. A flake
|
||||
is just a repository or tarball containing a file named `flake.nix`
|
||||
that specifies dependencies on other flakes and returns any Nix
|
||||
assets such as packages, Nixpkgs overlays, NixOS modules or CI
|
||||
tests. The new `nix` CLI is primarily based around flakes; for
|
||||
example, a command like `nix run nixpkgs#hello` runs the `hello`
|
||||
application from the `nixpkgs` flake.
|
||||
|
||||
Flakes are currently marked as experimental. For an introduction,
|
||||
see [this blog
|
||||
post](https://www.tweag.io/blog/2020-05-25-flakes/). For detailed
|
||||
information about flake syntax and semantics, see the [`nix flake`
|
||||
manual page](../command-ref/new-cli/nix3-flake.md).
|
||||
|
||||
* Nix's store can now be **content-addressed**, meaning that the hash
|
||||
component of a store path is the hash of the path's
|
||||
contents. Previously Nix could only build **input-addressed** store
|
||||
paths, where the hash is computed from the derivation dependency
|
||||
graph. Content-addressing allows deduplication, early cutoff in
|
||||
build systems, and unprivileged closure copying. This is still [an
|
||||
experimental
|
||||
feature](https://discourse.nixos.org/t/content-addressed-nix-call-for-testers/12881).
|
||||
|
||||
* The Nix manual has been converted into Markdown, making it easier to
|
||||
contribute. In addition, every `nix` subcommand now has a manual
|
||||
page, documenting every option.
|
||||
|
||||
* A new setting that allows **experimental features** to be enabled
|
||||
selectively. This allows us to merge unstable features into Nix more
|
||||
quickly and do more frequent releases.
|
||||
|
||||
## Other features
|
||||
|
||||
* There are many new `nix` subcommands:
|
||||
|
||||
- `nix develop` is intended to replace `nix-shell`. It has a number
|
||||
of new features:
|
||||
|
||||
* It automatically sets the output environment variables (such as
|
||||
`$out`) to writable locations (such as `./outputs/out`).
|
||||
|
||||
* It can store the environment in a profile. This is useful for
|
||||
offline work.
|
||||
|
||||
* It can run specific phases directly. For instance, `nix develop
|
||||
--build` runs `buildPhase`.
|
||||
|
||||
- It allows dependencies in the Nix store to be "redirected" to
|
||||
arbitrary directories using the `--redirect` flag. This is
|
||||
useful if you want to hack on a package *and* some of its
|
||||
dependencies at the same time.
|
||||
|
||||
- `nix print-dev-env` prints the environment variables and bash
|
||||
functions defined by a derivation. This is useful for users of
|
||||
other shells than bash (especially with `--json`).
|
||||
|
||||
- `nix shell` was previously named `nix run` and is intended to
|
||||
replace `nix-shell -p`, but without the `stdenv` overhead. It
|
||||
simply starts a shell where some packages have been added to
|
||||
`$PATH`.
|
||||
|
||||
- `nix run` (not to be confused with the old subcommand that has
|
||||
been renamed to `nix shell`) runs an "app", a flake output that
|
||||
specifies a command to run, or an eponymous program from a
|
||||
package. For example, `nix run nixpkgs#hello` runs the `hello`
|
||||
program from the `hello` package in `nixpkgs`.
|
||||
|
||||
- `nix flake` is the container for flake-related operations, such as
|
||||
creating a new flake, querying the contents of a flake or updating
|
||||
flake lock files.
|
||||
|
||||
- `nix registry` allows you to query and update the flake registry,
|
||||
which maps identifiers such as `nixpkgs` to concrete flake URLs.
|
||||
|
||||
- `nix profile` is intended to replace `nix-env`. Its main advantage
|
||||
is that it keeps track of the provenance of installed packages
|
||||
(e.g. exactly which flake version a package came from). It also
|
||||
has some helpful subcommands:
|
||||
|
||||
* `nix profile history` shows what packages were added, upgraded
|
||||
or removed between each version of a profile.
|
||||
|
||||
* `nix profile diff-closures` shows the changes between the
|
||||
closures of each version of a profile. This allows you to
|
||||
discover the addition or removal of dependencies or size
|
||||
changes.
|
||||
|
||||
**Warning**: after a profile has been updated using `nix profile`,
|
||||
it is no longer usable with `nix-env`.
|
||||
|
||||
- `nix store diff-closures` shows the differences between the
|
||||
closures of two store paths in terms of the versions and sizes of
|
||||
dependencies in the closures.
|
||||
|
||||
- `nix store make-content-addressable` rewrites an arbitrary closure
|
||||
to make it content-addressed. Such paths can be copied into other
|
||||
stores without requiring signatures.
|
||||
|
||||
- `nix bundle` uses the [`nix-bundle`
|
||||
program](https://github.com/matthewbauer/nix-bundle) to convert a
|
||||
closure into a self-extracting executable.
|
||||
|
||||
- Various other replacements for the old CLI, e.g. `nix store gc`,
|
||||
`nix store delete`, `nix store repair`, `nix nar dump-path`, `nix
|
||||
store prefetch-file`, `nix store prefetch-tarball`, `nix key` and
|
||||
`nix daemon`.
|
||||
|
||||
* Nix now has an **evaluation cache** for flake outputs. For example,
|
||||
a second invocation of the command `nix run nixpkgs#firefox` will
|
||||
not need to evaluate the `firefox` attribute because it's already in
|
||||
the evaluation cache. This is made possible by the hermetic
|
||||
evaluation model of flakes.
|
||||
|
||||
* The new `--offline` flag disables substituters and causes all
|
||||
locally cached tarballs and repositories to be considered
|
||||
up-to-date.
|
||||
|
||||
* The new `--refresh` flag causes all locally cached tarballs and
|
||||
repositories to be considered out-of-date.
|
||||
|
||||
* Many `nix` subcommands now have a `--json` option to produce
|
||||
machine-readable output.
|
||||
|
||||
* `nix repl` has a new `:doc` command to show documentation about
|
||||
builtin functions (e.g. `:doc builtins.map`).
|
||||
|
||||
* Binary cache stores now have an option `index-debug-info` to create
|
||||
an index of DWARF debuginfo files for use by
|
||||
[`dwarffs`](https://github.com/edolstra/dwarffs).
|
||||
|
||||
* To support flakes, Nix now has an extensible mechanism for fetching
|
||||
source trees. Currently it has the following backends:
|
||||
|
||||
* Git repositories
|
||||
|
||||
* Mercurial repositories
|
||||
|
||||
* GitHub and GitLab repositories (an optimisation for faster
|
||||
fetching than Git)
|
||||
|
||||
* Tarballs
|
||||
|
||||
* Arbitrary directories
|
||||
|
||||
The fetcher infrastructure is exposed via flake input specifications
|
||||
and via the `fetchTree` built-in.
|
||||
|
||||
* **Languages changes**: the only new language feature is that you can
|
||||
now have antiquotations in paths, e.g. `./${foo}` instead of `./. +
|
||||
foo`.
|
||||
|
||||
* **New built-in functions**:
|
||||
|
||||
- `builtins.fetchTree` allows fetching a source tree using any
|
||||
backends supported by the fetcher infrastructure. It subsumes the
|
||||
functionality of existing built-ins like `fetchGit`,
|
||||
`fetchMercurial` and `fetchTarball`.
|
||||
|
||||
- `builtins.getFlake` fetches a flake and returns its output
|
||||
attributes. This function should not be used inside flakes! Use
|
||||
flake inputs instead.
|
||||
|
||||
- `builtins.floor` and `builtins.ceil` round a floating-point number
|
||||
down and up, respectively.
|
||||
|
||||
* Experimental support for recursive Nix. This means that Nix
|
||||
derivations can now call Nix to build other derivations. This is not
|
||||
in a stable state yet and not well
|
||||
[documented](https://github.com/NixOS/nix/commit/c4d7c76b641d82b2696fef73ce0ac160043c18da).
|
||||
|
||||
* The new experimental feature `no-url-literals` disables URL
|
||||
literals. This helps to implement [RFC
|
||||
45](https://github.com/NixOS/rfcs/pull/45).
|
||||
|
||||
* Nix now uses `libarchive` to decompress and unpack tarballs and zip
|
||||
files, so `tar` is no longer required.
|
||||
|
||||
* The priority of substituters can now be overridden using the
|
||||
`priority` substituter setting (e.g. `--substituters
|
||||
'http://cache.nixos.org?priority=100 daemon?priority=10'`).
|
||||
|
||||
* `nix edit` now supports non-derivation attributes, e.g. `nix edit
|
||||
.#nixosConfigurations.bla`.
|
||||
|
||||
* The `nix` command now provides command line completion for `bash`,
|
||||
`zsh` and `fish`. Since the support for getting completions is built
|
||||
into `nix`, it's easy to add support for other shells.
|
||||
|
||||
* The new `--log-format` flag selects what Nix's output looks like. It
|
||||
defaults to a terse progress indicator. There is a new
|
||||
`internal-json` output format for use by other programs.
|
||||
|
||||
* `nix eval` has a new `--apply` flag that applies a function to the
|
||||
evaluation result.
|
||||
|
||||
* `nix eval` has a new `--write-to` flag that allows it to write a
|
||||
nested attribute set of string leaves to a corresponding directory
|
||||
tree.
|
||||
|
||||
* Memory improvements: many operations that add paths to the store or
|
||||
copy paths between stores now run in constant memory.
|
||||
|
||||
* Many `nix` commands now support the flag `--derivation` to operate
|
||||
on a `.drv` file itself instead of its outputs.
|
||||
|
||||
* There is a new store called `dummy://` that does not support
|
||||
building or adding paths. This is useful if you want to use the Nix
|
||||
evaluator but don't have a Nix store.
|
||||
|
||||
* The `ssh-ng://` store now allows substituting paths on the remote,
|
||||
as `ssh://` already did.
|
||||
|
||||
* When auto-calling a function with an ellipsis, all arguments are now
|
||||
passed.
|
||||
|
||||
* New `nix-shell` features:
|
||||
|
||||
- It preserves the `PS1` environment variable if
|
||||
`NIX_SHELL_PRESERVE_PROMPT` is set.
|
||||
|
||||
- With `-p`, it passes any `--arg`s as Nixpkgs arguments.
|
||||
|
||||
- Support for structured attributes.
|
||||
|
||||
* `nix-prefetch-url` has a new `--executable` flag.
|
||||
|
||||
* On `x86_64` systems, [`x86_64` microarchitecture
|
||||
levels](https://lwn.net/Articles/844831/) are mapped to additional
|
||||
system types (e.g. `x86_64-v1-linux`).
|
||||
|
||||
* The new `--eval-store` flag allows you to use a different store for
|
||||
evaluation than for building or storing the build result. This is
|
||||
primarily useful when you want to query whether something exists in
|
||||
a read-only store, such as a binary cache:
|
||||
|
||||
```
|
||||
# nix path-info --json --store https://cache.nixos.org \
|
||||
--eval-store auto nixpkgs#hello
|
||||
```
|
||||
|
||||
(Here `auto` indicates the local store.)
|
||||
|
||||
* The Nix daemon has a new low-latency mechanism for copying
|
||||
closures. This is useful when building on remote stores such as
|
||||
`ssh-ng://`.
|
||||
|
||||
* Plugins can now register `nix` subcommands.
|
||||
|
||||
## Incompatible changes
|
||||
|
||||
* The `nix` command is now marked as an experimental feature. This
|
||||
means that you need to add
|
||||
|
||||
```
|
||||
experimental-features = nix-command
|
||||
```
|
||||
|
||||
to your `nix.conf` if you want to use it, or pass
|
||||
`--extra-experimental-features nix-command` on the command line.
|
||||
|
||||
* The `nix` command no longer has a syntax for referring to packages
|
||||
in a channel. This means that the following no longer works:
|
||||
|
||||
```console
|
||||
nix build nixpkgs.hello # Nix 2.3
|
||||
```
|
||||
|
||||
Instead, you can either use the `#` syntax to select a package from
|
||||
a flake, e.g.
|
||||
|
||||
```console
|
||||
nix build nixpkgs#hello
|
||||
```
|
||||
|
||||
Or, if you want to use the `nixpkgs` channel in the `NIX_PATH`
|
||||
environment variable:
|
||||
|
||||
```console
|
||||
nix build -f '<nixpkgs>' hello
|
||||
```
|
||||
|
||||
* The old `nix run` has been renamed to `nix shell`, while there is a
|
||||
new `nix run` that runs a default command. So instead of
|
||||
|
||||
```console
|
||||
nix run nixpkgs.hello -c hello # Nix 2.3
|
||||
```
|
||||
|
||||
you should use
|
||||
|
||||
```console
|
||||
nix shell nixpkgs#hello -c hello
|
||||
```
|
||||
|
||||
or just
|
||||
|
||||
```console
|
||||
nix run nixpkgs#hello
|
||||
```
|
||||
|
||||
if the command you want to run has the same name as the package.
|
||||
|
||||
* It is now an error to modify the `plugin-files` setting via a
|
||||
command-line flag that appears after the first non-flag argument to
|
||||
any command, including a subcommand to `nix`. For example,
|
||||
`nix-instantiate default.nix --plugin-files ""` must now become
|
||||
`nix-instantiate --plugin-files "" default.nix`.
|
||||
|
||||
* We no longer release source tarballs. If you want to build from
|
||||
source, please build from the tags in the Git repository.
|
||||
|
||||
## Contributors
|
||||
|
||||
This release has contributions from
|
||||
Adam Höse,
|
||||
Albert Safin,
|
||||
Alex Kovar,
|
||||
Alex Zero,
|
||||
Alexander Bantyev,
|
||||
Alexandre Esteves,
|
||||
Alyssa Ross,
|
||||
Anatole Lucet,
|
||||
Anders Kaseorg,
|
||||
Andreas Rammhold,
|
||||
Antoine Eiche,
|
||||
Antoine Martin,
|
||||
Arnout Engelen,
|
||||
Arthur Gautier,
|
||||
aszlig,
|
||||
Ben Burdette,
|
||||
Benjamin Hipple,
|
||||
Bernardo Meurer,
|
||||
Björn Gohla,
|
||||
Bjørn Forsman,
|
||||
Bob van der Linden,
|
||||
Brian Leung,
|
||||
Brian McKenna,
|
||||
Brian Wignall,
|
||||
Bruce Toll,
|
||||
Bryan Richter,
|
||||
Calle Rosenquist,
|
||||
Calvin Loncaric,
|
||||
Carlo Nucera,
|
||||
Carlos D'Agostino,
|
||||
Chaz Schlarp,
|
||||
Christian Höppner,
|
||||
Christian Kampka,
|
||||
Chua Hou,
|
||||
Chuck,
|
||||
Cole Helbling,
|
||||
Daiderd Jordan,
|
||||
Dan Callahan,
|
||||
Dani,
|
||||
Daniel Fitzpatrick,
|
||||
Danila Fedorin,
|
||||
Daniël de Kok,
|
||||
Danny Bautista,
|
||||
DavHau,
|
||||
David McFarland,
|
||||
Dima,
|
||||
Domen Kožar,
|
||||
Dominik Schrempf,
|
||||
Dominique Martinet,
|
||||
dramforever,
|
||||
Dustin DeWeese,
|
||||
edef,
|
||||
Eelco Dolstra,
|
||||
Emilio Karakey,
|
||||
Emily,
|
||||
Eric Culp,
|
||||
Ersin Akinci,
|
||||
Fabian Möller,
|
||||
Farid Zakaria,
|
||||
Federico Pellegrin,
|
||||
Finn Behrens,
|
||||
Florian Franzen,
|
||||
Félix Baylac-Jacqué,
|
||||
Gabriel Gonzalez,
|
||||
Geoff Reedy,
|
||||
Georges Dubus,
|
||||
Graham Christensen,
|
||||
Greg Hale,
|
||||
Greg Price,
|
||||
Gregor Kleen,
|
||||
Gregory Hale,
|
||||
Griffin Smith,
|
||||
Guillaume Bouchard,
|
||||
Harald van Dijk,
|
||||
illustris,
|
||||
Ivan Zvonimir Horvat,
|
||||
Jade,
|
||||
Jake Waksbaum,
|
||||
jakobrs,
|
||||
James Ottaway,
|
||||
Jan Tojnar,
|
||||
Janne Heß,
|
||||
Jaroslavas Pocepko,
|
||||
Jarrett Keifer,
|
||||
Jeremy Schlatter,
|
||||
Joachim Breitner,
|
||||
Joe Hermaszewski,
|
||||
Joe Pea,
|
||||
John Ericson,
|
||||
Jonathan Ringer,
|
||||
Josef Kemetmüller,
|
||||
Joseph Lucas,
|
||||
Jude Taylor,
|
||||
Julian Stecklina,
|
||||
Julien Tanguy,
|
||||
Jörg Thalheim,
|
||||
Kai Wohlfahrt,
|
||||
keke,
|
||||
Keshav Kini,
|
||||
Kevin Quick,
|
||||
Kevin Stock,
|
||||
Kjetil Orbekk,
|
||||
Krzysztof Gogolewski,
|
||||
kvtb,
|
||||
Lars Mühmel,
|
||||
Leonhard Markert,
|
||||
Lily Ballard,
|
||||
Linus Heckemann,
|
||||
Lorenzo Manacorda,
|
||||
Lucas Desgouilles,
|
||||
Lucas Franceschino,
|
||||
Lucas Hoffmann,
|
||||
Luke Granger-Brown,
|
||||
Madeline Haraj,
|
||||
Marwan Aljubeh,
|
||||
Mat Marini,
|
||||
Mateusz Piotrowski,
|
||||
Matthew Bauer,
|
||||
Matthew Kenigsberg,
|
||||
Mauricio Scheffer,
|
||||
Maximilian Bosch,
|
||||
Michael Adler,
|
||||
Michael Bishop,
|
||||
Michael Fellinger,
|
||||
Michael Forney,
|
||||
Michael Reilly,
|
||||
mlatus,
|
||||
Mykola Orliuk,
|
||||
Nathan van Doorn,
|
||||
Naïm Favier,
|
||||
ng0,
|
||||
Nick Van den Broeck,
|
||||
Nicolas Stig124 Formichella,
|
||||
Niels Egberts,
|
||||
Niklas Hambüchen,
|
||||
Nikola Knezevic,
|
||||
oxalica,
|
||||
p01arst0rm,
|
||||
Pamplemousse,
|
||||
Patrick Hilhorst,
|
||||
Paul Opiyo,
|
||||
Pavol Rusnak,
|
||||
Peter Kolloch,
|
||||
Philipp Bartsch,
|
||||
Philipp Middendorf,
|
||||
Piotr Szubiakowski,
|
||||
Profpatsch,
|
||||
Puck Meerburg,
|
||||
Ricardo M. Correia,
|
||||
Rickard Nilsson,
|
||||
Robert Hensing,
|
||||
Robin Gloster,
|
||||
Rodrigo,
|
||||
Rok Garbas,
|
||||
Ronnie Ebrin,
|
||||
Rovanion Luckey,
|
||||
Ryan Burns,
|
||||
Ryan Mulligan,
|
||||
Ryne Everett,
|
||||
Sam Doshi,
|
||||
Sam Lidder,
|
||||
Samir Talwar,
|
||||
Samuel Dionne-Riel,
|
||||
Sebastian Ullrich,
|
||||
Sergei Trofimovich,
|
||||
Sevan Janiyan,
|
||||
Shao Cheng,
|
||||
Shea Levy,
|
||||
Silvan Mosberger,
|
||||
Stefan Frijters,
|
||||
Stefan Jaax,
|
||||
sternenseemann,
|
||||
Steven Shaw,
|
||||
Stéphan Kochen,
|
||||
SuperSandro2000,
|
||||
Suraj Barkale,
|
||||
Taeer Bar-Yam,
|
||||
Thomas Churchman,
|
||||
Théophane Hufschmitt,
|
||||
Timothy DeHerrera,
|
||||
Timothy Klim,
|
||||
Tobias Möst,
|
||||
Tobias Pflug,
|
||||
Tom Bereknyei,
|
||||
Travis A. Everett,
|
||||
Ujjwal Jain,
|
||||
Vladimír Čunát,
|
||||
Wil Taylor,
|
||||
Will Dietz,
|
||||
Yaroslav Bolyukin,
|
||||
Yestin L. Harrison,
|
||||
YI,
|
||||
Yorick van Pelt,
|
||||
Yuriy Taraday and
|
||||
zimbatm.
|
||||
5
doc/manual/src/release-notes/rl-next.md
Normal file
5
doc/manual/src/release-notes/rl-next.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# 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`.
|
||||
|
|
@ -1,7 +1,15 @@
|
|||
with builtins;
|
||||
|
||||
{
|
||||
rec {
|
||||
splitLines = s: filter (x: !isList x) (split "\n" s);
|
||||
|
||||
concatStrings = concatStringsSep "";
|
||||
|
||||
# FIXME: O(n^2)
|
||||
unique = foldl' (acc: e: if elem e acc then acc else acc ++ [ e ]) [];
|
||||
|
||||
nameValuePair = name: value: { inherit name value; };
|
||||
|
||||
filterAttrs = pred: set:
|
||||
listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set));
|
||||
}
|
||||
|
|
|
|||
14
flake.lock
generated
14
flake.lock
generated
|
|
@ -3,11 +3,11 @@
|
|||
"lowdown-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1598695561,
|
||||
"narHash": "sha256-gyH/5j+h/nWw0W8AcR2WKvNBUsiQ7QuxqSJNXAwV+8E=",
|
||||
"lastModified": 1633514407,
|
||||
"narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
|
||||
"owner": "kristapsdz",
|
||||
"repo": "lowdown",
|
||||
"rev": "1705b4a26fbf065d9574dce47a94e8c7c79e052f",
|
||||
"rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -18,16 +18,16 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1602702596,
|
||||
"narHash": "sha256-fqJ4UgOb4ZUnCDIapDb4gCrtAah5Rnr2/At3IzMitig=",
|
||||
"lastModified": 1632864508,
|
||||
"narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ad0d20345219790533ebe06571f82ed6b034db31",
|
||||
"rev": "82891b5e2c2359d7e58d08849e4c89511ab94234",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-20.09-small",
|
||||
"ref": "nixos-21.05-small",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
390
flake.nix
390
flake.nix
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
description = "The purely functional package manager";
|
||||
|
||||
inputs.nixpkgs.url = "nixpkgs/nixos-20.09-small";
|
||||
inputs.nixpkgs.url = "nixpkgs/nixos-21.05-small";
|
||||
inputs.lowdown-src = { url = "github:kristapsdz/lowdown"; flake = false; };
|
||||
|
||||
outputs = { self, nixpkgs, lowdown-src }:
|
||||
|
|
@ -18,7 +18,9 @@
|
|||
|
||||
linux64BitSystems = [ "x86_64-linux" "aarch64-linux" ];
|
||||
linuxSystems = linux64BitSystems ++ [ "i686-linux" ];
|
||||
systems = linuxSystems ++ [ "x86_64-darwin" ];
|
||||
systems = linuxSystems ++ [ "x86_64-darwin" "aarch64-darwin" ];
|
||||
|
||||
crossSystems = [ "armv6l-linux" "armv7l-linux" ];
|
||||
|
||||
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system);
|
||||
|
||||
|
|
@ -59,6 +61,7 @@
|
|||
|
||||
configureFlags =
|
||||
lib.optionals stdenv.isLinux [
|
||||
"--with-boost=${boost}/lib"
|
||||
"--with-sandbox-shell=${sh}/bin/busybox"
|
||||
"LDFLAGS=-fuse-ld=gold"
|
||||
];
|
||||
|
|
@ -68,7 +71,7 @@
|
|||
[
|
||||
buildPackages.bison
|
||||
buildPackages.flex
|
||||
(lib.getBin buildPackages.lowdown)
|
||||
(lib.getBin buildPackages.lowdown-nix)
|
||||
buildPackages.mdbook
|
||||
buildPackages.autoconf-archive
|
||||
buildPackages.autoreconfHook
|
||||
|
|
@ -76,22 +79,23 @@
|
|||
|
||||
# Tests
|
||||
buildPackages.git
|
||||
buildPackages.mercurial
|
||||
buildPackages.mercurial # FIXME: remove? only needed for tests
|
||||
buildPackages.jq
|
||||
];
|
||||
]
|
||||
++ lib.optionals stdenv.hostPlatform.isLinux [(buildPackages.util-linuxMinimal or buildPackages.utillinuxMinimal)];
|
||||
|
||||
buildDeps =
|
||||
[ curl
|
||||
bzip2 xz brotli zlib editline
|
||||
bzip2 xz brotli editline
|
||||
openssl sqlite
|
||||
libarchive
|
||||
boost
|
||||
nlohmann_json
|
||||
lowdown
|
||||
lowdown-nix
|
||||
gmock
|
||||
]
|
||||
++ lib.optionals stdenv.isLinux [libseccomp utillinuxMinimal]
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium;
|
||||
++ lib.optionals stdenv.isLinux [libseccomp]
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid;
|
||||
|
||||
awsDeps = lib.optional (stdenv.isLinux || stdenv.isDarwin)
|
||||
(aws-sdk-cpp.override {
|
||||
|
|
@ -100,7 +104,13 @@
|
|||
});
|
||||
|
||||
propagatedDeps =
|
||||
[ (boehmgc.override { enableLargeConfig = true; })
|
||||
[ ((boehmgc.override {
|
||||
enableLargeConfig = true;
|
||||
}).overrideAttrs(o: {
|
||||
patches = (o.patches or []) ++ [
|
||||
./boehmgc-coroutine-sp-fallback.diff
|
||||
];
|
||||
}))
|
||||
];
|
||||
|
||||
perlDeps =
|
||||
|
|
@ -109,13 +119,154 @@
|
|||
];
|
||||
};
|
||||
|
||||
installScriptFor = systems:
|
||||
with nixpkgsFor.x86_64-linux;
|
||||
runCommand "installer-script"
|
||||
{ buildInputs = [ nix ];
|
||||
}
|
||||
''
|
||||
mkdir -p $out/nix-support
|
||||
|
||||
# Converts /nix/store/50p3qk8k...-nix-2.4pre20201102_550e11f/bin/nix to 50p3qk8k.../bin/nix.
|
||||
tarballPath() {
|
||||
# Remove the store prefix
|
||||
local path=''${1#${builtins.storeDir}/}
|
||||
# Get the path relative to the derivation root
|
||||
local rest=''${path#*/}
|
||||
# Get the derivation hash
|
||||
local drvHash=''${path%%-*}
|
||||
echo "$drvHash/$rest"
|
||||
}
|
||||
|
||||
substitute ${./scripts/install.in} $out/install \
|
||||
${pkgs.lib.concatMapStrings
|
||||
(system: let
|
||||
tarball = if builtins.elem system crossSystems then self.hydraJobs.binaryTarballCross.x86_64-linux.${system} else self.hydraJobs.binaryTarball.${system};
|
||||
in '' \
|
||||
--replace '@tarballHash_${system}@' $(nix --experimental-features nix-command hash-file --base16 --type sha256 ${tarball}/*.tar.xz) \
|
||||
--replace '@tarballPath_${system}@' $(tarballPath ${tarball}/*.tar.xz) \
|
||||
''
|
||||
)
|
||||
systems
|
||||
} --replace '@nixVersion@' ${version}
|
||||
|
||||
echo "file installer $out/install" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
testNixVersions = pkgs: client: daemon: with commonDeps pkgs; with pkgs.lib; pkgs.stdenv.mkDerivation {
|
||||
NIX_DAEMON_PACKAGE = daemon;
|
||||
NIX_CLIENT_PACKAGE = client;
|
||||
name =
|
||||
"nix-tests"
|
||||
+ optionalString
|
||||
(versionAtLeast daemon.version "2.4pre20211005" &&
|
||||
versionAtLeast client.version "2.4pre20211005")
|
||||
"-${client.version}-against-${daemon.version}";
|
||||
inherit version;
|
||||
|
||||
src = self;
|
||||
|
||||
VERSION_SUFFIX = versionSuffix;
|
||||
|
||||
nativeBuildInputs = nativeBuildDeps;
|
||||
buildInputs = buildDeps ++ awsDeps;
|
||||
propagatedBuildInputs = propagatedDeps;
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
dontBuild = true;
|
||||
doInstallCheck = true;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
'';
|
||||
|
||||
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
|
||||
|
||||
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}
|
||||
|
||||
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
|
||||
|
||||
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 = final: prev: {
|
||||
|
||||
nix = with final; with commonDeps pkgs; (stdenv.mkDerivation {
|
||||
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;
|
||||
|
||||
|
|
@ -163,9 +314,10 @@
|
|||
installCheckFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
separateDebugInfo = true;
|
||||
}) // {
|
||||
|
||||
perl-bindings = with final; stdenv.mkDerivation {
|
||||
strictDeps = true;
|
||||
|
||||
passthru.perl-bindings = with final; stdenv.mkDerivation {
|
||||
name = "nix-perl-${version}";
|
||||
|
||||
src = self;
|
||||
|
|
@ -183,9 +335,9 @@
|
|||
xz
|
||||
pkgs.perl
|
||||
boost
|
||||
nlohmann_json
|
||||
]
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium;
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||
++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security;
|
||||
|
||||
configureFlags = ''
|
||||
--with-dbi=${perlPackages.DBI}/${pkgs.perl.libPrefix}
|
||||
|
|
@ -199,24 +351,17 @@
|
|||
|
||||
};
|
||||
|
||||
lowdown = with final; stdenv.mkDerivation {
|
||||
name = "lowdown-0.7.1";
|
||||
|
||||
/*
|
||||
src = fetchurl {
|
||||
url = https://kristaps.bsd.lv/lowdown/snapshots/lowdown-0.7.1.tar.gz;
|
||||
hash = "sha512-1daoAQfYD0LdhK6aFhrSQvadjc5GsSPBZw0fJDb+BEHYMBLjqiUl2A7H8N+l0W4YfGKqbsPYSrCy4vct+7U6FQ==";
|
||||
};
|
||||
*/
|
||||
lowdown-nix = with final; stdenv.mkDerivation rec {
|
||||
name = "lowdown-0.9.0";
|
||||
|
||||
src = lowdown-src;
|
||||
|
||||
outputs = [ "out" "bin" "dev" ];
|
||||
|
||||
nativeBuildInputs = [ which ];
|
||||
nativeBuildInputs = [ buildPackages.which ];
|
||||
|
||||
configurePhase =
|
||||
''
|
||||
configurePhase = ''
|
||||
${if (stdenv.isDarwin && stdenv.isAarch64) then "echo \"HAVE_SANDBOX_INIT=false\" > configure.local" else ""}
|
||||
./configure \
|
||||
PREFIX=${placeholder "dev"} \
|
||||
BINDIR=${placeholder "bin"}/bin
|
||||
|
|
@ -232,124 +377,33 @@
|
|||
|
||||
buildStatic = nixpkgs.lib.genAttrs linux64BitSystems (system: self.packages.${system}.nix-static);
|
||||
|
||||
buildCross = nixpkgs.lib.genAttrs crossSystems (crossSystem:
|
||||
nixpkgs.lib.genAttrs ["x86_64-linux"] (system: self.packages.${system}."nix-${crossSystem}"));
|
||||
|
||||
# Perl bindings for various platforms.
|
||||
perlBindings = nixpkgs.lib.genAttrs systems (system: self.packages.${system}.nix.perl-bindings);
|
||||
|
||||
# Binary tarball for various platforms, containing a Nix store
|
||||
# with the closure of 'nix' package, and the second half of
|
||||
# the installation script.
|
||||
binaryTarball = nixpkgs.lib.genAttrs systems (system:
|
||||
binaryTarball = nixpkgs.lib.genAttrs systems (system: binaryTarball nixpkgsFor.${system} nixpkgsFor.${system}.nix nixpkgsFor.${system});
|
||||
|
||||
with nixpkgsFor.${system};
|
||||
|
||||
let
|
||||
installerClosureInfo = closureInfo { rootPaths = [ nix cacert ]; };
|
||||
in
|
||||
|
||||
runCommand "nix-binary-tarball-${version}"
|
||||
{ #nativeBuildInputs = lib.optional (system != "aarch64-linux") shellcheck;
|
||||
meta.description = "Distribution-independent Nix bootstrap binaries for ${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}
|
||||
|
||||
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
|
||||
|
||||
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}-${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)
|
||||
'');
|
||||
binaryTarballCross = nixpkgs.lib.genAttrs ["x86_64-linux"] (system: builtins.listToAttrs (map (crossSystem: {
|
||||
name = crossSystem;
|
||||
value = let
|
||||
nixpkgsCross = import nixpkgs {
|
||||
inherit system crossSystem;
|
||||
overlays = [ self.overlay ];
|
||||
};
|
||||
in binaryTarball nixpkgsFor.${system} self.packages.${system}."nix-${crossSystem}" nixpkgsCross;
|
||||
}) crossSystems));
|
||||
|
||||
# The first half of the installation script. This is uploaded
|
||||
# to https://nixos.org/nix/install. It downloads the binary
|
||||
# tarball for the user's system and calls the second half of the
|
||||
# installation script.
|
||||
installerScript =
|
||||
with nixpkgsFor.x86_64-linux;
|
||||
runCommand "installer-script"
|
||||
{ buildInputs = [ nix ];
|
||||
}
|
||||
''
|
||||
mkdir -p $out/nix-support
|
||||
|
||||
# Converts /nix/store/50p3qk8kka9dl6wyq40vydq945k0j3kv-nix-2.4pre20201102_550e11f/bin/nix
|
||||
# To 50p3qk8kka9dl6wyq40vydq945k0j3kv/bin/nix
|
||||
tarballPath() {
|
||||
# Remove the store prefix
|
||||
local path=''${1#${builtins.storeDir}/}
|
||||
# Get the path relative to the derivation root
|
||||
local rest=''${path#*/}
|
||||
# Get the derivation hash
|
||||
local drvHash=''${path%%-*}
|
||||
echo "$drvHash/$rest"
|
||||
}
|
||||
|
||||
substitute ${./scripts/install.in} $out/install \
|
||||
${pkgs.lib.concatMapStrings
|
||||
(system:
|
||||
'' \
|
||||
--replace '@tarballHash_${system}@' $(nix --experimental-features nix-command hash-file --base16 --type sha256 ${self.hydraJobs.binaryTarball.${system}}/*.tar.xz) \
|
||||
--replace '@tarballPath_${system}@' $(tarballPath ${self.hydraJobs.binaryTarball.${system}}/*.tar.xz) \
|
||||
''
|
||||
)
|
||||
[ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" ]
|
||||
} \
|
||||
--replace '@nixVersion@' ${version}
|
||||
|
||||
echo "file installer $out/install" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
installerScript = installScriptFor [ "x86_64-linux" "i686-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" "armv6l-linux" "armv7l-linux" ];
|
||||
installerScriptForGHA = installScriptFor [ "x86_64-linux" "x86_64-darwin" "armv6l-linux" "armv7l-linux"];
|
||||
|
||||
# Line coverage analysis.
|
||||
coverage =
|
||||
|
|
@ -391,6 +445,12 @@
|
|||
inherit (self) overlay;
|
||||
};
|
||||
|
||||
tests.nssPreload = (import ./tests/nss-preload.nix rec {
|
||||
system = "x86_64-linux";
|
||||
inherit nixpkgs;
|
||||
inherit (self) overlay;
|
||||
});
|
||||
|
||||
tests.githubFlakes = (import ./tests/github-flakes.nix rec {
|
||||
system = "x86_64-linux";
|
||||
inherit nixpkgs;
|
||||
|
|
@ -429,16 +489,31 @@
|
|||
'';
|
||||
*/
|
||||
|
||||
installTests = forAllSystems (system:
|
||||
let pkgs = nixpkgsFor.${system}; in
|
||||
pkgs.runCommand "install-tests" {
|
||||
againstSelf = testNixVersions pkgs pkgs.nix pkgs.pkgs.nix;
|
||||
againstCurrentUnstable =
|
||||
# FIXME: temporarily disable this on macOS because of #3605.
|
||||
if system == "x86_64-linux"
|
||||
then testNixVersions pkgs pkgs.nix pkgs.nixUnstable
|
||||
else null;
|
||||
# Disabled because the latest stable version doesn't handle
|
||||
# `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work
|
||||
# againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable;
|
||||
} "touch $out");
|
||||
|
||||
};
|
||||
|
||||
checks = forAllSystems (system: {
|
||||
binaryTarball = self.hydraJobs.binaryTarball.${system};
|
||||
perlBindings = self.hydraJobs.perlBindings.${system};
|
||||
installTests = self.hydraJobs.installTests.${system};
|
||||
});
|
||||
|
||||
packages = forAllSystems (system: {
|
||||
inherit (nixpkgsFor.${system}) nix;
|
||||
} // nixpkgs.lib.optionalAttrs (builtins.elem system linux64BitSystems) {
|
||||
} // (nixpkgs.lib.optionalAttrs (builtins.elem system linux64BitSystems) {
|
||||
nix-static = let
|
||||
nixpkgs = nixpkgsFor.${system}.pkgsStatic;
|
||||
in with commonDeps nixpkgs; nixpkgs.stdenv.mkDerivation {
|
||||
|
|
@ -474,8 +549,51 @@
|
|||
installCheckFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
stripAllList = ["bin"];
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
hardeningDisable = [ "pie" ];
|
||||
};
|
||||
});
|
||||
} // builtins.listToAttrs (map (crossSystem: {
|
||||
name = "nix-${crossSystem}";
|
||||
value = let
|
||||
nixpkgsCross = import nixpkgs {
|
||||
inherit system crossSystem;
|
||||
overlays = [ self.overlay ];
|
||||
};
|
||||
in with commonDeps nixpkgsCross; nixpkgsCross.stdenv.mkDerivation {
|
||||
name = "nix-${version}";
|
||||
|
||||
src = self;
|
||||
|
||||
VERSION_SUFFIX = versionSuffix;
|
||||
|
||||
outputs = [ "out" "dev" "doc" ];
|
||||
|
||||
nativeBuildInputs = nativeBuildDeps;
|
||||
buildInputs = buildDeps ++ propagatedDeps;
|
||||
|
||||
configureFlags = [ "--sysconfdir=/etc" "--disable-doc-gen" ];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
makeFlags = "profiledir=$(out)/etc/profile.d";
|
||||
|
||||
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
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
doInstallCheck = true;
|
||||
installCheckFlags = "sysconfdir=$(out)/etc";
|
||||
};
|
||||
}) crossSystems)));
|
||||
|
||||
defaultPackage = forAllSystems (system: self.packages.${system}.nix);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ my $nixpkgsDir = "/home/eelco/Dev/nixpkgs-pristine";
|
|||
|
||||
my $TMPDIR = $ENV{'TMPDIR'} // "/tmp";
|
||||
|
||||
my $isLatest = ($ENV{'IS_LATEST'} // "") eq "1";
|
||||
|
||||
# FIXME: cut&paste from nixos-channel-scripts.
|
||||
sub fetch {
|
||||
my ($url, $type) = @_;
|
||||
|
|
@ -35,16 +37,18 @@ sub fetch {
|
|||
my $evalUrl = "https://hydra.nixos.org/eval/$evalId";
|
||||
my $evalInfo = decode_json(fetch($evalUrl, 'application/json'));
|
||||
#print Dumper($evalInfo);
|
||||
my $flakeUrl = $evalInfo->{flake} or die;
|
||||
my $flakeInfo = decode_json(`nix flake metadata --json "$flakeUrl"` or die);
|
||||
my $nixRev = $flakeInfo->{revision} or die;
|
||||
|
||||
my $nixRev = $evalInfo->{jobsetevalinputs}->{nix}->{revision} or die;
|
||||
my $buildInfo = decode_json(fetch("$evalUrl/job/build.x86_64-linux", 'application/json'));
|
||||
#print Dumper($buildInfo);
|
||||
|
||||
my $tarballInfo = decode_json(fetch("$evalUrl/job/tarball", 'application/json'));
|
||||
|
||||
my $releaseName = $tarballInfo->{releasename};
|
||||
my $releaseName = $buildInfo->{nixname};
|
||||
$releaseName =~ /nix-(.*)$/ or die;
|
||||
my $version = $1;
|
||||
|
||||
print STDERR "Nix revision is $nixRev, version is $version\n";
|
||||
print STDERR "Flake URL is $flakeUrl, Nix revision is $nixRev, version is $version\n";
|
||||
|
||||
my $releaseDir = "nix/$releaseName";
|
||||
|
||||
|
|
@ -83,12 +87,12 @@ sub downloadFile {
|
|||
|
||||
if (!-e $tmpFile) {
|
||||
print STDERR "downloading $srcFile to $tmpFile...\n";
|
||||
system("NIX_REMOTE=https://cache.nixos.org/ nix cat-store '$srcFile' > '$tmpFile'") == 0
|
||||
system("NIX_REMOTE=https://cache.nixos.org/ nix store cat '$srcFile' > '$tmpFile'") == 0
|
||||
or die "unable to fetch $srcFile\n";
|
||||
}
|
||||
|
||||
my $sha256_expected = $buildInfo->{buildproducts}->{$productNr}->{sha256hash} or die;
|
||||
my $sha256_actual = `nix hash-file --base16 --type sha256 '$tmpFile'`;
|
||||
my $sha256_actual = `nix hash file --base16 --type sha256 '$tmpFile'`;
|
||||
chomp $sha256_actual;
|
||||
if ($sha256_expected ne $sha256_actual) {
|
||||
print STDERR "file $tmpFile is corrupt, got $sha256_actual, expected $sha256_expected\n";
|
||||
|
|
@ -104,12 +108,13 @@ sub downloadFile {
|
|||
return $sha256_expected;
|
||||
}
|
||||
|
||||
downloadFile("tarball", "2"); # .tar.bz2
|
||||
my $tarballHash = downloadFile("tarball", "3"); # .tar.xz
|
||||
downloadFile("binaryTarball.i686-linux", "1");
|
||||
downloadFile("binaryTarball.x86_64-linux", "1");
|
||||
downloadFile("binaryTarball.aarch64-linux", "1");
|
||||
downloadFile("binaryTarball.x86_64-darwin", "1");
|
||||
downloadFile("binaryTarball.aarch64-darwin", "1");
|
||||
downloadFile("binaryTarballCross.x86_64-linux.armv6l-linux", "1");
|
||||
downloadFile("binaryTarballCross.x86_64-linux.armv7l-linux", "1");
|
||||
downloadFile("installerScript", "1");
|
||||
|
||||
for my $fn (glob "$tmpDir/*") {
|
||||
|
|
@ -131,53 +136,38 @@ for my $fn (glob "$tmpDir/*") {
|
|||
}
|
||||
}
|
||||
|
||||
exit if $version =~ /pre/;
|
||||
# Update nix-fallback-paths.nix.
|
||||
if ($isLatest) {
|
||||
system("cd $nixpkgsDir && git pull") == 0 or die;
|
||||
|
||||
# Update Nixpkgs in a very hacky way.
|
||||
system("cd $nixpkgsDir && git pull") == 0 or die;
|
||||
my $oldName = `nix-instantiate --eval $nixpkgsDir -A nix.name`; chomp $oldName;
|
||||
my $oldHash = `nix-instantiate --eval $nixpkgsDir -A nix.src.outputHash`; chomp $oldHash;
|
||||
print STDERR "old stable version in Nixpkgs = $oldName / $oldHash\n";
|
||||
|
||||
my $fn = "$nixpkgsDir/pkgs/tools/package-management/nix/default.nix";
|
||||
my $oldFile = read_file($fn);
|
||||
$oldFile =~ s/$oldName/"$releaseName"/g;
|
||||
$oldFile =~ s/$oldHash/"$tarballHash"/g;
|
||||
write_file($fn, $oldFile);
|
||||
|
||||
$oldName =~ s/nix-//g;
|
||||
$oldName =~ s/"//g;
|
||||
|
||||
sub getStorePath {
|
||||
my ($jobName) = @_;
|
||||
my $buildInfo = decode_json(fetch("$evalUrl/job/$jobName", 'application/json'));
|
||||
for my $product (values %{$buildInfo->{buildproducts}}) {
|
||||
next unless $product->{type} eq "nix-build";
|
||||
next if $product->{path} =~ /[a-z]+$/;
|
||||
return $product->{path};
|
||||
sub getStorePath {
|
||||
my ($jobName) = @_;
|
||||
my $buildInfo = decode_json(fetch("$evalUrl/job/$jobName", 'application/json'));
|
||||
return $buildInfo->{buildoutputs}->{out}->{path} or die "cannot get store path for '$jobName'";
|
||||
}
|
||||
die;
|
||||
|
||||
write_file("$nixpkgsDir/nixos/modules/installer/tools/nix-fallback-paths.nix",
|
||||
"{\n" .
|
||||
" x86_64-linux = \"" . getStorePath("build.x86_64-linux") . "\";\n" .
|
||||
" i686-linux = \"" . getStorePath("build.i686-linux") . "\";\n" .
|
||||
" aarch64-linux = \"" . getStorePath("build.aarch64-linux") . "\";\n" .
|
||||
" x86_64-darwin = \"" . getStorePath("build.x86_64-darwin") . "\";\n" .
|
||||
" aarch64-darwin = \"" . getStorePath("build.aarch64-darwin") . "\";\n" .
|
||||
"}\n");
|
||||
|
||||
system("cd $nixpkgsDir && git commit -a -m 'nix-fallback-paths.nix: Update to $version'") == 0 or die;
|
||||
}
|
||||
|
||||
write_file("$nixpkgsDir/nixos/modules/installer/tools/nix-fallback-paths.nix",
|
||||
"{\n" .
|
||||
" x86_64-linux = \"" . getStorePath("build.x86_64-linux") . "\";\n" .
|
||||
" i686-linux = \"" . getStorePath("build.i686-linux") . "\";\n" .
|
||||
" aarch64-linux = \"" . getStorePath("build.aarch64-linux") . "\";\n" .
|
||||
" x86_64-darwin = \"" . getStorePath("build.x86_64-darwin") . "\";\n" .
|
||||
"}\n");
|
||||
|
||||
system("cd $nixpkgsDir && git commit -a -m 'nix: $oldName -> $version'") == 0 or die;
|
||||
|
||||
# Update the "latest" symlink.
|
||||
$channelsBucket->add_key(
|
||||
"nix-latest/install", "",
|
||||
{ "x-amz-website-redirect-location" => "https://releases.nixos.org/$releaseDir/install" })
|
||||
or die $channelsBucket->err . ": " . $channelsBucket->errstr;
|
||||
or die $channelsBucket->err . ": " . $channelsBucket->errstr
|
||||
if $isLatest;
|
||||
|
||||
# Tag the release in Git.
|
||||
chdir("/home/eelco/Dev/nix-pristine") or die;
|
||||
system("git remote update origin") == 0 or die;
|
||||
system("git tag --force --sign $version $nixRev -m 'Tagging release $version'") == 0 or die;
|
||||
system("git push --tags") == 0 or die;
|
||||
system("git push --force-with-lease origin $nixRev:refs/heads/latest-release") == 0 or die;
|
||||
system("git push --force-with-lease origin $nixRev:refs/heads/latest-release") == 0 or die if $isLatest;
|
||||
|
|
|
|||
37
misc/fish/completion.fish
Normal file
37
misc/fish/completion.fish
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
function _nix_complete
|
||||
# Get the current command up to a cursor.
|
||||
# - Behaves correctly even with pipes and nested in commands like env.
|
||||
# - TODO: Returns the command verbatim (does not interpolate variables).
|
||||
# That might not be optimal for arguments like -f.
|
||||
set -l nix_args (commandline --current-process --tokenize --cut-at-cursor)
|
||||
# --cut-at-cursor with --tokenize removes the current token so we need to add it separately.
|
||||
# https://github.com/fish-shell/fish-shell/issues/7375
|
||||
# Can be an empty string.
|
||||
set -l current_token (commandline --current-token --cut-at-cursor)
|
||||
|
||||
# Nix wants the index of the argv item to complete but the $nix_args variable
|
||||
# also contains the program name (argv[0]) so we would need to subtract 1.
|
||||
# But the variable also misses the current token so it cancels out.
|
||||
set -l nix_arg_to_complete (count $nix_args)
|
||||
|
||||
env NIX_GET_COMPLETIONS=$nix_arg_to_complete $nix_args $current_token
|
||||
end
|
||||
|
||||
function _nix_accepts_files
|
||||
set -l response (_nix_complete)
|
||||
# First line is either filenames or no-filenames.
|
||||
test $response[1] = 'filenames'
|
||||
end
|
||||
|
||||
function _nix
|
||||
set -l response (_nix_complete)
|
||||
# Skip the first line since it handled by _nix_accepts_files.
|
||||
# Tail lines each contain a command followed by a tab character and, optionally, a description.
|
||||
# This is also the format fish expects.
|
||||
string collect -- $response[2..-1]
|
||||
end
|
||||
|
||||
# Disable file path completion if paths do not belong in the current context.
|
||||
complete --command nix --condition 'not _nix_accepts_files' --no-files
|
||||
|
||||
complete --command nix --arguments '(_nix)'
|
||||
1
misc/fish/local.mk
Normal file
1
misc/fish/local.mk
Normal file
|
|
@ -0,0 +1 @@
|
|||
$(eval $(call install-file-as, $(d)/completion.fish, $(datarootdir)/fish/vendor_completions.d/nix.fish, 0644))
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
ifeq ($(OS), Darwin)
|
||||
ifdef HOST_DARWIN
|
||||
|
||||
$(eval $(call install-data-in, $(d)/org.nixos.nix-daemon.plist, $(prefix)/Library/LaunchDaemons))
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
<array>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/var/nix/profiles/default/bin/nix-daemon && /nix/var/nix/profiles/default/bin/nix-daemon</string>
|
||||
<string>/bin/wait4path /nix/var/nix/profiles/default/bin/nix-daemon && exec /nix/var/nix/profiles/default/bin/nix-daemon</string>
|
||||
</array>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/var/log/nix-daemon.log</string>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
ifeq ($(OS), Linux)
|
||||
ifdef HOST_LINUX
|
||||
|
||||
$(foreach n, nix-daemon.socket nix-daemon.service, $(eval $(call install-file-in, $(d)/$(n), $(prefix)/lib/systemd/system, 0644)))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
ifeq ($(OS), Linux)
|
||||
ifdef HOST_LINUX
|
||||
|
||||
$(foreach n, nix-daemon.conf, $(eval $(call install-file-in, $(d)/$(n), $(sysconfdir)/init, 0644)))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#compdef nix
|
||||
|
||||
function _nix() {
|
||||
local ifs_bk="$IFS"
|
||||
local input=("${(Q)words[@]}")
|
||||
|
|
@ -18,4 +20,4 @@ function _nix() {
|
|||
_describe 'nix' suggestions
|
||||
}
|
||||
|
||||
compdef _nix nix
|
||||
_nix "$@"
|
||||
|
|
|
|||
1
misc/zsh/local.mk
Normal file
1
misc/zsh/local.mk
Normal file
|
|
@ -0,0 +1 @@
|
|||
$(eval $(call install-file-as, $(d)/completion.zsh, $(datarootdir)/zsh/site-functions/_nix, 0644))
|
||||
36
mk/jars.mk
36
mk/jars.mk
|
|
@ -1,36 +0,0 @@
|
|||
define build-jar
|
||||
|
||||
$(1)_NAME ?= $(1)
|
||||
|
||||
_d := $$(strip $$($(1)_DIR))
|
||||
|
||||
$(1)_PATH := $$(_d)/$$($(1)_NAME).jar
|
||||
|
||||
$(1)_TMPDIR := $$(_d)/.$$($(1)_NAME).jar.tmp
|
||||
|
||||
_jars := $$(foreach jar, $$($(1)_JARS), $$($$(jar)_PATH))
|
||||
|
||||
$$($(1)_PATH): $$($(1)_SOURCES) $$(_jars) $$($(1)_EXTRA_DEPS)| $$($(1)_ORDER_AFTER)
|
||||
@rm -rf $$($(1)_TMPDIR)
|
||||
@mkdir -p $$($(1)_TMPDIR)
|
||||
$$(trace-javac) javac $(GLOBAL_JAVACFLAGS) $$($(1)_JAVACFLAGS) -d $$($(1)_TMPDIR) \
|
||||
$$(foreach fn, $$($(1)_SOURCES), '$$(fn)') \
|
||||
-cp "$$(subst $$(space),,$$(foreach jar,$$($(1)_JARS),$$($$(jar)_PATH):))$$$$CLASSPATH"
|
||||
@echo -e '$$(subst $$(newline),\n,$$($(1)_MANIFEST))' > $$($(1)_PATH).manifest
|
||||
$$(trace-jar) jar cfm $$($(1)_PATH) $$($(1)_PATH).manifest -C $$($(1)_TMPDIR) .
|
||||
@rm $$($(1)_PATH).manifest
|
||||
@rm -rf $$($(1)_TMPDIR)
|
||||
|
||||
$(1)_INSTALL_DIR ?= $$(jardir)
|
||||
|
||||
$(1)_INSTALL_PATH := $$($(1)_INSTALL_DIR)/$$($(1)_NAME).jar
|
||||
|
||||
$$(eval $$(call install-file-as, $$($(1)_PATH), $$($(1)_INSTALL_PATH), 0644))
|
||||
|
||||
install: $$($(1)_INSTALL_PATH)
|
||||
|
||||
jars-list += $$($(1)_PATH)
|
||||
|
||||
clean-files += $$($(1)_PATH)
|
||||
|
||||
endef
|
||||
40
mk/lib.mk
40
mk/lib.mk
|
|
@ -10,8 +10,25 @@ bin-scripts :=
|
|||
noinst-scripts :=
|
||||
man-pages :=
|
||||
install-tests :=
|
||||
OS = $(shell uname -s)
|
||||
|
||||
ifdef HOST_OS
|
||||
HOST_KERNEL = $(firstword $(subst -, ,$(HOST_OS)))
|
||||
ifeq ($(HOST_KERNEL), cygwin)
|
||||
HOST_CYGWIN = 1
|
||||
endif
|
||||
ifeq ($(patsubst darwin%,,$(HOST_KERNEL)),)
|
||||
HOST_DARWIN = 1
|
||||
endif
|
||||
ifeq ($(patsubst freebsd%,,$(HOST_KERNEL)),)
|
||||
HOST_FREEBSD = 1
|
||||
endif
|
||||
ifeq ($(HOST_KERNEL), linux)
|
||||
HOST_LINUX = 1
|
||||
endif
|
||||
ifeq ($(patsubst solaris%,,$(HOST_KERNEL)),)
|
||||
HOST_SOLARIS = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
# Hack to define a literal space.
|
||||
space :=
|
||||
|
|
@ -31,7 +48,6 @@ libdir ?= $(prefix)/lib
|
|||
bindir ?= $(prefix)/bin
|
||||
libexecdir ?= $(prefix)/libexec
|
||||
datadir ?= $(prefix)/share
|
||||
jardir ?= $(datadir)/java
|
||||
localstatedir ?= $(prefix)/var
|
||||
sysconfdir ?= $(prefix)/etc
|
||||
mandir ?= $(prefix)/share/man
|
||||
|
|
@ -51,16 +67,16 @@ endif
|
|||
BUILD_SHARED_LIBS ?= 1
|
||||
|
||||
ifeq ($(BUILD_SHARED_LIBS), 1)
|
||||
ifeq (CYGWIN,$(findstring CYGWIN,$(OS)))
|
||||
ifdef HOST_CYGWIN
|
||||
GLOBAL_CFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE
|
||||
GLOBAL_CXXFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE
|
||||
else
|
||||
GLOBAL_CFLAGS += -fPIC
|
||||
GLOBAL_CXXFLAGS += -fPIC
|
||||
endif
|
||||
ifneq ($(OS), Darwin)
|
||||
ifneq ($(OS), SunOS)
|
||||
ifneq ($(OS), FreeBSD)
|
||||
ifndef HOST_DARWIN
|
||||
ifndef HOST_SOLARIS
|
||||
ifndef HOST_FREEBSD
|
||||
GLOBAL_LDFLAGS += -Wl,--no-copy-dt-needed-entries
|
||||
endif
|
||||
endif
|
||||
|
|
@ -74,7 +90,6 @@ BUILD_DEBUG ?= 1
|
|||
ifeq ($(BUILD_DEBUG), 1)
|
||||
GLOBAL_CFLAGS += -g
|
||||
GLOBAL_CXXFLAGS += -g
|
||||
GLOBAL_JAVACFLAGS += -g
|
||||
endif
|
||||
|
||||
|
||||
|
|
@ -84,7 +99,6 @@ include mk/clean.mk
|
|||
include mk/install.mk
|
||||
include mk/libraries.mk
|
||||
include mk/programs.mk
|
||||
include mk/jars.mk
|
||||
include mk/patterns.mk
|
||||
include mk/templates.mk
|
||||
include mk/tests.mk
|
||||
|
|
@ -102,7 +116,6 @@ $(foreach mf, $(makefiles), $(eval $(call include-sub-makefile, $(mf))))
|
|||
# Instantiate stuff.
|
||||
$(foreach lib, $(libraries), $(eval $(call build-library,$(lib))))
|
||||
$(foreach prog, $(programs), $(eval $(call build-program,$(prog))))
|
||||
$(foreach jar, $(jars), $(eval $(call build-jar,$(jar))))
|
||||
$(foreach script, $(bin-scripts), $(eval $(call install-program-in,$(script),$(bindir))))
|
||||
$(foreach script, $(bin-scripts), $(eval programs-list += $(script)))
|
||||
$(foreach script, $(noinst-scripts), $(eval programs-list += $(script)))
|
||||
|
|
@ -113,7 +126,7 @@ $(foreach file, $(man-pages), $(eval $(call install-data-in, $(file), $(mandir)/
|
|||
|
||||
.PHONY: default all man help
|
||||
|
||||
all: $(programs-list) $(libs-list) $(jars-list) $(man-pages)
|
||||
all: $(programs-list) $(libs-list) $(man-pages)
|
||||
|
||||
man: $(man-pages)
|
||||
|
||||
|
|
@ -137,12 +150,6 @@ ifdef libs-list
|
|||
@echo "The following libraries can be built:"
|
||||
@echo ""
|
||||
@for i in $(libs-list); do echo " $$i"; done
|
||||
endif
|
||||
ifdef jars-list
|
||||
@echo ""
|
||||
@echo "The following JARs can be built:"
|
||||
@echo ""
|
||||
@for i in $(jars-list); do echo " $$i"; done
|
||||
endif
|
||||
@echo ""
|
||||
@echo "The following variables control the build:"
|
||||
|
|
@ -153,4 +160,5 @@ endif
|
|||
@echo " CFLAGS: Flags for the C compiler"
|
||||
@echo " CXX ($(CXX)): C++ compiler to be used"
|
||||
@echo " CXXFLAGS: Flags for the C++ compiler"
|
||||
@echo " CPPFLAGS: C preprocessor flags, used for both CC and CXX"
|
||||
@$(print-var-help)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
libs-list :=
|
||||
|
||||
ifeq ($(OS), Darwin)
|
||||
ifdef HOST_DARWIN
|
||||
SO_EXT = dylib
|
||||
else
|
||||
ifeq (CYGWIN,$(findstring CYGWIN,$(OS)))
|
||||
ifdef HOST_CYGWIN
|
||||
SO_EXT = dll
|
||||
else
|
||||
SO_EXT = so
|
||||
|
|
@ -59,7 +59,7 @@ define build-library
|
|||
$(1)_OBJS := $$(addprefix $(buildprefix), $$(addsuffix .o, $$(basename $$(_srcs))))
|
||||
_libs := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_PATH))
|
||||
|
||||
ifeq (CYGWIN,$(findstring CYGWIN,$(OS)))
|
||||
ifdef HOST_CYGWIN
|
||||
$(1)_INSTALL_DIR ?= $$(bindir)
|
||||
else
|
||||
$(1)_INSTALL_DIR ?= $$(libdir)
|
||||
|
|
@ -73,18 +73,18 @@ define build-library
|
|||
ifeq ($(BUILD_SHARED_LIBS), 1)
|
||||
|
||||
ifdef $(1)_ALLOW_UNDEFINED
|
||||
ifeq ($(OS), Darwin)
|
||||
ifdef HOST_DARWIN
|
||||
$(1)_LDFLAGS += -undefined suppress -flat_namespace
|
||||
endif
|
||||
else
|
||||
ifneq ($(OS), Darwin)
|
||||
ifneq (CYGWIN,$(findstring CYGWIN,$(OS)))
|
||||
ifndef HOST_DARWIN
|
||||
ifndef HOST_CYGWIN
|
||||
$(1)_LDFLAGS += -Wl,-z,defs
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(OS), Darwin)
|
||||
ifndef HOST_DARWIN
|
||||
$(1)_LDFLAGS += -Wl,-soname=$$($(1)_NAME).$(SO_EXT)
|
||||
endif
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ define build-library
|
|||
$$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/
|
||||
$$(trace-ld) $(CXX) -o $$(abspath $$@) -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) $$($(1)_LDFLAGS_UNINSTALLED)
|
||||
|
||||
ifneq ($(OS), Darwin)
|
||||
ifndef HOST_DARWIN
|
||||
$(1)_LDFLAGS_USE += -Wl,-rpath,$$(abspath $$(_d))
|
||||
endif
|
||||
$(1)_LDFLAGS_USE += -L$$(_d) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME)))
|
||||
|
|
@ -108,7 +108,7 @@ define build-library
|
|||
$$(trace-ld) $(CXX) -o $$@ -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED))
|
||||
|
||||
$(1)_LDFLAGS_USE_INSTALLED += -L$$(DESTDIR)$$($(1)_INSTALL_DIR) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME)))
|
||||
ifneq ($(OS), Darwin)
|
||||
ifndef HOST_DARWIN
|
||||
ifeq ($(SET_RPATH_TO_LIBS), 1)
|
||||
$(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath,$$($(1)_INSTALL_DIR)
|
||||
else
|
||||
|
|
@ -125,8 +125,8 @@ define build-library
|
|||
$(1)_PATH := $$(_d)/$$($(1)_NAME).a
|
||||
|
||||
$$($(1)_PATH): $$($(1)_OBJS) | $$(_d)/
|
||||
$(trace-ld) $(LD) -Ur -o $$(_d)/$$($(1)_NAME).o $$?
|
||||
$(trace-ar) $(AR) crs $$@ $$(_d)/$$($(1)_NAME).o
|
||||
$$(trace-ld) $(LD) -Ur -o $$(_d)/$$($(1)_NAME).o $$?
|
||||
$$(trace-ar) $(AR) crs $$@ $$(_d)/$$($(1)_NAME).o
|
||||
|
||||
$(1)_LDFLAGS_USE += $$($(1)_PATH) $$($(1)_LDFLAGS)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
$(buildprefix)%.o: %.cc
|
||||
@mkdir -p "$(dir $@)"
|
||||
$(trace-cxx) $(CXX) -o $@ -c $< $(GLOBAL_CXXFLAGS_PCH) $(GLOBAL_CXXFLAGS) $(CXXFLAGS) $($@_CXXFLAGS) -MMD -MF $(call filename-to-dep, $@) -MP
|
||||
$(trace-cxx) $(CXX) -o $@ -c $< $(CPPFLAGS) $(GLOBAL_CXXFLAGS_PCH) $(GLOBAL_CXXFLAGS) $(CXXFLAGS) $($@_CXXFLAGS) -MMD -MF $(call filename-to-dep, $@) -MP
|
||||
|
||||
$(buildprefix)%.o: %.cpp
|
||||
@mkdir -p "$(dir $@)"
|
||||
$(trace-cxx) $(CXX) -o $@ -c $< $(GLOBAL_CXXFLAGS_PCH) $(GLOBAL_CXXFLAGS) $(CXXFLAGS) $($@_CXXFLAGS) -MMD -MF $(call filename-to-dep, $@) -MP
|
||||
$(trace-cxx) $(CXX) -o $@ -c $< $(CPPFLAGS) $(GLOBAL_CXXFLAGS_PCH) $(GLOBAL_CXXFLAGS) $(CXXFLAGS) $($@_CXXFLAGS) -MMD -MF $(call filename-to-dep, $@) -MP
|
||||
|
||||
$(buildprefix)%.o: %.c
|
||||
@mkdir -p "$(dir $@)"
|
||||
$(trace-cc) $(CC) -o $@ -c $< $(GLOBAL_CFLAGS) $(CFLAGS) $($@_CFLAGS) -MMD -MF $(call filename-to-dep, $@) -MP
|
||||
$(trace-cc) $(CC) -o $@ -c $< $(CPPFLAGS) $(GLOBAL_CFLAGS) $(CFLAGS) $($@_CFLAGS) -MMD -MF $(call filename-to-dep, $@) -MP
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ if [ -t 1 ]; then
|
|||
yellow="[33;1m"
|
||||
normal="[m"
|
||||
fi
|
||||
(cd $(dirname $1) && env ${TESTS_ENVIRONMENT} init.sh 2>/dev/null > /dev/null)
|
||||
(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
|
||||
|
|
|
|||
|
|
@ -8,8 +8,12 @@ define run-install-test
|
|||
|
||||
.PHONY: $1.test
|
||||
$1.test: $1 $(test-deps)
|
||||
@env TEST_NAME=$(notdir $(basename $1)) TESTS_ENVIRONMENT="$(tests-environment)" mk/run_test.sh $1 < /dev/null
|
||||
@env TEST_NAME=$(basename $1) TESTS_ENVIRONMENT="$(tests-environment)" mk/run_test.sh $1 < /dev/null
|
||||
|
||||
endef
|
||||
|
||||
.PHONY: check installcheck
|
||||
|
||||
print-top-help += \
|
||||
echo " check: Run unit tests"; \
|
||||
echo " installcheck: Run functional tests";
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ ifeq ($(V), 0)
|
|||
trace-ld = @echo " LD " $@;
|
||||
trace-ar = @echo " AR " $@;
|
||||
trace-install = @echo " INST " $@;
|
||||
trace-javac = @echo " JAVAC " $@;
|
||||
trace-jar = @echo " JAR " $@;
|
||||
trace-mkdir = @echo " MKDIR " $@;
|
||||
trace-test = @echo " TEST " $@;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,15 @@ 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 -ldl
|
||||
libnixrust_LDFLAGS_USE_INSTALLED := -L$(libdir) -lnixrust -ldl
|
||||
libnixrust_LDFLAGS_USE := -L$(d)/target/$(RUST_DIR) -lnixrust
|
||||
libnixrust_LDFLAGS_USE_INSTALLED := -L$(libdir) -lnixrust
|
||||
|
||||
ifeq ($(OS), Darwin)
|
||||
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))
|
||||
|
|
@ -26,7 +31,7 @@ $(libnixrust_PATH): $(call rwildcard, $(d)/src, *.rs) $(d)/Cargo.toml
|
|||
|
||||
$(libnixrust_INSTALL_PATH): $(libnixrust_PATH)
|
||||
$(target-gen) cp $^ $@
|
||||
ifeq ($(OS), Darwin)
|
||||
ifdef HOST_DARWIN
|
||||
install_name_tool -id $@ $@
|
||||
endif
|
||||
|
||||
|
|
@ -35,7 +40,7 @@ clean: clean-rust
|
|||
clean-rust:
|
||||
$(suppress) rm -rfv nix-rust/target
|
||||
|
||||
ifneq ($(OS), Darwin)
|
||||
ifndef HOST_DARWIN
|
||||
check: rust-tests
|
||||
|
||||
rust-tests:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
makefiles = local.mk
|
||||
|
||||
GLOBAL_CXXFLAGS += -g -Wall -std=c++17
|
||||
GLOBAL_CXXFLAGS += -g -Wall -std=c++17 -I ../src
|
||||
|
||||
-include Makefile.config
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
HOST_OS = @host_os@
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
HAVE_SODIUM = @HAVE_SODIUM@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
SODIUM_LIBS = @SODIUM_LIBS@
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ CXXFLAGS=
|
|||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
# Use 64-bit file system calls so that we can support files > 2 GiB.
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
|
|
@ -40,11 +42,7 @@ AC_SUBST(perllibdir, [${libdir}/perl5/site_perl/$perlversion/$perlarchname])
|
|||
AC_MSG_RESULT($perllibdir)
|
||||
|
||||
# Look for libsodium, an optional dependency.
|
||||
PKG_CHECK_MODULES([SODIUM], [libsodium],
|
||||
[AC_DEFINE([HAVE_SODIUM], [1], [Whether to use libsodium for cryptography.])
|
||||
CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"
|
||||
have_sodium=1], [have_sodium=])
|
||||
AC_SUBST(HAVE_SODIUM, [$have_sodium])
|
||||
PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"])
|
||||
|
||||
# Check for the required Perl dependencies (DBI and DBD::SQLite).
|
||||
perlFlags="-I$perllibdir"
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ our @EXPORT = qw(
|
|||
derivationFromPath
|
||||
addTempRoot
|
||||
getBinDir getStoreDir
|
||||
queryRawRealisation
|
||||
);
|
||||
|
||||
our $VERSION = '0.15';
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@
|
|||
#include "util.hh"
|
||||
#include "crypto.hh"
|
||||
|
||||
#if HAVE_SODIUM
|
||||
#include <sodium.h>
|
||||
#endif
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
|
||||
using namespace nix;
|
||||
|
|
@ -122,6 +121,18 @@ SV * queryPathInfo(char * path, int base32)
|
|||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
SV * queryRawRealisation(char * outputId)
|
||||
PPCODE:
|
||||
try {
|
||||
auto realisation = store()->queryRealisation(DrvOutput::parse(outputId));
|
||||
if (realisation)
|
||||
XPUSHs(sv_2mortal(newSVpv(realisation->toJSON().dump().c_str(), 0)));
|
||||
else
|
||||
XPUSHs(sv_2mortal(newSVpv("", 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * queryPathFromHashPart(char * hashPart)
|
||||
PPCODE:
|
||||
|
|
@ -239,12 +250,8 @@ SV * convertHash(char * algo, char * s, int toBase32)
|
|||
SV * signString(char * secretKey_, char * msg)
|
||||
PPCODE:
|
||||
try {
|
||||
#if HAVE_SODIUM
|
||||
auto sig = SecretKey(secretKey_).signDetached(msg);
|
||||
XPUSHs(sv_2mortal(newSVpv(sig.c_str(), sig.size())));
|
||||
#else
|
||||
throw Error("Nix was not compiled with libsodium, required for signed binary cache support");
|
||||
#endif
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
|
@ -253,7 +260,6 @@ SV * signString(char * secretKey_, char * msg)
|
|||
int checkSignature(SV * publicKey_, SV * sig_, char * msg)
|
||||
CODE:
|
||||
try {
|
||||
#if HAVE_SODIUM
|
||||
STRLEN publicKeyLen;
|
||||
unsigned char * publicKey = (unsigned char *) SvPV(publicKey_, publicKeyLen);
|
||||
if (publicKeyLen != crypto_sign_PUBLICKEYBYTES)
|
||||
|
|
@ -265,9 +271,6 @@ int checkSignature(SV * publicKey_, SV * sig_, char * msg)
|
|||
throw Error("signature is not valid");
|
||||
|
||||
RETVAL = crypto_sign_verify_detached(sig, (unsigned char *) msg, strlen(msg), publicKey) == 0;
|
||||
#else
|
||||
throw Error("Nix was not compiled with libsodium, required for signed binary cache support");
|
||||
#endif
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ Store_CXXFLAGS = \
|
|||
|
||||
Store_LDFLAGS := $(SODIUM_LIBS) $(NIX_LIBS)
|
||||
|
||||
ifeq (CYGWIN,$(findstring CYGWIN,$(OS)))
|
||||
ifdef HOST_CYGWIN
|
||||
archlib = $(shell perl -E 'use Config; print $$Config{archlib};')
|
||||
libperl = $(shell perl -E 'use Config; print $$Config{libperl};')
|
||||
Store_LDFLAGS += $(shell find ${archlib} -name ${libperl})
|
||||
|
|
|
|||
46
scripts/bigsur-nixbld-user-migration.sh
Executable file
46
scripts/bigsur-nixbld-user-migration.sh
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
((NEW_NIX_FIRST_BUILD_UID=301))
|
||||
|
||||
id_available(){
|
||||
dscl . list /Users UniqueID | grep -E '\b'$1'\b' >/dev/null
|
||||
}
|
||||
|
||||
change_nixbld_names_and_ids(){
|
||||
local name uid next_id
|
||||
((next_id=NEW_NIX_FIRST_BUILD_UID))
|
||||
echo "Attempting to migrate nixbld users."
|
||||
echo "Each user should change from nixbld# to _nixbld#"
|
||||
echo "and their IDs relocated to $next_id+"
|
||||
while read -r name uid; do
|
||||
echo " Checking $name (uid: $uid)"
|
||||
# iterate for a clean ID
|
||||
while id_available "$next_id"; do
|
||||
((next_id++))
|
||||
if ((next_id >= 400)); then
|
||||
echo "We've hit UID 400 without placing all of your users :("
|
||||
echo "You should use the commands in this script as a starting"
|
||||
echo "point to review your UID-space and manually move the"
|
||||
echo "remaining users (or delete them, if you don't need them)."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $name == _* ]]; then
|
||||
echo " It looks like $name has already been renamed--skipping."
|
||||
else
|
||||
# first 3 are cleanup, it's OK if they aren't here
|
||||
sudo dscl . delete /Users/$name dsAttrTypeNative:_writers_passwd &>/dev/null || true
|
||||
sudo dscl . change /Users/$name NFSHomeDirectory "/private/var/empty 1" "/var/empty" &>/dev/null || true
|
||||
# remove existing user from group
|
||||
sudo dseditgroup -o edit -t user -d $name nixbld || true
|
||||
sudo dscl . change /Users/$name UniqueID $uid $next_id
|
||||
sudo dscl . change /Users/$name RecordName $name _$name
|
||||
# add renamed user to group
|
||||
sudo dseditgroup -o edit -t user -a _$name nixbld
|
||||
echo " $name migrated to _$name (uid: $next_id)"
|
||||
fi
|
||||
done < <(dscl . list /Users UniqueID | grep nixbld | sort -n -k2)
|
||||
}
|
||||
|
||||
change_nixbld_names_and_ids
|
||||
|
|
@ -1,33 +1,262 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
root_disk() {
|
||||
diskutil info -plist /
|
||||
}
|
||||
# I'm a little agnostic on the choices, but supporting a wide
|
||||
# slate of uses for now, including:
|
||||
# - import-only: `. create-darwin-volume.sh no-main[ ...]`
|
||||
# - legacy: `./create-darwin-volume.sh` or `. create-darwin-volume.sh`
|
||||
# (both will run main())
|
||||
# - external alt-routine: `./create-darwin-volume.sh no-main func[ ...]`
|
||||
if [ "${1-}" = "no-main" ]; then
|
||||
shift
|
||||
readonly _CREATE_VOLUME_NO_MAIN=1
|
||||
else
|
||||
readonly _CREATE_VOLUME_NO_MAIN=0
|
||||
# declare some things we expect to inherit from install-multi-user
|
||||
# I don't love this (because it's a bit of a kludge).
|
||||
#
|
||||
# CAUTION: (Dec 19 2020)
|
||||
# This is a stopgap. It doesn't cover the full slate of
|
||||
# identifiers we inherit--just those necessary to:
|
||||
# - avoid breaking direct invocations of this script (here/now)
|
||||
# - avoid hard-to-reverse structural changes before the call to rm
|
||||
# single-user support is verified
|
||||
#
|
||||
# In the near-mid term, I (personally) think we should:
|
||||
# - decide to deprecate the direct call and add a notice
|
||||
# - fold all of this into install-darwin-multi-user.sh
|
||||
# - intentionally remove the old direct-invocation form (kill the
|
||||
# routine, replace this script w/ deprecation notice and a note
|
||||
# on the remove-after date)
|
||||
#
|
||||
readonly NIX_ROOT="${NIX_ROOT:-/nix}"
|
||||
|
||||
# i.e., "disk1"
|
||||
_sudo() {
|
||||
shift # throw away the 'explanation'
|
||||
/usr/bin/sudo "$@"
|
||||
}
|
||||
failure() {
|
||||
if [ "$*" = "" ]; then
|
||||
cat
|
||||
else
|
||||
echo "$@"
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
task() {
|
||||
echo "$@"
|
||||
}
|
||||
fi
|
||||
|
||||
# usually "disk1"
|
||||
root_disk_identifier() {
|
||||
diskutil info -plist / | xmllint --xpath "/plist/dict/key[text()='ParentWholeDisk']/following-sibling::string[1]/text()" -
|
||||
# For performance (~10ms vs 280ms) I'm parsing 'diskX' from stat output
|
||||
# (~diskXsY)--but I'm retaining the more-semantic approach since
|
||||
# it documents intent better.
|
||||
# /usr/sbin/diskutil info -plist / | xmllint --xpath "/plist/dict/key[text()='ParentWholeDisk']/following-sibling::string[1]/text()" -
|
||||
#
|
||||
local special_device
|
||||
special_device="$(/usr/bin/stat -f "%Sd" /)"
|
||||
echo "${special_device%s[0-9]*}"
|
||||
}
|
||||
|
||||
find_nix_volume() {
|
||||
diskutil apfs list -plist "$1" | xmllint --xpath "(/plist/dict/array/dict/key[text()='Volumes']/following-sibling::array/dict/key[text()='Name']/following-sibling::string[starts-with(translate(text(),'N','n'),'nix')]/text())[1]" - 2>/dev/null || true
|
||||
# make it easy to play w/ 'Case-sensitive APFS'
|
||||
readonly NIX_VOLUME_FS="${NIX_VOLUME_FS:-APFS}"
|
||||
readonly NIX_VOLUME_LABEL="${NIX_VOLUME_LABEL:-Nix Store}"
|
||||
# Strongly assuming we'll make a volume on the device / is on
|
||||
# But you can override NIX_VOLUME_USE_DISK to create it on some other device
|
||||
readonly NIX_VOLUME_USE_DISK="${NIX_VOLUME_USE_DISK:-$(root_disk_identifier)}"
|
||||
NIX_VOLUME_USE_SPECIAL="${NIX_VOLUME_USE_SPECIAL:-}"
|
||||
NIX_VOLUME_USE_UUID="${NIX_VOLUME_USE_UUID:-}"
|
||||
readonly NIX_VOLUME_MOUNTD_DEST="${NIX_VOLUME_MOUNTD_DEST:-/Library/LaunchDaemons/org.nixos.darwin-store.plist}"
|
||||
|
||||
if /usr/bin/fdesetup isactive >/dev/null; then
|
||||
test_filevault_in_use() { return 0; }
|
||||
# no readonly; we may modify if user refuses from cure_volume
|
||||
NIX_VOLUME_DO_ENCRYPT="${NIX_VOLUME_DO_ENCRYPT:-1}"
|
||||
else
|
||||
test_filevault_in_use() { return 1; }
|
||||
NIX_VOLUME_DO_ENCRYPT="${NIX_VOLUME_DO_ENCRYPT:-0}"
|
||||
fi
|
||||
|
||||
should_encrypt_volume() {
|
||||
test_filevault_in_use && (( NIX_VOLUME_DO_ENCRYPT == 1 ))
|
||||
}
|
||||
|
||||
substep() {
|
||||
printf " %s\n" "" "- $1" "" "${@:2}"
|
||||
}
|
||||
|
||||
|
||||
volumes_labeled() {
|
||||
local label="$1"
|
||||
xsltproc --novalid --stringparam label "$label" - <(/usr/sbin/ioreg -ra -c "AppleAPFSVolume") <<'EOF'
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:output method="text"/>
|
||||
<xsl:template match="/">
|
||||
<xsl:apply-templates select="/plist/array/dict/key[text()='IORegistryEntryName']/following-sibling::*[1][text()=$label]/.."/>
|
||||
</xsl:template>
|
||||
<xsl:template match="dict">
|
||||
<xsl:apply-templates match="string" select="key[text()='BSD Name']/following-sibling::*[1]"/>
|
||||
<xsl:text>=</xsl:text>
|
||||
<xsl:apply-templates match="string" select="key[text()='UUID']/following-sibling::*[1]"/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
EOF
|
||||
# I cut label out of the extracted values, but here it is for reference:
|
||||
# <xsl:apply-templates match="string" select="key[text()='IORegistryEntryName']/following-sibling::*[1]"/>
|
||||
# <xsl:text>=</xsl:text>
|
||||
}
|
||||
|
||||
right_disk() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
[[ "$volume_special" == "$NIX_VOLUME_USE_DISK"s* ]]
|
||||
}
|
||||
|
||||
right_volume() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
# if set, it must match; otherwise ensure it's on the right disk
|
||||
if [ -z "$NIX_VOLUME_USE_SPECIAL" ]; then
|
||||
if right_disk "$volume_special"; then
|
||||
NIX_VOLUME_USE_SPECIAL="$volume_special" # latch on
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
[ "$volume_special" = "$NIX_VOLUME_USE_SPECIAL" ]
|
||||
fi
|
||||
}
|
||||
|
||||
right_uuid() {
|
||||
local volume_uuid="$1"
|
||||
# if set, it must match; otherwise allow
|
||||
if [ -z "$NIX_VOLUME_USE_UUID" ]; then
|
||||
NIX_VOLUME_USE_UUID="$volume_uuid" # latch on
|
||||
return 0
|
||||
else
|
||||
[ "$volume_uuid" = "$NIX_VOLUME_USE_UUID" ]
|
||||
fi
|
||||
}
|
||||
|
||||
cure_volumes() {
|
||||
local found volume special uuid
|
||||
# loop just in case they have more than one volume
|
||||
# (nothing stops you from doing this)
|
||||
for volume in $(volumes_labeled "$NIX_VOLUME_LABEL"); do
|
||||
# CAUTION: this could (maybe) be a more normal read
|
||||
# loop like:
|
||||
# while IFS== read -r special uuid; do
|
||||
# # ...
|
||||
# done <<<"$(volumes_labeled "$NIX_VOLUME_LABEL")"
|
||||
#
|
||||
# I did it with for to skirt a problem with the obvious
|
||||
# pattern replacing stdin and causing user prompts
|
||||
# inside (which also use read and access stdin) to skip
|
||||
#
|
||||
# If there's an existing encrypted volume we can't find
|
||||
# in keychain, the user never gets prompted to delete
|
||||
# the volume, and the install fails.
|
||||
#
|
||||
# If you change this, a human needs to test a very
|
||||
# specific scenario: you already have an encrypted
|
||||
# Nix Store volume, and have deleted its credential
|
||||
# from keychain. Ensure the script asks you if it can
|
||||
# delete the volume, and then prompts for your sudo
|
||||
# password to confirm.
|
||||
#
|
||||
# shellcheck disable=SC1097
|
||||
IFS== read -r special uuid <<< "$volume"
|
||||
# take the first one that's on the right disk
|
||||
if [ -z "${found:-}" ]; then
|
||||
if right_volume "$special" && right_uuid "$uuid"; then
|
||||
cure_volume "$special" "$uuid"
|
||||
found="${special} (${uuid})"
|
||||
else
|
||||
warning <<EOF
|
||||
Ignoring ${special} (${uuid}) because I am looking for:
|
||||
disk=${NIX_VOLUME_USE_DISK} special=${NIX_VOLUME_USE_SPECIAL:-${NIX_VOLUME_USE_DISK}sX} uuid=${NIX_VOLUME_USE_UUID:-any}
|
||||
EOF
|
||||
# TODO: give chance to delete if ! headless?
|
||||
fi
|
||||
else
|
||||
warning <<EOF
|
||||
Ignoring ${special} (${uuid}), already found target: $found
|
||||
EOF
|
||||
# TODO reminder? I feel like I want one
|
||||
# idiom that reminds some warnings, or warns
|
||||
# some reminders?
|
||||
# TODO: if ! headless, chance to delete?
|
||||
fi
|
||||
done
|
||||
if [ -z "${found:-}" ]; then
|
||||
readonly NIX_VOLUME_USE_SPECIAL NIX_VOLUME_USE_UUID
|
||||
fi
|
||||
}
|
||||
|
||||
volume_encrypted() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
# Trying to match the first line of output; known first lines:
|
||||
# No cryptographic users for <special>
|
||||
# Cryptographic user for <special> (1 found)
|
||||
# Cryptographic users for <special> (2 found)
|
||||
/usr/sbin/diskutil apfs listCryptoUsers -plist "$volume_special" | /usr/bin/grep -q APFSCryptoUserUUID
|
||||
}
|
||||
|
||||
test_fstab() {
|
||||
grep -q "/nix apfs rw" /etc/fstab 2>/dev/null
|
||||
/usr/bin/grep -q "$NIX_ROOT apfs rw" /etc/fstab 2>/dev/null
|
||||
}
|
||||
|
||||
test_nix_symlink() {
|
||||
[ -L "/nix" ] || grep -q "^nix." /etc/synthetic.conf 2>/dev/null
|
||||
test_nix_root_is_symlink() {
|
||||
[ -L "$NIX_ROOT" ]
|
||||
}
|
||||
|
||||
test_synthetic_conf() {
|
||||
grep -q "^nix$" /etc/synthetic.conf 2>/dev/null
|
||||
test_synthetic_conf_either(){
|
||||
/usr/bin/grep -qE "^${NIX_ROOT:1}($|\t.{3,}$)" /etc/synthetic.conf 2>/dev/null
|
||||
}
|
||||
|
||||
test_synthetic_conf_mountable() {
|
||||
/usr/bin/grep -q "^${NIX_ROOT:1}$" /etc/synthetic.conf 2>/dev/null
|
||||
}
|
||||
|
||||
test_synthetic_conf_symlinked() {
|
||||
/usr/bin/grep -qE "^${NIX_ROOT:1}\t.{3,}$" /etc/synthetic.conf 2>/dev/null
|
||||
}
|
||||
|
||||
test_nix_volume_mountd_installed() {
|
||||
test -e "$NIX_VOLUME_MOUNTD_DEST"
|
||||
}
|
||||
|
||||
# current volume password
|
||||
test_keychain_by_uuid() {
|
||||
local volume_uuid="$1"
|
||||
# Note: doesn't need sudo just to check; doesn't output pw
|
||||
security find-generic-password -s "$volume_uuid" &>/dev/null
|
||||
}
|
||||
|
||||
get_volume_pass() {
|
||||
local volume_uuid="$1"
|
||||
_sudo \
|
||||
"to confirm keychain has a password that unlocks this volume" \
|
||||
security find-generic-password -s "$volume_uuid" -w
|
||||
}
|
||||
|
||||
verify_volume_pass() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
local volume_uuid="$2"
|
||||
/usr/sbin/diskutil apfs unlockVolume "$volume_special" -verify -stdinpassphrase -user "$volume_uuid"
|
||||
}
|
||||
|
||||
volume_pass_works() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
local volume_uuid="$2"
|
||||
get_volume_pass "$volume_uuid" | verify_volume_pass "$volume_special" "$volume_uuid"
|
||||
}
|
||||
|
||||
# Create the paths defined in synthetic.conf, saving us a reboot.
|
||||
create_synthetic_objects(){
|
||||
create_synthetic_objects() {
|
||||
# Big Sur takes away the -B flag we were using and replaces it
|
||||
# with a -t flag that appears to do the same thing (but they
|
||||
# don't behave exactly the same way in terms of return values).
|
||||
|
|
@ -41,129 +270,575 @@ create_synthetic_objects(){
|
|||
}
|
||||
|
||||
test_nix() {
|
||||
test -d "/nix"
|
||||
test -d "$NIX_ROOT"
|
||||
}
|
||||
|
||||
test_t2_chip_present(){
|
||||
# Use xartutil to see if system has a t2 chip.
|
||||
#
|
||||
# This isn't well-documented on its own; until it is,
|
||||
# let's keep track of knowledge/assumptions.
|
||||
#
|
||||
# Warnings:
|
||||
# - Don't search "xart" if porn will cause you trouble :)
|
||||
# - Other xartutil flags do dangerous things. Don't run them
|
||||
# naively. If you must, search "xartutil" first.
|
||||
#
|
||||
# Assumptions:
|
||||
# - the "xART session seeds recovery utility"
|
||||
# appears to interact with xartstorageremoted
|
||||
# - `sudo xartutil --list` lists xART sessions
|
||||
# and their seeds and exits 0 if successful. If
|
||||
# not, it exits 1 and prints an error such as:
|
||||
# xartutil: ERROR: No supported link to the SEP present
|
||||
# - xART sessions/seeds are present when a T2 chip is
|
||||
# (and not, otherwise)
|
||||
# - the presence of a T2 chip means a newly-created
|
||||
# volume on the primary drive will be
|
||||
# encrypted at rest
|
||||
# - all together: `sudo xartutil --list`
|
||||
# should exit 0 if a new Nix Store volume will
|
||||
# be encrypted at rest, and exit 1 if not.
|
||||
sudo xartutil --list >/dev/null 2>/dev/null
|
||||
test_voldaemon() {
|
||||
test -f "$NIX_VOLUME_MOUNTD_DEST"
|
||||
}
|
||||
|
||||
test_filevault_in_use() {
|
||||
fdesetup isactive >/dev/null
|
||||
generate_mount_command() {
|
||||
local cmd_type="$1" # encrypted|unencrypted
|
||||
local volume_uuid mountpoint cmd=()
|
||||
printf -v volume_uuid "%q" "$2"
|
||||
printf -v mountpoint "%q" "$NIX_ROOT"
|
||||
|
||||
case "$cmd_type" in
|
||||
encrypted)
|
||||
cmd=(/bin/sh -c "/usr/bin/security find-generic-password -s '$volume_uuid' -w | /usr/sbin/diskutil apfs unlockVolume '$volume_uuid' -mountpoint '$mountpoint' -stdinpassphrase");;
|
||||
unencrypted)
|
||||
cmd=(/usr/sbin/diskutil mount -mountPoint "$mountpoint" "$volume_uuid");;
|
||||
*)
|
||||
failure "Invalid first arg $cmd_type to generate_mount_command";;
|
||||
esac
|
||||
|
||||
printf " <string>%s</string>\n" "${cmd[@]}"
|
||||
}
|
||||
|
||||
# use after error msg for conditions we don't understand
|
||||
suggest_report_error(){
|
||||
# ex "error: something sad happened :(" >&2
|
||||
echo " please report this @ https://github.com/nixos/nix/issues" >&2
|
||||
generate_mount_daemon() {
|
||||
local cmd_type="$1" # encrypted|unencrypted
|
||||
local volume_uuid="$2"
|
||||
cat <<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>Label</key>
|
||||
<string>org.nixos.darwin-store</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
$(generate_mount_command "$cmd_type" "$volume_uuid")
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
(
|
||||
echo ""
|
||||
echo " ------------------------------------------------------------------ "
|
||||
echo " | This installer will create a volume for the nix store and |"
|
||||
echo " | configure it to mount at /nix. Follow these steps to uninstall. |"
|
||||
echo " ------------------------------------------------------------------ "
|
||||
echo ""
|
||||
echo " 1. Remove the entry from fstab using 'sudo vifs'"
|
||||
echo " 2. Destroy the data volume using 'diskutil apfs deleteVolume'"
|
||||
echo " 3. Remove the 'nix' line from /etc/synthetic.conf or the file"
|
||||
echo ""
|
||||
) >&2
|
||||
_eat_bootout_err() {
|
||||
/usr/bin/grep -v "Boot-out failed: 36: Operation now in progress"
|
||||
}
|
||||
|
||||
if test_nix_symlink; then
|
||||
echo "error: /nix is a symlink, please remove it and make sure it's not in synthetic.conf (in which case a reboot is required)" >&2
|
||||
echo " /nix -> $(readlink "/nix")" >&2
|
||||
exit 2
|
||||
# TODO: remove with --uninstall?
|
||||
uninstall_launch_daemon_directions() {
|
||||
local daemon_label="$1" # i.e., org.nixos.blah-blah
|
||||
local daemon_plist="$2" # abspath
|
||||
substep "Uninstall LaunchDaemon $daemon_label" \
|
||||
" sudo launchctl bootout system/$daemon_label" \
|
||||
" sudo rm $daemon_plist"
|
||||
}
|
||||
|
||||
uninstall_launch_daemon_prompt() {
|
||||
local daemon_label="$1" # i.e., org.nixos.blah-blah
|
||||
local daemon_plist="$2" # abspath
|
||||
local reason_for_daemon="$3"
|
||||
cat <<EOF
|
||||
|
||||
The installer adds a LaunchDaemon to $reason_for_daemon: $daemon_label
|
||||
EOF
|
||||
if ui_confirm "Can I remove it?"; then
|
||||
_sudo "to terminate the daemon" \
|
||||
launchctl bootout "system/$daemon_label" 2> >(_eat_bootout_err >&2) || true
|
||||
# this can "fail" with a message like:
|
||||
# Boot-out failed: 36: Operation now in progress
|
||||
_sudo "to remove the daemon definition" rm "$daemon_plist"
|
||||
fi
|
||||
}
|
||||
|
||||
nix_volume_mountd_uninstall_directions() {
|
||||
uninstall_launch_daemon_directions "org.nixos.darwin-store" \
|
||||
"$NIX_VOLUME_MOUNTD_DEST"
|
||||
}
|
||||
|
||||
nix_volume_mountd_uninstall_prompt() {
|
||||
uninstall_launch_daemon_prompt "org.nixos.darwin-store" \
|
||||
"$NIX_VOLUME_MOUNTD_DEST" \
|
||||
"mount your Nix volume"
|
||||
}
|
||||
|
||||
# TODO: move nix_daemon to install-darwin-multi-user if/when uninstall_launch_daemon_prompt moves up to install-multi-user
|
||||
nix_daemon_uninstall_prompt() {
|
||||
uninstall_launch_daemon_prompt "org.nixos.nix-daemon" \
|
||||
"$NIX_DAEMON_DEST" \
|
||||
"run the nix-daemon"
|
||||
}
|
||||
|
||||
# TODO: remove with --uninstall?
|
||||
nix_daemon_uninstall_directions() {
|
||||
uninstall_launch_daemon_directions "org.nixos.nix-daemon" \
|
||||
"$NIX_DAEMON_DEST"
|
||||
}
|
||||
|
||||
|
||||
# TODO: remove with --uninstall?
|
||||
synthetic_conf_uninstall_directions() {
|
||||
# :1 to strip leading slash
|
||||
substep "Remove ${NIX_ROOT:1} from /etc/synthetic.conf" \
|
||||
" If nix is the only entry: sudo rm /etc/synthetic.conf" \
|
||||
" Otherwise: sudo /usr/bin/sed -i '' -e '/^${NIX_ROOT:1}$/d' /etc/synthetic.conf"
|
||||
}
|
||||
|
||||
synthetic_conf_uninstall_prompt() {
|
||||
cat <<EOF
|
||||
|
||||
During install, I add '${NIX_ROOT:1}' to /etc/synthetic.conf, which instructs
|
||||
macOS to create an empty root directory for mounting the Nix volume.
|
||||
EOF
|
||||
# make the edit to a copy
|
||||
/usr/bin/grep -vE "^${NIX_ROOT:1}($|\t.{3,}$)" /etc/synthetic.conf > "$SCRATCH/synthetic.conf.edit"
|
||||
|
||||
if test_synthetic_conf_symlinked; then
|
||||
warning <<EOF
|
||||
|
||||
/etc/synthetic.conf already contains a line instructing your system
|
||||
to make '${NIX_ROOT}' as a symlink:
|
||||
$(/usr/bin/grep -nE "^${NIX_ROOT:1}\t.{3,}$" /etc/synthetic.conf)
|
||||
|
||||
This may mean your system has/had a non-standard Nix install.
|
||||
|
||||
The volume-creation process in this installer is *not* compatible
|
||||
with a symlinked store, so I'll have to remove this instruction to
|
||||
continue.
|
||||
|
||||
If you want/need to keep this instruction, answer 'n' to abort.
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
if ! test_synthetic_conf; then
|
||||
echo "Configuring /etc/synthetic.conf..." >&2
|
||||
echo nix | sudo tee -a /etc/synthetic.conf
|
||||
if ! test_synthetic_conf; then
|
||||
echo "error: failed to configure synthetic.conf;" >&2
|
||||
suggest_report_error
|
||||
exit 1
|
||||
# ask to rm if this left the file empty aside from comments, else edit
|
||||
if /usr/bin/diff -q <(:) <(/usr/bin/grep -v "^#" "$SCRATCH/synthetic.conf.edit") &>/dev/null; then
|
||||
if confirm_rm "/etc/synthetic.conf"; then
|
||||
if test_nix_root_is_symlink; then
|
||||
failure >&2 <<EOF
|
||||
I removed /etc/synthetic.conf, but $NIX_ROOT is already a symlink
|
||||
(-> $(readlink "$NIX_ROOT")). The system should remove it when you reboot.
|
||||
Once you've rebooted, run the installer again.
|
||||
EOF
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
if confirm_edit "$SCRATCH/synthetic.conf.edit" "/etc/synthetic.conf"; then
|
||||
if test_nix_root_is_symlink; then
|
||||
failure >&2 <<EOF
|
||||
I edited Nix out of /etc/synthetic.conf, but $NIX_ROOT is already a symlink
|
||||
(-> $(readlink "$NIX_ROOT")). The system should remove it when you reboot.
|
||||
Once you've rebooted, run the installer again.
|
||||
EOF
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
# fallback instructions
|
||||
echo "Manually remove nix from /etc/synthetic.conf"
|
||||
return 1
|
||||
}
|
||||
|
||||
if ! test_nix; then
|
||||
echo "Creating mountpoint for /nix..." >&2
|
||||
create_synthetic_objects # the ones we defined in synthetic.conf
|
||||
if ! test_nix; then
|
||||
sudo mkdir -p /nix 2>/dev/null || true
|
||||
add_nix_vol_fstab_line() {
|
||||
local uuid="$1"
|
||||
# shellcheck disable=SC1003,SC2026
|
||||
local escaped_mountpoint="${NIX_ROOT/ /'\\\'040}"
|
||||
shift
|
||||
EDITOR="/usr/bin/ex" _sudo "to add nix to fstab" "$@" <<EOF
|
||||
:a
|
||||
UUID=$uuid $escaped_mountpoint apfs rw,noauto,nobrowse,suid,owners
|
||||
.
|
||||
:x
|
||||
EOF
|
||||
# TODO: preserving my notes on suid,owners above until resolved
|
||||
# There *may* be some issue regarding volume ownership, see nix#3156
|
||||
#
|
||||
# It seems like the cheapest fix is adding "suid,owners" to fstab, but:
|
||||
# - We don't have much info on this condition yet
|
||||
# - I'm not certain if these cause other problems?
|
||||
# - There's a "chown" component some people claim to need to fix this
|
||||
# that I don't understand yet
|
||||
# (Note however that I've had to add a chown step to handle
|
||||
# single->multi-user reinstalls, which may cover this)
|
||||
#
|
||||
# I'm not sure if it's safe to approach this way?
|
||||
#
|
||||
# I think I think the most-proper way to test for it is:
|
||||
# diskutil info -plist "$NIX_VOLUME_LABEL" | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1][name()='true']" -; echo $?
|
||||
#
|
||||
# There's also `sudo /usr/sbin/vsdbutil -c /path` (which is much faster, but is also
|
||||
# deprecated and needs minor parsing).
|
||||
#
|
||||
# If no one finds a problem with doing so, I think the simplest approach
|
||||
# is to just eagerly set this. I found a few imperative approaches:
|
||||
# (diskutil enableOwnership, ~100ms), a cheap one (/usr/sbin/vsdbutil -a, ~40-50ms),
|
||||
# a very cheap one (append the internal format to /var/db/volinfo.database).
|
||||
#
|
||||
# But vsdbutil's deprecation notice suggests using fstab, so I want to
|
||||
# give that a whirl first.
|
||||
#
|
||||
# TODO: when this is workable, poke infinisil about reproducing the issue
|
||||
# and confirming this fix?
|
||||
}
|
||||
|
||||
delete_nix_vol_fstab_line() {
|
||||
# TODO: I'm scaffolding this to handle the new nix volumes
|
||||
# but it might be nice to generalize a smidge further to
|
||||
# go ahead and set up a pattern for curing "old" things
|
||||
# we no longer do?
|
||||
EDITOR="/usr/bin/patch" _sudo "to cut nix from fstab" "$@" < <(/usr/bin/diff /etc/fstab <(/usr/bin/grep -v "$NIX_ROOT apfs rw" /etc/fstab))
|
||||
# leaving some parts out of the grep; people may fiddle this a little?
|
||||
}
|
||||
|
||||
# TODO: hope to remove with --uninstall
|
||||
fstab_uninstall_directions() {
|
||||
substep "Remove ${NIX_ROOT} from /etc/fstab" \
|
||||
" If nix is the only entry: sudo rm /etc/fstab" \
|
||||
" Otherwise, run 'sudo /usr/sbin/vifs' to remove the nix line"
|
||||
}
|
||||
|
||||
fstab_uninstall_prompt() {
|
||||
cat <<EOF
|
||||
During install, I add '${NIX_ROOT}' to /etc/fstab so that macOS knows what
|
||||
mount options to use for the Nix volume.
|
||||
EOF
|
||||
cp /etc/fstab "$SCRATCH/fstab.edit"
|
||||
# technically doesn't need the _sudo path, but throwing away the
|
||||
# output is probably better than mostly-duplicating the code...
|
||||
delete_nix_vol_fstab_line patch "$SCRATCH/fstab.edit" &>/dev/null
|
||||
|
||||
# if the patch test edit, minus comment lines, is equal to empty (:)
|
||||
if /usr/bin/diff -q <(:) <(/usr/bin/grep -v "^#" "$SCRATCH/fstab.edit") &>/dev/null; then
|
||||
# this edit would leave it empty; propose deleting it
|
||||
if confirm_rm "/etc/fstab"; then
|
||||
return 0
|
||||
else
|
||||
echo "Remove nix from /etc/fstab (or remove the file)"
|
||||
fi
|
||||
if ! test_nix; then
|
||||
echo "error: failed to bootstrap /nix; if a reboot doesn't help," >&2
|
||||
suggest_report_error
|
||||
exit 1
|
||||
else
|
||||
echo "I might be able to help you make this edit. Here's the diff:"
|
||||
if ! _diff "/etc/fstab" "$SCRATCH/fstab.edit" && ui_confirm "Does the change above look right?"; then
|
||||
delete_nix_vol_fstab_line /usr/sbin/vifs
|
||||
else
|
||||
echo "Remove nix from /etc/fstab (or remove the file)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
disk="$(root_disk_identifier)"
|
||||
volume=$(find_nix_volume "$disk")
|
||||
if [ -z "$volume" ]; then
|
||||
echo "Creating a Nix Store volume..." >&2
|
||||
remove_volume() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
_sudo "to unmount the Nix volume" \
|
||||
/usr/sbin/diskutil unmount force "$volume_special" || true # might not be mounted
|
||||
_sudo "to delete the Nix volume" \
|
||||
/usr/sbin/diskutil apfs deleteVolume "$volume_special"
|
||||
}
|
||||
|
||||
if test_filevault_in_use; then
|
||||
# TODO: Not sure if it's in-scope now, but `diskutil apfs list`
|
||||
# shows both filevault and encrypted at rest status, and it
|
||||
# may be the more semantic way to test for this? It'll show
|
||||
# `FileVault: No (Encrypted at rest)`
|
||||
# `FileVault: No`
|
||||
# `FileVault: Yes (Unlocked)`
|
||||
# and so on.
|
||||
if test_t2_chip_present; then
|
||||
echo "warning: boot volume is FileVault-encrypted, but the Nix store volume" >&2
|
||||
echo " is only encrypted at rest." >&2
|
||||
echo " See https://nixos.org/nix/manual/#sect-macos-installation" >&2
|
||||
# aspiration: robust enough to both fix problems
|
||||
# *and* update older darwin volumes
|
||||
cure_volume() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
local volume_uuid="$2"
|
||||
header "Found existing Nix volume"
|
||||
row " special" "$volume_special"
|
||||
row " uuid" "$volume_uuid"
|
||||
|
||||
if volume_encrypted "$volume_special"; then
|
||||
row "encrypted" "yes"
|
||||
if volume_pass_works "$volume_special" "$volume_uuid"; then
|
||||
NIX_VOLUME_DO_ENCRYPT=0
|
||||
ok "Found a working decryption password in keychain :)"
|
||||
echo ""
|
||||
else
|
||||
# - this is a volume we made, and
|
||||
# - the user encrypted it on their own
|
||||
# - something deleted the credential
|
||||
# - this is an old or BYO volume and the pw
|
||||
# just isn't somewhere we can find it.
|
||||
#
|
||||
# We're going to explain why we're freaking out
|
||||
# and prompt them to either delete the volume
|
||||
# (requiring a sudo auth), or abort to fix
|
||||
warning <<EOF
|
||||
|
||||
This volume is encrypted, but I don't see a password to decrypt it.
|
||||
The quick fix is to let me delete this volume and make you a new one.
|
||||
If that's okay, enter your (sudo) password to continue. If not, you
|
||||
can ensure the decryption password is in your system keychain with a
|
||||
"Where" (service) field set to this volume's UUID:
|
||||
$volume_uuid
|
||||
EOF
|
||||
if password_confirm "delete this volume"; then
|
||||
remove_volume "$volume_special"
|
||||
else
|
||||
echo "error: refusing to create Nix store volume because the boot volume is" >&2
|
||||
echo " FileVault encrypted, but encryption-at-rest is not available." >&2
|
||||
echo " Manually create a volume for the store and re-run this script." >&2
|
||||
echo " See https://nixos.org/nix/manual/#sect-macos-installation" >&2
|
||||
exit 1
|
||||
# TODO: this is a good design case for a warn-and
|
||||
# remind idiom...
|
||||
failure <<EOF
|
||||
Your Nix volume is encrypted, but I couldn't find its password. Either:
|
||||
- Delete or rename the volume out of the way
|
||||
- Ensure its decryption password is in the system keychain with a
|
||||
"Where" (service) field set to this volume's UUID:
|
||||
$volume_uuid
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
elif test_filevault_in_use; then
|
||||
row "encrypted" "no"
|
||||
warning <<EOF
|
||||
FileVault is on, but your $NIX_VOLUME_LABEL volume isn't encrypted.
|
||||
EOF
|
||||
# if we're interactive, give them a chance to
|
||||
# encrypt the volume. If not, /shrug
|
||||
if ! headless && (( NIX_VOLUME_DO_ENCRYPT == 1 )); then
|
||||
if ui_confirm "Should I encrypt it and add the decryption key to your keychain?"; then
|
||||
encrypt_volume "$volume_uuid" "$NIX_VOLUME_LABEL"
|
||||
NIX_VOLUME_DO_ENCRYPT=0
|
||||
else
|
||||
NIX_VOLUME_DO_ENCRYPT=0
|
||||
reminder "FileVault is on, but your $NIX_VOLUME_LABEL volume isn't encrypted."
|
||||
fi
|
||||
fi
|
||||
|
||||
sudo diskutil apfs addVolume "$disk" APFS 'Nix Store' -mountpoint /nix
|
||||
volume="Nix Store"
|
||||
else
|
||||
echo "Using existing '$volume' volume" >&2
|
||||
fi
|
||||
|
||||
if ! test_fstab; then
|
||||
echo "Configuring /etc/fstab..." >&2
|
||||
label=$(echo "$volume" | sed 's/ /\\040/g')
|
||||
# shellcheck disable=SC2209
|
||||
printf "\$a\nLABEL=%s /nix apfs rw,nobrowse\n.\nwq\n" "$label" | EDITOR=ed sudo vifs
|
||||
row "encrypted" "no"
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
remove_volume_artifacts() {
|
||||
if test_synthetic_conf_either; then
|
||||
# NIX_ROOT is in synthetic.conf
|
||||
if synthetic_conf_uninstall_prompt; then
|
||||
# TODO: moot until we tackle uninstall, but when we're
|
||||
# actually uninstalling, we should issue:
|
||||
# reminder "macOS will clean up the empty mount-point directory at $NIX_ROOT on reboot."
|
||||
:
|
||||
fi
|
||||
fi
|
||||
if test_fstab; then
|
||||
fstab_uninstall_prompt
|
||||
fi
|
||||
|
||||
if test_nix_volume_mountd_installed; then
|
||||
nix_volume_mountd_uninstall_prompt
|
||||
fi
|
||||
}
|
||||
|
||||
setup_synthetic_conf() {
|
||||
if test_nix_root_is_symlink; then
|
||||
if ! test_synthetic_conf_symlinked; then
|
||||
failure >&2 <<EOF
|
||||
error: $NIX_ROOT is a symlink (-> $(readlink "$NIX_ROOT")).
|
||||
Please remove it. If nix is in /etc/synthetic.conf, remove it and reboot.
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
if ! test_synthetic_conf_mountable; then
|
||||
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...
|
||||
_sudo "to add Nix to /etc/synthetic.conf" \
|
||||
/usr/bin/ex /etc/synthetic.conf <<EOF
|
||||
:a
|
||||
${NIX_ROOT:1}
|
||||
.
|
||||
:x
|
||||
EOF
|
||||
if ! test_synthetic_conf_mountable; then
|
||||
failure "error: failed to configure synthetic.conf" >&2
|
||||
fi
|
||||
create_synthetic_objects
|
||||
if ! test_nix; then
|
||||
failure >&2 <<EOF
|
||||
error: failed to bootstrap $NIX_ROOT
|
||||
If you enabled FileVault after booting, this is likely a known issue
|
||||
with macOS that you'll have to reboot to fix. If you didn't enable FV,
|
||||
though, please open an issue describing how the system that you see
|
||||
this error on was set up.
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
setup_fstab() {
|
||||
local volume_uuid="$1"
|
||||
# fstab used to be responsible for mounting the volume. Now the last
|
||||
# step adds a LaunchDaemon responsible for mounting. This is technically
|
||||
# redundant for mounting, but diskutil appears to pick up mount options
|
||||
# from fstab (and diskutil's support for specifying them directly is not
|
||||
# consistent across versions/subcommands).
|
||||
if ! test_fstab; then
|
||||
task "Configuring /etc/fstab to specify volume mount options" >&2
|
||||
add_nix_vol_fstab_line "$volume_uuid" /usr/sbin/vifs
|
||||
fi
|
||||
}
|
||||
|
||||
encrypt_volume() {
|
||||
local volume_uuid="$1"
|
||||
local volume_label="$2"
|
||||
local password
|
||||
# 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.
|
||||
|
||||
/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 encrypt your Nix volume" \
|
||||
/usr/sbin/diskutil apfs encryptVolume "$volume_label" -user disk -stdinpassphrase
|
||||
|
||||
/usr/sbin/diskutil unmount force "$volume_label"
|
||||
}
|
||||
|
||||
create_volume() {
|
||||
# Notes:
|
||||
# 1) using `-nomount` instead of `-mountpoint "$NIX_ROOT"` to get
|
||||
# its UUID and set mount opts in fstab before first mount
|
||||
#
|
||||
# 2) system is in some sense less secure than user keychain... (it's
|
||||
# possible to read the password for decrypting the keychain) but
|
||||
# the user keychain appears to be available too late. As far as I
|
||||
# can tell, the file with this password (/var/db/SystemKey) is
|
||||
# inside the FileVault envelope. If that isn't true, it may make
|
||||
# sense to store the password inside the envelope?
|
||||
#
|
||||
# 3) At some point it would be ideal to have a small binary to serve
|
||||
# as the daemon itself, and for it to replace /usr/bin/security here.
|
||||
#
|
||||
# 4) *UserAgent exemptions should let the system seamlessly supply the
|
||||
# password if noauto is removed from fstab entry. This is intentional;
|
||||
# the user will hopefully look for help if the volume stops mounting,
|
||||
# rather than failing over into subtle race-condition problems.
|
||||
#
|
||||
# 5) If we ever get users griping about not having space to do
|
||||
# anything useful with Nix, it is possibly to specify
|
||||
# `-reserve 10g` or something, which will fail w/o that much
|
||||
#
|
||||
# 6) getting special w/ awk may be fragile, but doing it to:
|
||||
# - save time over running slow diskutil commands
|
||||
# - skirt risk we grab wrong volume if multiple match
|
||||
_sudo "to create a new APFS volume '$NIX_VOLUME_LABEL' on $NIX_VOLUME_USE_DISK" \
|
||||
/usr/sbin/diskutil apfs addVolume "$NIX_VOLUME_USE_DISK" "$NIX_VOLUME_FS" "$NIX_VOLUME_LABEL" -nomount | /usr/bin/awk '/Created new APFS Volume/ {print $5}'
|
||||
}
|
||||
|
||||
volume_uuid_from_special() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
# For reasons I won't pretend to fathom, this returns 253 when it works
|
||||
/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -k "$volume_special" || true
|
||||
}
|
||||
|
||||
# this sometimes clears immediately, and AFAIK clears
|
||||
# within about 1s. diskutil info on an unmounted path
|
||||
# fails in around 50-100ms and a match takes about
|
||||
# 250-300ms. I suspect it's usually ~250-750ms
|
||||
await_volume() {
|
||||
# caution: this could, in theory, get stuck
|
||||
until /usr/sbin/diskutil info "$NIX_ROOT" &>/dev/null; do
|
||||
:
|
||||
done
|
||||
}
|
||||
|
||||
setup_volume() {
|
||||
local use_special use_uuid profile_packages
|
||||
task "Creating a Nix volume" >&2
|
||||
|
||||
use_special="${NIX_VOLUME_USE_SPECIAL:-$(create_volume)}"
|
||||
|
||||
use_uuid=${NIX_VOLUME_USE_UUID:-$(volume_uuid_from_special "$use_special")}
|
||||
|
||||
setup_fstab "$use_uuid"
|
||||
|
||||
if should_encrypt_volume; then
|
||||
encrypt_volume "$use_uuid" "$NIX_VOLUME_LABEL"
|
||||
setup_volume_daemon "encrypted" "$use_uuid"
|
||||
# TODO: might be able to save ~60ms by caching or setting
|
||||
# this somewhere rather than re-checking here.
|
||||
elif volume_encrypted "$use_special"; then
|
||||
setup_volume_daemon "encrypted" "$use_uuid"
|
||||
else
|
||||
setup_volume_daemon "unencrypted" "$use_uuid"
|
||||
fi
|
||||
|
||||
await_volume
|
||||
|
||||
if [ "$(/usr/sbin/diskutil info -plist "$NIX_ROOT" | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]" -)" = "<false/>" ]; then
|
||||
_sudo "to set enableOwnership (enabling users to own files)" \
|
||||
/usr/sbin/diskutil enableOwnership "$NIX_ROOT"
|
||||
fi
|
||||
|
||||
# TODO: below is a vague kludge for now; I just don't know
|
||||
# what if any safe action there is to take here. Also, the
|
||||
# reminder isn't very helpful.
|
||||
# I'm less sure where this belongs, but it also wants mounted, pre-install
|
||||
if type -p nix-env; then
|
||||
profile_packages="$(nix-env --query --installed)"
|
||||
# TODO: can probably do below faster w/ read
|
||||
# intentionally unquoted string to eat whitespace in wc output
|
||||
# shellcheck disable=SC2046,SC2059
|
||||
if ! [ $(printf "$profile_packages" | /usr/bin/wc -l) = "0" ]; then
|
||||
reminder <<EOF
|
||||
Nix now supports only multi-user installs on Darwin/macOS, and your user's
|
||||
Nix profile has some packages in it. These packages may obscure those in the
|
||||
default profile, including the Nix this installer will add. You should
|
||||
review these packages:
|
||||
$profile_packages
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
setup_volume_daemon() {
|
||||
local cmd_type="$1" # encrypted|unencrypted
|
||||
local volume_uuid="$2"
|
||||
if ! test_voldaemon; then
|
||||
task "Configuring LaunchDaemon to mount '$NIX_VOLUME_LABEL'" >&2
|
||||
_sudo "to install the Nix volume mounter" /usr/bin/ex "$NIX_VOLUME_MOUNTD_DEST" <<EOF
|
||||
:a
|
||||
$(generate_mount_daemon "$cmd_type" "$volume_uuid")
|
||||
.
|
||||
:x
|
||||
EOF
|
||||
|
||||
# TODO: should probably alert the user if this is disabled?
|
||||
_sudo "to launch the Nix volume mounter" \
|
||||
launchctl bootstrap system "$NIX_VOLUME_MOUNTD_DEST" || true
|
||||
# TODO: confirm whether kickstart is necessesary?
|
||||
# I feel a little superstitous, but it can guard
|
||||
# against multiple problems (doesn't start, old
|
||||
# version still running for some reason...)
|
||||
_sudo "to launch the Nix volume mounter" \
|
||||
launchctl kickstart -k system/org.nixos.darwin-store
|
||||
fi
|
||||
}
|
||||
|
||||
setup_darwin_volume() {
|
||||
setup_synthetic_conf
|
||||
setup_volume
|
||||
}
|
||||
|
||||
if [ "$_CREATE_VOLUME_NO_MAIN" = 1 ]; then
|
||||
if [ -n "$*" ]; then
|
||||
"$@" # expose functions in case we want multiple routines?
|
||||
fi
|
||||
else
|
||||
# no reason to pay for bash to process this
|
||||
main() {
|
||||
{
|
||||
echo ""
|
||||
echo " ------------------------------------------------------------------ "
|
||||
echo " | This installer will create a volume for the nix store and |"
|
||||
echo " | configure it to mount at $NIX_ROOT. Follow these steps to uninstall. |"
|
||||
echo " ------------------------------------------------------------------ "
|
||||
echo ""
|
||||
echo " 1. Remove the entry from fstab using 'sudo /usr/sbin/vifs'"
|
||||
echo " 2. Run 'sudo launchctl bootout system/org.nixos.darwin-store'"
|
||||
echo " 3. Remove $NIX_VOLUME_MOUNTD_DEST"
|
||||
echo " 4. Destroy the data volume using '/usr/sbin/diskutil apfs deleteVolume'"
|
||||
echo " 5. Remove the 'nix' line from /etc/synthetic.conf (or the file)"
|
||||
echo ""
|
||||
} >&2
|
||||
|
||||
setup_darwin_volume
|
||||
}
|
||||
|
||||
main "$@"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -3,57 +3,110 @@
|
|||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
readonly PLIST_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
readonly NIX_DAEMON_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
# create by default; set 0 to DIY, use a symlink, etc.
|
||||
readonly NIX_VOLUME_CREATE=${NIX_VOLUME_CREATE:-1} # now default
|
||||
NIX_FIRST_BUILD_UID="301"
|
||||
NIX_BUILD_USER_NAME_TEMPLATE="_nixbld%d"
|
||||
|
||||
# caution: may update times on / if not run as normal non-root user
|
||||
read_only_root() {
|
||||
# this touch command ~should~ always produce an error
|
||||
# as of this change I confirmed /usr/bin/touch emits:
|
||||
# "touch: /: Operation not permitted" Monterey
|
||||
# "touch: /: Read-only file system" Catalina+ and Big Sur
|
||||
# "touch: /: Permission denied" Mojave
|
||||
# (not matching prefix for compat w/ coreutils touch in case using
|
||||
# an explicit path causes problems; its prefix differs)
|
||||
case "$(/usr/bin/touch / 2>&1)" in
|
||||
*"Read-only file system") # Catalina, Big Sur
|
||||
return 0
|
||||
;;
|
||||
*"Operation not permitted") # Monterey
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Avoiding the slow semantic way to get this information (~330ms vs ~8ms)
|
||||
# unless using touch causes problems. Just in case, that approach is:
|
||||
# diskutil info -plist / | <find the Writable or WritableVolume keys>, i.e.
|
||||
# diskutil info -plist / | xmllint --xpath "name(/plist/dict/key[text()='Writable']/following-sibling::*[1])" -
|
||||
}
|
||||
|
||||
if read_only_root && [ "$NIX_VOLUME_CREATE" = 1 ]; then
|
||||
should_create_volume() { return 0; }
|
||||
else
|
||||
should_create_volume() { return 1; }
|
||||
fi
|
||||
|
||||
# shellcheck source=./create-darwin-volume.sh
|
||||
. "$EXTRACTED_NIX_PATH/create-darwin-volume.sh" "no-main"
|
||||
|
||||
dsclattr() {
|
||||
/usr/bin/dscl . -read "$1" \
|
||||
| awk "/$2/ { print \$2 }"
|
||||
| /usr/bin/awk "/$2/ { print \$2 }"
|
||||
}
|
||||
|
||||
poly_validate_assumptions() {
|
||||
if [ "$(uname -s)" != "Darwin" ]; then
|
||||
failure "This script is for use with macOS!"
|
||||
test_nix_daemon_installed() {
|
||||
test -e "$NIX_DAEMON_DEST"
|
||||
}
|
||||
|
||||
poly_cure_artifacts() {
|
||||
if should_create_volume; then
|
||||
task "Fixing any leftover Nix volume state"
|
||||
cat <<EOF
|
||||
Before I try to install, I'll check for any existing Nix volume config
|
||||
and ask for your permission to remove it (so that the installer can
|
||||
start fresh). I'll also ask for permission to fix any issues I spot.
|
||||
EOF
|
||||
cure_volumes
|
||||
remove_volume_artifacts
|
||||
fi
|
||||
}
|
||||
|
||||
poly_service_installed_check() {
|
||||
[ -e "$PLIST_DEST" ]
|
||||
if should_create_volume; then
|
||||
test_nix_daemon_installed || test_nix_volume_mountd_installed
|
||||
else
|
||||
test_nix_daemon_installed
|
||||
fi
|
||||
}
|
||||
|
||||
poly_service_uninstall_directions() {
|
||||
cat <<EOF
|
||||
$1. Delete $PLIST_DEST
|
||||
|
||||
sudo launchctl unload $PLIST_DEST
|
||||
sudo rm $PLIST_DEST
|
||||
|
||||
EOF
|
||||
echo "$1. Remove macOS-specific components:"
|
||||
if should_create_volume && test_nix_volume_mountd_installed; then
|
||||
nix_volume_mountd_uninstall_directions
|
||||
fi
|
||||
if test_nix_daemon_installed; then
|
||||
nix_daemon_uninstall_directions
|
||||
fi
|
||||
}
|
||||
|
||||
poly_service_setup_note() {
|
||||
cat <<EOF
|
||||
- load and start a LaunchDaemon (at $PLIST_DEST) for nix-daemon
|
||||
|
||||
EOF
|
||||
if should_create_volume; then
|
||||
echo " - create a Nix volume and a LaunchDaemon to mount it"
|
||||
fi
|
||||
echo " - create a LaunchDaemon (at $NIX_DAEMON_DEST) for nix-daemon"
|
||||
echo ""
|
||||
}
|
||||
|
||||
poly_extra_try_me_commands(){
|
||||
:
|
||||
}
|
||||
poly_extra_setup_instructions(){
|
||||
:
|
||||
poly_extra_try_me_commands() {
|
||||
:
|
||||
}
|
||||
|
||||
poly_configure_nix_daemon_service() {
|
||||
task "Setting up the nix-daemon LaunchDaemon"
|
||||
_sudo "to set up the nix-daemon as a LaunchDaemon" \
|
||||
cp -f "/nix/var/nix/profiles/default$PLIST_DEST" "$PLIST_DEST"
|
||||
/bin/cp -f "/nix/var/nix/profiles/default$NIX_DAEMON_DEST" "$NIX_DAEMON_DEST"
|
||||
|
||||
_sudo "to load the LaunchDaemon plist for nix-daemon" \
|
||||
launchctl load /Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
|
||||
_sudo "to start the nix-daemon" \
|
||||
launchctl start org.nixos.nix-daemon
|
||||
|
||||
launchctl kickstart -k system/org.nixos.nix-daemon
|
||||
}
|
||||
|
||||
poly_group_exists() {
|
||||
|
|
@ -94,6 +147,8 @@ poly_user_home_get() {
|
|||
}
|
||||
|
||||
poly_user_home_set() {
|
||||
# This can trigger a permission prompt now:
|
||||
# "Terminal" would like to administer your computer. Administration can include modifying passwords, networking, and system settings.
|
||||
_sudo "in order to give $1 a safe home directory" \
|
||||
/usr/bin/dscl . -create "/Users/$1" "NFSHomeDirectory" "$2"
|
||||
}
|
||||
|
|
@ -119,7 +174,7 @@ poly_user_shell_set() {
|
|||
poly_user_in_group_check() {
|
||||
username=$1
|
||||
group=$2
|
||||
dseditgroup -o checkmember -m "$username" "$group" > /dev/null 2>&1
|
||||
/usr/sbin/dseditgroup -o checkmember -m "$username" "$group" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
poly_user_in_group_set() {
|
||||
|
|
@ -149,3 +204,21 @@ poly_create_build_user() {
|
|||
/usr/bin/dscl . create "/Users/$username" \
|
||||
UniqueID "${uid}"
|
||||
}
|
||||
|
||||
poly_prepare_to_install() {
|
||||
if should_create_volume; then
|
||||
header "Preparing a Nix volume"
|
||||
# intentional indent below to match task indent
|
||||
cat <<EOF
|
||||
Nix traditionally stores its data in the root directory $NIX_ROOT, but
|
||||
macOS now (starting in 10.15 Catalina) has a read-only root directory.
|
||||
To support Nix, I will create a volume and configure macOS to mount it
|
||||
at $NIX_ROOT.
|
||||
EOF
|
||||
setup_darwin_volume
|
||||
fi
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,13 +25,15 @@ readonly RED='\033[31m'
|
|||
readonly NIX_USER_COUNT=${NIX_USER_COUNT:-32}
|
||||
readonly NIX_BUILD_GROUP_ID="30000"
|
||||
readonly NIX_BUILD_GROUP_NAME="nixbld"
|
||||
readonly NIX_FIRST_BUILD_UID="30001"
|
||||
# darwin installer needs to override these
|
||||
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.
|
||||
readonly NIX_ROOT="/nix"
|
||||
readonly NIX_EXTRA_CONF=${NIX_EXTRA_CONF:-}
|
||||
|
||||
readonly PROFILE_TARGETS=("/etc/bashrc" "/etc/profile.d/nix.sh" "/etc/zshenv")
|
||||
readonly PROFILE_TARGETS=("/etc/bashrc" "/etc/profile.d/nix.sh" "/etc/zshrc" "/etc/bash.bashrc" "/etc/zsh/zshrc")
|
||||
readonly PROFILE_BACKUP_SUFFIX=".backup-before-nix"
|
||||
readonly PROFILE_NIX_FILE="$NIX_ROOT/var/nix/profiles/default/etc/profile.d/nix-daemon.sh"
|
||||
|
||||
|
|
@ -41,7 +43,7 @@ readonly NIX_INSTALLED_CACERT="@cacert@"
|
|||
#readonly NIX_INSTALLED_CACERT="/nix/store/7dxhzymvy330i28ii676fl1pqwcahv2f-nss-cacert-3.49.2"
|
||||
readonly EXTRACTED_NIX_PATH="$(dirname "$0")"
|
||||
|
||||
readonly ROOT_HOME=$(echo ~root)
|
||||
readonly ROOT_HOME=~root
|
||||
|
||||
if [ -t 0 ]; then
|
||||
readonly IS_HEADLESS='no'
|
||||
|
|
@ -57,14 +59,19 @@ headless() {
|
|||
fi
|
||||
}
|
||||
|
||||
contactme() {
|
||||
contact_us() {
|
||||
echo "You can open an issue at https://github.com/nixos/nix/issues"
|
||||
echo ""
|
||||
echo "Or feel free to contact the team:"
|
||||
echo " - Matrix: #nix:nixos.org"
|
||||
echo " - IRC: in #nixos on irc.libera.chat"
|
||||
echo " - twitter: @nixos_org"
|
||||
echo " - forum: https://discourse.nixos.org"
|
||||
}
|
||||
get_help() {
|
||||
echo "We'd love to help if you need it."
|
||||
echo ""
|
||||
echo "If you can, open an issue at https://github.com/nixos/nix/issues"
|
||||
echo ""
|
||||
echo "Or feel free to contact the team,"
|
||||
echo " - on IRC #nixos on irc.freenode.net"
|
||||
echo " - on twitter @nixos_org"
|
||||
contact_us
|
||||
}
|
||||
|
||||
uninstall_directions() {
|
||||
|
|
@ -100,11 +107,10 @@ $step. Delete the files Nix added to your system:
|
|||
and that is it.
|
||||
|
||||
EOF
|
||||
|
||||
}
|
||||
|
||||
nix_user_for_core() {
|
||||
printf "nixbld%d" "$1"
|
||||
printf "$NIX_BUILD_USER_NAME_TEMPLATE" "$1"
|
||||
}
|
||||
|
||||
nix_uid_for_core() {
|
||||
|
|
@ -168,7 +174,7 @@ failure() {
|
|||
header "oh no!"
|
||||
_textout "$RED" "$@"
|
||||
echo ""
|
||||
_textout "$RED" "$(contactme)"
|
||||
_textout "$RED" "$(get_help)"
|
||||
trap finish_cleanup EXIT
|
||||
exit 1
|
||||
}
|
||||
|
|
@ -199,6 +205,95 @@ ui_confirm() {
|
|||
return 1
|
||||
}
|
||||
|
||||
printf -v _UNCHANGED_GRP_FMT "%b" $'\033[2m%='"$ESC" # "dim"
|
||||
# bold+invert+red and bold+invert+green just for the +/- below
|
||||
# red/green foreground for rest of the line
|
||||
printf -v _OLD_LINE_FMT "%b" $'\033[1;7;31m-'"$ESC ${RED}%L${ESC}"
|
||||
printf -v _NEW_LINE_FMT "%b" $'\033[1;7;32m+'"$ESC ${GREEN}%L${ESC}"
|
||||
|
||||
_diff() {
|
||||
# simple colorized diff comatible w/ pre `--color` versions
|
||||
diff --unchanged-group-format="$_UNCHANGED_GRP_FMT" --old-line-format="$_OLD_LINE_FMT" --new-line-format="$_NEW_LINE_FMT" --unchanged-line-format=" %L" "$@"
|
||||
}
|
||||
|
||||
confirm_rm() {
|
||||
local path="$1"
|
||||
if ui_confirm "Can I remove $path?"; then
|
||||
_sudo "to remove $path" rm "$path"
|
||||
fi
|
||||
}
|
||||
|
||||
confirm_edit() {
|
||||
local path="$1"
|
||||
local edit_path="$2"
|
||||
cat <<EOF
|
||||
|
||||
Nix isn't the only thing in $path,
|
||||
but I think I know how to edit it out.
|
||||
Here's the diff:
|
||||
EOF
|
||||
|
||||
# could technically test the diff, but caller should do it
|
||||
_diff "$path" "$edit_path"
|
||||
if ui_confirm "Does the change above look right?"; then
|
||||
_sudo "remove nix from $path" cp "$edit_path" "$path"
|
||||
fi
|
||||
}
|
||||
|
||||
_SERIOUS_BUSINESS="${RED}%s:${ESC} "
|
||||
password_confirm() {
|
||||
local do_something_consequential="$1"
|
||||
if ui_confirm "Can I $do_something_consequential?"; then
|
||||
# shellcheck disable=SC2059
|
||||
sudo -kv --prompt="$(printf "${_SERIOUS_BUSINESS}" "Enter your password to $do_something_consequential")"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Support accumulating reminders over the course of a run and showing
|
||||
# them at the end. An example where this helps: the installer changes
|
||||
# something, but it won't work without a reboot. If you tell the user
|
||||
# when you do it, they may miss it in the stream. The value of the
|
||||
# setting isn't enough to decide whether to message because you only
|
||||
# need to message if you *changed* it.
|
||||
|
||||
# reminders stored in array delimited by empty entry; if ! headless,
|
||||
# user is asked to confirm after each delimiter.
|
||||
_reminders=()
|
||||
((_remind_num=1))
|
||||
|
||||
remind() {
|
||||
# (( arithmetic expression ))
|
||||
if (( _remind_num > 1 )); then
|
||||
header "Reminders"
|
||||
for line in "${_reminders[@]}"; do
|
||||
echo "$line"
|
||||
if ! headless && [ "${#line}" = 0 ]; then
|
||||
if read -r -p "Press enter/return to acknowledge."; then
|
||||
printf $'\033[A\33[2K\r'
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
reminder() {
|
||||
printf -v label "${BLUE}[ %d ]${ESC}" "$_remind_num"
|
||||
_reminders+=("$label")
|
||||
if [[ "$*" = "" ]]; then
|
||||
while read -r line; do
|
||||
_reminders+=("$line")
|
||||
done
|
||||
else
|
||||
# this expands each arg to an array entry (and each entry will
|
||||
# ultimately be a separate line in the output)
|
||||
_reminders+=("$@")
|
||||
fi
|
||||
_reminders+=("")
|
||||
((_remind_num++))
|
||||
}
|
||||
|
||||
__sudo() {
|
||||
local expl="$1"
|
||||
local cmd="$2"
|
||||
|
|
@ -219,18 +314,18 @@ _sudo() {
|
|||
local expl="$1"
|
||||
shift
|
||||
if ! headless; then
|
||||
__sudo "$expl" "$*"
|
||||
__sudo "$expl" "$*" >&2
|
||||
fi
|
||||
sudo "$@"
|
||||
}
|
||||
|
||||
|
||||
readonly SCRATCH=$(mktemp -d -t tmp.XXXXXXXXXX)
|
||||
function finish_cleanup {
|
||||
readonly SCRATCH=$(mktemp -d "${TMPDIR:-/tmp/}tmp.XXXXXXXXXX")
|
||||
finish_cleanup() {
|
||||
rm -rf "$SCRATCH"
|
||||
}
|
||||
|
||||
function finish_fail {
|
||||
finish_fail() {
|
||||
finish_cleanup
|
||||
|
||||
failure <<EOF
|
||||
|
|
@ -242,45 +337,46 @@ EOF
|
|||
}
|
||||
trap finish_fail EXIT
|
||||
|
||||
channel_update_failed=0
|
||||
function finish_success {
|
||||
finish_cleanup
|
||||
|
||||
finish_success() {
|
||||
ok "Alright! We're done!"
|
||||
if [ "x$channel_update_failed" = x1 ]; then
|
||||
echo ""
|
||||
echo "But fetching the nixpkgs channel failed. (Are you offline?)"
|
||||
echo "To try again later, run \"sudo -i nix-channel --update nixpkgs\"."
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Before Nix will work in your existing shells, you'll need to close
|
||||
them and open them again. Other than that, you should be ready to go.
|
||||
|
||||
Try it! Open a new terminal, and type:
|
||||
$(poly_extra_try_me_commands)
|
||||
$ nix-shell -p nix-info --run "nix-info -m"
|
||||
$(poly_extra_setup_instructions)
|
||||
Thank you for using this installer. If you have any feedback, don't
|
||||
hesitate:
|
||||
|
||||
$(contactme)
|
||||
Thank you for using this installer. If you have any feedback or need
|
||||
help, don't hesitate:
|
||||
|
||||
$(contact_us)
|
||||
EOF
|
||||
|
||||
remind
|
||||
finish_cleanup
|
||||
}
|
||||
|
||||
finish_uninstall_success() {
|
||||
ok "Alright! Nix should be removed!"
|
||||
|
||||
cat <<EOF
|
||||
If you spot anything this uninstaller missed or have feedback,
|
||||
don't hesitate:
|
||||
|
||||
$(contact_us)
|
||||
EOF
|
||||
remind
|
||||
finish_cleanup
|
||||
}
|
||||
|
||||
remove_nix_artifacts() {
|
||||
failure "Not implemented yet"
|
||||
}
|
||||
|
||||
cure_artifacts() {
|
||||
poly_cure_artifacts
|
||||
# remove_nix_artifacts (LATER)
|
||||
}
|
||||
|
||||
validate_starting_assumptions() {
|
||||
poly_validate_assumptions
|
||||
|
||||
if [ $EUID -eq 0 ]; then
|
||||
failure <<EOF
|
||||
Please do not run this script with root privileges. We will call sudo
|
||||
when we need to.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if type nix-env 2> /dev/null >&2; then
|
||||
warning <<EOF
|
||||
Nix already appears to be installed. This installer may run into issues.
|
||||
|
|
@ -442,18 +538,46 @@ create_build_users() {
|
|||
|
||||
create_directories() {
|
||||
# FIXME: remove all of this because it duplicates LocalStore::LocalStore().
|
||||
task "Setting up the basic directory structure"
|
||||
if [ -d "$NIX_ROOT" ]; then
|
||||
# if /nix already exists, take ownership
|
||||
#
|
||||
# Caution: notes below are macOS-y
|
||||
# This is a bit of a goldilocks zone for taking ownership
|
||||
# if there are already files on the volume; the volume is
|
||||
# now mounted, but we haven't added a bunch of new files
|
||||
|
||||
# this is probably a bit slow; I've been seeing 3.3-4s even
|
||||
# when promptly installed over a fresh single-user install.
|
||||
# In case anyone's aware of a shortcut.
|
||||
# `|| true`: .Trashes errors w/o full disk perm
|
||||
|
||||
# rumor per #4488 that macOS 11.2 may not have
|
||||
# sbin on path, and that's where chown is, but
|
||||
# since this bit is cross-platform:
|
||||
# - first try with `command -vp` to try and find
|
||||
# chown in the usual places
|
||||
# - 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="$(command -vp chown)"
|
||||
if [[ -z "$get_chr_own" ]]; then
|
||||
get_chr_own="$(command -v chown)"
|
||||
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)" \
|
||||
mkdir -pv -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
|
||||
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)" \
|
||||
mkdir -pv -m 1775 /nix/store
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 3)" \
|
||||
chgrp "$NIX_BUILD_GROUP_NAME" /nix/store
|
||||
install -dv -g "$NIX_BUILD_GROUP_NAME" -m 1775 /nix/store
|
||||
|
||||
_sudo "to place the default nix daemon configuration (part 1)" \
|
||||
mkdir -pv -m 0555 /etc/nix
|
||||
install -dv -m 0555 /etc/nix
|
||||
}
|
||||
|
||||
place_channel_configuration() {
|
||||
|
|
@ -473,7 +597,7 @@ This installation tool will set up your computer with the Nix package
|
|||
manager. This will happen in a few stages:
|
||||
|
||||
1. Make sure your computer doesn't already have Nix. If it does, I
|
||||
will show you instructions on how to clean up your old one.
|
||||
will show you instructions on how to clean up your old install.
|
||||
|
||||
2. Show you what we are going to install and where. Then we will ask
|
||||
if you are ready to continue.
|
||||
|
|
@ -572,11 +696,15 @@ EOF
|
|||
}
|
||||
|
||||
install_from_extracted_nix() {
|
||||
task "Installing Nix"
|
||||
(
|
||||
cd "$EXTRACTED_NIX_PATH"
|
||||
|
||||
_sudo "to copy the basic Nix files to the new store at $NIX_ROOT/store" \
|
||||
rsync -rlpt --chmod=-w ./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/"
|
||||
|
||||
if [ -d "$NIX_INSTALLED_NIX" ]; then
|
||||
echo " Alright! We have our first nix at $NIX_INSTALLED_NIX"
|
||||
|
|
@ -587,9 +715,8 @@ $NIX_INSTALLED_NIX.
|
|||
EOF
|
||||
fi
|
||||
|
||||
cat ./.reginfo \
|
||||
| _sudo "to load data for the first time in to the Nix Database" \
|
||||
"$NIX_INSTALLED_NIX/bin/nix-store" --load-db
|
||||
_sudo "to load data for the first time in to the Nix Database" \
|
||||
"$NIX_INSTALLED_NIX/bin/nix-store" --load-db < ./.reginfo
|
||||
|
||||
echo " Just finished getting the nix database ready."
|
||||
)
|
||||
|
|
@ -608,6 +735,7 @@ EOF
|
|||
}
|
||||
|
||||
configure_shell_profile() {
|
||||
task "Setting up shell profiles: ${PROFILE_TARGETS[*]}"
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target" ]; then
|
||||
_sudo "to back up your current $profile_target to $profile_target$PROFILE_BACKUP_SUFFIX" \
|
||||
|
|
@ -627,14 +755,27 @@ configure_shell_profile() {
|
|||
tee -a "$profile_target"
|
||||
fi
|
||||
done
|
||||
# TODO: should we suggest '. $PROFILE_NIX_FILE'? It would get them on
|
||||
# their way less disruptively, but a counter-argument is that they won't
|
||||
# immediately notice if something didn't get set up right?
|
||||
reminder "Nix won't work in active shell sessions until you restart them."
|
||||
}
|
||||
|
||||
cert_in_store() {
|
||||
# in a subshell
|
||||
# - change into the cert-file dir
|
||||
# - get the phyiscal pwd
|
||||
# and test if this path is in the Nix store
|
||||
[[ "$(cd -- "$(dirname "$NIX_SSL_CERT_FILE")" && exec pwd -P)" == "$NIX_ROOT/store/"* ]]
|
||||
}
|
||||
|
||||
setup_default_profile() {
|
||||
_sudo "to installing a bootstrapping Nix in to the default Profile" \
|
||||
task "Setting up the default profile"
|
||||
_sudo "to install a bootstrapping Nix in to the default profile" \
|
||||
HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_NIX"
|
||||
|
||||
if [ -z "${NIX_SSL_CERT_FILE:-}" ] || ! [ -f "${NIX_SSL_CERT_FILE:-}" ]; then
|
||||
_sudo "to installing a bootstrapping SSL certificate just for Nix in to the default Profile" \
|
||||
if [ -z "${NIX_SSL_CERT_FILE:-}" ] || ! [ -f "${NIX_SSL_CERT_FILE:-}" ] || cert_in_store; then
|
||||
_sudo "to install a bootstrapping SSL certificate just for Nix in to the default profile" \
|
||||
HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_CACERT"
|
||||
export NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt
|
||||
fi
|
||||
|
|
@ -643,9 +784,13 @@ setup_default_profile() {
|
|||
# Have to explicitly pass NIX_SSL_CERT_FILE as part of the sudo call,
|
||||
# otherwise it will be lost in environments where sudo doesn't pass
|
||||
# all the environment variables by default.
|
||||
_sudo "to update the default channel in the default profile" \
|
||||
HOME="$ROOT_HOME" NIX_SSL_CERT_FILE="$NIX_SSL_CERT_FILE" "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs \
|
||||
|| channel_update_failed=1
|
||||
if ! _sudo "to update the default channel in the default profile" \
|
||||
HOME="$ROOT_HOME" NIX_SSL_CERT_FILE="$NIX_SSL_CERT_FILE" "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs; then
|
||||
reminder <<EOF
|
||||
I had trouble fetching the nixpkgs channel (are you offline?)
|
||||
To try again later, run: sudo -i nix-channel --update nixpkgs
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -660,6 +805,17 @@ EOF
|
|||
}
|
||||
|
||||
main() {
|
||||
# TODO: I've moved this out of validate_starting_assumptions so we
|
||||
# can fail faster in this case. Sourcing install-darwin... now runs
|
||||
# `touch /` to detect Read-only root, but it could update times on
|
||||
# pre-Catalina macOS if run as root user.
|
||||
if [ $EUID -eq 0 ]; then
|
||||
failure <<EOF
|
||||
Please do not run this script with root privileges. We will call sudo
|
||||
when we need to.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
# shellcheck source=./install-darwin-multi-user.sh
|
||||
. "$EXTRACTED_NIX_PATH/install-darwin-multi-user.sh"
|
||||
|
|
@ -673,17 +829,24 @@ main() {
|
|||
welcome_to_nix
|
||||
chat_about_sudo
|
||||
|
||||
cure_artifacts
|
||||
# TODO: there's a tension between cure and validate. I moved the
|
||||
# the sudo/root check out of validate to the head of this func.
|
||||
# Cure is *intended* to subsume the validate-and-abort approach,
|
||||
# so it may eventually obsolete it.
|
||||
validate_starting_assumptions
|
||||
|
||||
setup_report
|
||||
|
||||
if ! ui_confirm "Ready to continue?"; then
|
||||
ok "Alright, no changes have been made :)"
|
||||
contactme
|
||||
get_help
|
||||
trap finish_cleanup EXIT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
poly_prepare_to_install
|
||||
|
||||
create_build_group
|
||||
create_build_users
|
||||
create_directories
|
||||
|
|
@ -693,6 +856,7 @@ main() {
|
|||
configure_shell_profile
|
||||
|
||||
set +eu
|
||||
# shellcheck disable=SC1091
|
||||
. /etc/profile
|
||||
set -eu
|
||||
|
||||
|
|
@ -704,5 +868,20 @@ main() {
|
|||
trap finish_success EXIT
|
||||
}
|
||||
|
||||
# set an empty initial arg for bare invocations in case we need to
|
||||
# disambiguate someone directly invoking this later.
|
||||
if [ "${#@}" = 0 ]; then
|
||||
set ""
|
||||
fi
|
||||
|
||||
main
|
||||
# ACTION for override
|
||||
case "${1-}" in
|
||||
# uninstall)
|
||||
# shift
|
||||
# uninstall "$@";;
|
||||
# install == same as the no-arg condition for now (but, explicit)
|
||||
""|install)
|
||||
main;;
|
||||
*) # holding space for future options (like uninstall + install?)
|
||||
failure "install-multi-user: invalid argument";;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -26,18 +26,9 @@ fi
|
|||
|
||||
# macOS support for 10.12.6 or higher
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
IFS='.' read macos_major macos_minor macos_patch << EOF
|
||||
IFS='.' read -r macos_major macos_minor macos_patch << EOF
|
||||
$(sw_vers -productVersion)
|
||||
EOF
|
||||
# TODO: this is a temporary speed-bump to keep people from naively installing Nix
|
||||
# on macOS Big Sur (11.0+, 10.16+) until nixpkgs updates are ready for them.
|
||||
# *Ideally* this is gone before next Nix release. If you're intentionally working on
|
||||
# Nix + Big Sur, just comment out this block and be on your way :)
|
||||
if [ "$macos_major" -gt 10 ] || { [ "$macos_major" -eq 10 ] && [ "$macos_minor" -gt 15 ]; }; then
|
||||
echo "$0: nixpkgs isn't quite ready to support macOS $(sw_vers -productVersion) yet"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$macos_major" -lt 10 ] || { [ "$macos_major" -eq 10 ] && [ "$macos_minor" -lt 12 ]; } || { [ "$macos_minor" -eq 12 ] && [ "$macos_patch" -lt 6 ]; }; then
|
||||
# patch may not be present; command substitution for simplicity
|
||||
echo "$0: macOS $(sw_vers -productVersion) is not supported, upgrade to 10.12.6 or higher"
|
||||
|
|
@ -46,21 +37,40 @@ EOF
|
|||
fi
|
||||
|
||||
# Determine if we could use the multi-user installer or not
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2
|
||||
elif [ "$(uname -s)" = "Linux" ]; then
|
||||
if [ "$(uname -s)" = "Linux" ]; then
|
||||
echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2
|
||||
fi
|
||||
|
||||
INSTALL_MODE=no-daemon
|
||||
CREATE_DARWIN_VOLUME=0
|
||||
case "$(uname -s)" in
|
||||
"Darwin")
|
||||
INSTALL_MODE=daemon;;
|
||||
*)
|
||||
INSTALL_MODE=no-daemon;;
|
||||
esac
|
||||
|
||||
# space-separated string
|
||||
ACTIONS=
|
||||
|
||||
# handle the command line flags
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
--daemon)
|
||||
INSTALL_MODE=daemon;;
|
||||
INSTALL_MODE=daemon
|
||||
ACTIONS="${ACTIONS}install "
|
||||
;;
|
||||
--no-daemon)
|
||||
INSTALL_MODE=no-daemon;;
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
printf '\e[1;31mError: --no-daemon installs are no-longer supported on Darwin/macOS!\e[0m\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
INSTALL_MODE=no-daemon
|
||||
# intentional tail space
|
||||
ACTIONS="${ACTIONS}install "
|
||||
;;
|
||||
# --uninstall)
|
||||
# # intentional tail space
|
||||
# ACTIONS="${ACTIONS}uninstall "
|
||||
# ;;
|
||||
--no-channel-add)
|
||||
export NIX_INSTALLER_NO_CHANNEL_ADD=1;;
|
||||
--daemon-user-count)
|
||||
|
|
@ -69,13 +79,18 @@ while [ $# -gt 0 ]; do
|
|||
--no-modify-profile)
|
||||
NIX_INSTALLER_NO_MODIFY_PROFILE=1;;
|
||||
--darwin-use-unencrypted-nix-store-volume)
|
||||
CREATE_DARWIN_VOLUME=1;;
|
||||
{
|
||||
echo "Warning: the flag --darwin-use-unencrypted-nix-store-volume"
|
||||
echo " is no longer needed and will be removed in the future."
|
||||
echo ""
|
||||
} >&2;;
|
||||
--nix-extra-conf-file)
|
||||
export NIX_EXTRA_CONF="$(cat $2)"
|
||||
# shellcheck disable=SC2155
|
||||
export NIX_EXTRA_CONF="$(cat "$2")"
|
||||
shift;;
|
||||
*)
|
||||
(
|
||||
echo "Nix Installer [--daemon|--no-daemon] [--daemon-user-count INT] [--no-channel-add] [--no-modify-profile] [--darwin-use-unencrypted-nix-store-volume] [--nix-extra-conf-file FILE]"
|
||||
{
|
||||
echo "Nix Installer [--daemon|--no-daemon] [--daemon-user-count INT] [--no-channel-add] [--no-modify-profile] [--nix-extra-conf-file FILE]"
|
||||
|
||||
echo "Choose installation method."
|
||||
echo ""
|
||||
|
|
@ -91,55 +106,25 @@ while [ $# -gt 0 ]; do
|
|||
echo ""
|
||||
echo " --no-channel-add: Don't add any channels. nixpkgs-unstable is installed by default."
|
||||
echo ""
|
||||
echo " --no-modify-profile: Skip channel installation. When not provided nixpkgs-unstable"
|
||||
echo " is installed by default."
|
||||
echo " --no-modify-profile: Don't modify the user profile to automatically load nix."
|
||||
echo ""
|
||||
echo " --daemon-user-count: Number of build users to create. Defaults to 32."
|
||||
echo ""
|
||||
echo " --nix-extra-conf-file: Path to nix.conf to prepend when installing /etc/nix.conf"
|
||||
echo " --nix-extra-conf-file: Path to nix.conf to prepend when installing /etc/nix/nix.conf"
|
||||
echo ""
|
||||
if [ -n "${INVOKED_FROM_INSTALL_IN:-}" ]; then
|
||||
echo " --tarball-url-prefix URL: Base URL to download the Nix tarball from."
|
||||
fi
|
||||
) >&2
|
||||
} >&2
|
||||
|
||||
# darwin and Catalina+
|
||||
if [ "$(uname -s)" = "Darwin" ] && { [ "$macos_major" -gt 10 ] || { [ "$macos_major" -eq 10 ] && [ "$macos_minor" -gt 14 ]; }; }; then
|
||||
(
|
||||
echo " --darwin-use-unencrypted-nix-store-volume: Create an APFS volume for the Nix"
|
||||
echo " store and mount it at /nix. This is the recommended way to create"
|
||||
echo " /nix with a read-only / on macOS >=10.15."
|
||||
echo " See: https://nixos.org/nix/manual/#sect-macos-installation"
|
||||
echo ""
|
||||
) >&2
|
||||
fi
|
||||
exit;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
if [ "$CREATE_DARWIN_VOLUME" = 1 ]; then
|
||||
printf '\e[1;31mCreating volume and mountpoint /nix.\e[0m\n'
|
||||
"$self/create-darwin-volume.sh"
|
||||
fi
|
||||
|
||||
writable="$(diskutil info -plist / | xmllint --xpath "name(/plist/dict/key[text()='Writable']/following-sibling::*[1])" -)"
|
||||
if ! [ -e $dest ] && [ "$writable" = "false" ]; then
|
||||
(
|
||||
echo ""
|
||||
echo "Installing on macOS >=10.15 requires relocating the store to an apfs volume."
|
||||
echo "Use sh <(curl -L https://nixos.org/nix/install) --darwin-use-unencrypted-nix-store-volume or run the preparation steps manually."
|
||||
echo "See https://nixos.org/nix/manual/#sect-macos-installation"
|
||||
echo ""
|
||||
) >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$INSTALL_MODE" = "daemon" ]; then
|
||||
printf '\e[1;31mSwitching to the Multi-user Installer\e[0m\n'
|
||||
exec "$self/install-multi-user"
|
||||
exec "$self/install-multi-user" $ACTIONS # let ACTIONS split
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
|
@ -166,9 +151,15 @@ fi
|
|||
mkdir -p $dest/store
|
||||
|
||||
printf "copying Nix to %s..." "${dest}/store" >&2
|
||||
# Insert a newline if no progress is shown.
|
||||
if [ ! -t 0 ]; then
|
||||
echo ""
|
||||
fi
|
||||
|
||||
for i in $(cd "$self/store" >/dev/null && echo ./*); do
|
||||
printf "." >&2
|
||||
if [ -t 0 ]; then
|
||||
printf "." >&2
|
||||
fi
|
||||
i_tmp="$dest/store/$i.$$"
|
||||
if [ -e "$i_tmp" ]; then
|
||||
rm -rf "$i_tmp"
|
||||
|
|
@ -188,6 +179,7 @@ if ! "$nix/bin/nix-store" --load-db < "$self/.reginfo"; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# shellcheck source=./nix-profile.sh.in
|
||||
. "$nix/etc/profile.d/nix.sh"
|
||||
|
||||
if ! "$nix/bin/nix-env" -i "$nix"; then
|
||||
|
|
@ -223,7 +215,7 @@ if [ -z "$NIX_INSTALLER_NO_MODIFY_PROFILE" ]; then
|
|||
if [ -w "$fn" ]; then
|
||||
if ! grep -q "$p" "$fn"; then
|
||||
echo "modifying $fn..." >&2
|
||||
echo -e "\nif [ -e $p ]; then . $p; fi # added by Nix installer" >> "$fn"
|
||||
printf '\nif [ -e %s ]; then . %s; fi # added by Nix installer\n' "$p" "$p" >> "$fn"
|
||||
fi
|
||||
added=1
|
||||
break
|
||||
|
|
@ -234,7 +226,7 @@ if [ -z "$NIX_INSTALLER_NO_MODIFY_PROFILE" ]; then
|
|||
if [ -w "$fn" ]; then
|
||||
if ! grep -q "$p" "$fn"; then
|
||||
echo "modifying $fn..." >&2
|
||||
echo -e "\nif [ -e $p ]; then . $p; fi # added by Nix installer" >> "$fn"
|
||||
printf '\nif [ -e %s ]; then . %s; fi # added by Nix installer\n' "$p" "$p" >> "$fn"
|
||||
fi
|
||||
added=1
|
||||
break
|
||||
|
|
|
|||
|
|
@ -41,10 +41,8 @@ handle_network_proxy() {
|
|||
fi
|
||||
}
|
||||
|
||||
poly_validate_assumptions() {
|
||||
if [ "$(uname -s)" != "Linux" ]; then
|
||||
failure "This script is for use with Linux!"
|
||||
fi
|
||||
poly_cure_artifacts() {
|
||||
:
|
||||
}
|
||||
|
||||
poly_service_installed_check() {
|
||||
|
|
@ -72,7 +70,7 @@ poly_service_setup_note() {
|
|||
EOF
|
||||
}
|
||||
|
||||
poly_extra_try_me_commands(){
|
||||
poly_extra_try_me_commands() {
|
||||
if [ -e /run/systemd/system ]; then
|
||||
:
|
||||
else
|
||||
|
|
@ -81,19 +79,10 @@ poly_extra_try_me_commands(){
|
|||
EOF
|
||||
fi
|
||||
}
|
||||
poly_extra_setup_instructions(){
|
||||
if [ -e /run/systemd/system ]; then
|
||||
:
|
||||
else
|
||||
cat <<EOF
|
||||
Additionally, you may want to add nix-daemon to your init-system.
|
||||
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
poly_configure_nix_daemon_service() {
|
||||
if [ -e /run/systemd/system ]; then
|
||||
task "Setting up the nix-daemon systemd service"
|
||||
_sudo "to set up the nix-daemon service" \
|
||||
systemctl link "/nix/var/nix/profiles/default$SERVICE_SRC"
|
||||
|
||||
|
|
@ -110,6 +99,8 @@ poly_configure_nix_daemon_service() {
|
|||
|
||||
_sudo "to start the nix-daemon.service" \
|
||||
systemctl restart nix-daemon.service
|
||||
else
|
||||
reminder "I don't support your init system yet; you may want to add nix-daemon manually."
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -207,3 +198,7 @@ poly_create_build_user() {
|
|||
--password "!" \
|
||||
"$username"
|
||||
}
|
||||
|
||||
poly_prepare_to_install() {
|
||||
:
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,27 +40,31 @@ case "$(uname -s).$(uname -m)" in
|
|||
path=@tarballPath_aarch64-linux@
|
||||
system=aarch64-linux
|
||||
;;
|
||||
Linux.armv6l_linux)
|
||||
hash=@tarballHash_armv6l-linux@
|
||||
path=@tarballPath_armv6l-linux@
|
||||
system=armv6l-linux
|
||||
;;
|
||||
Linux.armv7l_linux)
|
||||
hash=@tarballHash_armv7l-linux@
|
||||
path=@tarballPath_armv7l-linux@
|
||||
system=armv7l-linux
|
||||
;;
|
||||
Darwin.x86_64)
|
||||
hash=@tarballHash_x86_64-darwin@
|
||||
path=@tarballPath_x86_64-darwin@
|
||||
system=x86_64-darwin
|
||||
;;
|
||||
Darwin.arm64|Darwin.aarch64)
|
||||
# check for Rosetta 2 support
|
||||
if ! [ -f /Library/Apple/System/Library/LaunchDaemons/com.apple.oahd.plist ]; then
|
||||
oops "Rosetta 2 is not installed on this ARM64 macOS machine. Run softwareupdate --install-rosetta then restart installation"
|
||||
fi
|
||||
|
||||
hash=@binaryTarball_x86_64-darwin@
|
||||
path=@tarballPath_x86_64-darwin@
|
||||
# eventually maybe: aarch64-darwin
|
||||
system=x86_64-darwin
|
||||
hash=@tarballHash_aarch64-darwin@
|
||||
path=@tarballPath_aarch64-darwin@
|
||||
system=aarch64-darwin
|
||||
;;
|
||||
*) oops "sorry, there is no binary distribution of Nix for your platform";;
|
||||
esac
|
||||
|
||||
# Use this command-line option to fetch the tarballs using nar-serve or Cachix
|
||||
if "${1:---tarball-url-prefix}"; then
|
||||
if [ "${1:-}" = "--tarball-url-prefix" ]; then
|
||||
if [ -z "${2:-}" ]; then
|
||||
oops "missing argument for --tarball-url-prefix"
|
||||
fi
|
||||
|
|
@ -72,14 +76,21 @@ fi
|
|||
|
||||
tarball=$tmpDir/nix-@nixVersion@-$system.tar.xz
|
||||
|
||||
require_util curl "download the binary tarball"
|
||||
require_util tar "unpack the binary tarball"
|
||||
if [ "$(uname -s)" != "Darwin" ]; then
|
||||
require_util xz "unpack the binary tarball"
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null 2>&1; then
|
||||
fetch() { wget "$1" -O "$2"; }
|
||||
elif command -v curl > /dev/null 2>&1; then
|
||||
fetch() { curl -L "$1" -o "$2"; }
|
||||
else
|
||||
oops "you don't have wget or curl installed, which I need to download the binary tarball"
|
||||
fi
|
||||
|
||||
echo "downloading Nix @nixVersion@ binary tarball for $system from '$url' to '$tmpDir'..."
|
||||
curl -L "$url" -o "$tarball" || oops "failed to download '$url'"
|
||||
fetch "$url" "$tarball" || oops "failed to download '$url'"
|
||||
|
||||
if command -v sha256sum > /dev/null 2>&1; then
|
||||
hash2="$(sha256sum -b "$tarball" | cut -c1-64)"
|
||||
|
|
|
|||
10
scripts/prepare-installer-for-github-actions
Executable file
10
scripts/prepare-installer-for-github-actions
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
script=$(nix-build -A outputs.hydraJobs.installerScriptForGHA --no-out-link)
|
||||
installerHash=$(echo $script | cut -b12-43 -)
|
||||
|
||||
installerURL=https://$CACHIX_NAME.cachix.org/serve/$installerHash/install
|
||||
|
||||
echo "::set-output name=installerURL::$installerURL"
|
||||
|
|
@ -17,7 +17,8 @@
|
|||
#include "store-api.hh"
|
||||
#include "derivations.hh"
|
||||
#include "local-store.hh"
|
||||
#include "../nix/legacy.hh"
|
||||
#include "legacy.hh"
|
||||
#include "experimental-features.hh"
|
||||
|
||||
using namespace nix;
|
||||
using std::cin;
|
||||
|
|
@ -53,6 +54,9 @@ static int main_build_remote(int argc, char * * argv)
|
|||
unsetenv("DISPLAY");
|
||||
unsetenv("SSH_ASKPASS");
|
||||
|
||||
/* If we ever use the common args framework, make sure to
|
||||
remove initPlugins below and initialize settings first.
|
||||
*/
|
||||
if (argc != 2)
|
||||
throw UsageError("called without required arguments");
|
||||
|
||||
|
|
@ -71,11 +75,15 @@ static int main_build_remote(int argc, char * * argv)
|
|||
|
||||
initPlugins();
|
||||
|
||||
auto store = openStore().cast<LocalStore>();
|
||||
auto store = openStore();
|
||||
|
||||
/* It would be more appropriate to use $XDG_RUNTIME_DIR, since
|
||||
that gets cleared on reboot, but it wouldn't work on macOS. */
|
||||
currentLoad = store->stateDir + "/current-load";
|
||||
auto currentLoadName = "/current-load";
|
||||
if (auto localStore = store.dynamic_pointer_cast<LocalFSStore>())
|
||||
currentLoad = std::string { localStore->stateDir } + currentLoadName;
|
||||
else
|
||||
currentLoad = settings.nixStateDir + currentLoadName;
|
||||
|
||||
std::shared_ptr<Store> sshStore;
|
||||
AutoCloseFD bestSlotLock;
|
||||
|
|
@ -123,11 +131,14 @@ static int main_build_remote(int argc, char * * argv)
|
|||
for (auto & m : machines) {
|
||||
debug("considering building on remote machine '%s'", m.storeUri);
|
||||
|
||||
if (m.enabled && std::find(m.systemTypes.begin(),
|
||||
m.systemTypes.end(),
|
||||
neededSystem) != m.systemTypes.end() &&
|
||||
if (m.enabled
|
||||
&& (neededSystem == "builtin"
|
||||
|| std::find(m.systemTypes.begin(),
|
||||
m.systemTypes.end(),
|
||||
neededSystem) != m.systemTypes.end()) &&
|
||||
m.allSupported(requiredFeatures) &&
|
||||
m.mandatoryMet(requiredFeatures)) {
|
||||
m.mandatoryMet(requiredFeatures))
|
||||
{
|
||||
rightType = true;
|
||||
AutoCloseFD free;
|
||||
uint64_t load = 0;
|
||||
|
|
@ -172,13 +183,14 @@ static int main_build_remote(int argc, char * * argv)
|
|||
else
|
||||
{
|
||||
// build the hint template.
|
||||
string hintstring = "derivation: %s\nrequired (system, features): (%s, %s)";
|
||||
hintstring += "\n%s available machines:";
|
||||
hintstring += "\n(systems, maxjobs, supportedFeatures, mandatoryFeatures)";
|
||||
string errorText =
|
||||
"Failed to find a machine for remote build!\n"
|
||||
"derivation: %s\nrequired (system, features): (%s, %s)";
|
||||
errorText += "\n%s available machines:";
|
||||
errorText += "\n(systems, maxjobs, supportedFeatures, mandatoryFeatures)";
|
||||
|
||||
for (unsigned int i = 0; i < machines.size(); ++i) {
|
||||
hintstring += "\n(%s, %s, %s, %s)";
|
||||
}
|
||||
for (unsigned int i = 0; i < machines.size(); ++i)
|
||||
errorText += "\n(%s, %s, %s, %s)";
|
||||
|
||||
// add the template values.
|
||||
string drvstr;
|
||||
|
|
@ -187,25 +199,21 @@ static int main_build_remote(int argc, char * * argv)
|
|||
else
|
||||
drvstr = "<unknown>";
|
||||
|
||||
auto hint = hintformat(hintstring);
|
||||
hint
|
||||
% drvstr
|
||||
% neededSystem
|
||||
% concatStringsSep<StringSet>(", ", requiredFeatures)
|
||||
% machines.size();
|
||||
auto error = hintformat(errorText);
|
||||
error
|
||||
% drvstr
|
||||
% neededSystem
|
||||
% concatStringsSep<StringSet>(", ", requiredFeatures)
|
||||
% machines.size();
|
||||
|
||||
for (auto & m : machines) {
|
||||
hint % concatStringsSep<vector<string>>(", ", m.systemTypes)
|
||||
% m.maxJobs
|
||||
% concatStringsSep<StringSet>(", ", m.supportedFeatures)
|
||||
% concatStringsSep<StringSet>(", ", m.mandatoryFeatures);
|
||||
}
|
||||
for (auto & m : machines)
|
||||
error
|
||||
% concatStringsSep<vector<string>>(", ", m.systemTypes)
|
||||
% m.maxJobs
|
||||
% concatStringsSep<StringSet>(", ", m.supportedFeatures)
|
||||
% concatStringsSep<StringSet>(", ", m.mandatoryFeatures);
|
||||
|
||||
logErrorInfo(canBuildLocally ? lvlChatty : lvlWarn, {
|
||||
.name = "Remote build",
|
||||
.description = "Failed to find a machine for remote build!",
|
||||
.hint = hint
|
||||
});
|
||||
printMsg(canBuildLocally ? lvlChatty : lvlWarn, error);
|
||||
|
||||
std::cerr << "# decline\n";
|
||||
}
|
||||
|
|
@ -230,12 +238,9 @@ static int main_build_remote(int argc, char * * argv)
|
|||
|
||||
} catch (std::exception & e) {
|
||||
auto msg = chomp(drainFD(5, false));
|
||||
logError({
|
||||
.name = "Remote build",
|
||||
.hint = hintfmt("cannot build on '%s': %s%s",
|
||||
bestMachine->storeUri, e.what(),
|
||||
(msg.empty() ? "" : ": " + msg))
|
||||
});
|
||||
printError("cannot build on '%s': %s%s",
|
||||
bestMachine->storeUri, e.what(),
|
||||
msg.empty() ? "" : ": " + msg);
|
||||
bestMachine->enabled = false;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -250,7 +255,7 @@ connected:
|
|||
std::cerr << "# accept\n" << storeUri << "\n";
|
||||
|
||||
auto inputs = readStrings<PathSet>(source);
|
||||
auto outputs = readStrings<PathSet>(source);
|
||||
auto wantedOutputs = readStrings<StringSet>(source);
|
||||
|
||||
AutoCloseFD uploadLock = openLockFile(currentLoad + "/" + escapeUri(storeUri) + ".upload-lock", true);
|
||||
|
||||
|
|
@ -269,28 +274,65 @@ connected:
|
|||
|
||||
{
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri));
|
||||
copyPaths(store, ref<Store>(sshStore), store->parseStorePathSet(inputs), NoRepair, NoCheckSigs, substitute);
|
||||
copyPaths(*store, *sshStore, store->parseStorePathSet(inputs), NoRepair, NoCheckSigs, substitute);
|
||||
}
|
||||
|
||||
uploadLock = -1;
|
||||
|
||||
auto drv = store->readDerivation(*drvPath);
|
||||
drv.inputSrcs = store->parseStorePathSet(inputs);
|
||||
auto outputHashes = staticOutputHashes(*store, drv);
|
||||
|
||||
// Hijack the inputs paths of the derivation to include all the paths
|
||||
// that come from the `inputDrvs` set.
|
||||
// We don’t do that for the derivations whose `inputDrvs` is empty
|
||||
// because
|
||||
// 1. It’s not needed
|
||||
// 2. Changing the `inputSrcs` set changes the associated output ids,
|
||||
// which break CA derivations
|
||||
if (!drv.inputDrvs.empty())
|
||||
drv.inputSrcs = store->parseStorePathSet(inputs);
|
||||
|
||||
auto result = sshStore->buildDerivation(*drvPath, drv);
|
||||
|
||||
if (!result.success())
|
||||
throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg);
|
||||
|
||||
StorePathSet missing;
|
||||
for (auto & path : outputs)
|
||||
if (!store->isValidPath(store->parseStorePath(path))) missing.insert(store->parseStorePath(path));
|
||||
std::set<Realisation> missingRealisations;
|
||||
StorePathSet missingPaths;
|
||||
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations) && !derivationHasKnownOutputPaths(drv.type())) {
|
||||
for (auto & outputName : wantedOutputs) {
|
||||
auto thisOutputHash = outputHashes.at(outputName);
|
||||
auto thisOutputId = DrvOutput{ thisOutputHash, outputName };
|
||||
if (!store->queryRealisation(thisOutputId)) {
|
||||
debug("missing output %s", outputName);
|
||||
assert(result.builtOutputs.count(thisOutputId));
|
||||
auto newRealisation = result.builtOutputs.at(thisOutputId);
|
||||
missingRealisations.insert(newRealisation);
|
||||
missingPaths.insert(newRealisation.outPath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto outputPaths = drv.outputsAndOptPaths(*store);
|
||||
for (auto & [outputName, hopefullyOutputPath] : outputPaths) {
|
||||
assert(hopefullyOutputPath.second);
|
||||
if (!store->isValidPath(*hopefullyOutputPath.second))
|
||||
missingPaths.insert(*hopefullyOutputPath.second);
|
||||
}
|
||||
}
|
||||
|
||||
if (!missing.empty()) {
|
||||
if (!missingPaths.empty()) {
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri));
|
||||
for (auto & i : missing)
|
||||
store->locksHeld.insert(store->printStorePath(i)); /* FIXME: ugly */
|
||||
copyPaths(ref<Store>(sshStore), store, missing, NoRepair, NoCheckSigs, NoSubstitute);
|
||||
if (auto localStore = store.dynamic_pointer_cast<LocalStore>())
|
||||
for (auto & path : missingPaths)
|
||||
localStore->locksHeld.insert(store->printStorePath(path)); /* FIXME: ugly */
|
||||
copyPaths(*sshStore, *store, missingPaths, NoRepair, NoCheckSigs, NoSubstitute);
|
||||
}
|
||||
// XXX: Should be done as part of `copyPaths`
|
||||
for (auto & realisation : missingRealisations) {
|
||||
// Should hold, because if the feature isn't enabled the set
|
||||
// of missing realisations should be empty
|
||||
settings.requireExperimentalFeature(Xp::CaDerivations);
|
||||
store->registerDrvOutput(realisation);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -27,11 +27,6 @@ nix::Commands RegisterCommand::getCommandsFor(const std::vector<std::string> & p
|
|||
return res;
|
||||
}
|
||||
|
||||
void NixMultiCommand::printHelp(const string & programName, std::ostream & out)
|
||||
{
|
||||
MultiCommand::printHelp(programName, out);
|
||||
}
|
||||
|
||||
nlohmann::json NixMultiCommand::toJSON()
|
||||
{
|
||||
// FIXME: use Command::toJSON() as well.
|
||||
|
|
@ -59,57 +54,105 @@ void StoreCommand::run()
|
|||
run(getStore());
|
||||
}
|
||||
|
||||
StorePathsCommand::StorePathsCommand(bool recursive)
|
||||
EvalCommand::EvalCommand()
|
||||
{
|
||||
}
|
||||
|
||||
EvalCommand::~EvalCommand()
|
||||
{
|
||||
if (evalState)
|
||||
evalState->printStats();
|
||||
}
|
||||
|
||||
ref<Store> EvalCommand::getEvalStore()
|
||||
{
|
||||
if (!evalStore)
|
||||
evalStore = evalStoreUrl ? openStore(*evalStoreUrl) : getStore();
|
||||
return ref<Store>(evalStore);
|
||||
}
|
||||
|
||||
ref<EvalState> EvalCommand::getEvalState()
|
||||
{
|
||||
if (!evalState)
|
||||
evalState = std::make_shared<EvalState>(searchPath, getEvalStore(), getStore());
|
||||
return ref<EvalState>(evalState);
|
||||
}
|
||||
|
||||
BuiltPathsCommand::BuiltPathsCommand(bool recursive)
|
||||
: recursive(recursive)
|
||||
{
|
||||
if (recursive)
|
||||
addFlag({
|
||||
.longName = "no-recursive",
|
||||
.description = "apply operation to specified paths only",
|
||||
.description = "Apply operation to specified paths only.",
|
||||
.category = installablesCategory,
|
||||
.handler = {&this->recursive, false},
|
||||
});
|
||||
else
|
||||
addFlag({
|
||||
.longName = "recursive",
|
||||
.shortName = 'r',
|
||||
.description = "apply operation to closure of the specified paths",
|
||||
.description = "Apply operation to closure of the specified paths.",
|
||||
.category = installablesCategory,
|
||||
.handler = {&this->recursive, true},
|
||||
});
|
||||
|
||||
mkFlag(0, "all", "apply operation to the entire store", &all);
|
||||
addFlag({
|
||||
.longName = "all",
|
||||
.description = "Apply the operation to every store path.",
|
||||
.category = installablesCategory,
|
||||
.handler = {&all, true},
|
||||
});
|
||||
}
|
||||
|
||||
void StorePathsCommand::run(ref<Store> store)
|
||||
void BuiltPathsCommand::run(ref<Store> store)
|
||||
{
|
||||
StorePaths storePaths;
|
||||
|
||||
BuiltPaths paths;
|
||||
if (all) {
|
||||
if (installables.size())
|
||||
throw UsageError("'--all' does not expect arguments");
|
||||
// XXX: Only uses opaque paths, ignores all the realisations
|
||||
for (auto & p : store->queryAllValidPaths())
|
||||
storePaths.push_back(p);
|
||||
}
|
||||
|
||||
else {
|
||||
for (auto & p : toStorePaths(store, realiseMode, operateOn, installables))
|
||||
storePaths.push_back(p);
|
||||
|
||||
paths.push_back(BuiltPath::Opaque{p});
|
||||
} else {
|
||||
paths = toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables);
|
||||
if (recursive) {
|
||||
StorePathSet closure;
|
||||
store->computeFSClosure(StorePathSet(storePaths.begin(), storePaths.end()), closure, false, false);
|
||||
storePaths.clear();
|
||||
for (auto & p : closure)
|
||||
storePaths.push_back(p);
|
||||
// XXX: This only computes the store path closure, ignoring
|
||||
// intermediate realisations
|
||||
StorePathSet pathsRoots, pathsClosure;
|
||||
for (auto & root : paths) {
|
||||
auto rootFromThis = root.outPaths();
|
||||
pathsRoots.insert(rootFromThis.begin(), rootFromThis.end());
|
||||
}
|
||||
store->computeFSClosure(pathsRoots, pathsClosure);
|
||||
for (auto & path : pathsClosure)
|
||||
paths.push_back(BuiltPath::Opaque{path});
|
||||
}
|
||||
}
|
||||
|
||||
run(store, std::move(storePaths));
|
||||
run(store, std::move(paths));
|
||||
}
|
||||
|
||||
void StorePathCommand::run(ref<Store> store)
|
||||
StorePathsCommand::StorePathsCommand(bool recursive)
|
||||
: BuiltPathsCommand(recursive)
|
||||
{
|
||||
auto storePaths = toStorePaths(store, Realise::Nothing, operateOn, installables);
|
||||
}
|
||||
|
||||
void StorePathsCommand::run(ref<Store> store, BuiltPaths && paths)
|
||||
{
|
||||
StorePathSet storePaths;
|
||||
for (auto & builtPath : paths)
|
||||
for (auto & p : builtPath.outPaths())
|
||||
storePaths.insert(p);
|
||||
|
||||
auto sorted = store->topoSortPaths(storePaths);
|
||||
std::reverse(sorted.begin(), sorted.end());
|
||||
|
||||
run(store, std::move(sorted));
|
||||
}
|
||||
|
||||
void StorePathCommand::run(ref<Store> store, std::vector<StorePath> && storePaths)
|
||||
{
|
||||
if (storePaths.size() != 1)
|
||||
throw UsageError("this command requires exactly one store path");
|
||||
|
||||
|
|
@ -133,7 +176,7 @@ MixProfile::MixProfile()
|
|||
{
|
||||
addFlag({
|
||||
.longName = "profile",
|
||||
.description = "profile to update",
|
||||
.description = "The profile to update.",
|
||||
.labels = {"path"},
|
||||
.handler = {&profile},
|
||||
.completer = completePath
|
||||
|
|
@ -152,7 +195,7 @@ void MixProfile::updateProfile(const StorePath & storePath)
|
|||
profile2, storePath));
|
||||
}
|
||||
|
||||
void MixProfile::updateProfile(const Buildables & buildables)
|
||||
void MixProfile::updateProfile(const BuiltPaths & buildables)
|
||||
{
|
||||
if (!profile) return;
|
||||
|
||||
|
|
@ -160,22 +203,19 @@ void MixProfile::updateProfile(const Buildables & buildables)
|
|||
|
||||
for (auto & buildable : buildables) {
|
||||
std::visit(overloaded {
|
||||
[&](BuildableOpaque bo) {
|
||||
[&](const BuiltPath::Opaque & bo) {
|
||||
result.push_back(bo.path);
|
||||
},
|
||||
[&](BuildableFromDrv bfd) {
|
||||
[&](const BuiltPath::Built & bfd) {
|
||||
for (auto & output : bfd.outputs) {
|
||||
/* Output path should be known because we just tried to
|
||||
build it. */
|
||||
assert(output.second);
|
||||
result.push_back(*output.second);
|
||||
result.push_back(output.second);
|
||||
}
|
||||
},
|
||||
}, buildable);
|
||||
}, buildable.raw());
|
||||
}
|
||||
|
||||
if (result.size() != 1)
|
||||
throw Error("'--profile' requires that the arguments produce a single store path, but there are %d", result.size());
|
||||
throw UsageError("'--profile' requires that the arguments produce a single store path, but there are %d", result.size());
|
||||
|
||||
updateProfile(result[0]);
|
||||
}
|
||||
|
|
@ -190,14 +230,14 @@ MixEnvironment::MixEnvironment() : ignoreEnvironment(false)
|
|||
addFlag({
|
||||
.longName = "ignore-environment",
|
||||
.shortName = 'i',
|
||||
.description = "clear the entire environment (except those specified with --keep)",
|
||||
.description = "Clear the entire environment (except those specified with `--keep`).",
|
||||
.handler = {&ignoreEnvironment, true},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "keep",
|
||||
.shortName = 'k',
|
||||
.description = "keep specified environment variable",
|
||||
.description = "Keep the environment variable *name*.",
|
||||
.labels = {"name"},
|
||||
.handler = {[&](std::string s) { keep.insert(s); }},
|
||||
});
|
||||
|
|
@ -205,7 +245,7 @@ MixEnvironment::MixEnvironment() : ignoreEnvironment(false)
|
|||
addFlag({
|
||||
.longName = "unset",
|
||||
.shortName = 'u',
|
||||
.description = "unset specified environment variable",
|
||||
.description = "Unset the environment variable *name*.",
|
||||
.labels = {"name"},
|
||||
.handler = {[&](std::string s) { unset.insert(s); }},
|
||||
});
|
||||
|
|
@ -13,6 +13,8 @@ namespace nix {
|
|||
|
||||
extern std::string programPath;
|
||||
|
||||
extern char * * savedArgv;
|
||||
|
||||
class EvalState;
|
||||
struct Pos;
|
||||
class Store;
|
||||
|
|
@ -21,10 +23,10 @@ static constexpr Command::Category catSecondary = 100;
|
|||
static constexpr Command::Category catUtility = 101;
|
||||
static constexpr Command::Category catNixInstallation = 102;
|
||||
|
||||
static constexpr auto installablesCategory = "Options that change the interpretation of installables";
|
||||
|
||||
struct NixMultiCommand : virtual MultiCommand, virtual Command
|
||||
{
|
||||
void printHelp(const string & programName, std::ostream & out) override;
|
||||
|
||||
nlohmann::json toJSON() override;
|
||||
};
|
||||
|
||||
|
|
@ -43,8 +45,17 @@ private:
|
|||
|
||||
struct EvalCommand : virtual StoreCommand, MixEvalArgs
|
||||
{
|
||||
EvalCommand();
|
||||
|
||||
~EvalCommand();
|
||||
|
||||
ref<Store> getEvalStore();
|
||||
|
||||
ref<EvalState> getEvalState();
|
||||
|
||||
private:
|
||||
std::shared_ptr<Store> evalStore;
|
||||
|
||||
std::shared_ptr<EvalState> evalState;
|
||||
};
|
||||
|
||||
|
|
@ -97,6 +108,8 @@ enum class Realise {
|
|||
exists. */
|
||||
Derivation,
|
||||
/* Evaluate in dry-run mode. Postcondition: nothing. */
|
||||
// FIXME: currently unused, but could be revived if we can
|
||||
// evaluate derivations in-memory.
|
||||
Nothing
|
||||
};
|
||||
|
||||
|
|
@ -139,7 +152,7 @@ private:
|
|||
};
|
||||
|
||||
/* A command that operates on zero or more store paths. */
|
||||
struct StorePathsCommand : public InstallablesCommand
|
||||
struct BuiltPathsCommand : public InstallablesCommand
|
||||
{
|
||||
private:
|
||||
|
||||
|
|
@ -152,25 +165,36 @@ protected:
|
|||
|
||||
public:
|
||||
|
||||
StorePathsCommand(bool recursive = false);
|
||||
BuiltPathsCommand(bool recursive = false);
|
||||
|
||||
using StoreCommand::run;
|
||||
|
||||
virtual void run(ref<Store> store, std::vector<StorePath> storePaths) = 0;
|
||||
virtual void run(ref<Store> store, BuiltPaths && paths) = 0;
|
||||
|
||||
void run(ref<Store> store) override;
|
||||
|
||||
bool useDefaultInstallables() override { return !all; }
|
||||
};
|
||||
|
||||
/* A command that operates on exactly one store path. */
|
||||
struct StorePathCommand : public InstallablesCommand
|
||||
struct StorePathsCommand : public BuiltPathsCommand
|
||||
{
|
||||
using StoreCommand::run;
|
||||
StorePathsCommand(bool recursive = false);
|
||||
|
||||
using BuiltPathsCommand::run;
|
||||
|
||||
virtual void run(ref<Store> store, std::vector<StorePath> && storePaths) = 0;
|
||||
|
||||
void run(ref<Store> store, BuiltPaths && paths) override;
|
||||
};
|
||||
|
||||
/* A command that operates on exactly one store path. */
|
||||
struct StorePathCommand : public StorePathsCommand
|
||||
{
|
||||
using StorePathsCommand::run;
|
||||
|
||||
virtual void run(ref<Store> store, const StorePath & storePath) = 0;
|
||||
|
||||
void run(ref<Store> store) override;
|
||||
void run(ref<Store> store, std::vector<StorePath> && storePaths) override;
|
||||
};
|
||||
|
||||
/* A helper class for registering commands globally. */
|
||||
|
|
@ -201,21 +225,38 @@ static RegisterCommand registerCommand2(std::vector<std::string> && name)
|
|||
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
|
||||
}
|
||||
|
||||
Buildables build(ref<Store> store, Realise mode,
|
||||
std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode = bmNormal);
|
||||
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> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
std::vector<std::shared_ptr<Installable>> installables);
|
||||
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> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
StorePath toStorePath(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
std::shared_ptr<Installable> installable);
|
||||
|
||||
std::set<StorePath> toDerivations(ref<Store> store,
|
||||
std::vector<std::shared_ptr<Installable>> installables,
|
||||
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 Pos & pos);
|
||||
|
|
@ -231,7 +272,7 @@ struct MixProfile : virtual StoreCommand
|
|||
|
||||
/* If 'profile' is set, make it point at the store path produced
|
||||
by 'buildables'. */
|
||||
void updateProfile(const Buildables & buildables);
|
||||
void updateProfile(const BuiltPaths & buildables);
|
||||
};
|
||||
|
||||
struct MixDefaultProfile : MixProfile
|
||||
|
|
@ -261,6 +302,8 @@ void completeFlakeRefWithFragment(
|
|||
const Strings & defaultFlakeAttrPaths,
|
||||
std::string_view prefix);
|
||||
|
||||
std::string showVersions(const std::set<std::string> & versions);
|
||||
|
||||
void printClosureDiff(
|
||||
ref<Store> store,
|
||||
const StorePath & beforePath,
|
||||
|
|
@ -20,31 +20,6 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
nlohmann::json BuildableOpaque::toJSON(ref<Store> store) const {
|
||||
nlohmann::json res;
|
||||
res["path"] = store->printStorePath(path);
|
||||
return res;
|
||||
}
|
||||
|
||||
nlohmann::json BuildableFromDrv::toJSON(ref<Store> store) const {
|
||||
nlohmann::json res;
|
||||
res["drvPath"] = store->printStorePath(drvPath);
|
||||
for (const auto& [output, path] : outputs) {
|
||||
res["outputs"][output] = path ? store->printStorePath(*path) : "";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
nlohmann::json buildablesToJSON(const Buildables & buildables, ref<Store> store) {
|
||||
auto res = nlohmann::json::array();
|
||||
for (const Buildable & buildable : buildables) {
|
||||
std::visit([&res, store](const auto & buildable) {
|
||||
res.push_back(buildable.toJSON(store));
|
||||
}, buildable);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void completeFlakeInputPath(
|
||||
ref<EvalState> evalState,
|
||||
const FlakeRef & flakeRef,
|
||||
|
|
@ -58,39 +33,51 @@ void completeFlakeInputPath(
|
|||
|
||||
MixFlakeOptions::MixFlakeOptions()
|
||||
{
|
||||
auto category = "Common flake-related options";
|
||||
|
||||
addFlag({
|
||||
.longName = "recreate-lock-file",
|
||||
.description = "recreate lock file from scratch",
|
||||
.description = "Recreate the flake's lock file from scratch.",
|
||||
.category = category,
|
||||
.handler = {&lockFlags.recreateLockFile, true}
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "no-update-lock-file",
|
||||
.description = "do not allow any updates to the lock file",
|
||||
.description = "Do not allow any updates to the flake's lock file.",
|
||||
.category = category,
|
||||
.handler = {&lockFlags.updateLockFile, false}
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "no-write-lock-file",
|
||||
.description = "do not write the newly generated lock file",
|
||||
.description = "Do not write the flake's newly generated lock file.",
|
||||
.category = category,
|
||||
.handler = {&lockFlags.writeLockFile, false}
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "no-registries",
|
||||
.description = "don't use flake registries",
|
||||
.handler = {&lockFlags.useRegistries, false}
|
||||
.description =
|
||||
"Don't allow lookups in the flake registries. This option is deprecated; use `--no-use-registries`.",
|
||||
.category = category,
|
||||
.handler = {[&]() {
|
||||
lockFlags.useRegistries = false;
|
||||
warn("'--no-registries' is deprecated; use '--no-use-registries'");
|
||||
}}
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "commit-lock-file",
|
||||
.description = "commit changes to the lock file",
|
||||
.description = "Commit changes to the flake's lock file.",
|
||||
.category = category,
|
||||
.handler = {&lockFlags.commitLockFile, true}
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "update-input",
|
||||
.description = "update a specific flake input",
|
||||
.description = "Update a specific flake input (ignoring its previous entry in the lock file).",
|
||||
.category = category,
|
||||
.labels = {"input-path"},
|
||||
.handler = {[&](std::string s) {
|
||||
lockFlags.inputUpdates.insert(flake::parseInputPath(s));
|
||||
|
|
@ -103,9 +90,11 @@ MixFlakeOptions::MixFlakeOptions()
|
|||
|
||||
addFlag({
|
||||
.longName = "override-input",
|
||||
.description = "override a specific flake input (e.g. `dwarffs/nixpkgs`)",
|
||||
.description = "Override a specific flake input (e.g. `dwarffs/nixpkgs`). This implies `--no-write-lock-file`.",
|
||||
.category = category,
|
||||
.labels = {"input-path", "flake-url"},
|
||||
.handler = {[&](std::string inputPath, std::string flakeRef) {
|
||||
lockFlags.writeLockFile = false;
|
||||
lockFlags.inputOverrides.insert_or_assign(
|
||||
flake::parseInputPath(inputPath),
|
||||
parseFlakeRef(flakeRef, absPath(".")));
|
||||
|
|
@ -114,7 +103,8 @@ MixFlakeOptions::MixFlakeOptions()
|
|||
|
||||
addFlag({
|
||||
.longName = "inputs-from",
|
||||
.description = "use the inputs of the specified flake as registry entries",
|
||||
.description = "Use the inputs of the specified flake as registry entries.",
|
||||
.category = category,
|
||||
.labels = {"flake-url"},
|
||||
.handler = {[&](std::string flakeRef) {
|
||||
auto evalState = getEvalState();
|
||||
|
|
@ -143,22 +133,25 @@ SourceExprCommand::SourceExprCommand()
|
|||
addFlag({
|
||||
.longName = "file",
|
||||
.shortName = 'f',
|
||||
.description = "evaluate *file* rather than the default",
|
||||
.description = "Interpret installables as attribute paths relative to the Nix expression stored in *file*.",
|
||||
.category = installablesCategory,
|
||||
.labels = {"file"},
|
||||
.handler = {&file},
|
||||
.completer = completePath
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName ="expr",
|
||||
.description = "evaluate attributes from *expr*",
|
||||
.longName = "expr",
|
||||
.description = "Interpret installables as attribute paths relative to the Nix expression *expr*.",
|
||||
.category = installablesCategory,
|
||||
.labels = {"expr"},
|
||||
.handler = {&expr}
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName ="derivation",
|
||||
.description = "operate on the store derivation rather than its outputs",
|
||||
.longName = "derivation",
|
||||
.description = "Operate on the store derivation rather than its outputs.",
|
||||
.category = installablesCategory,
|
||||
.handler = {&operateOn, OperateOn::Derivation},
|
||||
});
|
||||
}
|
||||
|
|
@ -182,14 +175,50 @@ Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
|
|||
|
||||
void SourceExprCommand::completeInstallable(std::string_view prefix)
|
||||
{
|
||||
if (file) return; // FIXME
|
||||
if (file) {
|
||||
evalSettings.pureEval = false;
|
||||
auto state = getEvalState();
|
||||
Expr *e = state->parseExprFromFile(
|
||||
resolveExprPath(state->checkSourcePath(lookupFileArg(*state, *file)))
|
||||
);
|
||||
|
||||
completeFlakeRefWithFragment(
|
||||
getEvalState(),
|
||||
lockFlags,
|
||||
getDefaultFlakeAttrPathPrefixes(),
|
||||
getDefaultFlakeAttrPaths(),
|
||||
prefix);
|
||||
Value root;
|
||||
state->eval(e, root);
|
||||
|
||||
auto autoArgs = getAutoArgs(*state);
|
||||
|
||||
std::string prefix_ = std::string(prefix);
|
||||
auto sep = prefix_.rfind('.');
|
||||
std::string searchWord;
|
||||
if (sep != std::string::npos) {
|
||||
searchWord = prefix_.substr(sep, std::string::npos);
|
||||
prefix_ = prefix_.substr(0, sep);
|
||||
} else {
|
||||
searchWord = prefix_;
|
||||
prefix_ = "";
|
||||
}
|
||||
|
||||
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 = i.name;
|
||||
if (name.find(searchWord) == 0) {
|
||||
completions->add(i.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
completeFlakeRefWithFragment(
|
||||
getEvalState(),
|
||||
lockFlags,
|
||||
getDefaultFlakeAttrPathPrefixes(),
|
||||
getDefaultFlakeAttrPaths(),
|
||||
prefix);
|
||||
}
|
||||
}
|
||||
|
||||
void completeFlakeRefWithFragment(
|
||||
|
|
@ -260,13 +289,6 @@ void completeFlakeRefWithFragment(
|
|||
completeFlakeRef(evalState->store, prefix);
|
||||
}
|
||||
|
||||
ref<EvalState> EvalCommand::getEvalState()
|
||||
{
|
||||
if (!evalState)
|
||||
evalState = std::make_shared<EvalState>(searchPath, getStore());
|
||||
return ref<EvalState>(evalState);
|
||||
}
|
||||
|
||||
void completeFlakeRef(ref<Store> store, std::string_view prefix)
|
||||
{
|
||||
if (prefix == "")
|
||||
|
|
@ -290,9 +312,9 @@ void completeFlakeRef(ref<Store> store, std::string_view prefix)
|
|||
}
|
||||
}
|
||||
|
||||
Buildable Installable::toBuildable()
|
||||
DerivedPath Installable::toDerivedPath()
|
||||
{
|
||||
auto buildables = toBuildables();
|
||||
auto buildables = toDerivedPaths();
|
||||
if (buildables.size() != 1)
|
||||
throw Error("installable '%s' evaluates to %d derivations, where only one is expected", what(), buildables.size());
|
||||
return std::move(buildables[0]);
|
||||
|
|
@ -326,22 +348,19 @@ struct InstallableStorePath : Installable
|
|||
|
||||
std::string what() override { return store->printStorePath(storePath); }
|
||||
|
||||
Buildables toBuildables() override
|
||||
DerivedPaths toDerivedPaths() override
|
||||
{
|
||||
if (storePath.isDerivation()) {
|
||||
std::map<std::string, std::optional<StorePath>> outputs;
|
||||
auto drv = store->readDerivation(storePath);
|
||||
for (auto & [name, output] : drv.outputsAndOptPaths(*store))
|
||||
outputs.emplace(name, output.second);
|
||||
return {
|
||||
BuildableFromDrv {
|
||||
DerivedPath::Built {
|
||||
.drvPath = storePath,
|
||||
.outputs = std::move(outputs)
|
||||
.outputs = drv.outputNames(),
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
BuildableOpaque {
|
||||
DerivedPath::Opaque {
|
||||
.path = storePath,
|
||||
}
|
||||
};
|
||||
|
|
@ -354,22 +373,24 @@ struct InstallableStorePath : Installable
|
|||
}
|
||||
};
|
||||
|
||||
Buildables InstallableValue::toBuildables()
|
||||
DerivedPaths InstallableValue::toDerivedPaths()
|
||||
{
|
||||
Buildables res;
|
||||
DerivedPaths res;
|
||||
|
||||
std::map<StorePath, std::map<std::string, std::optional<StorePath>>> drvsToOutputs;
|
||||
std::map<StorePath, std::set<std::string>> drvsToOutputs;
|
||||
RealisedPath::Set drvsToCopy;
|
||||
|
||||
// Group by derivation, helps with .all in particular
|
||||
for (auto & drv : toDerivations()) {
|
||||
auto outputName = drv.outputName;
|
||||
if (outputName == "")
|
||||
throw Error("derivation '%s' lacks an 'outputName' attribute", state->store->printStorePath(drv.drvPath));
|
||||
drvsToOutputs[drv.drvPath].insert_or_assign(outputName, drv.outPath);
|
||||
drvsToOutputs[drv.drvPath].insert(outputName);
|
||||
drvsToCopy.insert(drv.drvPath);
|
||||
}
|
||||
|
||||
for (auto & i : drvsToOutputs)
|
||||
res.push_back(BuildableFromDrv { i.first, i.second });
|
||||
res.push_back(DerivedPath::Built { i.first, i.second });
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -483,6 +504,23 @@ static std::string showAttrPaths(const std::vector<std::string> & paths)
|
|||
return s;
|
||||
}
|
||||
|
||||
InstallableFlake::InstallableFlake(
|
||||
SourceExprCommand * cmd,
|
||||
ref<EvalState> state,
|
||||
FlakeRef && flakeRef,
|
||||
Strings && attrPaths,
|
||||
Strings && prefixes,
|
||||
const flake::LockFlags & lockFlags)
|
||||
: InstallableValue(state),
|
||||
flakeRef(flakeRef),
|
||||
attrPaths(attrPaths),
|
||||
prefixes(prefixes),
|
||||
lockFlags(lockFlags)
|
||||
{
|
||||
if (cmd && cmd->getAutoArgs(*state)->size())
|
||||
throw UsageError("'--arg' and '--argstr' are incompatible with flakes");
|
||||
}
|
||||
|
||||
std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableFlake::toDerivation()
|
||||
{
|
||||
auto lockedFlake = getLockedFlake();
|
||||
|
|
@ -493,7 +531,11 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF
|
|||
auto root = cache->getRoot();
|
||||
|
||||
for (auto & attrPath : getActualAttrPaths()) {
|
||||
auto attr = root->findAlongAttrPath(parseAttrPath(*state, attrPath));
|
||||
auto attr = root->findAlongAttrPath(
|
||||
parseAttrPath(*state, attrPath),
|
||||
true
|
||||
);
|
||||
|
||||
if (!attr) continue;
|
||||
|
||||
if (!attr->isDerivation())
|
||||
|
|
@ -503,7 +545,7 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF
|
|||
|
||||
auto drvInfo = DerivationInfo{
|
||||
std::move(drvPath),
|
||||
state->store->parseStorePath(attr->getAttr(state->sOutPath)->getString()),
|
||||
state->store->maybeParseStorePath(attr->getAttr(state->sOutPath)->getString()),
|
||||
attr->getAttr(state->sOutputName)->getString()
|
||||
};
|
||||
|
||||
|
|
@ -562,10 +604,10 @@ InstallableFlake::getCursors(EvalState & state)
|
|||
|
||||
std::shared_ptr<flake::LockedFlake> InstallableFlake::getLockedFlake() const
|
||||
{
|
||||
flake::LockFlags lockFlagsApplyConfig = lockFlags;
|
||||
lockFlagsApplyConfig.applyNixConfig = true;
|
||||
if (!_lockedFlake) {
|
||||
_lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(*state, flakeRef, lockFlags));
|
||||
_lockedFlake->flake.config.apply();
|
||||
// FIXME: send new config to the daemon.
|
||||
_lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(*state, flakeRef, lockFlagsApplyConfig));
|
||||
}
|
||||
return _lockedFlake;
|
||||
}
|
||||
|
|
@ -614,17 +656,6 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
|||
for (auto & s : ss) {
|
||||
std::exception_ptr ex;
|
||||
|
||||
try {
|
||||
auto [flakeRef, fragment] = parseFlakeRefWithFragment(s, absPath("."));
|
||||
result.push_back(std::make_shared<InstallableFlake>(
|
||||
getEvalState(), std::move(flakeRef),
|
||||
fragment == "" ? getDefaultFlakeAttrPaths() : Strings{fragment},
|
||||
getDefaultFlakeAttrPathPrefixes(), lockFlags));
|
||||
continue;
|
||||
} catch (...) {
|
||||
ex = std::current_exception();
|
||||
}
|
||||
|
||||
if (s.find('/') != std::string::npos) {
|
||||
try {
|
||||
result.push_back(std::make_shared<InstallableStorePath>(store, store->followLinksToStorePath(s)));
|
||||
|
|
@ -636,14 +667,21 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
|||
}
|
||||
}
|
||||
|
||||
std::rethrow_exception(ex);
|
||||
try {
|
||||
auto [flakeRef, fragment] = parseFlakeRefWithFragment(s, absPath("."));
|
||||
result.push_back(std::make_shared<InstallableFlake>(
|
||||
this,
|
||||
getEvalState(),
|
||||
std::move(flakeRef),
|
||||
fragment == "" ? getDefaultFlakeAttrPaths() : Strings{fragment},
|
||||
getDefaultFlakeAttrPathPrefixes(),
|
||||
lockFlags));
|
||||
continue;
|
||||
} catch (...) {
|
||||
ex = std::current_exception();
|
||||
}
|
||||
|
||||
/*
|
||||
throw Error(
|
||||
pathExists(s)
|
||||
? "path '%s' is not a flake or a store path"
|
||||
: "don't know how to handle argument '%s'", s);
|
||||
*/
|
||||
std::rethrow_exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -658,79 +696,121 @@ std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
|
|||
return installables.front();
|
||||
}
|
||||
|
||||
Buildables build(ref<Store> store, Realise mode,
|
||||
std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode)
|
||||
BuiltPaths getBuiltPaths(ref<Store> evalStore, ref<Store> store, const DerivedPaths & hopefullyBuiltPaths)
|
||||
{
|
||||
BuiltPaths res;
|
||||
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;
|
||||
}
|
||||
|
||||
BuiltPaths build(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||
BuildMode bMode)
|
||||
{
|
||||
if (mode == Realise::Nothing)
|
||||
settings.readOnlyMode = true;
|
||||
|
||||
Buildables buildables;
|
||||
|
||||
std::vector<StorePathWithOutputs> pathsToBuild;
|
||||
std::vector<DerivedPath> pathsToBuild;
|
||||
|
||||
for (auto & i : installables) {
|
||||
for (auto & b : i->toBuildables()) {
|
||||
std::visit(overloaded {
|
||||
[&](BuildableOpaque bo) {
|
||||
pathsToBuild.push_back({bo.path});
|
||||
},
|
||||
[&](BuildableFromDrv bfd) {
|
||||
StringSet outputNames;
|
||||
for (auto & output : bfd.outputs)
|
||||
outputNames.insert(output.first);
|
||||
pathsToBuild.push_back({bfd.drvPath, outputNames});
|
||||
},
|
||||
}, b);
|
||||
buildables.push_back(std::move(b));
|
||||
}
|
||||
auto b = i->toDerivedPaths();
|
||||
pathsToBuild.insert(pathsToBuild.end(), b.begin(), b.end());
|
||||
}
|
||||
|
||||
if (mode == Realise::Nothing)
|
||||
if (mode == Realise::Nothing || mode == Realise::Derivation)
|
||||
printMissing(store, pathsToBuild, lvlError);
|
||||
else if (mode == Realise::Outputs)
|
||||
store->buildPaths(pathsToBuild, bMode);
|
||||
store->buildPaths(pathsToBuild, bMode, evalStore);
|
||||
|
||||
return buildables;
|
||||
return getBuiltPaths(evalStore, store, pathsToBuild);
|
||||
}
|
||||
|
||||
StorePathSet toStorePaths(ref<Store> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
std::vector<std::shared_ptr<Installable>> installables)
|
||||
BuiltPaths toBuiltPaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables)
|
||||
{
|
||||
StorePathSet outPaths;
|
||||
|
||||
if (operateOn == OperateOn::Output) {
|
||||
for (auto & b : build(store, mode, installables))
|
||||
std::visit(overloaded {
|
||||
[&](BuildableOpaque bo) {
|
||||
outPaths.insert(bo.path);
|
||||
},
|
||||
[&](BuildableFromDrv bfd) {
|
||||
for (auto & output : bfd.outputs) {
|
||||
if (!output.second)
|
||||
throw Error("Cannot operate on output of unbuilt CA drv");
|
||||
outPaths.insert(*output.second);
|
||||
}
|
||||
},
|
||||
}, b);
|
||||
} else {
|
||||
if (operateOn == OperateOn::Output)
|
||||
return build(evalStore, store, mode, installables);
|
||||
else {
|
||||
if (mode == Realise::Nothing)
|
||||
settings.readOnlyMode = true;
|
||||
|
||||
for (auto & i : installables)
|
||||
for (auto & b : i->toBuildables())
|
||||
if (auto bfd = std::get_if<BuildableFromDrv>(&b))
|
||||
outPaths.insert(bfd->drvPath);
|
||||
BuiltPaths res;
|
||||
for (auto & drvPath : toDerivations(store, installables, true))
|
||||
res.push_back(BuiltPath::Opaque{drvPath});
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
StorePathSet toStorePaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables)
|
||||
{
|
||||
StorePathSet outPaths;
|
||||
for (auto & path : toBuiltPaths(evalStore, store, mode, operateOn, installables)) {
|
||||
auto thisOutPaths = path.outPaths();
|
||||
outPaths.insert(thisOutPaths.begin(), thisOutPaths.end());
|
||||
}
|
||||
return outPaths;
|
||||
}
|
||||
|
||||
StorePath toStorePath(ref<Store> store,
|
||||
StorePath toStorePath(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
std::shared_ptr<Installable> installable)
|
||||
{
|
||||
auto paths = toStorePaths(store, mode, operateOn, {installable});
|
||||
auto paths = toStorePaths(evalStore, store, mode, operateOn, {installable});
|
||||
|
||||
if (paths.size() != 1)
|
||||
throw Error("argument '%s' should evaluate to one store path", installable->what());
|
||||
|
|
@ -738,15 +818,17 @@ StorePath toStorePath(ref<Store> store,
|
|||
return *paths.begin();
|
||||
}
|
||||
|
||||
StorePathSet toDerivations(ref<Store> store,
|
||||
std::vector<std::shared_ptr<Installable>> installables, bool useDeriver)
|
||||
StorePathSet toDerivations(
|
||||
ref<Store> store,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||
bool useDeriver)
|
||||
{
|
||||
StorePathSet drvPaths;
|
||||
|
||||
for (auto & i : installables)
|
||||
for (auto & b : i->toBuildables())
|
||||
for (const auto & i : installables)
|
||||
for (const auto & b : i->toDerivedPaths())
|
||||
std::visit(overloaded {
|
||||
[&](BuildableOpaque bo) {
|
||||
[&](const DerivedPath::Opaque & bo) {
|
||||
if (!useDeriver)
|
||||
throw Error("argument '%s' did not evaluate to a derivation", i->what());
|
||||
auto derivers = store->queryValidDerivers(bo.path);
|
||||
|
|
@ -755,10 +837,10 @@ StorePathSet toDerivations(ref<Store> store,
|
|||
// FIXME: use all derivers?
|
||||
drvPaths.insert(*derivers.begin());
|
||||
},
|
||||
[&](BuildableFromDrv bfd) {
|
||||
[&](const DerivedPath::Built & bfd) {
|
||||
drvPaths.insert(bfd.drvPath);
|
||||
},
|
||||
}, b);
|
||||
}, b.raw());
|
||||
|
||||
return drvPaths;
|
||||
}
|
||||
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
#include "util.hh"
|
||||
#include "path.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
#include "derived-path.hh"
|
||||
#include "eval.hh"
|
||||
#include "flake/flake.hh"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
namespace nix {
|
||||
|
||||
struct DrvInfo;
|
||||
|
|
@ -16,25 +16,6 @@ struct SourceExprCommand;
|
|||
|
||||
namespace eval_cache { class EvalCache; class AttrCursor; }
|
||||
|
||||
struct BuildableOpaque {
|
||||
StorePath path;
|
||||
nlohmann::json toJSON(ref<Store> store) const;
|
||||
};
|
||||
|
||||
struct BuildableFromDrv {
|
||||
StorePath drvPath;
|
||||
std::map<std::string, std::optional<StorePath>> outputs;
|
||||
nlohmann::json toJSON(ref<Store> store) const;
|
||||
};
|
||||
|
||||
typedef std::variant<
|
||||
BuildableOpaque,
|
||||
BuildableFromDrv
|
||||
> Buildable;
|
||||
|
||||
typedef std::vector<Buildable> Buildables;
|
||||
nlohmann::json buildablesToJSON(const Buildables & buildables, ref<Store> store);
|
||||
|
||||
struct App
|
||||
{
|
||||
std::vector<StorePathWithOutputs> context;
|
||||
|
|
@ -42,17 +23,23 @@ struct App
|
|||
// FIXME: add args, sandbox settings, metadata, ...
|
||||
};
|
||||
|
||||
struct UnresolvedApp
|
||||
{
|
||||
App unresolved;
|
||||
App resolve(ref<Store> evalStore, ref<Store> store);
|
||||
};
|
||||
|
||||
struct Installable
|
||||
{
|
||||
virtual ~Installable() { }
|
||||
|
||||
virtual std::string what() = 0;
|
||||
|
||||
virtual Buildables toBuildables() = 0;
|
||||
virtual DerivedPaths toDerivedPaths() = 0;
|
||||
|
||||
Buildable toBuildable();
|
||||
DerivedPath toDerivedPath();
|
||||
|
||||
App toApp(EvalState & state);
|
||||
UnresolvedApp toApp(EvalState & state);
|
||||
|
||||
virtual std::pair<Value *, Pos> toValue(EvalState & state)
|
||||
{
|
||||
|
|
@ -93,7 +80,7 @@ struct InstallableValue : Installable
|
|||
|
||||
virtual std::vector<DerivationInfo> toDerivations() = 0;
|
||||
|
||||
Buildables toBuildables() override;
|
||||
DerivedPaths toDerivedPaths() override;
|
||||
};
|
||||
|
||||
struct InstallableFlake : InstallableValue
|
||||
|
|
@ -104,11 +91,13 @@ struct InstallableFlake : InstallableValue
|
|||
const flake::LockFlags & lockFlags;
|
||||
mutable std::shared_ptr<flake::LockedFlake> _lockedFlake;
|
||||
|
||||
InstallableFlake(ref<EvalState> state, FlakeRef && flakeRef,
|
||||
Strings && attrPaths, Strings && prefixes, const flake::LockFlags & lockFlags)
|
||||
: InstallableValue(state), flakeRef(flakeRef), attrPaths(attrPaths),
|
||||
prefixes(prefixes), lockFlags(lockFlags)
|
||||
{ }
|
||||
InstallableFlake(
|
||||
SourceExprCommand * cmd,
|
||||
ref<EvalState> state,
|
||||
FlakeRef && flakeRef,
|
||||
Strings && attrPaths,
|
||||
Strings && prefixes,
|
||||
const flake::LockFlags & lockFlags);
|
||||
|
||||
std::string what() override { return flakeRef.to_string() + "#" + *attrPaths.begin(); }
|
||||
|
||||
15
src/libcmd/local.mk
Normal file
15
src/libcmd/local.mk
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
libraries += libcmd
|
||||
|
||||
libcmd_NAME = libnixcmd
|
||||
|
||||
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
|
||||
|
||||
libcmd_LDFLAGS += -llowdown -pthread
|
||||
|
||||
libcmd_LIBS = libstore libutil libexpr libmain libfetchers
|
||||
|
||||
$(eval $(call install-file-in, $(d)/nix-cmd.pc, $(libdir)/pkgconfig, 0644))
|
||||
|
|
@ -3,9 +3,7 @@
|
|||
#include "finally.hh"
|
||||
|
||||
#include <sys/queue.h>
|
||||
extern "C" {
|
||||
#include <lowdown.h>
|
||||
}
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
|
@ -14,7 +12,7 @@ std::string renderMarkdownToTerminal(std::string_view markdown)
|
|||
struct lowdown_opts opts {
|
||||
.type = LOWDOWN_TERM,
|
||||
.maxdepth = 20,
|
||||
.cols = std::min(getWindowSize().second, (unsigned short) 80),
|
||||
.cols = std::max(getWindowSize().second, (unsigned short) 80),
|
||||
.hmargin = 0,
|
||||
.vmargin = 0,
|
||||
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
|
||||
|
|
@ -27,7 +25,7 @@ std::string renderMarkdownToTerminal(std::string_view markdown)
|
|||
Finally freeDoc([&]() { lowdown_doc_free(doc); });
|
||||
|
||||
size_t maxn = 0;
|
||||
auto node = lowdown_doc_parse(doc, &maxn, markdown.data(), markdown.size());
|
||||
auto node = lowdown_doc_parse(doc, &maxn, markdown.data(), markdown.size(), nullptr);
|
||||
if (!node)
|
||||
throw Error("cannot parse Markdown document");
|
||||
Finally freeNode([&]() { lowdown_node_free(node); });
|
||||
|
|
@ -42,9 +40,11 @@ std::string renderMarkdownToTerminal(std::string_view markdown)
|
|||
throw Error("cannot allocate Markdown output buffer");
|
||||
Finally freeBuffer([&]() { lowdown_buf_free(buf); });
|
||||
|
||||
lowdown_term_rndr(buf, nullptr, renderer, node);
|
||||
int rndr_res = lowdown_term_rndr(buf, renderer, node);
|
||||
if (!rndr_res)
|
||||
throw Error("allocation error while rendering Markdown");
|
||||
|
||||
return std::string(buf->data, buf->size);
|
||||
return filterANSIEscapes(std::string(buf->data, buf->size), !shouldANSI());
|
||||
}
|
||||
|
||||
}
|
||||
9
src/libcmd/nix-cmd.pc.in
Normal file
9
src/libcmd/nix-cmd.pc.in
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
prefix=@prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: Nix
|
||||
Description: Nix Package Manager
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -lnixcmd
|
||||
Cflags: -I${includedir}/nix -std=c++17
|
||||
|
|
@ -19,7 +19,7 @@ static Strings parseAttrPath(std::string_view s)
|
|||
++i;
|
||||
while (1) {
|
||||
if (i == s.end())
|
||||
throw Error("missing closing quote in selection path '%1%'", s);
|
||||
throw ParseError("missing closing quote in selection path '%1%'", s);
|
||||
if (*i == '"') break;
|
||||
cur.push_back(*i++);
|
||||
}
|
||||
|
|
@ -52,9 +52,7 @@ std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const string & attr
|
|||
for (auto & attr : tokens) {
|
||||
|
||||
/* Is i an index (integer) or a normal attribute name? */
|
||||
enum { apAttr, apIndex } apType = apAttr;
|
||||
unsigned int attrIndex;
|
||||
if (string2Int(attr, attrIndex)) apType = apIndex;
|
||||
auto attrIndex = string2Int<unsigned int>(attr);
|
||||
|
||||
/* Evaluate the expression. */
|
||||
Value * vNew = state.allocValue();
|
||||
|
|
@ -65,7 +63,7 @@ std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const string & attr
|
|||
/* It should evaluate to either a set or an expression,
|
||||
according to what is specified in the attrPath. */
|
||||
|
||||
if (apType == apAttr) {
|
||||
if (!attrIndex) {
|
||||
|
||||
if (v->type() != nAttrs)
|
||||
throw TypeError(
|
||||
|
|
@ -82,17 +80,17 @@ std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const string & attr
|
|||
pos = *a->pos;
|
||||
}
|
||||
|
||||
else if (apType == apIndex) {
|
||||
else {
|
||||
|
||||
if (!v->isList())
|
||||
throw TypeError(
|
||||
"the expression selected by the selection path '%1%' should be a list but is %2%",
|
||||
attrPath,
|
||||
showType(*v));
|
||||
if (attrIndex >= v->listSize())
|
||||
throw AttrPathNotFound("list index %1% in selection path '%2%' is out of range", attrIndex, attrPath);
|
||||
if (*attrIndex >= v->listSize())
|
||||
throw AttrPathNotFound("list index %1% in selection path '%2%' is out of range", *attrIndex, attrPath);
|
||||
|
||||
v = v->listElems()[attrIndex];
|
||||
v = v->listElems()[*attrIndex];
|
||||
pos = noPos;
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +100,7 @@ std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const string & attr
|
|||
}
|
||||
|
||||
|
||||
Pos findDerivationFilename(EvalState & state, Value & v, std::string what)
|
||||
Pos findPackageFilename(EvalState & state, Value & v, std::string what)
|
||||
{
|
||||
Value * v2;
|
||||
try {
|
||||
|
|
@ -118,14 +116,14 @@ Pos findDerivationFilename(EvalState & state, Value & v, std::string what)
|
|||
|
||||
auto colon = pos.rfind(':');
|
||||
if (colon == std::string::npos)
|
||||
throw Error("cannot parse meta.position attribute '%s'", pos);
|
||||
throw ParseError("cannot parse meta.position attribute '%s'", pos);
|
||||
|
||||
std::string filename(pos, 0, colon);
|
||||
unsigned int lineno;
|
||||
try {
|
||||
lineno = std::stoi(std::string(pos, colon + 1));
|
||||
} catch (std::invalid_argument & e) {
|
||||
throw Error("cannot parse line number '%s'", pos);
|
||||
throw ParseError("cannot parse line number '%s'", pos);
|
||||
}
|
||||
|
||||
Symbol file = state.symbols.create(filename);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const string & attr
|
|||
Bindings & autoArgs, Value & vIn);
|
||||
|
||||
/* Heuristic to find the filename and lineno or a nix value. */
|
||||
Pos findDerivationFilename(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);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ struct Attr
|
|||
{
|
||||
Symbol name;
|
||||
Value * value;
|
||||
Pos * pos;
|
||||
Attr(Symbol name, Value * value, Pos * pos = &noPos)
|
||||
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
|
||||
|
|
@ -35,12 +35,13 @@ class Bindings
|
|||
{
|
||||
public:
|
||||
typedef uint32_t size_t;
|
||||
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:
|
||||
|
|
@ -77,7 +78,7 @@ public:
|
|||
auto a = get(name);
|
||||
if (!a)
|
||||
throw Error({
|
||||
.hint = hintfmt("attribute '%s' missing", name),
|
||||
.msg = hintfmt("attribute '%s' missing", name),
|
||||
.errPos = pos
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -12,16 +12,20 @@ namespace nix {
|
|||
|
||||
MixEvalArgs::MixEvalArgs()
|
||||
{
|
||||
auto category = "Common evaluation options";
|
||||
|
||||
addFlag({
|
||||
.longName = "arg",
|
||||
.description = "argument to be passed to Nix functions",
|
||||
.description = "Pass the value *expr* as the argument *name* to Nix functions.",
|
||||
.category = category,
|
||||
.labels = {"name", "expr"},
|
||||
.handler = {[&](std::string name, std::string expr) { autoArgs[name] = 'E' + expr; }}
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "argstr",
|
||||
.description = "string-valued argument to be passed to Nix functions",
|
||||
.description = "Pass the string *string* as the argument *name* to Nix functions.",
|
||||
.category = category,
|
||||
.labels = {"name", "string"},
|
||||
.handler = {[&](std::string name, std::string s) { autoArgs[name] = 'S' + s; }},
|
||||
});
|
||||
|
|
@ -29,14 +33,16 @@ MixEvalArgs::MixEvalArgs()
|
|||
addFlag({
|
||||
.longName = "include",
|
||||
.shortName = 'I',
|
||||
.description = "add a path to the list of locations used to look up `<...>` file names",
|
||||
.description = "Add *path* to the list of locations used to look up `<...>` file names.",
|
||||
.category = category,
|
||||
.labels = {"path"},
|
||||
.handler = {[&](std::string s) { searchPath.push_back(s); }}
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "impure",
|
||||
.description = "allow access to mutable paths and repositories",
|
||||
.description = "Allow access to mutable paths and repositories.",
|
||||
.category = category,
|
||||
.handler = {[&]() {
|
||||
evalSettings.pureEval = false;
|
||||
}},
|
||||
|
|
@ -44,7 +50,8 @@ MixEvalArgs::MixEvalArgs()
|
|||
|
||||
addFlag({
|
||||
.longName = "override-flake",
|
||||
.description = "override a flake registry value",
|
||||
.description = "Override the flake registries, redirecting *original-ref* to *resolved-ref*.",
|
||||
.category = category,
|
||||
.labels = {"original-ref", "resolved-ref"},
|
||||
.handler = {[&](std::string _from, std::string _to) {
|
||||
auto from = parseFlakeRef(_from, absPath("."));
|
||||
|
|
@ -54,6 +61,14 @@ MixEvalArgs::MixEvalArgs()
|
|||
fetchers::overrideRegistry(from.input, to.input, extraAttrs);
|
||||
}}
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "eval-store",
|
||||
.description = "The Nix store to use for evaluations.",
|
||||
.category = category,
|
||||
.labels = {"store-url"},
|
||||
.handler = {&evalStoreUrl},
|
||||
});
|
||||
}
|
||||
|
||||
Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ struct MixEvalArgs : virtual Args
|
|||
|
||||
Strings searchPath;
|
||||
|
||||
private:
|
||||
std::optional<std::string> evalStoreUrl;
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> autoArgs;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -486,11 +486,11 @@ std::shared_ptr<AttrCursor> AttrCursor::getAttr(std::string_view name)
|
|||
return getAttr(root->state.symbols.create(name));
|
||||
}
|
||||
|
||||
std::shared_ptr<AttrCursor> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath)
|
||||
std::shared_ptr<AttrCursor> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force)
|
||||
{
|
||||
auto res = shared_from_this();
|
||||
for (auto & attr : attrPath) {
|
||||
res = res->maybeGetAttr(attr);
|
||||
res = res->maybeGetAttr(attr, force);
|
||||
if (!res) return {};
|
||||
}
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ public:
|
|||
|
||||
std::shared_ptr<AttrCursor> getAttr(std::string_view name);
|
||||
|
||||
std::shared_ptr<AttrCursor> findAlongAttrPath(const std::vector<Symbol> & attrPath);
|
||||
std::shared_ptr<AttrCursor> findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force = false);
|
||||
|
||||
std::string getString();
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace nix {
|
|||
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s))
|
||||
{
|
||||
throw EvalError({
|
||||
.hint = hintfmt(s),
|
||||
.msg = hintfmt(s),
|
||||
.errPos = pos
|
||||
});
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v))
|
|||
LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const Value & v))
|
||||
{
|
||||
throw TypeError({
|
||||
.hint = hintfmt(s, showType(v)),
|
||||
.msg = hintfmt(s, showType(v)),
|
||||
.errPos = pos
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue