Compare commits
1 Commits
2.0
...
installati
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02ea337a36 |
@@ -1,26 +0,0 @@
|
||||
# EditorConfig configuration for nix
|
||||
# http://EditorConfig.org
|
||||
|
||||
# Top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file, utf-8 charset
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
charset = utf-8
|
||||
|
||||
# Match nix files, set indent to spaces with width of two
|
||||
[*.nix]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# Match c++/shell/perl, set indent to spaces with width of four
|
||||
[*.{hpp,cc,hh,sh,pl}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# Match diffs, avoid to trim trailing whitespace
|
||||
[*.{diff,patch}]
|
||||
trim_trailing_whitespace = false
|
||||
27
.github/ISSUE_TEMPLATE.md
vendored
27
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,27 +0,0 @@
|
||||
<!--
|
||||
|
||||
# Filing a Nix issue
|
||||
|
||||
*WAIT* Are you sure you're filing your issue in the right repository?
|
||||
|
||||
We appreciate you taking the time to tell us about issues you encounter, but routing the issue to the right place will get you help sooner and save everyone time.
|
||||
|
||||
This is the Nix repository, and issues here should be about Nix the build and package management *_tool_*.
|
||||
|
||||
If you have a problem with a specific package on NixOS or when using Nix, you probably want to file an issue with _nixpkgs_, whose issue tracker is over at https://github.com/NixOS/nixpkgs/issues.
|
||||
|
||||
Examples of _Nix_ issues:
|
||||
|
||||
- Nix segfaults when I run `nix-build -A blahblah`
|
||||
- The Nix language needs a new builtin: `builtins.foobar`
|
||||
- Regression in the behavior of `nix-env` in Nix 2.0
|
||||
|
||||
Examples of _nixpkgs_ issues:
|
||||
|
||||
- glibc is b0rked on aarch64
|
||||
- chromium in NixOS doesn't support U2F but google-chrome does!
|
||||
- The OpenJDK package on macOS is missing a key component
|
||||
|
||||
Chances are if you're a newcomer to the Nix world, you'll probably want the [nixpkgs tracker](https://github.com/NixOS/nixpkgs/issues). It also gets a lot more eyeball traffic so you'll probably get a response a lot more quickly.
|
||||
|
||||
-->
|
||||
17
.gitignore
vendored
17
.gitignore
vendored
@@ -1,5 +1,4 @@
|
||||
Makefile.config
|
||||
perl/Makefile.config
|
||||
|
||||
# /
|
||||
/aclocal.m4
|
||||
@@ -36,9 +35,9 @@ perl/Makefile.config
|
||||
# /scripts/
|
||||
/scripts/nix-profile.sh
|
||||
/scripts/nix-copy-closure
|
||||
/scripts/build-remote.pl
|
||||
/scripts/nix-reduce-build
|
||||
/scripts/nix-http-export.cgi
|
||||
/scripts/nix-profile-daemon.sh
|
||||
|
||||
# /src/libexpr/
|
||||
/src/libexpr/lexer-tab.cc
|
||||
@@ -49,7 +48,8 @@ perl/Makefile.config
|
||||
/src/libexpr/nix.tbl
|
||||
|
||||
# /src/libstore/
|
||||
/src/libstore/*.gen.hh
|
||||
/src/libstore/schema.sql.hh
|
||||
/src/libstore/sandbox-defaults.sb
|
||||
|
||||
/src/nix/nix
|
||||
|
||||
@@ -72,16 +72,15 @@ perl/Makefile.config
|
||||
# /src/nix-channel/
|
||||
/src/nix-channel/nix-channel
|
||||
|
||||
# /src/download-via-ssh/
|
||||
/src/download-via-ssh/download-via-ssh
|
||||
|
||||
# /src/buildenv/
|
||||
/src/buildenv/buildenv
|
||||
|
||||
# /src/nix-build/
|
||||
/src/nix-build/nix-build
|
||||
|
||||
/src/nix-copy-closure/nix-copy-closure
|
||||
|
||||
/src/build-remote/build-remote
|
||||
|
||||
# /tests/
|
||||
/tests/test-tmp
|
||||
/tests/common.sh
|
||||
@@ -100,20 +99,16 @@ perl/Makefile.config
|
||||
/misc/systemd/nix-daemon.socket
|
||||
/misc/upstart/nix-daemon.conf
|
||||
|
||||
/src/resolve-system-dependencies/resolve-system-dependencies
|
||||
|
||||
inst/
|
||||
|
||||
*.a
|
||||
*.o
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
*.exe
|
||||
*.dep
|
||||
*~
|
||||
*.pc
|
||||
*.plist
|
||||
|
||||
# GNU Global
|
||||
GPATH
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
os: osx
|
||||
script: ./tests/install-darwin.sh
|
||||
10
Makefile
10
Makefile
@@ -11,23 +11,23 @@ makefiles = \
|
||||
src/nix-env/local.mk \
|
||||
src/nix-daemon/local.mk \
|
||||
src/nix-collect-garbage/local.mk \
|
||||
src/nix-copy-closure/local.mk \
|
||||
src/nix-prefetch-url/local.mk \
|
||||
src/buildenv/local.mk \
|
||||
src/resolve-system-dependencies/local.mk \
|
||||
src/nix-channel/local.mk \
|
||||
src/nix-build/local.mk \
|
||||
src/build-remote/local.mk \
|
||||
perl/local.mk \
|
||||
scripts/local.mk \
|
||||
corepkgs/local.mk \
|
||||
misc/systemd/local.mk \
|
||||
misc/launchd/local.mk \
|
||||
misc/upstart/local.mk \
|
||||
misc/emacs/local.mk \
|
||||
doc/manual/local.mk \
|
||||
tests/local.mk \
|
||||
tests/plugins/local.mk
|
||||
tests/local.mk
|
||||
#src/download-via-ssh/local.mk \
|
||||
|
||||
GLOBAL_CXXFLAGS += -std=c++14 -g -Wall -include config.h
|
||||
GLOBAL_CXXFLAGS += -std=c++11 -g -Wall
|
||||
|
||||
-include Makefile.config
|
||||
|
||||
|
||||
@@ -5,9 +5,6 @@ CXX = @CXX@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
ENABLE_S3 = @ENABLE_S3@
|
||||
HAVE_SODIUM = @HAVE_SODIUM@
|
||||
HAVE_READLINE = @HAVE_READLINE@
|
||||
HAVE_BROTLI = @HAVE_BROTLI@
|
||||
HAVE_SECCOMP = @HAVE_SECCOMP@
|
||||
LIBCURL_LIBS = @LIBCURL_LIBS@
|
||||
OPENSSL_LIBS = @OPENSSL_LIBS@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
@@ -15,11 +12,10 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
SODIUM_LIBS = @SODIUM_LIBS@
|
||||
LIBLZMA_LIBS = @LIBLZMA_LIBS@
|
||||
SQLITE3_LIBS = @SQLITE3_LIBS@
|
||||
LIBBROTLI_LIBS = @LIBBROTLI_LIBS@
|
||||
bash = @bash@
|
||||
bindir = @bindir@
|
||||
brotli = @brotli@
|
||||
lsof = @lsof@
|
||||
bsddiff_compat_include = @bsddiff_compat_include@
|
||||
curl = @curl@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
@@ -29,9 +25,11 @@ libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
perl = @perl@
|
||||
perlbindings = @perlbindings@
|
||||
perllibdir = @perllibdir@
|
||||
pkglibdir = $(libdir)/$(PACKAGE_NAME)
|
||||
prefix = @prefix@
|
||||
sandbox_shell = @sandbox_shell@
|
||||
storedir = @storedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
doc_generate = @doc_generate@
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Nix, the purely functional package manager
|
||||
------------------------------------------
|
||||
|
||||
Nix is a new take on package management that is fairly unique. Because of its
|
||||
Nix is a new take on package management that is fairly unique. Because of it's
|
||||
purity aspects, a lot of issues found in traditional package managers don't
|
||||
appear with Nix.
|
||||
|
||||
|
||||
101
configure.ac
101
configure.ac
@@ -61,7 +61,6 @@ CFLAGS=
|
||||
CXXFLAGS=
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CPP
|
||||
AX_CXX_COMPILE_STDCXX_11
|
||||
|
||||
|
||||
@@ -115,12 +114,14 @@ if test -z "$$1"; then
|
||||
fi
|
||||
])
|
||||
|
||||
NEED_PROG(curl, curl)
|
||||
NEED_PROG(bash, bash)
|
||||
NEED_PROG(patch, patch)
|
||||
AC_PATH_PROG(xmllint, xmllint, false)
|
||||
AC_PATH_PROG(xsltproc, xsltproc, false)
|
||||
AC_PATH_PROG(flex, flex, false)
|
||||
AC_PATH_PROG(bison, bison, false)
|
||||
NEED_PROG(perl, perl)
|
||||
NEED_PROG(sed, sed)
|
||||
NEED_PROG(tar, tar)
|
||||
NEED_PROG(bzip2, bzip2)
|
||||
@@ -128,8 +129,23 @@ NEED_PROG(gzip, gzip)
|
||||
NEED_PROG(xz, xz)
|
||||
AC_PATH_PROG(dot, dot)
|
||||
AC_PATH_PROG(pv, pv, pv)
|
||||
AC_PATH_PROGS(brotli, brotli bro, bro)
|
||||
AC_PATH_PROG(lsof, lsof, lsof)
|
||||
|
||||
|
||||
# Test that Perl has the open/fork feature (Perl 5.8.0 and beyond).
|
||||
AC_MSG_CHECKING([whether Perl is recent enough])
|
||||
if ! $perl -e 'open(FOO, "-|", "true"); while (<FOO>) { print; }; close FOO or die;'; then
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([Your Perl version is too old. Nix requires Perl 5.8.0 or newer.])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
|
||||
# Figure out where to install Perl modules.
|
||||
AC_MSG_CHECKING([for the Perl installation prefix])
|
||||
perlversion=$($perl -e 'use Config; print $Config{version};')
|
||||
perlarchname=$($perl -e 'use Config; print $Config{archname};')
|
||||
AC_SUBST(perllibdir, [${libdir}/perl5/site_perl/$perlversion/$perlarchname])
|
||||
AC_MSG_RESULT($perllibdir)
|
||||
|
||||
|
||||
NEED_PROG(cat, cat)
|
||||
@@ -175,51 +191,16 @@ 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 libbrotli{enc,dec}, optional dependencies
|
||||
PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec],
|
||||
[AC_DEFINE([HAVE_BROTLI], [1], [Whether to use libbrotli.])
|
||||
CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"]
|
||||
have_brotli=1], [have_brotli=])
|
||||
AC_SUBST(HAVE_BROTLI, [$have_brotli])
|
||||
|
||||
# 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
|
||||
have_seccomp=
|
||||
fi
|
||||
else
|
||||
have_seccomp=
|
||||
fi
|
||||
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.])
|
||||
[AC_DEFINE([ENABLE_S3], [1], [Whether to enable S3 support via aws-cpp-sdk-s3.])
|
||||
enable_s3=1], [enable_s3=])
|
||||
AC_SUBST(ENABLE_S3, [$enable_s3])
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
if test -n "$enable_s3"; then
|
||||
declare -a aws_version_tokens=($(printf '#include <aws/core/VersionConfig.h>\nAWS_SDK_VERSION_STRING' | $CPP - | grep -v '^#.*' | sed 's/"//g' | tr '.' ' '))
|
||||
AC_DEFINE_UNQUOTED([AWS_VERSION_MAJOR], ${aws_version_tokens@<:@0@:>@}, [Major version of aws-sdk-cpp.])
|
||||
AC_DEFINE_UNQUOTED([AWS_VERSION_MINOR], ${aws_version_tokens@<:@1@:>@}, [Minor version of aws-sdk-cpp.])
|
||||
fi
|
||||
|
||||
|
||||
# Whether to use the Boehm garbage collector.
|
||||
AC_ARG_ENABLE(gc, AC_HELP_STRING([--enable-gc],
|
||||
@@ -232,6 +213,40 @@ if test "$gc" = yes; then
|
||||
fi
|
||||
|
||||
|
||||
# Check for the required Perl dependencies (DBI, DBD::SQLite).
|
||||
perlFlags="-I$perllibdir"
|
||||
|
||||
AC_ARG_WITH(dbi, AC_HELP_STRING([--with-dbi=PATH],
|
||||
[prefix of the Perl DBI library]),
|
||||
perlFlags="$perlFlags -I$withval")
|
||||
|
||||
AC_ARG_WITH(dbd-sqlite, AC_HELP_STRING([--with-dbd-sqlite=PATH],
|
||||
[prefix of the Perl DBD::SQLite library]),
|
||||
perlFlags="$perlFlags -I$withval")
|
||||
|
||||
AC_MSG_CHECKING([whether DBD::SQLite works])
|
||||
if ! $perl $perlFlags -e 'use DBI; use DBD::SQLite;' 2>&5; then
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_FAILURE([The Perl modules DBI and/or DBD::SQLite are missing.])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
AC_SUBST(perlFlags)
|
||||
|
||||
|
||||
# Whether to build the Perl bindings
|
||||
AC_MSG_CHECKING([whether to build the Perl bindings])
|
||||
AC_ARG_ENABLE(perl-bindings, AC_HELP_STRING([--enable-perl-bindings],
|
||||
[whether to build the Perl bindings (recommended) [default=yes]]),
|
||||
perlbindings=$enableval, perlbindings=yes)
|
||||
if test "$enable_shared" = no; then
|
||||
# Perl bindings require shared libraries.
|
||||
perlbindings=no
|
||||
fi
|
||||
AC_SUBST(perlbindings)
|
||||
AC_MSG_RESULT($perlbindings)
|
||||
|
||||
|
||||
AC_ARG_ENABLE(init-state, AC_HELP_STRING([--disable-init-state],
|
||||
[do not initialise DB etc. in `make install']),
|
||||
init_state=$enableval, init_state=yes)
|
||||
@@ -250,7 +265,7 @@ AC_CHECK_FUNCS([setresuid setreuid lchown])
|
||||
|
||||
|
||||
# Nice to have, but not essential.
|
||||
AC_CHECK_FUNCS([strsignal posix_fallocate sysconf])
|
||||
AC_CHECK_FUNCS([strsignal posix_fallocate nanosleep sysconf])
|
||||
|
||||
|
||||
# This is needed if bzip2 is a static library, and the Nix libraries
|
||||
@@ -276,12 +291,6 @@ 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]),
|
||||
sandbox_shell=$withval)
|
||||
AC_SUBST(sandbox_shell)
|
||||
|
||||
|
||||
# Expand all variables in config.status.
|
||||
test "$prefix" = NONE && prefix=$ac_default_prefix
|
||||
test "$exec_prefix" = NONE && exec_prefix='${prefix}'
|
||||
|
||||
@@ -14,9 +14,6 @@ in rec {
|
||||
nixBinDir = fromEnv "NIX_BIN_DIR" "@bindir@";
|
||||
nixPrefix = "@prefix@";
|
||||
nixLibexecDir = fromEnv "NIX_LIBEXEC_DIR" "@libexecdir@";
|
||||
nixLocalstateDir = "@localstatedir@";
|
||||
nixSysconfDir = "@sysconfdir@";
|
||||
nixStoreDir = fromEnv "NIX_STORE_DIR" "@storedir@";
|
||||
|
||||
# If Nix is installed in the Nix store, then automatically add it as
|
||||
# a dependency to the core packages. This ensures that they work
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
{ system ? "" # obsolete
|
||||
{ system ? builtins.currentSystem
|
||||
, url
|
||||
, md5 ? "", sha1 ? "", sha256 ? "", sha512 ? ""
|
||||
, outputHash ?
|
||||
if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256
|
||||
, outputHashAlgo ?
|
||||
if sha512 != "" then "sha512" else if sha1 != "" then "sha1" else if md5 != "" then "md5" else "sha256"
|
||||
, outputHash ? ""
|
||||
, outputHashAlgo ? ""
|
||||
, md5 ? "", sha1 ? "", sha256 ? ""
|
||||
, executable ? false
|
||||
, unpack ? false
|
||||
, name ? baseNameOf (toString url)
|
||||
}:
|
||||
|
||||
assert (outputHash != "" && outputHashAlgo != "")
|
||||
|| md5 != "" || sha1 != "" || sha256 != "";
|
||||
|
||||
derivation {
|
||||
builder = "builtin:fetchurl";
|
||||
|
||||
# New-style output content requirements.
|
||||
inherit outputHashAlgo outputHash;
|
||||
outputHashAlgo = if outputHashAlgo != "" then outputHashAlgo else
|
||||
if sha256 != "" then "sha256" else if sha1 != "" then "sha1" else "md5";
|
||||
outputHash = if outputHash != "" then outputHash else
|
||||
if sha256 != "" then sha256 else if sha1 != "" then sha1 else md5;
|
||||
outputHashMode = if unpack || executable then "recursive" else "flat";
|
||||
|
||||
inherit name url executable unpack;
|
||||
|
||||
system = "builtin";
|
||||
inherit name system url executable unpack;
|
||||
|
||||
# No need to double the amount of network traffic
|
||||
preferLocalBuild = true;
|
||||
|
||||
@@ -15,9 +15,7 @@ let
|
||||
else
|
||||
${bzip2} -d < $src | ${tar} xf - ${tarFlags}
|
||||
fi
|
||||
if [ * != $channelName ]; then
|
||||
mv * $out/$channelName
|
||||
fi
|
||||
mv * $out/$channelName
|
||||
if [ -n "$binaryCacheURL" ]; then
|
||||
mkdir $out/binary-caches
|
||||
echo -n "$binaryCacheURL" > $out/binary-caches/$channelName
|
||||
|
||||
@@ -4,109 +4,74 @@
|
||||
version="5.0"
|
||||
xml:id='chap-distributed-builds'>
|
||||
|
||||
<title>Remote Builds</title>
|
||||
<title>Distributed Builds</title>
|
||||
|
||||
<para>Nix supports remote builds, where a local Nix installation can
|
||||
forward Nix builds to other machines. This allows multiple builds to
|
||||
be performed in parallel and allows Nix to perform multi-platform
|
||||
builds in a semi-transparent way. For instance, if you perform a
|
||||
build for a <literal>x86_64-darwin</literal> on an
|
||||
<literal>i686-linux</literal> machine, Nix can automatically forward
|
||||
the build to a <literal>x86_64-darwin</literal> machine, if
|
||||
available.</para>
|
||||
<para>Nix supports distributed builds, where a local Nix installation can
|
||||
forward Nix builds to other machines over the network. This allows
|
||||
multiple builds to be performed in parallel (thus improving
|
||||
performance) and allows Nix to perform multi-platform builds in a
|
||||
semi-transparent way. For instance, if you perform a build for a
|
||||
<literal>x86_64-darwin</literal> on an <literal>i686-linux</literal>
|
||||
machine, Nix can automatically forward the build to a
|
||||
<literal>x86_64-darwin</literal> machine, if available.</para>
|
||||
|
||||
<para>To forward a build to a remote machine, it’s required that the
|
||||
remote machine is accessible via SSH and that it has Nix
|
||||
installed. You can test whether connecting to the remote Nix instance
|
||||
works, e.g.
|
||||
<para>You can enable distributed builds by setting the environment
|
||||
variable <envar>NIX_BUILD_HOOK</envar> to point to a program that Nix
|
||||
will call whenever it wants to build a derivation. The build hook
|
||||
(typically a shell or Perl script) can decline the build, in which Nix
|
||||
will perform it in the usual way if possible, or it can accept it, in
|
||||
which case it is responsible for somehow getting the inputs of the
|
||||
build to another machine, doing the build there, and getting the
|
||||
results back. The details of the build hook protocol are described in
|
||||
the documentation of the <link
|
||||
linkend="envar-build-hook"><envar>NIX_BUILD_HOOK</envar>
|
||||
variable</link>.</para>
|
||||
|
||||
<screen>
|
||||
$ nix ping-store --store ssh://mac
|
||||
</screen>
|
||||
<example xml:id='ex-remote-systems'><title>Remote machine configuration:
|
||||
<filename>remote-systems.conf</filename></title>
|
||||
<programlisting>
|
||||
nix@mcflurry.labs.cs.uu.nl x86_64-darwin /home/nix/.ssh/id_quarterpounder_auto 2
|
||||
nix@scratchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 1 kvm
|
||||
nix@itchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 2
|
||||
nix@poochie.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 2 kvm perf
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
will try to connect to the machine named <literal>mac</literal>. It is
|
||||
possible to specify an SSH identity file as part of the remote store
|
||||
URI, e.g.
|
||||
|
||||
<screen>
|
||||
$ nix ping-store --store ssh://mac?ssh-key=/home/alice/my-key
|
||||
</screen>
|
||||
|
||||
Since builds should be non-interactive, the key should not have a
|
||||
passphrase. Alternatively, you can load identities ahead of time into
|
||||
<command>ssh-agent</command> or <command>gpg-agent</command>.</para>
|
||||
|
||||
<para>If you get the error
|
||||
|
||||
<screen>
|
||||
bash: nix-store: command not found
|
||||
error: cannot connect to 'mac'
|
||||
</screen>
|
||||
|
||||
then you need to ensure that the <envar>PATH</envar> of
|
||||
non-interactive login shells contains Nix.</para>
|
||||
|
||||
<warning><para>If you are building via the Nix daemon, it is the Nix
|
||||
daemon user account (that is, <literal>root</literal>) that should
|
||||
have SSH access to the remote machine. If you can’t or don’t want to
|
||||
configure <literal>root</literal> to be able to access to remote
|
||||
machine, you can use a private Nix store instead by passing
|
||||
e.g. <literal>--store ~/my-nix</literal>.</para></warning>
|
||||
|
||||
<para>The list of remote machines can be specified on the command line
|
||||
or in the Nix configuration file. The former is convenient for
|
||||
testing. For example, the following command allows you to build a
|
||||
derivation for <literal>x86_64-darwin</literal> on a Linux machine:
|
||||
|
||||
<screen>
|
||||
$ uname
|
||||
Linux
|
||||
|
||||
$ nix build \
|
||||
'(with import <nixpkgs> { system = "x86_64-darwin"; }; runCommand "foo" {} "uname > $out")' \
|
||||
--builders 'ssh://mac x86_64-darwin'
|
||||
[1/0/1 built, 0.0 MiB DL] building foo on ssh://mac
|
||||
|
||||
$ cat ./result
|
||||
Darwin
|
||||
</screen>
|
||||
|
||||
It is possible to specify multiple builders separated by a semicolon
|
||||
or a newline, e.g.
|
||||
|
||||
<screen>
|
||||
--builders 'ssh://mac x86_64-darwin ; ssh://beastie x86_64-freebsd'
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>Each machine specification consists of the following elements,
|
||||
separated by spaces. Only the first element is required.
|
||||
<para>Nix ships with a build hook that should be suitable for most
|
||||
purposes. It uses <command>ssh</command> and
|
||||
<command>nix-copy-closure</command> to copy the build inputs and
|
||||
outputs and perform the remote build. To use it, you should set
|
||||
<envar>NIX_BUILD_HOOK</envar> to
|
||||
<filename><replaceable>prefix</replaceable>/libexec/nix/build-remote.pl</filename>.
|
||||
You should also define a list of available build machines and point
|
||||
the environment variable <envar>NIX_REMOTE_SYSTEMS</envar> to
|
||||
it. <envar>NIX_REMOTE_SYSTEMS</envar> must be an absolute path. An
|
||||
example configuration is shown in <xref linkend='ex-remote-systems'
|
||||
/>. Each line in the file specifies a machine, with the following
|
||||
bits of information:
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem><para>The URI of the remote store in the format
|
||||
<literal>ssh://[<replaceable>username</replaceable>@]<replaceable>hostname</replaceable></literal>,
|
||||
e.g. <literal>ssh://nix@mac</literal> or
|
||||
<literal>ssh://mac</literal>. For backward compatibility,
|
||||
<literal>ssh://</literal> may be omitted. The hostname may be an
|
||||
alias defined in your
|
||||
<listitem><para>The name of the remote machine, with optionally the
|
||||
user under which the remote build should be performed. This is
|
||||
actually passed as an argument to <command>ssh</command>, so it can
|
||||
be an alias defined in your
|
||||
<filename>~/.ssh/config</filename>.</para></listitem>
|
||||
|
||||
<listitem><para>A comma-separated list of Nix platform type
|
||||
identifiers, such as <literal>x86_64-darwin</literal>. It is
|
||||
possible for a machine to support multiple platform types, e.g.,
|
||||
<literal>i686-linux,x86_64-linux</literal>. If omitted, this
|
||||
defaults to the local platform type.</para></listitem>
|
||||
<literal>i686-linux,x86_64-linux</literal>.</para></listitem>
|
||||
|
||||
<listitem><para>The SSH identity file to be used to log in to the
|
||||
remote machine. If omitted, SSH will use its regular
|
||||
identities.</para></listitem>
|
||||
<listitem><para>The SSH private key to be used to log in to the
|
||||
remote machine. Since builds should be non-interactive, this key
|
||||
should not have a passphrase!</para></listitem>
|
||||
|
||||
<listitem><para>The maximum number of builds that Nix will execute
|
||||
in parallel on the machine. Typically this should be equal to the
|
||||
number of CPU cores. For instance, the machine
|
||||
<literal>itchy</literal> in the example will execute up to 8 builds
|
||||
in parallel.</para></listitem>
|
||||
<listitem><para>The maximum number of builds that
|
||||
<filename>build-remote.pl</filename> will execute in parallel on the
|
||||
machine. Typically this should be equal to the number of CPU cores.
|
||||
For instance, the machine <literal>itchy</literal> in the example
|
||||
will execute up to 8 builds in parallel.</para></listitem>
|
||||
|
||||
<listitem><para>The “speed factor”, indicating the relative speed of
|
||||
the machine. If there are multiple machines of the right type, Nix
|
||||
@@ -114,69 +79,38 @@ separated by spaces. Only the first element is required.
|
||||
|
||||
<listitem><para>A comma-separated list of <emphasis>supported
|
||||
features</emphasis>. If a derivation has the
|
||||
<varname>requiredSystemFeatures</varname> attribute, then Nix will
|
||||
only perform the derivation on a machine that has the specified
|
||||
features. For instance, the attribute
|
||||
<varname>requiredSystemFeatures</varname> attribute, then
|
||||
<filename>build-remote.pl</filename> will only perform the
|
||||
derivation on a machine that has the specified features. For
|
||||
instance, the attribute
|
||||
|
||||
<programlisting>
|
||||
requiredSystemFeatures = [ "kvm" ];
|
||||
</programlisting>
|
||||
|
||||
will cause the build to be performed on a machine that has the
|
||||
<literal>kvm</literal> feature.</para></listitem>
|
||||
<literal>kvm</literal> feature (i.e., <literal>scratchy</literal> in
|
||||
the example above).</para></listitem>
|
||||
|
||||
<listitem><para>A comma-separated list of <emphasis>mandatory
|
||||
features</emphasis>. A machine will only be used to build a
|
||||
derivation if all of the machine’s mandatory features appear in the
|
||||
derivation’s <varname>requiredSystemFeatures</varname>
|
||||
attribute..</para></listitem>
|
||||
derivation’s <varname>requiredSystemFeatures</varname> attribute.
|
||||
Thus, in the example, the machine <literal>poochie</literal> will
|
||||
only do derivations that have
|
||||
<varname>requiredSystemFeatures</varname> set to <literal>["kvm"
|
||||
"perf"]</literal> or <literal>["perf"]</literal>.</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
For example, the machine specification
|
||||
|
||||
<programlisting>
|
||||
nix@scratchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 1 kvm
|
||||
nix@itchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 2
|
||||
nix@poochie.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 1 2 kvm benchmark
|
||||
</programlisting>
|
||||
|
||||
specifies several machines that can perform
|
||||
<literal>i686-linux</literal> builds. However,
|
||||
<literal>poochie</literal> will only do builds that have the attribute
|
||||
|
||||
<programlisting>
|
||||
requiredSystemFeatures = [ "benchmark" ];
|
||||
</programlisting>
|
||||
|
||||
or
|
||||
|
||||
<programlisting>
|
||||
requiredSystemFeatures = [ "benchmark" "kvm" ];
|
||||
</programlisting>
|
||||
|
||||
<literal>itchy</literal> cannot do builds that require
|
||||
<literal>kvm</literal>, but <literal>scratchy</literal> does support
|
||||
such builds. For regular builds, <literal>itchy</literal> will be
|
||||
preferred over <literal>scratchy</literal> because it has a higher
|
||||
speed factor.</para>
|
||||
|
||||
<para>Remote builders can also be configured in
|
||||
<filename>nix.conf</filename>, e.g.
|
||||
|
||||
<programlisting>
|
||||
builders = ssh://mac x86_64-darwin ; ssh://beastie x86_64-freebsd
|
||||
</programlisting>
|
||||
|
||||
Finally, remote builders can be configured in a separate configuration
|
||||
file included in <option>builders</option> via the syntax
|
||||
<literal>@<replaceable>file</replaceable></literal>. For example,
|
||||
|
||||
<programlisting>
|
||||
builders = @/etc/nix/machines
|
||||
</programlisting>
|
||||
|
||||
causes the list of machines in <filename>/etc/nix/machines</filename>
|
||||
to be included. (This is the default.)</para>
|
||||
You should also set up the environment variable
|
||||
<envar>NIX_CURRENT_LOAD</envar> to point at a directory (e.g.,
|
||||
<filename>/var/run/nix/current-load</filename>) that
|
||||
<filename>build-remote.pl</filename> uses to remember how many builds
|
||||
it is currently executing remotely. It doesn't look at the actual
|
||||
load on the remote machine, so if you have multiple instances of Nix
|
||||
running, they should use the same <envar>NIX_CURRENT_LOAD</envar>
|
||||
file. Maybe in the future <filename>build-remote.pl</filename> will
|
||||
look at the actual remote load.</para>
|
||||
|
||||
</chapter>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -148,14 +148,145 @@ $ mount -o bind /mnt/otherdisk/nix /nix</screen>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="envar-build-hook"><term><envar>NIX_BUILD_HOOK</envar></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>Specifies the location of the <emphasis>build hook</emphasis>,
|
||||
which is a program (typically some script) that Nix will call
|
||||
whenever it wants to build a derivation. This is used to implement
|
||||
distributed builds<phrase condition="manual"> (see <xref
|
||||
linkend="chap-distributed-builds" />)</phrase>.</para>
|
||||
|
||||
<!--
|
||||
The protocol by
|
||||
which the calling Nix process and the build hook communicate is as
|
||||
follows.
|
||||
|
||||
<para>The build hook is called with the following command-line
|
||||
arguments:
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem><para>A boolean value <literal>0</literal> or
|
||||
<literal>1</literal> specifying whether Nix can locally execute
|
||||
more builds, as per the <link
|
||||
linkend="opt-max-jobs"><option>- -max-jobs</option> option</link>.
|
||||
The purpose of this argument is to allow the hook to not have to
|
||||
maintain bookkeeping for the local machine.</para></listitem>
|
||||
|
||||
<listitem><para>The Nix platform identifier for the local machine
|
||||
(e.g., <literal>i686-linux</literal>).</para></listitem>
|
||||
|
||||
<listitem><para>The Nix platform identifier for the derivation,
|
||||
i.e., its <link linkend="attr-system"><varname>system</varname>
|
||||
attribute</link>.</para></listitem>
|
||||
|
||||
<listitem><para>The store path of the derivation.</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>On the basis of this information, and whatever persistent
|
||||
state the build hook keeps about other machines and their current
|
||||
load, it has to decide what to do with the build. It should print
|
||||
out on standard error one of the following responses (terminated by
|
||||
a newline, <literal>"\n"</literal>):
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><literal># decline</literal></term>
|
||||
|
||||
<listitem><para>The build hook is not willing or able to perform
|
||||
the build; the calling Nix process should do the build itself,
|
||||
if possible.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal># postpone</literal></term>
|
||||
|
||||
<listitem><para>The build hook cannot perform the build now, but
|
||||
can do so in the future (e.g., because all available build slots
|
||||
on remote machines are in use). The calling Nix process should
|
||||
postpone this build until at least one currently running build
|
||||
has terminated.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal># accept</literal></term>
|
||||
|
||||
<listitem><para>The build hook has accepted the
|
||||
build.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>After sending <literal># accept</literal>, the hook should
|
||||
read one line from standard input, which will be the string
|
||||
<literal>okay</literal>. It can then proceed with the build.
|
||||
Before sending <literal>okay</literal>, Nix will store in the hook’s
|
||||
current directory a number of text files that contain information
|
||||
about the derivation:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><filename>inputs</filename></term>
|
||||
|
||||
<listitem><para>The set of store paths that are inputs to the
|
||||
build process (one per line). These have to be copied
|
||||
<emphasis>to</emphasis> the remote machine (in addition to the
|
||||
store derivation itself).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><filename>outputs</filename></term>
|
||||
|
||||
<listitem><para>The set of store paths that are outputs of the
|
||||
derivation (one per line). These have to be copied
|
||||
<emphasis>from</emphasis> the remote machine if the build
|
||||
succeeds.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><filename>references</filename></term>
|
||||
|
||||
<listitem><para>The reference graph of the inputs, in the format
|
||||
accepted by the command <command>nix-store
|
||||
- -register-validity</command>. It is necessary to run this
|
||||
command on the remote machine after copying the inputs to inform
|
||||
Nix on the remote machine that the inputs are valid
|
||||
paths.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The hook should copy the inputs to the remote machine,
|
||||
register the validity of the inputs, perform the remote build, and
|
||||
copy the outputs back to the local machine. An exit code other than
|
||||
<literal>0</literal> indicates that the hook has failed. An exit
|
||||
code equal to 100 means that the remote build failed (as opposed to,
|
||||
e.g., a network error).</para>
|
||||
-->
|
||||
|
||||
</listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="envar-remote"><term><envar>NIX_REMOTE</envar></term>
|
||||
|
||||
<listitem><para>This variable should be set to
|
||||
<literal>daemon</literal> if you want to use the Nix daemon to
|
||||
execute Nix operations. This is necessary in <link
|
||||
linkend="ssec-multi-user">multi-user Nix installations</link>.
|
||||
If the Nix daemon's Unix socket is at some non-standard path,
|
||||
this variable should be set to <literal>unix://path/to/socket</literal>.
|
||||
Otherwise, it should be left unset.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
</group>
|
||||
<replaceable>attrPath</replaceable>
|
||||
</arg>
|
||||
<arg><option>--drv-link</option> <replaceable>drvlink</replaceable></arg>
|
||||
<arg><option>--add-drv-link</option></arg>
|
||||
<arg><option>--no-out-link</option></arg>
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
@@ -89,6 +91,25 @@ also <xref linkend="sec-common-options" />.</phrase></para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--drv-link</option> <replaceable>drvlink</replaceable></term>
|
||||
|
||||
<listitem><para>Add a symlink named
|
||||
<replaceable>drvlink</replaceable> to the store derivation
|
||||
produced by <command>nix-instantiate</command>. The derivation is
|
||||
a root of the garbage collector until the symlink is deleted or
|
||||
renamed. If there are multiple derivations, numbers are suffixed
|
||||
to <replaceable>drvlink</replaceable> to distinguish between
|
||||
them.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--add-drv-link</option></term>
|
||||
|
||||
<listitem><para>Shorthand for <option>--drv-link</option>
|
||||
<filename>./derivation</filename>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--no-out-link</option></term>
|
||||
|
||||
<listitem><para>Do not create a symlink to the output path. Note
|
||||
|
||||
@@ -27,10 +27,8 @@
|
||||
<arg><option>- -show-progress</option></arg>
|
||||
-->
|
||||
<arg><option>--include-outputs</option></arg>
|
||||
<group>
|
||||
<arg choice='plain'><option>--use-substitutes</option></arg>
|
||||
<arg choice='plain'><option>-s</option></arg>
|
||||
</group>
|
||||
<arg><option>--use-substitutes</option></arg>
|
||||
<arg><option>-s</option></arg>
|
||||
<arg><option>-v</option></arg>
|
||||
<arg choice='plain'>
|
||||
<replaceable>user@</replaceable><replaceable>machine</replaceable>
|
||||
|
||||
@@ -146,7 +146,8 @@ also <xref linkend="sec-common-options" />.</phrase></para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--file</option> / <option>-f</option> <replaceable>path</replaceable></term>
|
||||
<varlistentry><term><option>--file</option></term>
|
||||
<term><option>-f</option></term>
|
||||
|
||||
<listitem><para>Specifies the Nix expression (designated below as
|
||||
the <emphasis>active Nix expression</emphasis>) used by the
|
||||
@@ -165,7 +166,8 @@ also <xref linkend="sec-common-options" />.</phrase></para>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--profile</option> / <option>-p</option> <replaceable>path</replaceable></term>
|
||||
<varlistentry><term><option>--profile</option></term>
|
||||
<term><option>-p</option></term>
|
||||
|
||||
<listitem><para>Specifies the profile to be used by those
|
||||
operations that operate on a profile (designated below as the
|
||||
@@ -1134,7 +1136,7 @@ user environment elements, etc. -->
|
||||
|
||||
<listitem><para>Print all of the meta-attributes of the
|
||||
derivation. This option is only available with
|
||||
<option>--xml</option> or <option>--json</option>.</para></listitem>
|
||||
<option>--xml</option>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
@@ -44,9 +44,7 @@
|
||||
cryptographic hash of the contents of each
|
||||
<replaceable>path</replaceable> and prints it on standard output. By
|
||||
default, it computes an MD5 hash, but other hash algorithms are
|
||||
available as well. The hash is printed in hexadecimal. To generate
|
||||
the same hash as <command>nix-prefetch-url</command> you have to
|
||||
specify multiple arguments, see below for an example.</para>
|
||||
available as well. The hash is printed in hexadecimal.</para>
|
||||
|
||||
<para>The hash is computed over a <emphasis>serialisation</emphasis>
|
||||
of each path: a dump of the file system tree rooted at the path. This
|
||||
@@ -124,15 +122,6 @@ cryptographic hash as <literal>nix-store --dump
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<para>Computing the same hash as <command>nix-prefetch-url</command>:
|
||||
<screen>
|
||||
$ nix-prefetch-url file://<(echo test)
|
||||
1lkgqb6fclns49861dwk9rzb6xnfkxbpws74mxnx01z9qyv1pjpj
|
||||
$ nix-hash --type sha256 --flat --base32 <(echo test)
|
||||
1lkgqb6fclns49861dwk9rzb6xnfkxbpws74mxnx01z9qyv1pjpj
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>Computing hashes:
|
||||
|
||||
<screen>
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
<arg choice='plain'>
|
||||
<option>--eval</option>
|
||||
<arg><option>--strict</option></arg>
|
||||
<arg><option>--json</option></arg>
|
||||
<arg><option>--xml</option></arg>
|
||||
</arg>
|
||||
</group>
|
||||
@@ -39,13 +38,12 @@
|
||||
</arg>
|
||||
<arg><option>--add-root</option> <replaceable>path</replaceable></arg>
|
||||
<arg><option>--indirect</option></arg>
|
||||
<group>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--expr</option></arg>
|
||||
<arg choice='plain'><option>-E</option></arg>
|
||||
</group>
|
||||
<arg choice='plain' rep='repeat'><replaceable>files</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<sbr/>
|
||||
<command>nix-instantiate</command>
|
||||
<arg choice='plain'><option>--find-file</option></arg>
|
||||
<arg choice='plain' rep='repeat'><replaceable>files</replaceable></arg>
|
||||
@@ -117,6 +115,26 @@ input.</para>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--xml</option></term>
|
||||
|
||||
<listitem><para>When used with <option>--parse</option> and
|
||||
<option>--eval</option>, print the resulting expression as an
|
||||
XML representation of the abstract syntax tree rather than as an
|
||||
ATerm. The schema is the same as that used by the <link
|
||||
linkend="builtin-toXML"><function>toXML</function>
|
||||
built-in</link>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--json</option></term>
|
||||
|
||||
<listitem><para>When used with <option>--parse</option> and
|
||||
<option>--eval</option>, print the resulting expression as an
|
||||
JSON representation of the abstract syntax tree rather than as an
|
||||
ATerm.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--strict</option></term>
|
||||
|
||||
<listitem><para>When used with <option>--eval</option>,
|
||||
@@ -131,24 +149,6 @@ input.</para>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--json</option></term>
|
||||
|
||||
<listitem><para>When used with <option>--eval</option>, print the resulting
|
||||
value as an JSON representation of the abstract syntax tree rather
|
||||
than as an ATerm.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--xml</option></term>
|
||||
|
||||
<listitem><para>When used with <option>--eval</option>, 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 <link
|
||||
linkend="builtin-toXML"><function>toXML</function> built-in</link>.
|
||||
</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--read-write-mode</option></term>
|
||||
|
||||
<listitem><para>When used with <option>--eval</option>, perform
|
||||
|
||||
@@ -19,16 +19,14 @@
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-prefetch-url</command>
|
||||
<arg><option>--version</option></arg>
|
||||
<arg><option>--type</option> <replaceable>hashAlgo</replaceable></arg>
|
||||
<arg><option>--print-path</option></arg>
|
||||
<arg><option>--unpack</option></arg>
|
||||
<arg><option>--name</option> <replaceable>name</replaceable></arg>
|
||||
<arg choice='plain'><replaceable>url</replaceable></arg>
|
||||
<arg><replaceable>hash</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The command <command>nix-prefetch-url</command> downloads the
|
||||
@@ -93,7 +91,7 @@ downloaded file in the Nix store is also printed.</para>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--name</option> <replaceable>name</replaceable></term>
|
||||
<varlistentry><term><option>--name</option></term>
|
||||
|
||||
<listitem><para>Override the name of the file in the Nix store. By
|
||||
default, this is
|
||||
|
||||
@@ -33,13 +33,13 @@
|
||||
<arg><option>--exclude</option> <replaceable>regexp</replaceable></arg>
|
||||
<arg><option>--pure</option></arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'>
|
||||
<group choice='req'>
|
||||
<group choice='plain'>
|
||||
<group>
|
||||
<arg choice='plain'><option>--packages</option></arg>
|
||||
<arg choice='plain'><option>-p</option></arg>
|
||||
</group>
|
||||
<arg choice='plain' rep='repeat'><replaceable>packages</replaceable></arg>
|
||||
</arg>
|
||||
<replaceable>packages</replaceable>
|
||||
</group>
|
||||
<arg><replaceable>path</replaceable></arg>
|
||||
</group>
|
||||
</cmdsynopsis>
|
||||
@@ -144,7 +144,7 @@ also <xref linkend="sec-common-options" />.</phrase></para>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--packages</option> / <option>-p</option> <replaceable>packages</replaceable>…</term>
|
||||
<varlistentry><term><option>--packages</option> / <option>-p</option></term>
|
||||
|
||||
<listitem><para>Set up an environment in which the specified
|
||||
packages are present. The command line arguments are interpreted
|
||||
|
||||
@@ -234,7 +234,7 @@ linkend="sec-nix-build"><command>nix-build</command></link> does.</para>
|
||||
<para>To test whether a previously-built derivation is deterministic:
|
||||
|
||||
<screen>
|
||||
$ nix-build '<nixpkgs>' -A hello --check -K
|
||||
$ nix-build -r '<nixpkgs>' -A hello --check -K
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
@@ -397,9 +397,9 @@ options control what gets deleted and in what order:
|
||||
</para>
|
||||
|
||||
<para>The behaviour of the collector is also influenced by the <link
|
||||
linkend="conf-keep-outputs"><literal>keep-outputs</literal></link>
|
||||
linkend="conf-gc-keep-outputs"><literal>gc-keep-outputs</literal></link>
|
||||
and <link
|
||||
linkend="conf-keep-derivations"><literal>keep-derivations</literal></link>
|
||||
linkend="conf-gc-keep-derivations"><literal>gc-keep-derivations</literal></link>
|
||||
variables in the Nix configuration file.</para>
|
||||
|
||||
<para>With <option>--delete</option>, the collector prints the total
|
||||
@@ -1236,7 +1236,12 @@ the store path is used.</para>
|
||||
<filename>/nix/var/log/nix/drvs</filename>. However, there is no
|
||||
guarantee that a build log is available for any particular store path.
|
||||
For instance, if the path was downloaded as a pre-built binary through
|
||||
a substitute, then the log is unavailable.</para>
|
||||
a substitute, then the log is unavailable. If the log is not available
|
||||
locally, then <command>nix-store</command> will try to download the
|
||||
log from the servers specified in the Nix option
|
||||
<option>log-servers</option>. For example, if it’s set to
|
||||
<literal>http://hydra.nixos.org/log</literal>, then Nix will check
|
||||
<literal>http://hydra.nixos.org/log/<replaceable>base-name</replaceable></literal>.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
@@ -2,18 +2,10 @@
|
||||
|
||||
<arg><option>--help</option></arg>
|
||||
<arg><option>--version</option></arg>
|
||||
<arg rep='repeat'>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--verbose</option></arg>
|
||||
<arg choice='plain'><option>-v</option></arg>
|
||||
</group>
|
||||
</arg>
|
||||
<arg>
|
||||
<group choice='plain'>
|
||||
<arg choice='plain'><option>--no-build-output</option></arg>
|
||||
<arg choice='plain'><option>-Q</option></arg>
|
||||
</group>
|
||||
</arg>
|
||||
<arg rep='repeat'><option>--verbose</option></arg>
|
||||
<arg rep='repeat'><option>-v</option></arg>
|
||||
<arg><option>--no-build-output</option></arg>
|
||||
<arg><option>-Q</option></arg>
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--max-jobs</option></arg>
|
||||
@@ -33,20 +25,13 @@
|
||||
<option>--timeout</option>
|
||||
<replaceable>number</replaceable>
|
||||
</arg>
|
||||
<arg>
|
||||
<group choice='plain'>
|
||||
<arg choice='plain'><option>--keep-going</option></arg>
|
||||
<arg choice='plain'><option>-k</option></arg>
|
||||
</group>
|
||||
</arg>
|
||||
<arg>
|
||||
<group choice='plain'>
|
||||
<arg choice='plain'><option>--keep-failed</option></arg>
|
||||
<arg choice='plain'><option>-K</option></arg>
|
||||
</group>
|
||||
</arg>
|
||||
<arg><option>--keep-going</option></arg>
|
||||
<arg><option>-k</option></arg>
|
||||
<arg><option>--keep-failed</option></arg>
|
||||
<arg><option>-K</option></arg>
|
||||
<arg><option>--fallback</option></arg>
|
||||
<arg><option>--readonly-mode</option></arg>
|
||||
<arg><option>--show-trace</option></arg>
|
||||
<arg>
|
||||
<option>-I</option>
|
||||
<replaceable>path</replaceable>
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--verbose</option> / <option>-v</option></term>
|
||||
<varlistentry><term><option>--verbose</option></term>
|
||||
<term><option>-v</option></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
@@ -75,7 +76,8 @@
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--no-build-output</option> / <option>-Q</option></term>
|
||||
<varlistentry><term><option>--no-build-output</option></term>
|
||||
<term><option>-Q</option></term>
|
||||
|
||||
<listitem><para>By default, output written by builders to standard
|
||||
output and standard error is echoed to the Nix command's standard
|
||||
@@ -87,14 +89,13 @@
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="opt-max-jobs"><term><option>--max-jobs</option> / <option>-j</option>
|
||||
<replaceable>number</replaceable></term>
|
||||
<varlistentry xml:id="opt-max-jobs"><term><option>--max-jobs</option></term>
|
||||
<term><option>-j</option></term>
|
||||
|
||||
<listitem><para>Sets the maximum number of build jobs that Nix will
|
||||
perform in parallel to the specified number. Specify
|
||||
<literal>auto</literal> to use the number of CPUs in the system.
|
||||
The default is specified by the <link
|
||||
linkend='conf-max-jobs'><literal>max-jobs</literal></link>
|
||||
perform in parallel to the specified number. The default is
|
||||
specified by the <link
|
||||
linkend='conf-build-max-jobs'><literal>build-max-jobs</literal></link>
|
||||
configuration setting, which itself defaults to
|
||||
<literal>1</literal>. A higher value is useful on SMP systems or to
|
||||
exploit I/O latency.</para></listitem>
|
||||
@@ -112,7 +113,7 @@
|
||||
<literal>true</literal>, the builder passes the
|
||||
<option>-j<replaceable>N</replaceable></option> flag to GNU Make.
|
||||
It defaults to the value of the <link
|
||||
linkend='conf-cores'><literal>cores</literal></link>
|
||||
linkend='conf-build-cores'><literal>build-cores</literal></link>
|
||||
configuration setting, if set, or <literal>1</literal> otherwise.
|
||||
The value <literal>0</literal> means that the builder should use all
|
||||
available CPU cores in the system.</para></listitem>
|
||||
@@ -125,7 +126,7 @@
|
||||
<listitem><para>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 <link
|
||||
linkend='conf-max-silent-time'><literal>max-silent-time</literal></link>
|
||||
linkend='conf-build-max-silent-time'><literal>build-max-silent-time</literal></link>
|
||||
configuration setting. <literal>0</literal> means no
|
||||
time-out.</para></listitem>
|
||||
|
||||
@@ -135,13 +136,14 @@
|
||||
|
||||
<listitem><para>Sets the maximum number of seconds that a builder
|
||||
can run. The default is specified by the <link
|
||||
linkend='conf-timeout'><literal>timeout</literal></link>
|
||||
linkend='conf-build-timeout'><literal>build-timeout</literal></link>
|
||||
configuration setting. <literal>0</literal> means no
|
||||
timeout.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--keep-going</option> / <option>-k</option></term>
|
||||
<varlistentry><term><option>--keep-going</option></term>
|
||||
<term><option>-k</option></term>
|
||||
|
||||
<listitem><para>Keep going in case of failed builds, to the
|
||||
greatest extent possible. That is, if building an input of some
|
||||
@@ -153,7 +155,8 @@
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--keep-failed</option> / <option>-K</option></term>
|
||||
<varlistentry><term><option>--keep-failed</option></term>
|
||||
<term><option>-K</option></term>
|
||||
|
||||
<listitem><para>Specifies that in case of a build failure, the
|
||||
temporary directory (usually in <filename>/tmp</filename>) in which
|
||||
@@ -301,6 +304,13 @@
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--show-trace</option></term>
|
||||
|
||||
<listitem><para>Causes Nix to print out a stack trace in case of Nix
|
||||
expression evaluation errors.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="opt-I"><term><option>-I</option> <replaceable>path</replaceable></term>
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ impureEnvVars = [ "http_proxy" "https_proxy" <replaceable>...</replaceable> ];
|
||||
<programlisting>
|
||||
fetchurl {
|
||||
url = http://ftp.gnu.org/pub/gnu/hello/hello-2.1.1.tar.gz;
|
||||
sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
|
||||
md5 = "70c9ccf9fac07f762c24f2df2290784d";
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
@@ -150,7 +150,7 @@ fetchurl {
|
||||
<programlisting>
|
||||
fetchurl {
|
||||
url = ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz;
|
||||
sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
|
||||
md5 = "70c9ccf9fac07f762c24f2df2290784d";
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ available as <function>builtins.derivation</function>.</para>
|
||||
<replaceable>set</replaceable></term>
|
||||
|
||||
<listitem><para>Return the names of the attributes in the set
|
||||
<replaceable>set</replaceable> in an alphabetically sorted list. For instance,
|
||||
<replaceable>set</replaceable> in a sorted list. For instance,
|
||||
<literal>builtins.attrNames { y = 1; x = "foo"; }</literal>
|
||||
evaluates to <literal>[ "x" "y" ]</literal>.</para></listitem>
|
||||
|
||||
@@ -126,17 +126,6 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.splitVersion</function>
|
||||
<replaceable>s</replaceable></term>
|
||||
|
||||
<listitem><para>Split a string representing a version into its
|
||||
components, by the same version splitting logic underlying the
|
||||
version comparison in <link linkend="ssec-version-comparisons">
|
||||
<command>nix-env -u</command></link>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.concatLists</function>
|
||||
<replaceable>lists</replaceable></term>
|
||||
|
||||
@@ -145,14 +134,6 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><function>builtins.concatStringsSep</function>
|
||||
<replaceable>separator</replaceable> <replaceable>list</replaceable></term>
|
||||
|
||||
<listitem><para>Concatenate a list of strings with a separator
|
||||
between each element, e.g. <literal>concatStringsSep "/"
|
||||
["usr" "local" "bin"] == "usr/local/bin"</literal></para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry
|
||||
xml:id='builtin-currentSystem'><term><varname>builtins.currentSystem</varname></term>
|
||||
@@ -229,6 +210,36 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><function>builtins.match</function>
|
||||
<replaceable>regex</replaceable> <replaceable>str</replaceable></term>
|
||||
|
||||
<listitem><para>Returns a list if
|
||||
<replaceable>regex</replaceable> matches
|
||||
<replaceable>str</replaceable> precisely, otherwise returns <literal>null</literal>.
|
||||
Each item in the list is a regex group.
|
||||
|
||||
<programlisting>
|
||||
builtins.match "ab" "abc"
|
||||
</programlisting>
|
||||
|
||||
Evaluates to <literal>null</literal>.
|
||||
|
||||
<programlisting>
|
||||
builtins.match "abc" "abc"
|
||||
</programlisting>
|
||||
|
||||
Evaluates to <literal>[ ]</literal>.
|
||||
|
||||
<programlisting>
|
||||
builtins.match "a(b)(c)" "abc"
|
||||
</programlisting>
|
||||
|
||||
Evaluates to <literal>[ "b" "c" ]</literal>.
|
||||
|
||||
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><function>builtins.elem</function>
|
||||
<replaceable>x</replaceable> <replaceable>xs</replaceable></term>
|
||||
|
||||
@@ -278,24 +289,6 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
|
||||
<programlisting>
|
||||
with import (fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz) {};
|
||||
|
||||
stdenv.mkDerivation { … }
|
||||
</programlisting>
|
||||
|
||||
Note that when obtaining the hash with <varname>nix-prefetch-url
|
||||
</varname> the option <varname>--unpack</varname> is required.
|
||||
</para>
|
||||
|
||||
<para>This function can also verify the contents against a hash.
|
||||
In that case, the function takes a set instead of a URL. The set
|
||||
requires the attribute <varname>url</varname> and the attribute
|
||||
<varname>sha256</varname>, e.g.
|
||||
|
||||
<programlisting>
|
||||
with import (fetchTarball {
|
||||
url = https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz;
|
||||
sha256 = "1jppksrfvbk5ypiqdz4cddxdl8z6zyzdb2srq8fcffr327ld5jj2";
|
||||
}) {};
|
||||
|
||||
stdenv.mkDerivation { … }
|
||||
</programlisting>
|
||||
|
||||
@@ -319,9 +312,8 @@ stdenv.mkDerivation { … }
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id='builtin-filterSource'>
|
||||
<term><function>builtins.filterSource</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
<varlistentry><term><function>builtins.filterSource</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
@@ -424,7 +416,7 @@ builtins.fromJSON ''{"x": [1, 2, 3], "y": null}''
|
||||
|
||||
<listitem><para>Generate list of size
|
||||
<replaceable>length</replaceable>, with each element
|
||||
<replaceable>i</replaceable> equal to the value returned by
|
||||
<replaceable>i></replaceable> equal to the value returned by
|
||||
<replaceable>generator</replaceable> <literal>i</literal>. For
|
||||
example,
|
||||
|
||||
@@ -620,16 +612,6 @@ x: x + 456</programlisting>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.isFloat</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if
|
||||
<replaceable>e</replaceable> evaluates to a float, and
|
||||
<literal>false</literal> otherwise.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.isBool</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
@@ -720,42 +702,6 @@ map (x: "foo" + x) [ "bar" "bla" "abc" ]</programlisting>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.match</function>
|
||||
<replaceable>regex</replaceable> <replaceable>str</replaceable></term>
|
||||
|
||||
<listitem><para>Returns a list if the <link
|
||||
xlink:href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04">extended
|
||||
POSIX regular expression</link> <replaceable>regex</replaceable>
|
||||
matches <replaceable>str</replaceable> precisely, otherwise returns
|
||||
<literal>null</literal>. Each item in the list is a regex group.
|
||||
|
||||
<programlisting>
|
||||
builtins.match "ab" "abc"
|
||||
</programlisting>
|
||||
|
||||
Evaluates to <literal>null</literal>.
|
||||
|
||||
<programlisting>
|
||||
builtins.match "abc" "abc"
|
||||
</programlisting>
|
||||
|
||||
Evaluates to <literal>[ ]</literal>.
|
||||
|
||||
<programlisting>
|
||||
builtins.match "a(b)(c)" "abc"
|
||||
</programlisting>
|
||||
|
||||
Evaluates to <literal>[ "b" "c" ]</literal>.
|
||||
|
||||
<programlisting>
|
||||
builtins.match "[[:space:]]+([[:upper:]]+)[[:space:]]+" " FOO "
|
||||
</programlisting>
|
||||
|
||||
Evaluates to <literal>[ "foo" ]</literal>.
|
||||
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><function>builtins.mul</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
|
||||
@@ -780,75 +726,6 @@ Evaluates to <literal>[ "foo" ]</literal>.
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<function>builtins.path</function>
|
||||
<replaceable>args</replaceable>
|
||||
</term>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
An enrichment of the built-in path type, based on the attributes
|
||||
present in <replaceable>args</replaceable>. All are optional
|
||||
except <varname>path</varname>:
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>path</term>
|
||||
<listitem>
|
||||
<para>The underlying path.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>name</term>
|
||||
<listitem>
|
||||
<para>
|
||||
The name of the path when added to the store. This can
|
||||
used to reference paths that have nix-illegal characters
|
||||
in their names, like <literal>@</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>filter</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A function of the type expected by
|
||||
<link linkend="builtin-filterSource">builtins.filterSource</link>,
|
||||
with the same semantics.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>recursive</term>
|
||||
<listitem>
|
||||
<para>
|
||||
When <literal>false</literal>, when
|
||||
<varname>path</varname> is added to the store it is with a
|
||||
flat hash, rather than a hash of the NAR serialization of
|
||||
the file. Thus, <varname>path</varname> must refer to a
|
||||
regular file, not a directory. This allows similar
|
||||
behavior to <literal>fetchurl</literal>. Defaults to
|
||||
<literal>true</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>sha256</term>
|
||||
<listitem>
|
||||
<para>
|
||||
When provided, this is the expected hash of the file at
|
||||
the path. Evaluation will fail if the hash is incorrect,
|
||||
and providing a hash allows
|
||||
<literal>builtins.path</literal> to be used even when the
|
||||
<literal>pure-eval</literal> nix config option is on.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><function>builtins.pathExists</function>
|
||||
<replaceable>path</replaceable></term>
|
||||
@@ -972,43 +849,6 @@ builtins.sort builtins.lessThan [ 483 249 526 147 42 77 ]
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.split</function>
|
||||
<replaceable>regex</replaceable> <replaceable>str</replaceable></term>
|
||||
|
||||
<listitem><para>Returns a list composed of non matched strings interleaved
|
||||
with the lists of the <link
|
||||
xlink:href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04">extended
|
||||
POSIX regular expression</link> <replaceable>regex</replaceable> matches
|
||||
of <replaceable>str</replaceable>. Each item in the lists of matched
|
||||
sequences is a regex group.
|
||||
|
||||
<programlisting>
|
||||
builtins.split "(a)b" "abc"
|
||||
</programlisting>
|
||||
|
||||
Evaluates to <literal>[ "" [ "a" ] "c" ]</literal>.
|
||||
|
||||
<programlisting>
|
||||
builtins.split "([ac])" "abc"
|
||||
</programlisting>
|
||||
|
||||
Evaluates to <literal>[ "" [ "a" ] "b" [ "c" ] "" ]</literal>.
|
||||
|
||||
<programlisting>
|
||||
builtins.split "(a)|(c)" "abc"
|
||||
</programlisting>
|
||||
|
||||
Evaluates to <literal>[ "" [ "a" null ] "b" [ null "c" ] "" ]</literal>.
|
||||
|
||||
<programlisting>
|
||||
builtins.split "([[:upper:]]+)" " FOO "
|
||||
</programlisting>
|
||||
|
||||
Evaluates to <literal>[ " " [ "FOO" ] " " ]</literal>.
|
||||
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><function>builtins.stringLength</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
@@ -1109,8 +949,8 @@ stdenv.mkDerivation {
|
||||
";
|
||||
|
||||
src = fetchurl {
|
||||
url = http://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz;
|
||||
sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
|
||||
url = http://nix.cs.uu.nl/dist/tarballs/hello-2.1.1.tar.gz;
|
||||
md5 = "70c9ccf9fac07f762c24f2df2290784d";
|
||||
};
|
||||
inherit perl;
|
||||
}</programlisting>
|
||||
@@ -1183,17 +1023,10 @@ in foo</programlisting>
|
||||
|
||||
<listitem><para>Convert the expression
|
||||
<replaceable>e</replaceable> to a string.
|
||||
<replaceable>e</replaceable> can be:</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>A string (in which case the string is returned unmodified).</para></listitem>
|
||||
<listitem><para>A path (e.g., <literal>toString /foo/bar</literal> yields <literal>"/foo/bar"</literal>.</para></listitem>
|
||||
<listitem><para>A set containing <literal>{ __toString = self: ...; }</literal>.</para></listitem>
|
||||
<listitem><para>An integer.</para></listitem>
|
||||
<listitem><para>A list, in which case the string representations of its elements are joined with spaces.</para></listitem>
|
||||
<listitem><para>A Boolean (<literal>false</literal> yields <literal>""</literal>, <literal>true</literal> yields <literal>"1"</literal>.</para></listitem>
|
||||
<listitem><para><literal>null</literal>, which yields the empty string.</para></listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
<replaceable>e</replaceable> can be a string (in which case
|
||||
<function>toString</function> is a no-op), a path (e.g.,
|
||||
<literal>toString /foo/bar</literal> yields
|
||||
<literal>"/foo/bar"</literal> or a set containing <literal>{ __toString = self: ...; }</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
@@ -1323,19 +1156,6 @@ stdenv.mkDerivation (rec {
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><function>builtins.tryEval</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Try to evaluate <replaceable>e</replaceable>.
|
||||
Return a set containing the attributes <literal>success</literal>
|
||||
(<literal>true</literal> if <replaceable>e</replaceable> evaluated
|
||||
successfully, <literal>false</literal> if an error was thrown) and
|
||||
<literal>value</literal>, equalling <replaceable>e</replaceable>
|
||||
if successful and <literal>false</literal> otherwise.
|
||||
</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.typeOf</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
@@ -1344,9 +1164,8 @@ stdenv.mkDerivation (rec {
|
||||
<replaceable>e</replaceable>, namely <literal>"int"</literal>,
|
||||
<literal>"bool"</literal>, <literal>"string"</literal>,
|
||||
<literal>"path"</literal>, <literal>"null"</literal>,
|
||||
<literal>"set"</literal>, <literal>"list"</literal>,
|
||||
<literal>"lambda"</literal> or
|
||||
<literal>"float"</literal>.</para></listitem>
|
||||
<literal>"set"</literal>, <literal>"list"</literal> or
|
||||
<literal>"lambda"</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
34
doc/manual/expressions/debug-build.xml
Normal file
34
doc/manual/expressions/debug-build.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-debug-build">
|
||||
|
||||
<title>Debugging Build Failures</title>
|
||||
|
||||
<para>At the beginning of each phase of the build (such as unpacking,
|
||||
building or installing), the set of all shell variables is written to
|
||||
the file <filename>env-vars</filename> at the top-level build
|
||||
directory. This is useful for debugging: it allows you to recreate
|
||||
the environment in which a build was performed. For instance, if a
|
||||
build fails, then assuming you used the <option>-K</option> flag, you
|
||||
can go to the output directory and <quote>switch</quote> to the
|
||||
environment of the builder:
|
||||
|
||||
<screen>
|
||||
$ nix-build -K ./foo.nix
|
||||
... fails, keeping build directory `/tmp/nix-1234-0'
|
||||
|
||||
$ cd /tmp/nix-1234-0
|
||||
|
||||
$ source env-vars
|
||||
|
||||
<lineannotation>(edit some files...)</lineannotation>
|
||||
|
||||
$ make
|
||||
|
||||
<lineannotation>(execution continues with the same GCC, make, etc.)</lineannotation></screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
@@ -100,7 +100,7 @@ outputs = [ "lib" "headers" "doc" ];
|
||||
<programlisting>
|
||||
buildInputs = [ pkg.lib pkg.headers ];
|
||||
</programlisting>
|
||||
The first element of <varname>outputs</varname> determines the
|
||||
The first element of <varname>output</varname> determines the
|
||||
<emphasis>default output</emphasis>. Thus, you could also write
|
||||
<programlisting>
|
||||
buildInputs = [ pkg pkg.headers ];
|
||||
|
||||
@@ -16,7 +16,7 @@ stdenv.mkDerivation { <co xml:id='ex-hello-nix-co-2' />
|
||||
builder = ./builder.sh; <co xml:id='ex-hello-nix-co-4' />
|
||||
src = fetchurl { <co xml:id='ex-hello-nix-co-5' />
|
||||
url = ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz;
|
||||
sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
|
||||
md5 = "70c9ccf9fac07f762c24f2df2290784d";
|
||||
};
|
||||
inherit perl; <co xml:id='ex-hello-nix-co-6' />
|
||||
}</programlisting>
|
||||
@@ -108,7 +108,7 @@ the single Nix expression in that directory
|
||||
<para>The builder has to know what the sources of the package
|
||||
are. Here, the attribute <varname>src</varname> is bound to the
|
||||
result of a call to the <command>fetchurl</command> function.
|
||||
Given a URL and a SHA-256 hash of the expected contents of the file
|
||||
Given a URL and an MD5 hash of the expected contents of the file
|
||||
at that URL, this function builds a derivation that downloads the
|
||||
file and checks its hash. So the sources are a dependency that
|
||||
like all other dependencies is built before Hello itself is
|
||||
@@ -145,4 +145,4 @@ perl = perl;</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
@@ -61,7 +61,7 @@ evaluates to <literal>"foobar"</literal>.
|
||||
|
||||
<simplesect><title>Inheriting attributes</title>
|
||||
|
||||
<para>When defining a set or in a let-expression it is often convenient to copy variables
|
||||
<para>When defining a set it is often convenient to copy variables
|
||||
from the surrounding lexical scope (e.g., when you want to propagate
|
||||
attributes). This can be shortened using the
|
||||
<literal>inherit</literal> keyword. For instance,
|
||||
@@ -72,15 +72,7 @@ let x = 123; in
|
||||
y = 456;
|
||||
}</programlisting>
|
||||
|
||||
is equivalent to
|
||||
|
||||
<programlisting>
|
||||
let x = 123; in
|
||||
{ x = x;
|
||||
y = 456;
|
||||
}</programlisting>
|
||||
|
||||
and both evaluate to <literal>{ x = 123; y = 456; }</literal>. (Note that
|
||||
evaluates to <literal>{ x = 123; y = 456; }</literal>. (Note that
|
||||
this works because <varname>x</varname> is added to the lexical scope
|
||||
by the <literal>let</literal> construct.) It is also possible to
|
||||
inherit attributes from another set. For instance, in this fragment
|
||||
@@ -109,26 +101,6 @@ variables from the surrounding scope (<varname>fetchurl</varname>
|
||||
<varname>libXaw</varname> (the X Athena Widgets) from the
|
||||
<varname>xlibs</varname> (X11 client-side libraries) set.</para>
|
||||
|
||||
<para>
|
||||
Summarizing the fragment
|
||||
|
||||
<programlisting>
|
||||
...
|
||||
inherit x y z;
|
||||
inherit (src-set) a b c;
|
||||
...</programlisting>
|
||||
|
||||
is equivalent to
|
||||
|
||||
<programlisting>
|
||||
...
|
||||
x = x; y = y; z = z;
|
||||
a = src-set.a; b = src-set.b; c = src-set.c;
|
||||
...</programlisting>
|
||||
|
||||
when used while defining local variables in a let-expression or
|
||||
while defining a set.</para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
@@ -361,20 +333,7 @@ with (import ./definitions.nix); ...</programlisting>
|
||||
|
||||
makes all attributes defined in the file
|
||||
<filename>definitions.nix</filename> available as if they were defined
|
||||
locally in a <literal>let</literal>-expression.</para>
|
||||
|
||||
<para>The bindings introduced by <literal>with</literal> do not shadow bindings
|
||||
introduced by other means, e.g.
|
||||
|
||||
<programlisting>
|
||||
let a = 3; in with { a = 1; }; let a = 4; in with { a = 2; }; ...</programlisting>
|
||||
|
||||
establishes the same scope as
|
||||
|
||||
<programlisting>
|
||||
let a = 1; in let a = 2; in let a = 3; in let a = 4; in ...</programlisting>
|
||||
|
||||
</para>
|
||||
locally in a <literal>rec</literal>-expression.</para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
@@ -40,11 +40,6 @@ weakest binding).</para>
|
||||
<entry>Call function <replaceable>e1</replaceable> with
|
||||
argument <replaceable>e2</replaceable>.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>-</literal> <replaceable>e</replaceable></entry>
|
||||
<entry>none</entry>
|
||||
<entry>Arithmetic negation.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><replaceable>e</replaceable> <literal>?</literal>
|
||||
<replaceable>attrpath</replaceable></entry>
|
||||
@@ -60,24 +55,13 @@ weakest binding).</para>
|
||||
<entry>List concatenation.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal>*</literal> <replaceable>e2</replaceable>,
|
||||
<replaceable>e1</replaceable> <literal>/</literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry><replaceable>e1</replaceable> <literal>+</literal> <replaceable>e2</replaceable></entry>
|
||||
<entry>left</entry>
|
||||
<entry>Arithmetic multiplication and division.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal>+</literal> <replaceable>e2</replaceable>,
|
||||
<replaceable>e1</replaceable> <literal>-</literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry>left</entry>
|
||||
<entry>Arithmetic addition and subtraction. String or path concatenation (only by <literal>+</literal>).</entry>
|
||||
<entry>String or path concatenation.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>!</literal> <replaceable>e</replaceable></entry>
|
||||
<entry>none</entry>
|
||||
<entry>left</entry>
|
||||
<entry>Boolean negation.</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -91,22 +75,16 @@ weakest binding).</para>
|
||||
attributes).</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal><</literal> <replaceable>e2</replaceable>,
|
||||
<replaceable>e1</replaceable> <literal>></literal> <replaceable>e2</replaceable>,
|
||||
<replaceable>e1</replaceable> <literal><=</literal> <replaceable>e2</replaceable>,
|
||||
<replaceable>e1</replaceable> <literal>>=</literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry><replaceable>e1</replaceable> <literal>==</literal>
|
||||
<replaceable>e2</replaceable></entry>
|
||||
<entry>none</entry>
|
||||
<entry>Arithmetic comparison.</entry>
|
||||
<entry>Equality.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal>==</literal> <replaceable>e2</replaceable>,
|
||||
<replaceable>e1</replaceable> <literal>!=</literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry><replaceable>e1</replaceable> <literal>!=</literal>
|
||||
<replaceable>e2</replaceable></entry>
|
||||
<entry>none</entry>
|
||||
<entry>Equality and inequality.</entry>
|
||||
<entry>Inequality.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><replaceable>e1</replaceable> <literal>&&</literal>
|
||||
|
||||
@@ -98,17 +98,13 @@ configureFlags = "
|
||||
|
||||
<para>Since <literal>${</literal> and <literal>''</literal> have
|
||||
special meaning in indented strings, you need a way to quote them.
|
||||
<literal>$</literal> can be escaped by prefixing it with
|
||||
<literal>${</literal> can be escaped by prefixing it with
|
||||
<literal>''</literal> (that is, two single quotes), i.e.,
|
||||
<literal>''$</literal>. <literal>''</literal> can be escaped by
|
||||
<literal>''${</literal>. <literal>''</literal> can be escaped by
|
||||
prefixing it with <literal>'</literal>, i.e.,
|
||||
<literal>'''</literal>. <literal>$</literal> removes any special meaning
|
||||
from the following <literal>$</literal>. Linefeed, carriage-return and tab
|
||||
characters can be written as <literal>''\n</literal>,
|
||||
<literal>''\r</literal>, <literal>''\t</literal>, and <literal>''\</literal>
|
||||
escapes any other character.
|
||||
|
||||
</para>
|
||||
<literal>'''</literal>. Finally, linefeed, carriage-return and
|
||||
tab characters can be written as <literal>''\n</literal>,
|
||||
<literal>''\r</literal>, <literal>''\t</literal>.</para>
|
||||
|
||||
<para>Indented strings are primarily useful in that they allow
|
||||
multi-line string literals to follow the indentation of the
|
||||
|
||||
@@ -81,4 +81,6 @@ Just pass the option <link linkend='opt-max-jobs'><option>-j
|
||||
in parallel, or set. Typically this should be the number of
|
||||
CPUs.</para>
|
||||
|
||||
<xi:include href="debug-build.xml" />
|
||||
|
||||
</section>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
|
||||
<glossdef><para>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
|
||||
normal the 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.</para></glossdef>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<title>Installing a Binary Distribution</title>
|
||||
|
||||
<para>If you are using Linux or macOS, the easiest way to install
|
||||
<para>If you are using Linux or Mac OS X, the easiest way to install
|
||||
Nix is to run the following command:
|
||||
|
||||
<screen>
|
||||
@@ -39,7 +39,7 @@ behaviour.
|
||||
<!--
|
||||
<para>You can also manually download and install a binary package.
|
||||
Binary packages of the latest stable release are available for Fedora,
|
||||
Debian, Ubuntu, macOS and various other systems from the <link
|
||||
Debian, Ubuntu, Mac OS X and various other systems from the <link
|
||||
xlink:href="http://nixos.org/nix/download.html">Nix homepage</link>.
|
||||
You can also get builds of the latest development release from our
|
||||
<link
|
||||
@@ -79,6 +79,16 @@ alice$ ./install
|
||||
|
||||
</para>
|
||||
|
||||
<para>Nix can be uninstalled using <command>rpm -e nix</command> or
|
||||
<command>dpkg -r nix</command> on RPM- and Dpkg-based systems,
|
||||
respectively. After this you should manually remove the Nix store and
|
||||
other auxiliary data, if desired:
|
||||
|
||||
<screen>
|
||||
$ rm -rf /nix</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>You can uninstall Nix simply by running:
|
||||
|
||||
<screen>
|
||||
|
||||
@@ -52,6 +52,34 @@ This creates 10 build users. There can never be more concurrent builds
|
||||
than the number of build users, so you may want to increase this if
|
||||
you expect to do many builds at the same time.</para>
|
||||
|
||||
<para>On Mac OS X, you can create the required group and users by
|
||||
running the following script:
|
||||
|
||||
<programlisting>
|
||||
#! /bin/bash -e
|
||||
|
||||
dseditgroup -o create nixbld -q
|
||||
|
||||
gid=$(dscl . -read /Groups/nixbld | awk '($1 == "PrimaryGroupID:") {print $2 }')
|
||||
|
||||
echo "created nixbld group with gid $gid"
|
||||
|
||||
for i in $(seq 1 10); do
|
||||
user=/Users/nixbld$i
|
||||
uid="$((30000 + $i))"
|
||||
dscl . create $user
|
||||
dscl . create $user RealName "Nix build user $i"
|
||||
dscl . create $user PrimaryGroupID "$gid"
|
||||
dscl . create $user UserShell /usr/bin/false
|
||||
dscl . create $user NFSHomeDirectory /var/empty
|
||||
dscl . create $user UniqueID "$uid"
|
||||
dseditgroup -o edit -a nixbld$i -t user nixbld
|
||||
echo "created nixbld$i user with uid $uid"
|
||||
done
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
|
||||
@@ -10,14 +10,16 @@
|
||||
|
||||
<listitem><para>GNU Make.</para></listitem>
|
||||
|
||||
<listitem><para>A version of GCC or Clang that supports C++14.</para></listitem>
|
||||
<listitem><para>A version of GCC or Clang that supports C++11.</para></listitem>
|
||||
|
||||
<listitem><para>Perl 5.8 or higher.</para></listitem>
|
||||
|
||||
<listitem><para><command>pkg-config</command> to locate
|
||||
dependencies. If your distribution does not provide it, you can get
|
||||
it from <link
|
||||
xlink:href="http://www.freedesktop.org/wiki/Software/pkg-config"
|
||||
/>.</para></listitem>
|
||||
|
||||
|
||||
<listitem><para>The OpenSSL library to calculate cryptographic hashes.
|
||||
If your distribution does not provide it, you can get it from <link
|
||||
xlink:href="https://www.openssl.org"/>.</para></listitem>
|
||||
@@ -32,6 +34,11 @@
|
||||
or higher. If your distribution does not provide it, please install
|
||||
it from <link xlink:href="http://www.sqlite.org/" />.</para></listitem>
|
||||
|
||||
<listitem><para>The Perl DBI and DBD::SQLite libraries, which are
|
||||
available from <link
|
||||
xlink:href="http://search.cpan.org/">CPAN</link> if your
|
||||
distribution does not provide them.</para></listitem>
|
||||
|
||||
<listitem><para>The <link
|
||||
xlink:href="http://www.hboehm.info/gc/">Boehm
|
||||
garbage collector</link> to reduce the evaluator’s memory
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<listitem><para>Linux (i686, x86_64).</para></listitem>
|
||||
|
||||
<listitem><para>macOS (x86_64).</para></listitem>
|
||||
<listitem><para>Mac OS X (x86_64).</para></listitem>
|
||||
|
||||
<!--
|
||||
<listitem><para>FreeBSD (only tested on Intel).</para></listitem>
|
||||
@@ -33,4 +33,7 @@
|
||||
|
||||
</para>
|
||||
|
||||
<para>Nix is fairly portable, so it should work on most platforms that
|
||||
support POSIX threads and have a C++11 compiler.</para>
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -93,7 +93,7 @@ time window in which the package has some files from the old version
|
||||
and some files from the new version — which would be bad because a
|
||||
program might well crash if it’s started during that period.</para>
|
||||
|
||||
<para>And since packages aren’t overwritten, the old versions are still
|
||||
<para>And since package aren’t overwritten, the old versions are still
|
||||
there after an upgrade. This means that you can <emphasis>roll
|
||||
back</emphasis> to the old version:</para>
|
||||
|
||||
@@ -236,7 +236,7 @@ href="[%root%]hydra">a continuous build system</a>.</para>
|
||||
|
||||
<simplesect><title>Portability</title>
|
||||
|
||||
<para>Nix runs on Linux and macOS.</para>
|
||||
<para>Nix runs on Linux and Mac OS X.</para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
@@ -261,12 +261,6 @@ xlink:href="http://nixos.org/">NixOS homepage</link>.</para>
|
||||
xlink:href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">GNU
|
||||
LGPLv2.1 or (at your option) any later version</link>.</para>
|
||||
|
||||
<para>Nix uses the <link
|
||||
xlink:href="https://github.com/arangodb/linenoise-ng">linenoise-ng
|
||||
library</link>, which has the following license:</para>
|
||||
|
||||
<programlisting><xi:include href="../../../src/linenoise/LICENSE" parse="text" /></programlisting>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ to subsequent chapters.</para>
|
||||
<step><para>Install single-user Nix by running the following:
|
||||
|
||||
<screen>
|
||||
$ bash <(curl https://nixos.org/nix/install)
|
||||
$ curl https://nixos.org/nix/install | sh
|
||||
</screen>
|
||||
|
||||
This will install Nix in <filename>/nix</filename>. The install script
|
||||
@@ -40,7 +40,7 @@ libxslt-1.1.28
|
||||
<step><para>Install some packages from the channel:
|
||||
|
||||
<screen>
|
||||
$ nix-env -i hello</screen>
|
||||
$ nix-env -i hello <replaceable>...</replaceable> </screen>
|
||||
|
||||
This should download pre-built packages; it should not build them
|
||||
locally (if it does, something went wrong).</para></step>
|
||||
|
||||
@@ -12,14 +12,19 @@
|
||||
<firstname>Eelco</firstname>
|
||||
<surname>Dolstra</surname>
|
||||
</personname>
|
||||
<affiliation>
|
||||
<orgname>LogicBlox</orgname>
|
||||
</affiliation>
|
||||
<contrib>Author</contrib>
|
||||
</author>
|
||||
|
||||
<copyright>
|
||||
<year>2004-2018</year>
|
||||
<year>2004-2014</year>
|
||||
<holder>Eelco Dolstra</holder>
|
||||
</copyright>
|
||||
|
||||
<date>November 2014</date>
|
||||
|
||||
</info>
|
||||
|
||||
<!--
|
||||
@@ -36,6 +41,7 @@
|
||||
<xi:include href="expressions/writing-nix-expressions.xml" />
|
||||
<xi:include href="advanced-topics/advanced-topics.xml" />
|
||||
<xi:include href="command-ref/command-ref.xml" />
|
||||
<xi:include href="troubleshooting/troubleshooting.xml" />
|
||||
<xi:include href="glossary/glossary.xml" />
|
||||
<xi:include href="hacking.xml" />
|
||||
<xi:include href="release-notes/release-notes.xml" />
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
</partintro>
|
||||
-->
|
||||
|
||||
<xi:include href="rl-2.0.xml" />
|
||||
<xi:include href="rl-1.11.10.xml" />
|
||||
<xi:include href="rl-1.12.xml" />
|
||||
<xi:include href="rl-1.11.xml" />
|
||||
<xi:include href="rl-1.10.xml" />
|
||||
<xi:include href="rl-1.9.xml" />
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.11.10">
|
||||
|
||||
<title>Release 1.11.10 (2017-06-12)</title>
|
||||
|
||||
<para>This release fixes a security bug in Nix’s “build user” build
|
||||
isolation mechanism. Previously, Nix builders had the ability to
|
||||
create setuid binaries owned by a <literal>nixbld</literal>
|
||||
user. Such a binary could then be used by an attacker to assume a
|
||||
<literal>nixbld</literal> identity and interfere with subsequent
|
||||
builds running under the same UID.</para>
|
||||
|
||||
<para>To prevent this issue, Nix now disallows builders to create
|
||||
setuid and setgid binaries. On Linux, this is done using a seccomp BPF
|
||||
filter. Note that this imposes a small performance penalty (e.g. 1%
|
||||
when building GNU Hello). Using seccomp, we now also prevent the
|
||||
creation of extended attributes and POSIX ACLs since these cannot be
|
||||
represented in the NAR format and (in the case of POSIX ACLs) allow
|
||||
bypassing regular Nix store permissions. On macOS, the restriction is
|
||||
implemented using the existing sandbox mechanism, which now uses a
|
||||
minimal “allow all except the creation of setuid/setgid binaries”
|
||||
profile when regular sandboxing is disabled. On other platforms, the
|
||||
“build user” mechanism is now disabled.</para>
|
||||
|
||||
<para>Thanks go to Linus Heckemann for discovering and reporting this
|
||||
bug.</para>
|
||||
|
||||
</section>
|
||||
@@ -121,6 +121,13 @@ $ diffoscope /nix/store/11a27shh6n2i…-zlib-1.2.8 /nix/store/11a27shh6n2i…-zl
|
||||
also improves performance.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The Nix language now supports floating point numbers. They are
|
||||
based on regular C++ <literal>float</literal> and compatible with
|
||||
existing integers and number-related operations. Export and import to and
|
||||
from JSON and XML works, too.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>All "chroot"-containing strings got renamed to "sandbox".
|
||||
In particular, some Nix options got renamed, but the old names
|
||||
|
||||
24
doc/manual/release-notes/rl-1.12.xml
Normal file
24
doc/manual/release-notes/rl-1.12.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.12">
|
||||
|
||||
<title>Release 1.12 (TBA)</title>
|
||||
|
||||
<para>This release has the following new features:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>It is no longer necessary to set the
|
||||
<envar>NIX_REMOTE</envar> environment variable if you need to use
|
||||
the Nix daemon. Nix will use the daemon automatically if you don’t
|
||||
have write access to the Nix database.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>This release has contributions from TBD.</para>
|
||||
|
||||
</section>
|
||||
@@ -40,7 +40,7 @@ $ nix-env -i thunderbird --option binary-caches http://cache.nixos.org
|
||||
<para>Binary caches are created using <command>nix-push</command>.
|
||||
For details on the operation and format of binary caches, see the
|
||||
<command>nix-push</command> manpage. More details are provided in
|
||||
<link xlink:href="https://nixos.org/nix-dev/2012-September/009826.html">this
|
||||
<link xlink:href="http://lists.science.uu.nl/pipermail/nix-dev/2012-September/009826.html">this
|
||||
nix-dev posting</link>.</para>
|
||||
</listitem>
|
||||
|
||||
|
||||
@@ -83,8 +83,8 @@ $ nix-store -l $(which xterm)
|
||||
caches).</para></listitem>
|
||||
|
||||
<listitem><para>The configuration option
|
||||
<option>build-cores</option> now defaults to the number of available
|
||||
CPU cores.</para></listitem>
|
||||
<option>build-max-jobs</option> now defaults to the number of
|
||||
available CPU cores.</para></listitem>
|
||||
|
||||
<listitem><para>Build users are now used by default when Nix is
|
||||
invoked as root. This prevents builds from accidentally running as
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -96,6 +96,7 @@ div.example
|
||||
margin-right: 1.5em;
|
||||
background: #f4f4f8;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.example p.title
|
||||
@@ -105,6 +106,7 @@ div.example p.title
|
||||
|
||||
div.example pre
|
||||
{
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,12 +116,15 @@ div.example pre
|
||||
|
||||
pre.screen, pre.programlisting
|
||||
{
|
||||
padding: 6px 6px;
|
||||
border: 1px solid #b0b0b0;
|
||||
padding: 3px 3px;
|
||||
margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
color: #600000;
|
||||
background: #f4f4f8;
|
||||
font-family: monospace;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.example pre.programlisting
|
||||
@@ -144,6 +149,7 @@ div.example pre.programlisting
|
||||
padding: 0.3em 0.3em 0.3em 0.3em;
|
||||
background: #fffff5;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.note, div.warning
|
||||
@@ -250,14 +256,16 @@ span.command strong
|
||||
|
||||
div.calloutlist table
|
||||
{
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.affiliation
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
38
doc/manual/troubleshooting/collisions-nixenv.xml
Normal file
38
doc/manual/troubleshooting/collisions-nixenv.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-collisions-nixenv">
|
||||
|
||||
<title>Collisions in <command>nix-env</command></title>
|
||||
|
||||
<para>Symptom: when installing or upgrading, you get an error message such as
|
||||
|
||||
<screen>
|
||||
$ nix-env -i docbook-xml
|
||||
...
|
||||
adding /nix/store/s5hyxgm62gk2...-docbook-xml-4.2
|
||||
collision between `/nix/store/s5hyxgm62gk2...-docbook-xml-4.2/xml/dtd/docbook/calstblx.dtd'
|
||||
and `/nix/store/06h377hr4b33...-docbook-xml-4.3/xml/dtd/docbook/calstblx.dtd'
|
||||
at /nix/store/...-builder.pl line 62.</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The cause is that two installed packages in the user environment
|
||||
have overlapping filenames (e.g.,
|
||||
<filename>xml/dtd/docbook/calstblx.dtd</filename>. This usually
|
||||
happens when you accidentally try to install two versions of the same
|
||||
package. For instance, in the example above, the Nix Packages
|
||||
collection contains two versions of <literal>docbook-xml</literal>, so
|
||||
<command>nix-env -i</command> will try to install both. The default
|
||||
user environment builder has no way to way to resolve such conflicts,
|
||||
so it just gives up.</para>
|
||||
|
||||
<para>Solution: remove one of the offending packages from the user
|
||||
environment (if already installed) using <command>nix-env
|
||||
-e</command>, or specify exactly which version should be installed
|
||||
(e.g., <literal>nix-env -i docbook-xml-4.2</literal>).</para>
|
||||
|
||||
<!-- FIXME: describe priorities -->
|
||||
|
||||
</section>
|
||||
43
doc/manual/troubleshooting/links-nix-store.xml
Normal file
43
doc/manual/troubleshooting/links-nix-store.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-links-nix-store">
|
||||
|
||||
<title><quote>Too many links</quote> Error in the Nix store</title>
|
||||
|
||||
|
||||
<para>Symptom: when building something, you get an error message such as
|
||||
|
||||
<screen>
|
||||
...
|
||||
<literal>mkdir: cannot create directory `/nix/store/<replaceable>name</replaceable>': Too many links</literal></screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>This is usually because you have more than 32,000 subdirectories
|
||||
in <filename>/nix/store</filename>, as can be seen using <command>ls
|
||||
-l</command>:
|
||||
|
||||
<screen>
|
||||
$ ls -ld /nix/store
|
||||
drwxrwxrwt 32000 nix nix 4620288 Sep 8 15:08 store</screen>
|
||||
|
||||
The <literal>ext2</literal> file system is limited to an inode link
|
||||
count of 32,000 (each subdirectory increasing the count by one).
|
||||
Furthermore, the <literal>st_nlink</literal> field of the
|
||||
<function>stat</function> system call is a 16-bit value.</para>
|
||||
|
||||
<para>This only happens on very large Nix installations (such as build
|
||||
machines).</para>
|
||||
|
||||
<para>Quick solution: run the garbage collector. You may want to use
|
||||
the <option>--max-links</option> option.</para>
|
||||
|
||||
<para>Real solution: put the Nix store on a file system that supports
|
||||
more than 32,000 subdirectories per directory, such as ext4. (This
|
||||
doesn’t solve the <literal>st_nlink</literal> limit, but ext4 lies to
|
||||
the kernel by reporting a link count of 1 if it exceeds the
|
||||
limit.)</para>
|
||||
|
||||
</section>
|
||||
16
doc/manual/troubleshooting/troubleshooting.xml
Normal file
16
doc/manual/troubleshooting/troubleshooting.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<appendix xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ch-troubleshooting">
|
||||
|
||||
<title>Troubleshooting</title>
|
||||
|
||||
<para>This section provides solutions for some common problems. See
|
||||
the <link xlink:href="https://github.com/NixOS/nix/issues">Nix bug
|
||||
tracker</link> for a list of currently known issues.</para>
|
||||
|
||||
<xi:include href="collisions-nixenv.xml" />
|
||||
<xi:include href="links-nix-store.xml" />
|
||||
|
||||
</appendix>
|
||||
10
local.mk
10
local.mk
@@ -1,14 +1,16 @@
|
||||
ifeq ($(MAKECMDGOALS), dist)
|
||||
dist-files += $(shell cat .dist-files)
|
||||
# Make sure we are in repo root with `--git-dir`
|
||||
dist-files += $(shell git --git-dir=.git ls-files || find * -type f)
|
||||
endif
|
||||
|
||||
dist-files += configure config.h.in nix.spec perl/configure
|
||||
dist-files += configure config.h.in nix.spec
|
||||
|
||||
clean-files += Makefile.config
|
||||
|
||||
GLOBAL_CXXFLAGS += -I . -I src -I src/libutil -I src/libstore -I src/libmain -I src/libexpr
|
||||
GLOBAL_CXXFLAGS += -I . -I src -I src/libutil -I src/libstore -I src/libmain -I src/libexpr \
|
||||
-Wno-unneeded-internal-declaration
|
||||
|
||||
$(foreach i, config.h $(call rwildcard, src/lib*, *.hh), \
|
||||
$(foreach i, config.h $(call rwildcard, src/lib*, *.hh) src/nix-store/serve-protocol.hh, \
|
||||
$(eval $(call install-file-in, $(i), $(includedir)/nix, 0644)))
|
||||
|
||||
$(foreach i, $(call rwildcard, src/boost, *.hpp), $(eval $(call install-file-in, $(i), $(includedir)/nix/$(patsubst src/%/,%,$(dir $(i))), 0644)))
|
||||
|
||||
@@ -83,7 +83,6 @@ downloadFile("tarball", "3"); # .tar.bz2
|
||||
my ($tarball, $tarballHash) = downloadFile("tarball", "4"); # .tar.xz
|
||||
my ($tarball_i686_linux, $tarball_i686_linux_hash) = downloadFile("binaryTarball.i686-linux", "1");
|
||||
my ($tarball_x86_64_linux, $tarball_x86_64_linux_hash) = downloadFile("binaryTarball.x86_64-linux", "1");
|
||||
my ($tarball_aarch64_linux, $tarball_aarch64_linux_hash) = downloadFile("binaryTarball.aarch64-linux", "1");
|
||||
my ($tarball_x86_64_darwin, $tarball_x86_64_darwin_hash) = downloadFile("binaryTarball.x86_64-darwin", "1");
|
||||
|
||||
# Update Nixpkgs in a very hacky way.
|
||||
@@ -112,7 +111,6 @@ 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");
|
||||
|
||||
@@ -146,7 +144,6 @@ write_file("$siteDir/nix-release.tt",
|
||||
"latestNixVersion = \"$version\"\n" .
|
||||
"nix_hash_i686_linux = \"$tarball_i686_linux_hash\"\n" .
|
||||
"nix_hash_x86_64_linux = \"$tarball_x86_64_linux_hash\"\n" .
|
||||
"nix_hash_aarch64_linux = \"$tarball_aarch64_linux_hash\"\n" .
|
||||
"nix_hash_x86_64_darwin = \"$tarball_x86_64_darwin_hash\"\n" .
|
||||
"-%]\n");
|
||||
|
||||
|
||||
@@ -1,26 +1,23 @@
|
||||
FROM alpine
|
||||
|
||||
# Enable HTTPS support in wget.
|
||||
RUN apk add --update openssl
|
||||
|
||||
# Download Nix and install it into the system.
|
||||
RUN wget -O- https://nixos.org/releases/nix/nix-1.11.14/nix-1.11.14-x86_64-linux.tar.bz2 | bzcat - | tar xf - \
|
||||
&& addgroup -g 30000 -S nixbld \
|
||||
&& for i in $(seq 1 30); do adduser -S -D -h /var/empty -g "Nix build user $i" -u $((30000 + i)) -G nixbld nixbld$i ; done \
|
||||
&& mkdir -m 0755 /nix && USER=root sh nix-*-x86_64-linux/install \
|
||||
&& ln -s /nix/var/nix/profiles/default/etc/profile.d/nix.sh /etc/profile.d/ \
|
||||
&& rm -r /nix-*-x86_64-linux \
|
||||
&& rm -r /var/cache/apk/*
|
||||
RUN wget -O- http://nixos.org/releases/nix/nix-1.11.2/nix-1.11.2-x86_64-linux.tar.bz2 | bzcat - | tar xf - \
|
||||
&& echo "nixbld:x:30000:nixbld1,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9,nixbld10,nixbld11,nixbld12,nixbld13,nixbld14,nixbld15,nixbld16,nixbld17,nixbld18,nixbld19,nixbld20,nixbld21,nixbld22,nixbld23,nixbld24,nixbld25,nixbld26,nixbld27,nixbld28,nixbld29,nixbld30" >> /etc/group \
|
||||
&& for i in $(seq 1 30); do echo "nixbld$i:x:$((30000 + $i)):30000:::" >> /etc/passwd; done \
|
||||
&& mkdir -m 0755 /nix && USER=root sh nix-*-x86_64-linux/install \
|
||||
&& echo ". /root/.nix-profile/etc/profile.d/nix.sh" >> /etc/profile \
|
||||
&& rm -r /nix-*-x86_64-linux \
|
||||
&& apk --update add bash tar \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
ONBUILD ENV \
|
||||
ENV=/etc/profile \
|
||||
PATH=/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
|
||||
GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt \
|
||||
NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt
|
||||
PATH=/root/.nix-profile/bin:/root/.nix-profile/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
|
||||
GIT_SSL_CAINFO=/root/.nix-profile/etc/ssl/certs/ca-bundle.crt \
|
||||
NIX_SSL_CERT_FILE=/root/.nix-profile/etc/ssl/certs/ca-bundle.crt
|
||||
|
||||
ENV \
|
||||
ENV=/etc/profile \
|
||||
PATH=/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
|
||||
GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt \
|
||||
NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt \
|
||||
NIX_PATH=/nix/var/nix/profiles/per-user/root/channels
|
||||
PATH=/root/.nix-profile/bin:/root/.nix-profile/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
|
||||
GIT_SSL_CAINFO=/root/.nix-profile/etc/ssl/certs/ca-bundle.crt \
|
||||
NIX_SSL_CERT_FILE=/root/.nix-profile/etc/ssl/certs/ca-bundle.crt \
|
||||
NIX_PATH=/nix/var/nix/profiles/per-user/root/channels/
|
||||
|
||||
10
misc/emacs/README
Normal file
10
misc/emacs/README
Normal file
@@ -0,0 +1,10 @@
|
||||
The Nix Emacs mode supports syntax highlighting, somewhat sensible
|
||||
indenting, and refilling of comments.
|
||||
|
||||
To enable Nix mode in Emacs, add something like this to your ~/.emacs
|
||||
file:
|
||||
|
||||
(load "/nix/share/emacs/site-lisp/nix-mode.el")
|
||||
|
||||
This automatically causes Nix mode to be activated for all files with
|
||||
extension `.nix'.
|
||||
1
misc/emacs/local.mk
Normal file
1
misc/emacs/local.mk
Normal file
@@ -0,0 +1 @@
|
||||
$(eval $(call install-data-in,$(d)/nix-mode.el,$(datadir)/emacs/site-lisp))
|
||||
177
misc/emacs/nix-mode.el
Normal file
177
misc/emacs/nix-mode.el
Normal file
@@ -0,0 +1,177 @@
|
||||
;;; nix-mode.el --- Major mode for editing Nix expressions
|
||||
|
||||
;; Author: Eelco Dolstra
|
||||
;; URL: https://github.com/NixOS/nix/tree/master/misc/emacs
|
||||
;; Version: 1.0
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defun nix-syntax-match-antiquote (limit)
|
||||
(let ((pos (next-single-char-property-change (point) 'nix-syntax-antiquote
|
||||
nil limit)))
|
||||
(when (and pos (> pos (point)))
|
||||
(goto-char pos)
|
||||
(let ((char (char-after pos)))
|
||||
(pcase char
|
||||
(`?$
|
||||
(forward-char 2))
|
||||
(`?}
|
||||
(forward-char 1)))
|
||||
(set-match-data (list pos (point)))
|
||||
t))))
|
||||
|
||||
(defconst nix-font-lock-keywords
|
||||
'("\\_<if\\_>" "\\_<then\\_>" "\\_<else\\_>" "\\_<assert\\_>" "\\_<with\\_>"
|
||||
"\\_<let\\_>" "\\_<in\\_>" "\\_<rec\\_>" "\\_<inherit\\_>" "\\_<or\\_>"
|
||||
("\\_<true\\_>" . font-lock-builtin-face)
|
||||
("\\_<false\\_>" . font-lock-builtin-face)
|
||||
("\\_<null\\_>" . font-lock-builtin-face)
|
||||
("\\_<import\\_>" . font-lock-builtin-face)
|
||||
("\\_<derivation\\_>" . font-lock-builtin-face)
|
||||
("\\_<baseNameOf\\_>" . font-lock-builtin-face)
|
||||
("\\_<toString\\_>" . font-lock-builtin-face)
|
||||
("\\_<isNull\\_>" . font-lock-builtin-face)
|
||||
("[a-zA-Z][a-zA-Z0-9\\+-\\.]*:[a-zA-Z0-9%/\\?:@&=\\+\\$,_\\.!~\\*'-]+"
|
||||
. font-lock-constant-face)
|
||||
("\\<\\([a-zA-Z_][a-zA-Z0-9_'\-\.]*\\)[ \t]*="
|
||||
(1 font-lock-variable-name-face nil nil))
|
||||
("<[a-zA-Z0-9._\\+-]+\\(/[a-zA-Z0-9._\\+-]+\\)*>"
|
||||
. font-lock-constant-face)
|
||||
("[a-zA-Z0-9._\\+-]*\\(/[a-zA-Z0-9._\\+-]+\\)+"
|
||||
. font-lock-constant-face)
|
||||
(nix-syntax-match-antiquote 0 font-lock-preprocessor-face t))
|
||||
"Font lock keywords for nix.")
|
||||
|
||||
(defvar nix-mode-syntax-table
|
||||
(let ((table (make-syntax-table)))
|
||||
(modify-syntax-entry ?/ ". 14" table)
|
||||
(modify-syntax-entry ?* ". 23" table)
|
||||
(modify-syntax-entry ?# "< b" table)
|
||||
(modify-syntax-entry ?\n "> b" table)
|
||||
table)
|
||||
"Syntax table for Nix mode.")
|
||||
|
||||
(defun nix-syntax-propertize-escaped-antiquote ()
|
||||
"Set syntax properies for escaped antiquote marks."
|
||||
nil)
|
||||
|
||||
(defun nix-syntax-propertize-multiline-string ()
|
||||
"Set syntax properies for multiline string delimiters."
|
||||
(let* ((start (match-beginning 0))
|
||||
(end (match-end 0))
|
||||
(context (save-excursion (save-match-data (syntax-ppss start))))
|
||||
(string-type (nth 3 context)))
|
||||
(pcase string-type
|
||||
(`t
|
||||
;; inside a multiline string
|
||||
;; ending multi-line string delimiter
|
||||
(put-text-property (1- end) end
|
||||
'syntax-table (string-to-syntax "|")))
|
||||
(`nil
|
||||
;; beginning multi-line string delimiter
|
||||
(put-text-property start (1+ start)
|
||||
'syntax-table (string-to-syntax "|"))))))
|
||||
|
||||
(defun nix-syntax-propertize-antiquote ()
|
||||
"Set syntax properties for antiquote marks."
|
||||
(let* ((start (match-beginning 0)))
|
||||
(put-text-property start (1+ start)
|
||||
'syntax-table (string-to-syntax "|"))
|
||||
(put-text-property start (+ start 2)
|
||||
'nix-syntax-antiquote t)))
|
||||
|
||||
(defun nix-syntax-propertize-close-brace ()
|
||||
"Set syntax properties for close braces.
|
||||
If a close brace `}' ends an antiquote, the next character begins a string."
|
||||
(let* ((start (match-beginning 0))
|
||||
(end (match-end 0))
|
||||
(context (save-excursion (save-match-data (syntax-ppss start))))
|
||||
(open (nth 1 context)))
|
||||
(when open ;; a corresponding open-brace was found
|
||||
(let* ((antiquote (get-text-property open 'nix-syntax-antiquote)))
|
||||
(when antiquote
|
||||
(put-text-property (+ start 1) (+ start 2)
|
||||
'syntax-table (string-to-syntax "|"))
|
||||
(put-text-property start (1+ start)
|
||||
'nix-syntax-antiquote t))))))
|
||||
|
||||
(defun nix-syntax-propertize (start end)
|
||||
"Special syntax properties for Nix."
|
||||
;; search for multi-line string delimiters
|
||||
(goto-char start)
|
||||
(remove-text-properties start end '(syntax-table nil nix-syntax-antiquote nil))
|
||||
(funcall
|
||||
(syntax-propertize-rules
|
||||
("''\\${"
|
||||
(0 (ignore (nix-syntax-propertize-escaped-antiquote))))
|
||||
("''"
|
||||
(0 (ignore (nix-syntax-propertize-multiline-string))))
|
||||
("\\${"
|
||||
(0 (ignore (nix-syntax-propertize-antiquote))))
|
||||
("}"
|
||||
(0 (ignore (nix-syntax-propertize-close-brace)))))
|
||||
start end))
|
||||
|
||||
(defun nix-indent-line ()
|
||||
"Indent current line in a Nix expression."
|
||||
(interactive)
|
||||
(indent-relative-maybe))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode nix-mode prog-mode "Nix"
|
||||
"Major mode for editing Nix expressions.
|
||||
|
||||
The following commands may be useful:
|
||||
|
||||
'\\[newline-and-indent]'
|
||||
Insert a newline and move the cursor to align with the previous
|
||||
non-empty line.
|
||||
|
||||
'\\[fill-paragraph]'
|
||||
Refill a paragraph so that all lines are at most `fill-column'
|
||||
lines long. This should do the right thing for comments beginning
|
||||
with `#'. However, this command doesn't work properly yet if the
|
||||
comment is adjacent to code (i.e., no intervening empty lines).
|
||||
In that case, select the text to be refilled and use
|
||||
`\\[fill-region]' instead.
|
||||
|
||||
The hook `nix-mode-hook' is run when Nix mode is started.
|
||||
|
||||
\\{nix-mode-map}
|
||||
"
|
||||
(set-syntax-table nix-mode-syntax-table)
|
||||
|
||||
;; Font lock support.
|
||||
(setq-local font-lock-defaults '(nix-font-lock-keywords nil nil nil nil))
|
||||
|
||||
;; Special syntax properties for Nix
|
||||
(setq-local syntax-propertize-function 'nix-syntax-propertize)
|
||||
|
||||
;; Look at text properties when parsing
|
||||
(setq-local parse-sexp-lookup-properties t)
|
||||
|
||||
;; Automatic indentation [C-j].
|
||||
(set (make-local-variable 'indent-line-function) 'nix-indent-line)
|
||||
|
||||
;; Indenting of comments.
|
||||
(set (make-local-variable 'comment-start) "# ")
|
||||
(set (make-local-variable 'comment-end) "")
|
||||
(set (make-local-variable 'comment-start-skip) "\\(^\\|\\s-\\);?#+ *")
|
||||
|
||||
;; Filling of comments.
|
||||
(set (make-local-variable 'adaptive-fill-mode) t)
|
||||
(set (make-local-variable 'paragraph-start) "[ \t]*\\(#+[ \t]*\\)?$")
|
||||
(set (make-local-variable 'paragraph-separate) paragraph-start))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(progn
|
||||
(add-to-list 'auto-mode-alist '("\\.nix\\'" . nix-mode))
|
||||
(add-to-list 'auto-mode-alist '("\\.nix.in\\'" . nix-mode)))
|
||||
|
||||
(provide 'nix-mode)
|
||||
|
||||
;;; nix-mode.el ends here
|
||||
@@ -12,5 +12,10 @@
|
||||
<string>/var/log/nix-daemon.log</string>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/dev/null</string>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>NIX_SSL_CERT_FILE</key>
|
||||
<string>/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -7,3 +7,4 @@ ConditionPathIsReadWrite=@localstatedir@/nix/daemon-socket
|
||||
[Service]
|
||||
ExecStart=@@bindir@/nix-daemon nix-daemon --daemon
|
||||
KillMode=process
|
||||
Environment=XDG_CACHE_HOME=/root/.cache
|
||||
|
||||
@@ -53,8 +53,8 @@ BUILD_SHARED_LIBS ?= 1
|
||||
|
||||
ifeq ($(BUILD_SHARED_LIBS), 1)
|
||||
ifeq (CYGWIN,$(findstring CYGWIN,$(OS)))
|
||||
GLOBAL_CFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE
|
||||
GLOBAL_CXXFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE
|
||||
GLOBAL_CFLAGS += -U__STRICT_ANSI__
|
||||
GLOBAL_CXXFLAGS += -U__STRICT_ANSI__
|
||||
else
|
||||
GLOBAL_CFLAGS += -fPIC
|
||||
GLOBAL_CXXFLAGS += -fPIC
|
||||
|
||||
@@ -45,11 +45,6 @@ endif
|
||||
# - $(1)_INSTALL_DIR: the directory where the library will be
|
||||
# installed. Defaults to $(libdir).
|
||||
#
|
||||
# - $(1)_EXCLUDE_FROM_LIBRARY_LIST: if defined, the library will not
|
||||
# be automatically marked as a dependency of the top-level all
|
||||
# target andwill not be listed in the make help output. This is
|
||||
# useful for libraries built solely for testing, for example.
|
||||
#
|
||||
# - BUILD_SHARED_LIBS: if equal to ‘1’, a dynamic library will be
|
||||
# built, otherwise a static library.
|
||||
define build-library
|
||||
@@ -154,9 +149,7 @@ define build-library
|
||||
$(1)_DEPS := $$(foreach fn, $$($(1)_OBJS), $$(call filename-to-dep, $$(fn)))
|
||||
-include $$($(1)_DEPS)
|
||||
|
||||
ifndef $(1)_EXCLUDE_FROM_LIBRARY_LIST
|
||||
libs-list += $$($(1)_PATH)
|
||||
endif
|
||||
clean-files += $$(_d)/*.a $$(_d)/*.$(SO_EXT) $$(_d)/*.o $$(_d)/.*.dep $$($(1)_DEPS) $$($(1)_OBJS)
|
||||
dist-files += $$(_srcs)
|
||||
endef
|
||||
|
||||
31
mk/tests.mk
31
mk/tests.mk
@@ -7,39 +7,20 @@ define run-install-test
|
||||
|
||||
endef
|
||||
|
||||
# Color code from https://unix.stackexchange.com/a/10065
|
||||
installcheck:
|
||||
@total=0; failed=0; \
|
||||
red=""; \
|
||||
green=""; \
|
||||
yellow=""; \
|
||||
normal=""; \
|
||||
if [ -t 1 ]; then \
|
||||
red="[31;1m"; \
|
||||
green="[32;1m"; \
|
||||
yellow="[33;1m"; \
|
||||
normal="[m"; \
|
||||
fi; \
|
||||
for i in $(_installcheck-list); do \
|
||||
@total=0; failed=0; for i in $(_installcheck-list); do \
|
||||
total=$$((total + 1)); \
|
||||
printf "running test $$i..."; \
|
||||
log="$$(cd $$(dirname $$i) && $(tests-environment) $$(basename $$i) 2>&1)"; \
|
||||
status=$$?; \
|
||||
if [ $$status -eq 0 ]; then \
|
||||
echo " [$${green}PASS$$normal]"; \
|
||||
elif [ $$status -eq 99 ]; then \
|
||||
echo " [$${yellow}SKIP$$normal]"; \
|
||||
echo "running test $$i"; \
|
||||
if (cd $$(dirname $$i) && $(tests-environment) $$(basename $$i)); then \
|
||||
echo "PASS: $$i"; \
|
||||
else \
|
||||
echo " [$${red}FAIL$$normal]"; \
|
||||
echo "$$log" | sed 's/^/ /'; \
|
||||
echo "FAIL: $$i"; \
|
||||
failed=$$((failed + 1)); \
|
||||
fi; \
|
||||
done; \
|
||||
if [ "$$failed" != 0 ]; then \
|
||||
echo "$${red}$$failed out of $$total tests failed $$normal"; \
|
||||
echo "$$failed out of $$total tests failed "; \
|
||||
exit 1; \
|
||||
else \
|
||||
echo "$${green}All tests succeeded$$normal"; \
|
||||
fi
|
||||
|
||||
.PHONY: check installcheck
|
||||
|
||||
58
nix.spec.in
58
nix.spec.in
@@ -1,5 +1,3 @@
|
||||
%undefine _hardened_build
|
||||
|
||||
%global nixbld_user "nix-builder-"
|
||||
%global nixbld_group "nixbld"
|
||||
|
||||
@@ -16,15 +14,18 @@ Source0: %{name}-%{version}.tar.bz2
|
||||
%if 0%{?el5}
|
||||
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||
%endif
|
||||
BuildRequires: perl(DBD::SQLite)
|
||||
BuildRequires: perl(DBI)
|
||||
BuildRequires: perl(ExtUtils::ParseXS)
|
||||
Requires: /usr/bin/perl
|
||||
Requires: curl
|
||||
Requires: perl-DBD-SQLite
|
||||
Requires: bzip2
|
||||
Requires: gzip
|
||||
Requires: xz
|
||||
Requires: libseccomp
|
||||
BuildRequires: bzip2-devel
|
||||
BuildRequires: sqlite-devel
|
||||
BuildRequires: libcurl-devel
|
||||
BuildRequires: libseccomp-devel
|
||||
|
||||
# Hack to make that shitty RPM scanning hack shut up.
|
||||
Provides: perl(Nix::SSH)
|
||||
@@ -60,8 +61,40 @@ Requires: %{name} = %{version}-%{release}
|
||||
%description doc
|
||||
The %{name}-doc package contains documentation files for %{name}.
|
||||
|
||||
|
||||
%package -n emacs-%{name}
|
||||
Summary: Nix mode for Emacs
|
||||
%if 0%{?rhel} && 0%{?rhel} < 7
|
||||
Group: Applications/Editors
|
||||
%endif
|
||||
BuildArch: noarch
|
||||
BuildRequires: emacs
|
||||
Requires: emacs(bin) >= %{_emacs_version}
|
||||
|
||||
%description -n emacs-%{name}
|
||||
This package provides a major mode for editing Nix expressions.
|
||||
|
||||
%package -n emacs-%{name}-el
|
||||
Summary: Elisp source files for emacs-%{name}
|
||||
%if 0%{?rhel} && 0%{?rhel} < 7
|
||||
Group: Applications/Editors
|
||||
%endif
|
||||
BuildArch: noarch
|
||||
Requires: emacs-%{name} = %{version}-%{release}
|
||||
|
||||
%description -n emacs-%{name}-el
|
||||
This package contains the elisp source file for the Nix major mode for
|
||||
GNU Emacs. You do not need to install this package to run Nix. Install
|
||||
the emacs-%{name} package to edit Nix expressions with GNU Emacs.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
# Install Perl modules to vendor_perl
|
||||
# configure.ac need to be changed to make this global; however, this will
|
||||
# also affect NixOS. Use discretion.
|
||||
%{__sed} -i 's|perl5/site_perl/$perlversion/$perlarchname|perl5/vendor_perl|' \
|
||||
configure
|
||||
|
||||
|
||||
%build
|
||||
@@ -72,7 +105,8 @@ extraFlags=
|
||||
%configure --localstatedir=/nix/var \
|
||||
--docdir=%{_defaultdocdir}/%{name}-doc-%{version} \
|
||||
$extraFlags
|
||||
make -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES
|
||||
make %{?_smp_flags}
|
||||
%{_emacs_bytecompile} misc/emacs/nix-mode.el
|
||||
|
||||
|
||||
%install
|
||||
@@ -98,6 +132,9 @@ done
|
||||
# (until this is fixed in the relevant Makefile)
|
||||
chmod -x $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/nix.sh
|
||||
|
||||
# Copy the byte-compiled mode file by hand
|
||||
cp -p misc/emacs/nix-mode.elc $RPM_BUILD_ROOT%{_emacs_sitelispdir}/
|
||||
|
||||
# we ship this file in the base package
|
||||
rm -f $RPM_BUILD_ROOT%{_defaultdocdir}/%{name}-doc-%{version}/README
|
||||
|
||||
@@ -130,17 +167,19 @@ systemctl start nix-daemon.socket
|
||||
%files
|
||||
%{_bindir}/nix*
|
||||
%{_libdir}/*.so
|
||||
%{perl_vendorarch}/*
|
||||
%exclude %dir %{perl_vendorarch}/auto/
|
||||
%{_prefix}/libexec/*
|
||||
%if ! 0%{?rhel} || 0%{?rhel} >= 7
|
||||
%{_prefix}/lib/systemd/system/nix-daemon.socket
|
||||
%{_prefix}/lib/systemd/system/nix-daemon.service
|
||||
%endif
|
||||
%{_datadir}/emacs/site-lisp/nix-mode.el
|
||||
%{_datadir}/nix
|
||||
%{_mandir}/man1/*.1*
|
||||
%{_mandir}/man5/*.5*
|
||||
%{_mandir}/man8/*.8*
|
||||
%config(noreplace) %{_sysconfdir}/profile.d/nix.sh
|
||||
%config(noreplace) %{_sysconfdir}/profile.d/nix-daemon.sh
|
||||
/nix
|
||||
|
||||
%files devel
|
||||
@@ -150,3 +189,10 @@ systemctl start nix-daemon.socket
|
||||
%files doc
|
||||
%docdir %{_defaultdocdir}/%{name}-doc-%{version}
|
||||
%{_defaultdocdir}/%{name}-doc-%{version}
|
||||
|
||||
%files -n emacs-%{name}
|
||||
%{_emacs_sitelispdir}/*.elc
|
||||
#{_emacs_sitestartdir}/*.el
|
||||
|
||||
%files -n emacs-%{name}-el
|
||||
%{_emacs_sitelispdir}/*.el
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
makefiles = local.mk
|
||||
|
||||
GLOBAL_CXXFLAGS += -std=c++14 -g -Wall
|
||||
|
||||
-include Makefile.config
|
||||
|
||||
OPTIMIZE = 1
|
||||
|
||||
ifeq ($(OPTIMIZE), 1)
|
||||
GLOBAL_CFLAGS += -O3
|
||||
GLOBAL_CXXFLAGS += -O3
|
||||
endif
|
||||
|
||||
include mk/lib.mk
|
||||
@@ -1,18 +0,0 @@
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
HAVE_SODIUM = @HAVE_SODIUM@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
SODIUM_LIBS = @SODIUM_LIBS@
|
||||
NIX_CFLAGS = @NIX_CFLAGS@
|
||||
NIX_LIBS = @NIX_LIBS@
|
||||
nixbindir = @nixbindir@
|
||||
curl = @curl@
|
||||
nixlibexecdir = @nixlibexecdir@
|
||||
nixlocalstatedir = @nixlocalstatedir@
|
||||
perl = @perl@
|
||||
perllibdir = @perllibdir@
|
||||
nixstoredir = @nixstoredir@
|
||||
nixsysconfdir = @nixsysconfdir@
|
||||
@@ -1,99 +0,0 @@
|
||||
AC_INIT(nix-perl, m4_esyscmd([bash -c "echo -n $(cat ../version)$VERSION_SUFFIX"]))
|
||||
AC_CONFIG_SRCDIR(MANIFEST)
|
||||
AC_CONFIG_AUX_DIR(../config)
|
||||
|
||||
CFLAGS=
|
||||
CXXFLAGS=
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AX_CXX_COMPILE_STDCXX_11
|
||||
|
||||
# Use 64-bit file system calls so that we can support files > 2 GiB.
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
AC_DEFUN([NEED_PROG],
|
||||
[
|
||||
AC_PATH_PROG($1, $2)
|
||||
if test -z "$$1"; then
|
||||
AC_MSG_ERROR([$2 is required])
|
||||
fi
|
||||
])
|
||||
|
||||
NEED_PROG(perl, perl)
|
||||
NEED_PROG(curl, curl)
|
||||
NEED_PROG(bzip2, bzip2)
|
||||
NEED_PROG(xz, xz)
|
||||
|
||||
# Test that Perl has the open/fork feature (Perl 5.8.0 and beyond).
|
||||
AC_MSG_CHECKING([whether Perl is recent enough])
|
||||
if ! $perl -e 'open(FOO, "-|", "true"); while (<FOO>) { print; }; close FOO or die;'; then
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([Your Perl version is too old. Nix requires Perl 5.8.0 or newer.])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
|
||||
# Figure out where to install Perl modules.
|
||||
AC_MSG_CHECKING([for the Perl installation prefix])
|
||||
perlversion=$($perl -e 'use Config; print $Config{version};')
|
||||
perlarchname=$($perl -e 'use Config; print $Config{archname};')
|
||||
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])
|
||||
|
||||
# Check for the required Perl dependencies (DBI and DBD::SQLite).
|
||||
perlFlags="-I$perllibdir"
|
||||
|
||||
AC_ARG_WITH(dbi, AC_HELP_STRING([--with-dbi=PATH],
|
||||
[prefix of the Perl DBI library]),
|
||||
perlFlags="$perlFlags -I$withval")
|
||||
|
||||
AC_ARG_WITH(dbd-sqlite, AC_HELP_STRING([--with-dbd-sqlite=PATH],
|
||||
[prefix of the Perl DBD::SQLite library]),
|
||||
perlFlags="$perlFlags -I$withval")
|
||||
|
||||
AC_MSG_CHECKING([whether DBD::SQLite works])
|
||||
if ! $perl $perlFlags -e 'use DBI; use DBD::SQLite;' 2>&5; then
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_FAILURE([The Perl modules DBI and/or DBD::SQLite are missing.])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
AC_SUBST(perlFlags)
|
||||
|
||||
PKG_CHECK_MODULES([NIX], [nix-store])
|
||||
|
||||
NEED_PROG([NIX_INSTANTIATE_PROGRAM], [nix-instantiate])
|
||||
|
||||
# Get nix configure values
|
||||
nixbindir=$("$NIX_INSTANTIATE_PROGRAM" --eval '<nix/config.nix>' -A nixBinDir | tr -d \")
|
||||
nixlibexecdir=$("$NIX_INSTANTIATE_PROGRAM" --eval '<nix/config.nix>' -A nixLibexecDir | tr -d \")
|
||||
nixlocalstatedir=$("$NIX_INSTANTIATE_PROGRAM" --eval '<nix/config.nix>' -A nixLocalstateDir | tr -d \")
|
||||
nixsysconfdir=$("$NIX_INSTANTIATE_PROGRAM" --eval '<nix/config.nix>' -A nixSysconfDir | tr -d \")
|
||||
nixstoredir=$("$NIX_INSTANTIATE_PROGRAM" --eval '<nix/config.nix>' -A nixStoreDir | tr -d \")
|
||||
AC_SUBST(nixbindir)
|
||||
AC_SUBST(nixlibexecdir)
|
||||
AC_SUBST(nixlocalstatedir)
|
||||
AC_SUBST(nixsysconfdir)
|
||||
AC_SUBST(nixstoredir)
|
||||
|
||||
# Expand all variables in config.status.
|
||||
test "$prefix" = NONE && prefix=$ac_default_prefix
|
||||
test "$exec_prefix" = NONE && exec_prefix='${prefix}'
|
||||
for name in $ac_subst_vars; do
|
||||
declare $name="$(eval echo "${!name}")"
|
||||
declare $name="$(eval echo "${!name}")"
|
||||
declare $name="$(eval echo "${!name}")"
|
||||
done
|
||||
|
||||
rm -f Makefile.config
|
||||
ln -sfn ../mk mk
|
||||
|
||||
AC_CONFIG_FILES([])
|
||||
AC_OUTPUT
|
||||
@@ -4,31 +4,48 @@ use MIME::Base64;
|
||||
|
||||
$version = "@PACKAGE_VERSION@";
|
||||
|
||||
$binDir = $ENV{"NIX_BIN_DIR"} || "@nixbindir@";
|
||||
$libexecDir = $ENV{"NIX_LIBEXEC_DIR"} || "@nixlibexecdir@";
|
||||
$stateDir = $ENV{"NIX_STATE_DIR"} || "@nixlocalstatedir@/nix";
|
||||
$logDir = $ENV{"NIX_LOG_DIR"} || "@nixlocalstatedir@/log/nix";
|
||||
$confDir = $ENV{"NIX_CONF_DIR"} || "@nixsysconfdir@/nix";
|
||||
$storeDir = $ENV{"NIX_STORE_DIR"} || "@nixstoredir@";
|
||||
$binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
$libexecDir = $ENV{"NIX_LIBEXEC_DIR"} || "@libexecdir@";
|
||||
$stateDir = $ENV{"NIX_STATE_DIR"} || "@localstatedir@/nix";
|
||||
$logDir = $ENV{"NIX_LOG_DIR"} || "@localstatedir@/log/nix";
|
||||
$confDir = $ENV{"NIX_CONF_DIR"} || "@sysconfdir@/nix";
|
||||
$storeDir = $ENV{"NIX_STORE_DIR"} || "@storedir@";
|
||||
|
||||
$bzip2 = "@bzip2@";
|
||||
$xz = "@xz@";
|
||||
$curl = "@curl@";
|
||||
|
||||
$useBindings = 1;
|
||||
$useBindings = "@perlbindings@" eq "yes";
|
||||
|
||||
%config = ();
|
||||
|
||||
sub readConfig {
|
||||
my $config = "$confDir/nix.conf";
|
||||
return unless -f $config;
|
||||
%binaryCachePublicKeys = ();
|
||||
|
||||
open CONFIG, "<$config" or die "cannot open '$config'";
|
||||
while (<CONFIG>) {
|
||||
/^\s*([\w\-\.]+)\s*=\s*(.*)$/ or next;
|
||||
$config{$1} = $2;
|
||||
$defaultPublicKeys = "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=";
|
||||
|
||||
sub readConfig {
|
||||
if (defined $ENV{'_NIX_OPTIONS'}) {
|
||||
foreach my $s (split '\n', $ENV{'_NIX_OPTIONS'}) {
|
||||
my ($n, $v) = split '=', $s, 2;
|
||||
$config{$n} = $v;
|
||||
}
|
||||
} else {
|
||||
my $config = "$confDir/nix.conf";
|
||||
return unless -f $config;
|
||||
|
||||
open CONFIG, "<$config" or die "cannot open ‘$config’";
|
||||
while (<CONFIG>) {
|
||||
/^\s*([\w\-\.]+)\s*=\s*(.*)$/ or next;
|
||||
$config{$1} = $2;
|
||||
}
|
||||
close CONFIG;
|
||||
}
|
||||
|
||||
foreach my $s (split(/ /, $config{"binary-cache-public-keys"} // $defaultPublicKeys)) {
|
||||
my ($keyName, $publicKey) = split ":", $s;
|
||||
next unless defined $keyName && defined $publicKey;
|
||||
$binaryCachePublicKeys{$keyName} = decode_base64($publicKey);
|
||||
}
|
||||
close CONFIG;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -35,14 +35,14 @@ sub copyToOpen {
|
||||
my $missingSize = 0;
|
||||
$missingSize += (queryPathInfo($_, 1))[3] foreach @missing;
|
||||
|
||||
printf STDERR "copying %d missing paths (%.2f MiB) to '$sshHost'...\n",
|
||||
printf STDERR "copying %d missing paths (%.2f MiB) to ‘$sshHost’...\n",
|
||||
scalar(@missing), $missingSize / (1024**2);
|
||||
return if $dryRun;
|
||||
|
||||
# Send the "import paths" command.
|
||||
syswrite($to, pack("L<x4", 4)) or die;
|
||||
exportPaths(fileno($to), @missing);
|
||||
readInt($from) == 1 or die "remote machine '$sshHost' failed to import closure\n";
|
||||
readInt($from) == 1 or die "remote machine ‘$sshHost’ failed to import closure\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -60,10 +60,10 @@ sub readManifest_ {
|
||||
# Decompress the manifest if necessary.
|
||||
if ($manifest =~ /\.bz2$/) {
|
||||
open MANIFEST, "$Nix::Config::bzip2 -d < $manifest |"
|
||||
or die "cannot decompress '$manifest': $!";
|
||||
or die "cannot decompress ‘$manifest’: $!";
|
||||
} else {
|
||||
open MANIFEST, "<$manifest"
|
||||
or die "cannot open '$manifest': $!";
|
||||
or die "cannot open ‘$manifest’: $!";
|
||||
}
|
||||
|
||||
my $inside = 0;
|
||||
@@ -287,7 +287,7 @@ sub parseNARInfo {
|
||||
# FIXME: might be useful to support multiple signatures per .narinfo.
|
||||
|
||||
if (!defined $sig) {
|
||||
warn "NAR info file '$location' lacks a signature; ignoring\n";
|
||||
warn "NAR info file ‘$location’ lacks a signature; ignoring\n";
|
||||
return undef;
|
||||
}
|
||||
my ($keyName, $sig64) = split ":", $sig;
|
||||
@@ -295,7 +295,7 @@ sub parseNARInfo {
|
||||
|
||||
my $publicKey = $Nix::Config::binaryCachePublicKeys{$keyName};
|
||||
if (!defined $publicKey) {
|
||||
warn "NAR info file '$location' is signed by unknown key '$keyName'; ignoring\n";
|
||||
warn "NAR info file ‘$location’ is signed by unknown key ‘$keyName’; ignoring\n";
|
||||
return undef;
|
||||
}
|
||||
|
||||
@@ -306,12 +306,12 @@ sub parseNARInfo {
|
||||
[ map { "$Nix::Config::storeDir/$_" } @refs ]);
|
||||
};
|
||||
if ($@) {
|
||||
warn "cannot compute fingerprint of '$location'; ignoring\n";
|
||||
warn "cannot compute fingerprint of ‘$location’; ignoring\n";
|
||||
return undef;
|
||||
}
|
||||
|
||||
if (!checkSignature($publicKey, decode_base64($sig64), $fingerprint)) {
|
||||
warn "NAR info file '$location' has an incorrect signature; ignoring\n";
|
||||
warn "NAR info file ‘$location’ has an incorrect signature; ignoring\n";
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ sub connectToRemoteNix {
|
||||
syswrite($to, pack("L<x4L<x4", $SERVE_MAGIC_1, $clientVersion)) or die;
|
||||
$magic = readInt($from);
|
||||
};
|
||||
die "unable to connect to '$sshHost'\n" if $@;
|
||||
die "unable to connect to ‘$sshHost’\n" if $@;
|
||||
die "did not get valid handshake from remote host\n" if $magic != 0x5452eecb;
|
||||
|
||||
my $serverVersion = readInt($from);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "EXTERN.h"
|
||||
#include "perl.h"
|
||||
#include "XSUB.h"
|
||||
@@ -27,7 +25,10 @@ static ref<Store> store()
|
||||
static std::shared_ptr<Store> _store;
|
||||
if (!_store) {
|
||||
try {
|
||||
logger = makeDefaultLogger();
|
||||
settings.processEnvironment();
|
||||
settings.loadConfFile();
|
||||
settings.update();
|
||||
settings.lockCPU = false;
|
||||
_store = openStore();
|
||||
} catch (Error & e) {
|
||||
@@ -81,7 +82,8 @@ SV * queryReferences(char * path)
|
||||
SV * queryPathHash(char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
auto s = store()->queryPathInfo(path)->narHash.to_string();
|
||||
auto hash = store()->queryPathInfo(path)->narHash;
|
||||
string s = "sha256:" + printHash32(hash);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
@@ -107,7 +109,7 @@ SV * queryPathInfo(char * path, int base32)
|
||||
XPUSHs(&PL_sv_undef);
|
||||
else
|
||||
XPUSHs(sv_2mortal(newSVpv(info->deriver.c_str(), 0)));
|
||||
auto s = info->narHash.to_string(base32 ? Base32 : Base16);
|
||||
string s = "sha256:" + (base32 ? printHash32(info->narHash) : printHash(info->narHash));
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
mXPUSHi(info->registrationTime);
|
||||
mXPUSHi(info->narSize);
|
||||
@@ -183,7 +185,7 @@ void importPaths(int fd, int dontCheckSigs)
|
||||
PPCODE:
|
||||
try {
|
||||
FdSource source(fd);
|
||||
store()->importPaths(source, nullptr, dontCheckSigs ? NoCheckSigs : CheckSigs);
|
||||
store()->importPaths(source, 0, dontCheckSigs);
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
}
|
||||
@@ -193,7 +195,7 @@ SV * hashPath(char * algo, int base32, char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h = hashPath(parseHashType(algo), path).first;
|
||||
auto s = h.to_string(base32 ? Base32 : Base16, false);
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
@@ -204,7 +206,7 @@ SV * hashFile(char * algo, int base32, char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h = hashFile(parseHashType(algo), path);
|
||||
auto s = h.to_string(base32 ? Base32 : Base16, false);
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
@@ -215,7 +217,7 @@ SV * hashString(char * algo, int base32, char * s)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h = hashString(parseHashType(algo), s);
|
||||
auto s = h.to_string(base32 ? Base32 : Base16, false);
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
@@ -225,8 +227,8 @@ SV * hashString(char * algo, int base32, char * s)
|
||||
SV * convertHash(char * algo, char * s, int toBase32)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h(s, parseHashType(algo));
|
||||
string s = h.to_string(toBase32 ? Base32 : Base16, false);
|
||||
Hash h = parseHash16or32(parseHashType(algo), s);
|
||||
string s = toBase32 ? printHash32(h) : printHash(h);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
@@ -285,7 +287,8 @@ SV * addToStore(char * srcPath, int recursive, char * algo)
|
||||
SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h(hash, parseHashType(algo));
|
||||
HashType ht = parseHashType(algo);
|
||||
Hash h = parseHash16or32(ht, hash);
|
||||
Path path = store()->makeFixedOutputPath(recursive, h, name);
|
||||
XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
|
||||
@@ -10,7 +10,7 @@ $urlRE = "(?: [a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!
|
||||
|
||||
sub checkURL {
|
||||
my ($url) = @_;
|
||||
die "invalid URL '$url'\n" unless $url =~ /^ $urlRE $ /x;
|
||||
die "invalid URL ‘$url’\n" unless $url =~ /^ $urlRE $ /x;
|
||||
}
|
||||
|
||||
sub uniq {
|
||||
@@ -26,7 +26,7 @@ sub uniq {
|
||||
|
||||
sub writeFile {
|
||||
my ($fn, $s) = @_;
|
||||
open TMP, ">$fn" or die "cannot create file '$fn': $!";
|
||||
open TMP, ">$fn" or die "cannot create file ‘$fn’: $!";
|
||||
print TMP "$s" or die;
|
||||
close TMP or die;
|
||||
}
|
||||
@@ -34,7 +34,7 @@ sub writeFile {
|
||||
sub readFile {
|
||||
local $/ = undef;
|
||||
my ($fn) = @_;
|
||||
open TMP, "<$fn" or die "cannot open file '$fn': $!";
|
||||
open TMP, "<$fn" or die "cannot open file ‘$fn’: $!";
|
||||
my $s = <TMP>;
|
||||
close TMP or die;
|
||||
return $s;
|
||||
|
||||
@@ -1,43 +1,48 @@
|
||||
nix_perl_sources := \
|
||||
lib/Nix/Store.pm \
|
||||
lib/Nix/Manifest.pm \
|
||||
lib/Nix/SSH.pm \
|
||||
lib/Nix/CopyClosure.pm \
|
||||
lib/Nix/Config.pm.in \
|
||||
lib/Nix/Utils.pm
|
||||
$(d)/lib/Nix/Store.pm \
|
||||
$(d)/lib/Nix/Manifest.pm \
|
||||
$(d)/lib/Nix/SSH.pm \
|
||||
$(d)/lib/Nix/CopyClosure.pm \
|
||||
$(d)/lib/Nix/Config.pm.in \
|
||||
$(d)/lib/Nix/Utils.pm
|
||||
|
||||
nix_perl_modules := $(nix_perl_sources:.in=)
|
||||
|
||||
$(foreach x, $(nix_perl_modules), $(eval $(call install-data-in, $(x), $(perllibdir)/Nix)))
|
||||
|
||||
lib/Nix/Store.cc: lib/Nix/Store.xs
|
||||
ifeq ($(perlbindings), yes)
|
||||
|
||||
$(d)/lib/Nix/Store.cc: $(d)/lib/Nix/Store.xs
|
||||
$(trace-gen) xsubpp $^ -output $@
|
||||
|
||||
libraries += Store
|
||||
libraries += Store
|
||||
|
||||
Store_DIR := lib/Nix
|
||||
Store_DIR := $(d)/lib/Nix
|
||||
|
||||
Store_SOURCES := $(Store_DIR)/Store.cc
|
||||
Store_SOURCES := $(Store_DIR)/Store.cc
|
||||
|
||||
Store_CXXFLAGS = \
|
||||
$(NIX_CFLAGS) \
|
||||
-I$(shell perl -e 'use Config; print $$Config{archlibexp};')/CORE \
|
||||
-D_FILE_OFFSET_BITS=64 \
|
||||
-Wno-unknown-warning-option -Wno-unused-variable -Wno-literal-suffix \
|
||||
-Wno-reserved-user-defined-literal -Wno-duplicate-decl-specifier -Wno-pointer-bool-conversion
|
||||
Store_CXXFLAGS = \
|
||||
-I$(shell $(perl) -e 'use Config; print $$Config{archlibexp};')/CORE \
|
||||
-D_FILE_OFFSET_BITS=64 \
|
||||
-Wno-unknown-warning-option -Wno-unused-variable -Wno-literal-suffix \
|
||||
-Wno-reserved-user-defined-literal -Wno-duplicate-decl-specifier -Wno-pointer-bool-conversion
|
||||
|
||||
Store_LDFLAGS := $(SODIUM_LIBS) $(NIX_LIBS)
|
||||
Store_LIBS = libstore libutil
|
||||
|
||||
Store_LDFLAGS := $(SODIUM_LIBS)
|
||||
|
||||
ifeq (CYGWIN,$(findstring CYGWIN,$(OS)))
|
||||
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})
|
||||
endif
|
||||
|
||||
Store_ALLOW_UNDEFINED = 1
|
||||
|
||||
Store_FORCE_INSTALL = 1
|
||||
|
||||
Store_INSTALL_DIR = $(perllibdir)/auto/Nix/Store
|
||||
|
||||
ifeq (CYGWIN,$(findstring CYGWIN,$(OS)))
|
||||
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})
|
||||
endif
|
||||
|
||||
Store_ALLOW_UNDEFINED = 1
|
||||
|
||||
Store_FORCE_INSTALL = 1
|
||||
|
||||
Store_INSTALL_DIR = $(perllibdir)/auto/Nix/Store
|
||||
|
||||
clean-files += lib/Nix/Config.pm lib/Nix/Store.cc Makefile.config
|
||||
clean-files += $(d)/lib/Nix/Config.pm $(d)/lib/Nix/Store.cc
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
{ pkgs }:
|
||||
|
||||
rec {
|
||||
# Use "busybox-sandbox-shell" if present,
|
||||
# if not (legacy) fallback and hope it's sufficient.
|
||||
sh = pkgs.busybox-sandbox-shell or (pkgs.busybox.override {
|
||||
useMusl = true;
|
||||
enableStatic = true;
|
||||
enableMinimal = true;
|
||||
extraConfig = ''
|
||||
CONFIG_FEATURE_FANCY_ECHO y
|
||||
CONFIG_FEATURE_SH_MATH y
|
||||
CONFIG_FEATURE_SH_MATH_64 y
|
||||
|
||||
CONFIG_ASH y
|
||||
CONFIG_ASH_OPTIMIZE_FOR_SIZE y
|
||||
|
||||
CONFIG_ASH_ALIAS y
|
||||
CONFIG_ASH_BASH_COMPAT y
|
||||
CONFIG_ASH_CMDCMD y
|
||||
CONFIG_ASH_ECHO y
|
||||
CONFIG_ASH_GETOPTS y
|
||||
CONFIG_ASH_INTERNAL_GLOB y
|
||||
CONFIG_ASH_JOB_CONTROL y
|
||||
CONFIG_ASH_PRINTF y
|
||||
CONFIG_ASH_TEST y
|
||||
'';
|
||||
});
|
||||
|
||||
configureFlags =
|
||||
[ "--disable-init-state"
|
||||
"--enable-gc"
|
||||
] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [
|
||||
"--with-sandbox-shell=${sh}/bin/busybox"
|
||||
];
|
||||
}
|
||||
170
release.nix
170
release.nix
@@ -1,12 +1,14 @@
|
||||
{ nix ? builtins.fetchGit ./.
|
||||
, nixpkgs ? builtins.fetchGit { url = https://github.com/NixOS/nixpkgs.git; ref = "nix-2.0"; }
|
||||
{ nix ? { outPath = ./.; revCount = 1234; shortRev = "abcdef"; }
|
||||
, nixpkgs ? { outPath = <nixpkgs>; revCount = 1234; shortRev = "abcdef"; }
|
||||
, officialRelease ? false
|
||||
, systems ? [ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" ]
|
||||
}:
|
||||
|
||||
let
|
||||
|
||||
pkgs = import nixpkgs { system = builtins.currentSystem or "x86_64-linux"; };
|
||||
pkgs = import <nixpkgs> {};
|
||||
|
||||
systems = [ "x86_64-linux" "i686-linux" "x86_64-darwin" /* "x86_64-freebsd" "i686-freebsd" */ ];
|
||||
|
||||
|
||||
jobs = rec {
|
||||
|
||||
@@ -18,26 +20,30 @@ let
|
||||
name = "nix-tarball";
|
||||
version = builtins.readFile ./version;
|
||||
versionSuffix = if officialRelease then "" else "pre${toString nix.revCount}_${nix.shortRev}";
|
||||
src = nix;
|
||||
src = if lib.inNixShell then null else nix;
|
||||
inherit officialRelease;
|
||||
|
||||
buildInputs =
|
||||
[ curl bison flex libxml2 libxslt
|
||||
bzip2 xz brotli
|
||||
[ curl bison flex perl libxml2 libxslt bzip2 xz
|
||||
pkgconfig sqlite libsodium boehmgc
|
||||
docbook5 docbook5_xsl
|
||||
autoconf-archive
|
||||
] ++ lib.optional stdenv.isLinux libseccomp;
|
||||
] ++ lib.optional (!lib.inNixShell) git;
|
||||
|
||||
configureFlags = "--enable-gc";
|
||||
configureFlags = ''
|
||||
--with-dbi=${perlPackages.DBI}/${perl.libPrefix}
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/${perl.libPrefix}
|
||||
--enable-gc
|
||||
'';
|
||||
|
||||
postUnpack = ''
|
||||
(cd source && find . -type f) | cut -c3- > source/.dist-files
|
||||
cat source/.dist-files
|
||||
# Clean up when building from a working tree.
|
||||
if [[ -d $sourceRoot/.git ]]; then
|
||||
git -C $sourceRoot clean -fd
|
||||
fi
|
||||
'';
|
||||
|
||||
preConfigure = ''
|
||||
(cd perl ; autoreconf --install --force --verbose)
|
||||
# TeX needs a writable font cache.
|
||||
export VARTEXFONTS=$TMPDIR/texfonts
|
||||
'';
|
||||
@@ -59,33 +65,28 @@ let
|
||||
|
||||
build = pkgs.lib.genAttrs systems (system:
|
||||
|
||||
with import nixpkgs { inherit system; };
|
||||
|
||||
with import ./release-common.nix { inherit pkgs; };
|
||||
with import <nixpkgs> { inherit system; };
|
||||
|
||||
releaseTools.nixBuild {
|
||||
name = "nix";
|
||||
src = tarball;
|
||||
|
||||
buildInputs =
|
||||
[ curl
|
||||
bzip2 xz brotli
|
||||
openssl pkgconfig sqlite boehmgc
|
||||
|
||||
# Tests
|
||||
git
|
||||
mercurial
|
||||
]
|
||||
++ lib.optional stdenv.isLinux libseccomp
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin)
|
||||
[ curl perl bzip2 xz openssl pkgconfig sqlite boehmgc ]
|
||||
++ lib.optional stdenv.isLinux libsodium
|
||||
++ lib.optional stdenv.isLinux
|
||||
(aws-sdk-cpp.override {
|
||||
apis = ["s3"];
|
||||
customMemoryManagement = false;
|
||||
});
|
||||
|
||||
configureFlags = configureFlags ++
|
||||
[ "--sysconfdir=/etc" ];
|
||||
configureFlags = ''
|
||||
--disable-init-state
|
||||
--with-dbi=${perlPackages.DBI}/${perl.libPrefix}
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/${perl.libPrefix}
|
||||
--enable-gc
|
||||
--sysconfdir=/etc
|
||||
'';
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
@@ -100,34 +101,10 @@ let
|
||||
});
|
||||
|
||||
|
||||
perlBindings = pkgs.lib.genAttrs systems (system:
|
||||
|
||||
let pkgs = import nixpkgs { inherit system; }; in with pkgs;
|
||||
|
||||
releaseTools.nixBuild {
|
||||
name = "nix-perl";
|
||||
src = tarball;
|
||||
|
||||
buildInputs =
|
||||
[ (builtins.getAttr system jobs.build) curl bzip2 xz pkgconfig pkgs.perl ]
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium;
|
||||
|
||||
configureFlags = ''
|
||||
--with-dbi=${perlPackages.DBI}/${pkgs.perl.libPrefix}
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/${pkgs.perl.libPrefix}
|
||||
'';
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
postUnpack = "sourceRoot=$sourceRoot/perl";
|
||||
|
||||
preBuild = "unset NIX_INDENT_MAKE";
|
||||
});
|
||||
|
||||
|
||||
binaryTarball = pkgs.lib.genAttrs systems (system:
|
||||
|
||||
with import nixpkgs { inherit system; };
|
||||
# FIXME: temporarily use a different branch for the Darwin build.
|
||||
with import <nixpkgs> { inherit system; };
|
||||
|
||||
let
|
||||
toplevel = builtins.getAttr system jobs.build;
|
||||
@@ -136,7 +113,7 @@ let
|
||||
|
||||
runCommand "nix-binary-tarball-${version}"
|
||||
{ exportReferencesGraph = [ "closure1" toplevel "closure2" cacert ];
|
||||
buildInputs = [ perl ] ++ lib.optional (system != "aarch64-linux") shellcheck;
|
||||
buildInputs = [ perl ];
|
||||
meta.description = "Distribution-independent Nix bootstrap binaries for ${system}";
|
||||
}
|
||||
''
|
||||
@@ -145,17 +122,7 @@ let
|
||||
substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \
|
||||
--subst-var-by nix ${toplevel} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user \
|
||||
--subst-var-by nix ${toplevel} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
|
||||
if type -p shellcheck; then
|
||||
shellcheck -e SC1090 $TMPDIR/install
|
||||
shellcheck -e SC1091,SC2002 $TMPDIR/install-darwin-multi-user
|
||||
fi
|
||||
|
||||
chmod +x $TMPDIR/install
|
||||
chmod +x $TMPDIR/install-darwin-multi-user
|
||||
dir=nix-${version}-${system}
|
||||
fn=$out/$dir.tar.bz2
|
||||
mkdir -p $out/nix-support
|
||||
@@ -167,32 +134,34 @@ let
|
||||
--transform "s,$TMPDIR/install,$dir/install," \
|
||||
--transform "s,$TMPDIR/reginfo,$dir/.reginfo," \
|
||||
--transform "s,$NIX_STORE,$dir/store,S" \
|
||||
$TMPDIR/install $TMPDIR/install-darwin-multi-user $TMPDIR/reginfo $storePaths
|
||||
$TMPDIR/install $TMPDIR/reginfo $storePaths
|
||||
'');
|
||||
|
||||
|
||||
coverage =
|
||||
with import nixpkgs { system = "x86_64-linux"; };
|
||||
with import <nixpkgs> { system = "x86_64-linux"; };
|
||||
|
||||
releaseTools.coverageAnalysis {
|
||||
name = "nix-build";
|
||||
src = tarball;
|
||||
|
||||
buildInputs =
|
||||
[ curl bzip2 openssl pkgconfig sqlite xz libsodium libseccomp
|
||||
[ curl perl bzip2 openssl pkgconfig sqlite xz libsodium
|
||||
# These are for "make check" only:
|
||||
graphviz libxml2 libxslt git mercurial
|
||||
graphviz libxml2 libxslt
|
||||
];
|
||||
|
||||
configureFlags = ''
|
||||
--disable-init-state
|
||||
--with-dbi=${perlPackages.DBI}/${perl.libPrefix}
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/${perl.libPrefix}
|
||||
'';
|
||||
|
||||
dontInstall = false;
|
||||
|
||||
doInstallCheck = true;
|
||||
|
||||
lcovFilter = [ "*/boost/*" "*-tab.*" "*/nlohmann/*" "*/linenoise/*" ];
|
||||
lcovFilter = [ "*/boost/*" "*-tab.*" ];
|
||||
|
||||
# We call `dot', and even though we just use it to
|
||||
# syntax-check generated dot files, it still requires some
|
||||
@@ -201,40 +170,34 @@ let
|
||||
};
|
||||
|
||||
|
||||
rpm_fedora25i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora25i386) [ "libsodium-devel" ];
|
||||
rpm_fedora25x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora25x86_64) [ "libsodium-devel" ];
|
||||
rpm_fedora21i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora21i386) [ "libsodium-devel" ];
|
||||
rpm_fedora21x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora21x86_64) [ "libsodium-devel" ];
|
||||
|
||||
|
||||
#deb_debian8i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.debian8i386) [ "libsodium-dev" ] [ "libsodium13" ];
|
||||
#deb_debian8x86_64 = makeDeb_x86_64 (diskImageFunsFun: diskImageFunsFun.debian8x86_64) [ "libsodium-dev" ] [ "libsodium13" ];
|
||||
deb_debian8i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.debian8i386) [ "libsodium-dev" ] [ "libsodium13" ];
|
||||
deb_debian8x86_64 = makeDeb_x86_64 (diskImageFunsFun: diskImageFunsFun.debian8x86_64) [ "libsodium-dev" ] [ "libsodium13" ];
|
||||
|
||||
deb_ubuntu1410i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1410i386) [] [];
|
||||
deb_ubuntu1410x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1410x86_64) [] [];
|
||||
deb_ubuntu1504i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1504i386) [ "libsodium-dev" ] [ "libsodium13" ];
|
||||
deb_ubuntu1504x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1504x86_64) [ "libsodium-dev" ] [ "libsodium13" ];
|
||||
deb_ubuntu1510i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1510i386) [ "libsodium-dev" ] [ "libsodium13"];
|
||||
deb_ubuntu1510x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1510x86_64) [ "libsodium-dev" ] [ "libsodium13" ];
|
||||
deb_ubuntu1604i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1604i386) [ "libsodium-dev" ] [ "libsodium18" ];
|
||||
deb_ubuntu1604x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1604x86_64) [ "libsodium-dev" ] [ "libsodium18" ];
|
||||
deb_ubuntu1610i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1610i386) [ "libsodium-dev" ] [ "libsodium18" ];
|
||||
deb_ubuntu1610x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1610x86_64) [ "libsodium-dev" ] [ "libsodium18" ];
|
||||
|
||||
|
||||
# System tests.
|
||||
tests.remoteBuilds = (import ./tests/remote-builds.nix rec {
|
||||
inherit nixpkgs;
|
||||
nix = build.x86_64-linux; system = "x86_64-linux";
|
||||
});
|
||||
|
||||
tests.nix-copy-closure = (import ./tests/nix-copy-closure.nix rec {
|
||||
inherit nixpkgs;
|
||||
nix = build.x86_64-linux; system = "x86_64-linux";
|
||||
});
|
||||
|
||||
tests.setuid = pkgs.lib.genAttrs
|
||||
["i686-linux" "x86_64-linux"]
|
||||
(system:
|
||||
import ./tests/setuid.nix rec {
|
||||
inherit nixpkgs;
|
||||
nix = build.${system}; inherit system;
|
||||
});
|
||||
|
||||
tests.binaryTarball =
|
||||
with import nixpkgs { system = "x86_64-linux"; };
|
||||
with import <nixpkgs> { system = "x86_64-linux"; };
|
||||
vmTools.runInLinuxImage (runCommand "nix-binary-tarball-test"
|
||||
{ diskImage = vmTools.diskImages.ubuntu1204x86_64;
|
||||
}
|
||||
@@ -253,7 +216,7 @@ let
|
||||
''); # */
|
||||
|
||||
tests.evalNixpkgs =
|
||||
import (nixpkgs + "/pkgs/top-level/make-tarball.nix") {
|
||||
import <nixpkgs/pkgs/top-level/make-tarball.nix> {
|
||||
inherit nixpkgs;
|
||||
inherit pkgs;
|
||||
nix = build.x86_64-linux;
|
||||
@@ -278,18 +241,22 @@ let
|
||||
meta.description = "Release-critical builds";
|
||||
constituents =
|
||||
[ tarball
|
||||
#build.i686-freebsd
|
||||
build.i686-linux
|
||||
build.x86_64-darwin
|
||||
#build.x86_64-freebsd
|
||||
build.x86_64-linux
|
||||
#binaryTarball.i686-freebsd
|
||||
binaryTarball.i686-linux
|
||||
binaryTarball.x86_64-darwin
|
||||
#binaryTarball.x86_64-freebsd
|
||||
binaryTarball.x86_64-linux
|
||||
#deb_debian8i386
|
||||
#deb_debian8x86_64
|
||||
deb_ubuntu1604i386
|
||||
deb_ubuntu1604x86_64
|
||||
rpm_fedora25i386
|
||||
rpm_fedora25x86_64
|
||||
deb_debian8i386
|
||||
deb_debian8x86_64
|
||||
deb_ubuntu1504i386
|
||||
deb_ubuntu1504x86_64
|
||||
rpm_fedora21i386
|
||||
rpm_fedora21x86_64
|
||||
tests.remoteBuilds
|
||||
tests.nix-copy-closure
|
||||
tests.binaryTarball
|
||||
@@ -307,20 +274,18 @@ let
|
||||
makeRPM =
|
||||
system: diskImageFun: extraPackages:
|
||||
|
||||
with import nixpkgs { inherit system; };
|
||||
with import <nixpkgs> { inherit system; };
|
||||
|
||||
releaseTools.rpmBuild rec {
|
||||
name = "nix-rpm";
|
||||
src = jobs.tarball;
|
||||
diskImage = (diskImageFun vmTools.diskImageFuns)
|
||||
{ extraPackages =
|
||||
[ "sqlite" "sqlite-devel" "bzip2-devel" "libcurl-devel" "openssl-devel" "xz-devel" "libseccomp-devel" ]
|
||||
[ "perl-DBD-SQLite" "perl-devel" "sqlite" "sqlite-devel" "bzip2-devel" "emacs" "libcurl-devel" "openssl-devel" "xz-devel" ]
|
||||
++ extraPackages; };
|
||||
# At most 2047MB can be simulated in qemu-system-i386
|
||||
memSize = 2047;
|
||||
memSize = 1024;
|
||||
meta.schedulingPriority = 50;
|
||||
postRPMInstall = "cd /tmp/rpmout/BUILD/nix-* && make installcheck";
|
||||
#enableParallelBuilding = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -330,25 +295,24 @@ let
|
||||
makeDeb =
|
||||
system: diskImageFun: extraPackages: extraDebPackages:
|
||||
|
||||
with import nixpkgs { inherit system; };
|
||||
with import <nixpkgs> { inherit system; };
|
||||
|
||||
releaseTools.debBuild {
|
||||
name = "nix-deb";
|
||||
src = jobs.tarball;
|
||||
diskImage = (diskImageFun vmTools.diskImageFuns)
|
||||
{ extraPackages =
|
||||
[ "libsqlite3-dev" "libbz2-dev" "libcurl-dev" "libcurl3-nss" "libssl-dev" "liblzma-dev" "libseccomp-dev" ]
|
||||
[ "libdbd-sqlite3-perl" "libsqlite3-dev" "libbz2-dev" "libwww-curl-perl" "libcurl-dev" "libcurl3-nss" "libssl-dev" "liblzma-dev" ]
|
||||
++ extraPackages; };
|
||||
memSize = 1024;
|
||||
meta.schedulingPriority = 50;
|
||||
postInstall = "make installcheck";
|
||||
configureFlags = "--sysconfdir=/etc";
|
||||
debRequires =
|
||||
[ "curl" "libsqlite3-0" "libbz2-1.0" "bzip2" "xz-utils" "libssl1.0.0" "liblzma5" "libseccomp2" ]
|
||||
[ "curl" "libdbd-sqlite3-perl" "libsqlite3-0" "libbz2-1.0" "bzip2" "xz-utils" "libwww-curl-perl" "libssl1.0.0" "liblzma5" ]
|
||||
++ extraDebPackages;
|
||||
debMaintainer = "Eelco Dolstra <eelco.dolstra@logicblox.com>";
|
||||
doInstallCheck = true;
|
||||
#enableParallelBuilding = true;
|
||||
};
|
||||
|
||||
|
||||
|
||||
275
scripts/build-remote.pl.in
Executable file
275
scripts/build-remote.pl.in
Executable file
@@ -0,0 +1,275 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use utf8;
|
||||
use Fcntl qw(:DEFAULT :flock);
|
||||
use English '-no_match_vars';
|
||||
use IO::Handle;
|
||||
use Nix::Config;
|
||||
use Nix::SSH;
|
||||
use Nix::CopyClosure;
|
||||
use Nix::Store;
|
||||
use Encode;
|
||||
no warnings('once');
|
||||
|
||||
STDERR->autoflush(1);
|
||||
binmode STDERR, ":encoding(utf8)";
|
||||
|
||||
my $debug = defined $ENV{NIX_DEBUG_HOOK};
|
||||
|
||||
|
||||
# General operation:
|
||||
#
|
||||
# Try to find a free machine of type $neededSystem. We do this as
|
||||
# follows:
|
||||
# - We acquire an exclusive lock on $currentLoad/main-lock.
|
||||
# - For each machine $machine of type $neededSystem and for each $slot
|
||||
# less than the maximum load for that machine, we try to get an
|
||||
# exclusive lock on $currentLoad/$machine-$slot (without blocking).
|
||||
# If we get such a lock, we send "accept" to the caller. Otherwise,
|
||||
# we send "postpone" and exit.
|
||||
# - We release the exclusive lock on $currentLoad/main-lock.
|
||||
# - We perform the build on $neededSystem.
|
||||
# - We release the exclusive lock on $currentLoad/$machine-$slot.
|
||||
#
|
||||
# The nice thing about this scheme is that if we die prematurely, the
|
||||
# locks are released automatically.
|
||||
|
||||
|
||||
# Make sure that we don't get any SSH passphrase or host key popups -
|
||||
# if there is any problem it should fail, not do something
|
||||
# interactive.
|
||||
$ENV{"DISPLAY"} = "";
|
||||
$ENV{"SSH_ASKPASS"} = "";
|
||||
|
||||
|
||||
sub sendReply {
|
||||
my $reply = shift;
|
||||
print STDERR "# $reply\n";
|
||||
}
|
||||
|
||||
sub all { $_ || return 0 for @_; 1 }
|
||||
|
||||
|
||||
# Initialisation.
|
||||
my $loadIncreased = 0;
|
||||
|
||||
my ($localSystem, $maxSilentTime, $buildTimeout) = @ARGV;
|
||||
|
||||
my $currentLoad = $ENV{"NIX_CURRENT_LOAD"} // "/run/nix/current-load";
|
||||
my $conf = $ENV{"NIX_REMOTE_SYSTEMS"} // "@sysconfdir@/nix/machines";
|
||||
|
||||
|
||||
sub openSlotLock {
|
||||
my ($machine, $slot) = @_;
|
||||
my $slotLockFn = "$currentLoad/" . (join '+', @{$machine->{systemTypes}}) . "-" . $machine->{hostName} . "-$slot";
|
||||
my $slotLock = new IO::Handle;
|
||||
sysopen $slotLock, "$slotLockFn", O_RDWR|O_CREAT, 0600 or die;
|
||||
return $slotLock;
|
||||
}
|
||||
|
||||
|
||||
# Read the list of machines.
|
||||
my @machines;
|
||||
if (defined $conf && -e $conf) {
|
||||
open CONF, "<$conf" or die;
|
||||
while (<CONF>) {
|
||||
chomp;
|
||||
s/\#.*$//g;
|
||||
next if /^\s*$/;
|
||||
my @tokens = split /\s/, $_;
|
||||
my @supportedFeatures = split(/,/, $tokens[5] || "");
|
||||
my @mandatoryFeatures = split(/,/, $tokens[6] || "");
|
||||
push @machines,
|
||||
{ hostName => $tokens[0]
|
||||
, systemTypes => [ split(/,/, $tokens[1]) ]
|
||||
, sshKey => $tokens[2]
|
||||
, maxJobs => int($tokens[3])
|
||||
, speedFactor => 1.0 * (defined $tokens[4] ? int($tokens[4]) : 1)
|
||||
, supportedFeatures => [ @supportedFeatures, @mandatoryFeatures ]
|
||||
, mandatoryFeatures => [ @mandatoryFeatures ]
|
||||
, enabled => 1
|
||||
};
|
||||
}
|
||||
close CONF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Wait for the calling process to ask us whether we can build some derivation.
|
||||
my ($drvPath, $hostName, $slotLock);
|
||||
my ($from, $to);
|
||||
|
||||
REQ: while (1) {
|
||||
$_ = <STDIN> || exit 0;
|
||||
(my $amWilling, my $neededSystem, $drvPath, my $requiredFeatures) = split;
|
||||
my @requiredFeatures = split /,/, $requiredFeatures;
|
||||
|
||||
my $canBuildLocally = $amWilling && ($localSystem eq $neededSystem);
|
||||
|
||||
if (!defined $currentLoad) {
|
||||
sendReply "decline";
|
||||
next;
|
||||
}
|
||||
|
||||
# Acquire the exclusive lock on $currentLoad/main-lock.
|
||||
mkdir $currentLoad, 0777 or die unless -d $currentLoad;
|
||||
my $mainLock = "$currentLoad/main-lock";
|
||||
sysopen MAINLOCK, "$mainLock", O_RDWR|O_CREAT, 0600 or die;
|
||||
flock(MAINLOCK, LOCK_EX) or die;
|
||||
|
||||
|
||||
while (1) {
|
||||
# Find all machine that can execute this build, i.e., that
|
||||
# support builds for the given platform and features, and are
|
||||
# not at their job limit.
|
||||
my $rightType = 0;
|
||||
my @available = ();
|
||||
LOOP: foreach my $cur (@machines) {
|
||||
if ($cur->{enabled}
|
||||
&& (grep { $neededSystem eq $_ } @{$cur->{systemTypes}})
|
||||
&& all(map { my $f = $_; 0 != grep { $f eq $_ } @{$cur->{supportedFeatures}} } (@requiredFeatures, @mandatoryFeatures))
|
||||
&& all(map { my $f = $_; 0 != grep { $f eq $_ } @requiredFeatures } @{$cur->{mandatoryFeatures}})
|
||||
)
|
||||
{
|
||||
$rightType = 1;
|
||||
|
||||
# We have a machine of the right type. Determine the load on
|
||||
# the machine.
|
||||
my $slot = 0;
|
||||
my $load = 0;
|
||||
my $free;
|
||||
while ($slot < $cur->{maxJobs}) {
|
||||
my $slotLock = openSlotLock($cur, $slot);
|
||||
if (flock($slotLock, LOCK_EX | LOCK_NB)) {
|
||||
$free = $slot unless defined $free;
|
||||
flock($slotLock, LOCK_UN) or die;
|
||||
} else {
|
||||
$load++;
|
||||
}
|
||||
close $slotLock;
|
||||
$slot++;
|
||||
}
|
||||
|
||||
push @available, { machine => $cur, load => $load, free => $free }
|
||||
if $load < $cur->{maxJobs};
|
||||
}
|
||||
}
|
||||
|
||||
if ($debug) {
|
||||
print STDERR "load on " . $_->{machine}->{hostName} . " = " . $_->{load} . "\n"
|
||||
foreach @available;
|
||||
}
|
||||
|
||||
|
||||
# Didn't find any available machine? Then decline or postpone.
|
||||
if (scalar @available == 0) {
|
||||
# Postpone if we have a machine of the right type, except
|
||||
# if the local system can and wants to do the build.
|
||||
if ($rightType && !$canBuildLocally) {
|
||||
sendReply "postpone";
|
||||
} else {
|
||||
sendReply "decline";
|
||||
}
|
||||
close MAINLOCK;
|
||||
next REQ;
|
||||
}
|
||||
|
||||
|
||||
# Prioritise the available machines as follows:
|
||||
# - First by load divided by speed factor, rounded to the nearest
|
||||
# integer. This causes fast machines to be preferred over slow
|
||||
# machines with similar loads.
|
||||
# - Then by speed factor.
|
||||
# - Finally by load.
|
||||
sub lf { my $x = shift; return int($x->{load} / $x->{machine}->{speedFactor} + 0.4999); }
|
||||
@available = sort
|
||||
{ lf($a) <=> lf($b)
|
||||
|| $b->{machine}->{speedFactor} <=> $a->{machine}->{speedFactor}
|
||||
|| $a->{load} <=> $b->{load}
|
||||
} @available;
|
||||
|
||||
|
||||
# Select the best available machine and lock a free slot.
|
||||
my $selected = $available[0];
|
||||
my $machine = $selected->{machine};
|
||||
|
||||
$slotLock = openSlotLock($machine, $selected->{free});
|
||||
flock($slotLock, LOCK_EX | LOCK_NB) or die;
|
||||
utime undef, undef, $slotLock;
|
||||
|
||||
close MAINLOCK;
|
||||
|
||||
|
||||
# Connect to the selected machine.
|
||||
my @sshOpts = ("-i", $machine->{sshKey});
|
||||
$hostName = $machine->{hostName};
|
||||
eval {
|
||||
($from, $to) = connectToRemoteNix($hostName, \@sshOpts, "2>&4");
|
||||
# FIXME: check if builds are inhibited.
|
||||
};
|
||||
last REQ unless $@;
|
||||
print STDERR "$@";
|
||||
warn "unable to open SSH connection to ‘$hostName’, trying other available machines...\n";
|
||||
$from = undef;
|
||||
$to = undef;
|
||||
$machine->{enabled} = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Tell Nix we've accepted the build.
|
||||
sendReply "accept";
|
||||
my @inputs = split /\s/, readline(STDIN);
|
||||
my @outputs = split /\s/, readline(STDIN);
|
||||
|
||||
|
||||
# Copy the derivation and its dependencies to the build machine. This
|
||||
# is guarded by an exclusive lock per machine to prevent multiple
|
||||
# build-remote instances from copying to a machine simultaneously.
|
||||
# That's undesirable because we may end up with N instances uploading
|
||||
# the same missing path simultaneously, causing the effective network
|
||||
# bandwidth and target disk speed to be divided by N.
|
||||
my $uploadLock = "$currentLoad/$hostName.upload-lock";
|
||||
sysopen UPLOADLOCK, "$uploadLock", O_RDWR|O_CREAT, 0600 or die;
|
||||
eval {
|
||||
local $SIG{ALRM} = sub { die "alarm\n" };
|
||||
# Don't wait forever, so that a process that gets stuck while
|
||||
# holding the lock doesn't block everybody else indefinitely.
|
||||
# It's safe to continue after a timeout, just (potentially)
|
||||
# inefficient.
|
||||
alarm 15 * 60;
|
||||
flock(UPLOADLOCK, LOCK_EX);
|
||||
alarm 0;
|
||||
};
|
||||
if ($@) {
|
||||
die unless $@ eq "alarm\n";
|
||||
print STDERR "somebody is hogging $uploadLock, continuing...\n";
|
||||
unlink $uploadLock;
|
||||
}
|
||||
Nix::CopyClosure::copyToOpen($from, $to, $hostName, [ $drvPath, @inputs ], 0, 0);
|
||||
close UPLOADLOCK;
|
||||
|
||||
|
||||
# Perform the build.
|
||||
print STDERR "building ‘$drvPath’ on ‘$hostName’\n";
|
||||
writeInt(6, $to) or die; # == cmdBuildPaths
|
||||
writeStrings([$drvPath], $to);
|
||||
writeInt($maxSilentTime, $to);
|
||||
writeInt($buildTimeout, $to);
|
||||
my $res = readInt($from);
|
||||
if ($res != 0) {
|
||||
my $msg = decode("utf-8", readString($from));
|
||||
print STDERR "error: $msg on ‘$hostName’\n";
|
||||
exit $res;
|
||||
}
|
||||
|
||||
|
||||
# Copy the output from the build machine.
|
||||
my @outputs2 = grep { !isValidPath($_) } @outputs;
|
||||
if (scalar @outputs2 > 0) {
|
||||
writeInt(5, $to); # == cmdExportPaths
|
||||
writeInt(0, $to); # don't sign
|
||||
writeStrings(\@outputs2, $to);
|
||||
$ENV{'NIX_HELD_LOCKS'} = "@outputs2"; # FIXME: ugly
|
||||
importPaths(fileno($from), 1);
|
||||
}
|
||||
@@ -1,819 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
# Sourced from:
|
||||
# - https://github.com/LnL7/nix-darwin/blob/8c29d0985d74b4a990238497c47a2542a5616b3c/bootstrap.sh
|
||||
# - https://gist.github.com/expipiplus1/e571ce88c608a1e83547c918591b149f/ac504c6c1b96e65505fbda437a28ce563408ecb0
|
||||
# - https://github.com/NixOS/nixos-org-configurations/blob/a122f418797713d519aadf02e677fce0dc1cb446/delft/scripts/nix-mac-installer.sh
|
||||
# - https://github.com/matthewbauer/macNixOS/blob/f6045394f9153edea417be90c216788e754feaba/install-macNixOS.sh
|
||||
# - https://gist.github.com/LnL7/9717bd6cdcb30b086fd7f2093e5f8494/86b26f852ce563e973acd30f796a9a416248c34a
|
||||
#
|
||||
# however tracking which bits came from which would be impossible.
|
||||
|
||||
readonly ESC='\033[0m'
|
||||
readonly BOLD='\033[38;1m'
|
||||
readonly BLUE='\033[38;34m'
|
||||
readonly BLUE_UL='\033[38;4;34m'
|
||||
readonly GREEN='\033[38;32m'
|
||||
readonly GREEN_UL='\033[38;4;32m'
|
||||
readonly RED='\033[38;31m'
|
||||
readonly RED_UL='\033[38;4;31m'
|
||||
readonly YELLOW='\033[38;33m'
|
||||
readonly YELLOW_UL='\033[38;4;33m'
|
||||
|
||||
readonly CORES=$(sysctl -n hw.ncpu)
|
||||
readonly NIX_USER_COUNT="32"
|
||||
readonly NIX_BUILD_GROUP_ID="30000"
|
||||
readonly NIX_BUILD_GROUP_NAME="nixbld"
|
||||
readonly NIX_FIRST_BUILD_UID="30001"
|
||||
# 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 PLIST_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
|
||||
readonly PROFILE_TARGETS=("/etc/bashrc" "/etc/zshrc")
|
||||
readonly PROFILE_BACKUP_SUFFIX=".backup-before-nix"
|
||||
readonly PROFILE_NIX_FILE="$NIX_ROOT/var/nix/profiles/default/etc/profile.d/nix-daemon.sh"
|
||||
|
||||
readonly NIX_INSTALLED_NIX="@nix@"
|
||||
readonly NIX_INSTALLED_CACERT="@cacert@"
|
||||
readonly EXTRACTED_NIX_PATH="$(dirname "$0")"
|
||||
|
||||
readonly ROOT_HOME="/var/root"
|
||||
|
||||
if [ -t 0 ]; then
|
||||
readonly IS_HEADLESS='no'
|
||||
else
|
||||
readonly IS_HEADLESS='yes'
|
||||
fi
|
||||
|
||||
headless() {
|
||||
if [ "$IS_HEADLESS" = "yes" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
contactme() {
|
||||
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"
|
||||
}
|
||||
|
||||
uninstall_directions() {
|
||||
subheader "Uninstalling nix:"
|
||||
local step=0
|
||||
|
||||
if [ -e "$PLIST_DEST" ]; then
|
||||
step=$((step + 1))
|
||||
cat <<EOF
|
||||
$step. Delete $PLIST_DEST
|
||||
|
||||
sudo launchctl unload $PLIST_DEST
|
||||
sudo rm $PLIST_DEST
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target" ] && [ -e "$profile_target$PROFILE_BACKUP_SUFFIX" ]; then
|
||||
step=$((step + 1))
|
||||
cat <<EOF
|
||||
$step. Restore $profile_target$PROFILE_BACKUP_SUFFIX back to $profile_target
|
||||
|
||||
sudo mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
|
||||
|
||||
(after this one, you may need to re-open any terminals that were
|
||||
opened while it existed.)
|
||||
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
|
||||
step=$((step + 1))
|
||||
cat <<EOF
|
||||
$step. Delete the files Nix added to your system:
|
||||
|
||||
sudo rm -rf /etc/nix $NIX_ROOT $ROOT_HOME/.nix-profile $ROOT_HOME/.nix-defexpr $ROOT_HOME/.nix-channels $HOME/.nix-profile $HOME/.nix-defexpr $HOME/.nix-channels
|
||||
|
||||
and that is it.
|
||||
|
||||
EOF
|
||||
|
||||
}
|
||||
|
||||
nix_user_for_core() {
|
||||
printf "nixbld%d" "$1"
|
||||
}
|
||||
|
||||
nix_uid_for_core() {
|
||||
echo $((NIX_FIRST_BUILD_UID + $1 - 1))
|
||||
}
|
||||
|
||||
dsclattr() {
|
||||
/usr/bin/dscl . -read "$1" \
|
||||
| awk "/$2/ { print \$2 }"
|
||||
}
|
||||
|
||||
_textout() {
|
||||
echo -en "$1"
|
||||
shift
|
||||
if [ "$*" = "" ]; then
|
||||
cat
|
||||
else
|
||||
echo "$@"
|
||||
fi
|
||||
echo -en "$ESC"
|
||||
}
|
||||
|
||||
header() {
|
||||
follow="---------------------------------------------------------"
|
||||
header=$(echo "---- $* $follow$follow$follow" | head -c 80)
|
||||
echo ""
|
||||
_textout "$BLUE" "$header"
|
||||
}
|
||||
|
||||
warningheader() {
|
||||
follow="---------------------------------------------------------"
|
||||
header=$(echo "---- $* $follow$follow$follow" | head -c 80)
|
||||
echo ""
|
||||
_textout "$RED" "$header"
|
||||
}
|
||||
|
||||
subheader() {
|
||||
echo ""
|
||||
_textout "$BLUE_UL" "$*"
|
||||
}
|
||||
|
||||
row() {
|
||||
printf "$BOLD%s$ESC:\\t%s\\n" "$1" "$2"
|
||||
}
|
||||
|
||||
task() {
|
||||
echo ""
|
||||
ok "~~> $1"
|
||||
}
|
||||
|
||||
bold() {
|
||||
echo "$BOLD$*$ESC"
|
||||
}
|
||||
|
||||
ok() {
|
||||
_textout "$GREEN" "$@"
|
||||
}
|
||||
|
||||
warning() {
|
||||
warningheader "warning!"
|
||||
cat
|
||||
echo ""
|
||||
}
|
||||
|
||||
failure() {
|
||||
header "oh no!"
|
||||
_textout "$RED" "$@"
|
||||
echo ""
|
||||
_textout "$RED" "$(contactme)"
|
||||
trap finish_cleanup EXIT
|
||||
exit 1
|
||||
}
|
||||
|
||||
ui_confirm() {
|
||||
_textout "$GREEN$GREEN_UL" "$1"
|
||||
|
||||
if headless; then
|
||||
echo "No TTY, assuming you would say yes :)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local prompt="[y/n] "
|
||||
echo -n "$prompt"
|
||||
while read -r y; do
|
||||
if [ "$y" = "y" ]; then
|
||||
echo ""
|
||||
return 0
|
||||
elif [ "$y" = "n" ]; then
|
||||
echo ""
|
||||
return 1
|
||||
else
|
||||
_textout "$RED" "Sorry, I didn't understand. I can only understand answers of y or n"
|
||||
echo -n "$prompt"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
return 1
|
||||
}
|
||||
|
||||
__sudo() {
|
||||
local expl="$1"
|
||||
local cmd="$2"
|
||||
shift
|
||||
header "sudo execution"
|
||||
|
||||
echo "I am executing:"
|
||||
echo ""
|
||||
printf " $ sudo %s\\n" "$cmd"
|
||||
echo ""
|
||||
echo "$expl"
|
||||
echo ""
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_sudo() {
|
||||
local expl="$1"
|
||||
shift
|
||||
if ! headless; then
|
||||
__sudo "$expl" "$*"
|
||||
fi
|
||||
sudo "$@"
|
||||
}
|
||||
|
||||
|
||||
readonly SCRATCH=$(mktemp -d -t tmp.XXXXXXXXXX)
|
||||
function finish_cleanup {
|
||||
rm -rf "$SCRATCH"
|
||||
}
|
||||
|
||||
function finish_fail {
|
||||
finish_cleanup
|
||||
|
||||
failure <<EOF
|
||||
Jeeze, something went wrong. If you can take all the output and open
|
||||
an issue, we'd love to fix the problem so nobody else has this issue.
|
||||
|
||||
:(
|
||||
EOF
|
||||
}
|
||||
trap finish_fail EXIT
|
||||
|
||||
function finish_success {
|
||||
finish_cleanup
|
||||
|
||||
ok "Alright! We're done!"
|
||||
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:
|
||||
|
||||
$ nix-shell -p nix-info --run "nix-info -m"
|
||||
|
||||
Thank you for using this installer. If you have any feedback, don't
|
||||
hesitate:
|
||||
|
||||
$(contactme)
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
validate_starting_assumptions() {
|
||||
if [ "$(uname -s)" != "Darwin" ]; then
|
||||
failure "This script is for use with macOS!"
|
||||
fi
|
||||
|
||||
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
|
||||
failure <<EOF
|
||||
Nix already appears to be installed, and this tool assumes it is
|
||||
_not_ yet installed.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "${NIX_REMOTE:-}" != "" ]; then
|
||||
failure <<EOF
|
||||
For some reason, \$NIX_REMOTE is set. It really should not be set
|
||||
before this installer runs, and it hints that Nix is currently
|
||||
installed. Please delete the old Nix installation and start again.
|
||||
|
||||
Note: You might need to close your shell window and open a new shell
|
||||
to clear the variable.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if echo "${SSL_CERT_FILE:-}" | grep -qE "(nix/var/nix|nix-profile)"; then
|
||||
failure <<EOF
|
||||
It looks like \$SSL_CERT_FILE is set to a path that used to be part of
|
||||
the old Nix installation. Please unset that variable and try again:
|
||||
|
||||
$ unset SSL_CERT_FILE
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
for file in ~/.bash_profile ~/.bash_login ~/.profile ~/.zshenv ~/.zprofile ~/.zshrc ~/.zlogin; do
|
||||
if [ -f "$file" ]; then
|
||||
if grep -l "^[^#].*.nix-profile" "$file"; then
|
||||
failure <<EOF
|
||||
I found a reference to a ".nix-profile" in $file.
|
||||
This has a high chance of breaking a new nix installation. It was most
|
||||
likely put there by a previous Nix installer.
|
||||
|
||||
Please remove this reference and try running this again. You should
|
||||
also look for similar references in:
|
||||
|
||||
- ~/.bash_profile
|
||||
- ~/.bash_login
|
||||
- ~/.profile
|
||||
|
||||
or other shell init files that you may have.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -d /nix ]; then
|
||||
failure <<EOF
|
||||
There are some relics of a previous installation of Nix at /nix, and
|
||||
this scripts assumes Nix is _not_ yet installed. Please delete the old
|
||||
Nix installation and start again.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ -d /etc/nix ]; then
|
||||
failure <<EOF
|
||||
There are some relics of a previous installation of Nix at /etc/nix, and
|
||||
this scripts assumes Nix is _not_ yet installed. Please delete the old
|
||||
Nix installation and start again.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target$PROFILE_BACKUP_SUFFIX" ]; then
|
||||
failure <<EOF
|
||||
When this script runs, it backs up the current $profile_target to
|
||||
$profile_target$PROFILE_BACKUP_SUFFIX. This backup file already exists, though.
|
||||
|
||||
Please follow these instructions to clean up the old backup file:
|
||||
|
||||
1. Copy $profile_target and $profile_target$PROFILE_BACKUP_SUFFIX to another place, just
|
||||
in case.
|
||||
|
||||
2. Take care to make sure that $profile_target$PROFILE_BACKUP_SUFFIX doesn't look like
|
||||
it has anything nix-related in it. If it does, something is probably
|
||||
quite wrong. Please open an issue or get in touch immediately.
|
||||
|
||||
3. Take care to make sure that $profile_target doesn't look like it has
|
||||
anything nix-related in it. If it does, and $profile_target _did not_,
|
||||
run:
|
||||
|
||||
$ /usr/bin/sudo /bin/mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
|
||||
|
||||
and try again.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if grep -qi "nix" "$profile_target"; then
|
||||
failure <<EOF
|
||||
It looks like $profile_target already has some Nix configuration in
|
||||
there. There should be no reason to run this again. If you're having
|
||||
trouble, please open an issue.
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
|
||||
danger_paths=("$ROOT_HOME/.nix-defexpr" "$ROOT_HOME/.nix-channels" "$ROOT_HOME/.nix-profile")
|
||||
for danger_path in "${danger_paths[@]}"; do
|
||||
if _sudo "making sure that $danger_path doesn't exist" \
|
||||
test -e "$danger_path"; then
|
||||
failure <<EOF
|
||||
I found a file at $danger_path, which is a relic of a previous
|
||||
installation. You must first delete this file before continuing.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
setup_report() {
|
||||
header "hardware report"
|
||||
row " Cores" "$CORES"
|
||||
|
||||
header "Nix config report"
|
||||
row " Temp Dir" "$SCRATCH"
|
||||
row " Nix Root" "$NIX_ROOT"
|
||||
row " Build Users" "$NIX_USER_COUNT"
|
||||
row " Build Group ID" "$NIX_BUILD_GROUP_ID"
|
||||
row "Build Group Name" "$NIX_BUILD_GROUP_NAME"
|
||||
if [ "${ALLOW_PREEXISTING_INSTALLATION:-}" != "" ]; then
|
||||
row "Preexisting Install" "Allowed"
|
||||
fi
|
||||
|
||||
subheader "build users:"
|
||||
|
||||
row " Username" "UID"
|
||||
for i in $(seq 1 "$NIX_USER_COUNT"); do
|
||||
row " $(nix_user_for_core "$i")" "$(nix_uid_for_core "$i")"
|
||||
done
|
||||
echo ""
|
||||
}
|
||||
|
||||
create_build_group() {
|
||||
local primary_group_id
|
||||
|
||||
task "Setting up the build group $NIX_BUILD_GROUP_NAME"
|
||||
if ! /usr/bin/dscl . -read "/Groups/$NIX_BUILD_GROUP_NAME" > /dev/null 2>&1; then
|
||||
_sudo "Create the Nix build group, $NIX_BUILD_GROUP_NAME" \
|
||||
/usr/sbin/dseditgroup -o create \
|
||||
-r "Nix build group for nix-daemon" \
|
||||
-i "$NIX_BUILD_GROUP_ID" \
|
||||
"$NIX_BUILD_GROUP_NAME" >&2
|
||||
row " Created" "Yes"
|
||||
else
|
||||
primary_group_id=$(dsclattr "/Groups/$NIX_BUILD_GROUP_NAME" "PrimaryGroupID")
|
||||
if [ "$primary_group_id" -ne "$NIX_BUILD_GROUP_ID" ]; then
|
||||
failure <<EOF
|
||||
It seems the build group $NIX_BUILD_GROUP_NAME already exists, but
|
||||
with the UID $primary_group_id. This script can't really handle
|
||||
that right now, so I'm going to give up.
|
||||
|
||||
You can fix this by editing this script and changing the
|
||||
NIX_BUILD_GROUP_ID variable near the top to from $NIX_BUILD_GROUP_ID
|
||||
to $primary_group_id and re-run.
|
||||
EOF
|
||||
else
|
||||
row " Exists" "Yes"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
create_build_user_for_core() {
|
||||
local coreid
|
||||
local username
|
||||
local uid
|
||||
|
||||
coreid="$1"
|
||||
username=$(nix_user_for_core "$coreid")
|
||||
uid=$(nix_uid_for_core "$coreid")
|
||||
dsclpath="/Users/$username"
|
||||
|
||||
task "Setting up the build user $username"
|
||||
|
||||
if ! /usr/bin/dscl . -read "$dsclpath" > /dev/null 2>&1; then
|
||||
_sudo "Creating the Nix build user, $username" \
|
||||
/usr/bin/dscl . create "$dsclpath" \
|
||||
UniqueID "${uid}"
|
||||
row " Created" "Yes"
|
||||
else
|
||||
actual_uid=$(dsclattr "$dsclpath" "UniqueID")
|
||||
if [ "$actual_uid" -ne "$uid" ]; then
|
||||
failure <<EOF
|
||||
It seems the build user $username already exists, but with the UID
|
||||
with the UID $actual_uid. This script can't really handle that right
|
||||
now, so I'm going to give up.
|
||||
|
||||
If you already created the users and you know they start from
|
||||
$actual_uid and go up from there, you can edit this script and change
|
||||
NIX_FIRST_BUILD_UID near the top of the file to $actual_uid and try
|
||||
again.
|
||||
EOF
|
||||
else
|
||||
row " Exists" "Yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$(dsclattr "$dsclpath" "IsHidden")" = "1" ]; then
|
||||
row " IsHidden" "Yes"
|
||||
else
|
||||
_sudo "in order to make $username a hidden user" \
|
||||
/usr/bin/dscl . -create "$dsclpath" "IsHidden" "1"
|
||||
row " IsHidden" "Yes"
|
||||
fi
|
||||
|
||||
if [ "$(dsclattr "$dsclpath" "NFSHomeDirectory")" = "/var/empty" ]; then
|
||||
row " NFSHomeDirectory" "/var/empty"
|
||||
else
|
||||
_sudo "in order to give $username a safe home directory" \
|
||||
/usr/bin/dscl . -create "$dsclpath" "NFSHomeDirectory" "/var/empty"
|
||||
row " NFSHomeDirectory" "/var/empty"
|
||||
fi
|
||||
|
||||
if [ "$(dsclattr "$dsclpath" "RealName")" = "Nix build user $coreid" ]; then
|
||||
row " RealName" "Nix build user $coreid"
|
||||
else
|
||||
_sudo "in order to give $username a useful name" \
|
||||
/usr/bin/dscl . -create "$dsclpath" "RealName" "Nix build user $coreid"
|
||||
row " RealName" "Nix build user $coreid"
|
||||
fi
|
||||
|
||||
if [ "$(dsclattr "$dsclpath" "UserShell")" = "/sbin/nologin" ]; then
|
||||
row " Logins Disabled" "Yes"
|
||||
else
|
||||
_sudo "in order to prevent $username from logging in" \
|
||||
/usr/bin/dscl . -create "$dsclpath" "UserShell" "/sbin/nologin"
|
||||
row " Logins Disabled" "Yes"
|
||||
fi
|
||||
|
||||
if dseditgroup -o checkmember -m "$username" "$NIX_BUILD_GROUP_NAME" > /dev/null 2>&1 ; then
|
||||
row " Member of $NIX_BUILD_GROUP_NAME" "Yes"
|
||||
else
|
||||
_sudo "Add $username to the $NIX_BUILD_GROUP_NAME group"\
|
||||
/usr/sbin/dseditgroup -o edit -t user \
|
||||
-a "$username" "$NIX_BUILD_GROUP_NAME"
|
||||
row " Member of $NIX_BUILD_GROUP_NAME" "Yes"
|
||||
fi
|
||||
|
||||
if [ "$(dsclattr "$dsclpath" "PrimaryGroupID")" = "$NIX_BUILD_GROUP_ID" ]; then
|
||||
row " PrimaryGroupID" "$NIX_BUILD_GROUP_ID"
|
||||
else
|
||||
_sudo "to let the nix daemon use this user for builds (this might seem redundant, but there are two concepts of group membership)" \
|
||||
/usr/bin/dscl . -create "$dsclpath" "PrimaryGroupID" "$NIX_BUILD_GROUP_ID"
|
||||
row " PrimaryGroupID" "$NIX_BUILD_GROUP_ID"
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
create_build_users() {
|
||||
for i in $(seq 1 "$NIX_USER_COUNT"); do
|
||||
create_build_user_for_core "$i"
|
||||
done
|
||||
}
|
||||
|
||||
create_directories() {
|
||||
_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}
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 2)" \
|
||||
mkdir -pv -m 1777 /nix/var/nix/{gcroots,profiles}/per-user
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 3)" \
|
||||
mkdir -pv -m 1775 /nix/store
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 4)" \
|
||||
chgrp "$NIX_BUILD_GROUP_NAME" /nix/store
|
||||
|
||||
_sudo "to set up the root user's profile (part 1)" \
|
||||
mkdir -pv -m 0755 /nix/var/nix/profiles/per-user/root
|
||||
|
||||
_sudo "to set up the root user's profile (part 2)" \
|
||||
mkdir -pv -m 0700 "$ROOT_HOME/.nix-defexpr"
|
||||
|
||||
_sudo "to place the default nix daemon configuration (part 1)" \
|
||||
mkdir -pv -m 0555 /etc/nix
|
||||
}
|
||||
|
||||
place_channel_configuration() {
|
||||
echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > "$SCRATCH/.nix-channels"
|
||||
_sudo "to set up the default system channel (part 1)" \
|
||||
install -m 0664 "$SCRATCH/.nix-channels" "$ROOT_HOME/.nix-channels"
|
||||
}
|
||||
|
||||
welcome_to_nix() {
|
||||
ok "Welcome to the Multi-User Nix Installation"
|
||||
|
||||
cat <<EOF
|
||||
|
||||
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.
|
||||
|
||||
2. Show you what we are going to install and where. Then we will ask
|
||||
if you are ready to continue.
|
||||
|
||||
3. Create the system users and groups that the Nix daemon uses to run
|
||||
builds.
|
||||
|
||||
4. Perform the basic installation of the Nix files daemon.
|
||||
|
||||
5. Configure your shell to import special Nix Profile files, so you
|
||||
can use Nix.
|
||||
|
||||
6. Start the Nix daemon.
|
||||
|
||||
EOF
|
||||
|
||||
if ui_confirm "Would you like to see a more detailed list of what we will do?"; then
|
||||
cat <<EOF
|
||||
|
||||
We will:
|
||||
|
||||
- make sure your computer doesn't already have Nix files
|
||||
(if it does, I will tell you how to clean them up.)
|
||||
- create local users (see the list above for the users we'll make)
|
||||
- create a local group ($NIX_BUILD_GROUP_NAME)
|
||||
- install Nix in to $NIX_ROOT
|
||||
- create a configuration file in /etc/nix
|
||||
- set up the "default profile" by creating some Nix-related files in
|
||||
$ROOT_HOME
|
||||
EOF
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target" ]; then
|
||||
cat <<EOF
|
||||
- back up $profile_target to $profile_target$PROFILE_BACKUP_SUFFIX
|
||||
- update $profile_target to include some Nix configuration
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
cat <<EOF
|
||||
- load and start a LaunchDaemon (at $PLIST_DEST) for nix-daemon
|
||||
|
||||
EOF
|
||||
if ! ui_confirm "Ready to continue?"; then
|
||||
failure <<EOF
|
||||
Okay, maybe you would like to talk to the team.
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
chat_about_sudo() {
|
||||
header "let's talk about sudo"
|
||||
|
||||
if headless; then
|
||||
cat <<EOF
|
||||
This script is going to call sudo a lot. Normally, it would show you
|
||||
exactly what commands it is running and why. However, the script is
|
||||
run in a headless fashion, like this:
|
||||
|
||||
$ curl https://nixos.org/nix/install | sh
|
||||
|
||||
or maybe in a CI pipeline. Because of that, we're going to skip the
|
||||
verbose output in the interest of brevity.
|
||||
|
||||
If you would like to
|
||||
see the output, try like this:
|
||||
|
||||
$ curl -o install-nix https://nixos.org/nix/install
|
||||
$ sh ./install-nix
|
||||
|
||||
EOF
|
||||
return 0
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
This script is going to call sudo a lot. Every time we do, it'll
|
||||
output exactly what it'll do, and why.
|
||||
|
||||
Just like this:
|
||||
EOF
|
||||
|
||||
__sudo "to demonstrate how our sudo prompts look" \
|
||||
echo "this is a sudo prompt"
|
||||
|
||||
cat <<EOF
|
||||
|
||||
This might look scary, but everything can be undone by running just a
|
||||
few commands. We used to ask you to confirm each time sudo ran, but it
|
||||
was too many times. Instead, I'll just ask you this one time:
|
||||
|
||||
EOF
|
||||
if ui_confirm "Can we use sudo?"; then
|
||||
ok "Yay! Thanks! Let's get going!"
|
||||
else
|
||||
failure <<EOF
|
||||
That is okay, but we can't install.
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
install_from_extracted_nix() {
|
||||
(
|
||||
cd "$EXTRACTED_NIX_PATH"
|
||||
|
||||
_sudo "to copy the basic Nix files to the new store at $NIX_ROOT/store" \
|
||||
rsync -rlpt ./store/* "$NIX_ROOT/store/"
|
||||
|
||||
if [ -d "$NIX_INSTALLED_NIX" ]; then
|
||||
echo " Alright! We have our first nix at $NIX_INSTALLED_NIX"
|
||||
else
|
||||
failure <<EOF
|
||||
Something went wrong, and I didn't find Nix installed at
|
||||
$NIX_INSTALLED_NIX.
|
||||
EOF
|
||||
fi
|
||||
|
||||
_sudo "to initialize the Nix Database" \
|
||||
$NIX_INSTALLED_NIX/bin/nix-store --init
|
||||
|
||||
cat ./.reginfo \
|
||||
| _sudo "to load data for the first time in to the Nix Database" \
|
||||
"$NIX_INSTALLED_NIX/bin/nix-store" --load-db
|
||||
|
||||
echo " Just finished getting the nix database ready."
|
||||
)
|
||||
}
|
||||
|
||||
shell_source_lines() {
|
||||
cat <<EOF
|
||||
|
||||
# Nix
|
||||
if [ -e '$PROFILE_NIX_FILE' ]; then
|
||||
. '$PROFILE_NIX_FILE'
|
||||
fi
|
||||
# End Nix
|
||||
|
||||
EOF
|
||||
}
|
||||
configure_shell_profile() {
|
||||
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" \
|
||||
cp "$profile_target" "$profile_target$PROFILE_BACKUP_SUFFIX"
|
||||
|
||||
shell_source_lines \
|
||||
| _sudo "extend your $profile_target with nix-daemon settings" \
|
||||
tee -a "$profile_target"
|
||||
fi
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
setup_default_profile() {
|
||||
_sudo "to installing a bootstrapping Nix in to the default Profile" \
|
||||
HOME=$ROOT_HOME "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_NIX"
|
||||
|
||||
_sudo "to installing 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"
|
||||
|
||||
_sudo "to update the default channel in the default profile" \
|
||||
HOME=$ROOT_HOME NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs
|
||||
}
|
||||
|
||||
|
||||
place_nix_configuration() {
|
||||
cat <<EOF > "$SCRATCH/nix.conf"
|
||||
build-users-group = $NIX_BUILD_GROUP_NAME
|
||||
|
||||
max-jobs = $NIX_USER_COUNT
|
||||
cores = 1
|
||||
sandbox = false
|
||||
EOF
|
||||
_sudo "to place the default nix daemon configuration (part 2)" \
|
||||
install -m 0664 "$SCRATCH/nix.conf" /etc/nix/nix.conf
|
||||
}
|
||||
|
||||
configure_nix_daemon_plist() {
|
||||
_sudo "to set up the nix-daemon as a LaunchDaemon" \
|
||||
ln -sfn "/nix/var/nix/profiles/default$PLIST_DEST" "$PLIST_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
|
||||
|
||||
}
|
||||
|
||||
|
||||
main() {
|
||||
welcome_to_nix
|
||||
chat_about_sudo
|
||||
|
||||
if [ "${ALLOW_PREEXISTING_INSTALLATION:-}" = "" ]; then
|
||||
validate_starting_assumptions
|
||||
fi
|
||||
|
||||
setup_report
|
||||
|
||||
if ! ui_confirm "Ready to continue?"; then
|
||||
ok "Alright, no changes have been made :)"
|
||||
contactme
|
||||
trap finish_cleanup EXIT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
create_build_group
|
||||
create_build_users
|
||||
create_directories
|
||||
place_channel_configuration
|
||||
install_from_extracted_nix
|
||||
|
||||
configure_shell_profile
|
||||
|
||||
set +eu
|
||||
. /etc/profile
|
||||
set -eu
|
||||
|
||||
setup_default_profile
|
||||
place_nix_configuration
|
||||
configure_nix_daemon_plist
|
||||
|
||||
trap finish_success EXIT
|
||||
}
|
||||
|
||||
|
||||
main
|
||||
@@ -7,9 +7,9 @@ self="$(dirname "$0")"
|
||||
nix="@nix@"
|
||||
cacert="@cacert@"
|
||||
|
||||
|
||||
if ! [ -e "$self/.reginfo" ]; then
|
||||
echo "$0: incomplete installer (.reginfo is missing)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$USER" ]; then
|
||||
@@ -17,23 +17,6 @@ if [ -z "$USER" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$HOME" ]; then
|
||||
echo "$0: \$HOME is not set" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# macOS support for 10.10 or higher
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
if [ $(($(sw_vers -productVersion | cut -d '.' -f 2))) -lt 10 ]; then
|
||||
echo "$0: macOS $(sw_vers -productVersion) is not supported, upgrade to 10.10 or higher"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '\e[1;31mSwitching to the Multi-User Darwin Installer\e[0m\n'
|
||||
exec "$self/install-darwin-multi-user"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
printf '\e[1;31mwarning: installing Nix as root is not supported by this script!\e[0m\n'
|
||||
fi
|
||||
@@ -44,13 +27,13 @@ if ! [ -e $dest ]; then
|
||||
cmd="mkdir -m 0755 $dest && chown $USER $dest"
|
||||
echo "directory $dest does not exist; creating it by running '$cmd' using sudo" >&2
|
||||
if ! sudo sh -c "$cmd"; then
|
||||
echo "$0: please manually run '$cmd' as root to create $dest" >&2
|
||||
echo "$0: please manually run ‘$cmd’ as root to create $dest" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [ -w $dest ]; then
|
||||
echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see http://nixos.org/nix/manual/#ssec-multi-user. If you wish to continue with a single-user install for $USER please run 'chown -R $USER $dest' as root." >&2
|
||||
echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see http://nixos.org/nix/manual/#ssec-multi-user. If you wish to continue with a single-user install for $USER please run ‘chown -R $USER $dest’ as root." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -107,43 +90,37 @@ if [ -z "$_NIX_INSTALLER_TEST" ]; then
|
||||
fi
|
||||
|
||||
added=
|
||||
|
||||
# Make the shell source nix.sh during login.
|
||||
p=$HOME/.nix-profile/etc/profile.d/nix.sh
|
||||
|
||||
if [ -z "$NIX_INSTALLER_NO_MODIFY_PROFILE" ]; then
|
||||
|
||||
# Make the shell source nix.sh during login.
|
||||
p=$HOME/.nix-profile/etc/profile.d/nix.sh
|
||||
|
||||
for i in .bash_profile .bash_login .profile; do
|
||||
fn="$HOME/$i"
|
||||
if [ -w "$fn" ]; then
|
||||
if ! grep -q "$p" "$fn"; then
|
||||
echo "modifying $fn..." >&2
|
||||
echo "$0: modifying $fn..." >&2
|
||||
echo "if [ -e $p ]; then . $p; fi # added by Nix installer" >> "$fn"
|
||||
fi
|
||||
added=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
if [ -z "$added" ]; then
|
||||
cat >&2 <<EOF
|
||||
|
||||
Installation finished! To ensure that the necessary environment
|
||||
variables are set, please add the line
|
||||
|
||||
. $p
|
||||
|
||||
to your shell profile (e.g. ~/.profile).
|
||||
EOF
|
||||
else
|
||||
cat >&2 <<EOF
|
||||
|
||||
Installation finished! To ensure that the necessary environment
|
||||
variables are set, either log in again, or type
|
||||
|
||||
. $p
|
||||
|
||||
in your shell.
|
||||
EOF
|
||||
echo "$0: creating ~/.bash_profile ..." >&2
|
||||
touch ~/.bash_profile
|
||||
chmod +x ~/.bash_profile
|
||||
echo "if [ -e $p ]; then . $p; fi # added by Nix installer" >> /.bash_profile
|
||||
fi
|
||||
|
||||
cat >&2 <<EOF
|
||||
|
||||
Installation has finished successfully.
|
||||
|
||||
To start using Nix, execute in your shell:
|
||||
|
||||
$ source $p
|
||||
|
||||
EOF
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
nix_bin_scripts := \
|
||||
$(d)/nix-copy-closure \
|
||||
|
||||
bin-scripts += $(nix_bin_scripts)
|
||||
|
||||
nix_noinst_scripts := \
|
||||
$(d)/build-remote.pl \
|
||||
$(d)/nix-http-export.cgi \
|
||||
$(d)/nix-profile.sh \
|
||||
$(d)/nix-reduce-build
|
||||
@@ -8,6 +14,6 @@ noinst-scripts += $(nix_noinst_scripts)
|
||||
profiledir = $(sysconfdir)/profile.d
|
||||
|
||||
$(eval $(call install-file-as, $(d)/nix-profile.sh, $(profiledir)/nix.sh, 0644))
|
||||
$(eval $(call install-file-as, $(d)/nix-profile-daemon.sh, $(profiledir)/nix-daemon.sh, 0644))
|
||||
$(eval $(call install-program-in, $(d)/build-remote.pl, $(libexecdir)/nix))
|
||||
|
||||
clean-files += $(nix_noinst_scripts)
|
||||
clean-files += $(nix_bin_scripts) $(nix_noinst_scripts)
|
||||
|
||||
103
scripts/nix-copy-closure.in
Executable file
103
scripts/nix-copy-closure.in
Executable file
@@ -0,0 +1,103 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use utf8;
|
||||
use strict;
|
||||
use Nix::SSH;
|
||||
use Nix::Config;
|
||||
use Nix::Store;
|
||||
use Nix::CopyClosure;
|
||||
use List::Util qw(sum);
|
||||
|
||||
binmode STDERR, ":encoding(utf8)";
|
||||
|
||||
if (scalar @ARGV < 1) {
|
||||
print STDERR <<EOF
|
||||
Usage: nix-copy-closure [--from | --to] HOSTNAME [--gzip] [--bzip2] [--xz] PATHS...
|
||||
EOF
|
||||
;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
# Get the target host.
|
||||
my $sshHost;
|
||||
my $toMode = 1;
|
||||
my $includeOutputs = 0;
|
||||
my $dryRun = 0;
|
||||
my $useSubstitutes = 0;
|
||||
my $verbosity = 1;
|
||||
|
||||
|
||||
# !!! Copied from nix-pack-closure, should put this in a module.
|
||||
my @storePaths = ();
|
||||
|
||||
while (@ARGV) {
|
||||
my $arg = shift @ARGV;
|
||||
|
||||
if ($arg eq "--help") {
|
||||
exec "man nix-copy-closure" or die;
|
||||
}
|
||||
elsif ($arg eq "--gzip" || $arg eq "--bzip2" || $arg eq "--xz") {
|
||||
warn "$0: ‘$arg’ is not implemented\n" if $arg ne "--gzip";
|
||||
push @globalSshOpts, "-C";
|
||||
}
|
||||
elsif ($arg eq "--from") {
|
||||
$toMode = 0;
|
||||
}
|
||||
elsif ($arg eq "--to") {
|
||||
$toMode = 1;
|
||||
}
|
||||
elsif ($arg eq "--include-outputs") {
|
||||
$includeOutputs = 1;
|
||||
}
|
||||
elsif ($arg eq "--show-progress") {
|
||||
warn "$0: ‘$arg’ is not implemented\n";
|
||||
}
|
||||
elsif ($arg eq "--dry-run") {
|
||||
$dryRun = 1;
|
||||
}
|
||||
elsif ($arg eq "--use-substitutes" || $arg eq "-s") {
|
||||
$useSubstitutes = 1;
|
||||
}
|
||||
elsif ($arg eq "-v") {
|
||||
$verbosity++;
|
||||
setVerbosity($verbosity);
|
||||
}
|
||||
elsif (!defined $sshHost) {
|
||||
$sshHost = $arg;
|
||||
}
|
||||
else {
|
||||
push @storePaths, $arg;
|
||||
}
|
||||
}
|
||||
|
||||
die "$0: you did not specify a host name\n" unless defined $sshHost;
|
||||
|
||||
|
||||
if ($toMode) { # Copy TO the remote machine.
|
||||
Nix::CopyClosure::copyTo(
|
||||
$sshHost, [ @storePaths ],
|
||||
$includeOutputs, $dryRun, $useSubstitutes);
|
||||
}
|
||||
|
||||
else { # Copy FROM the remote machine.
|
||||
|
||||
my ($from, $to) = connectToRemoteNix($sshHost, []);
|
||||
|
||||
# Query the closure of the given store paths on the remote
|
||||
# machine. Paths are assumed to be store paths; there is no
|
||||
# resolution (following of symlinks).
|
||||
syswrite($to, pack("L<x4L<x4", 7, $includeOutputs ? 1 : 0)) or die;
|
||||
writeStrings(\@storePaths, $to);
|
||||
my @missing = grep { !isValidPath($_) } readStrings($from);
|
||||
|
||||
# Export the store paths on the remote machine and import them locally.
|
||||
if (scalar @missing > 0) {
|
||||
print STDERR "copying ", scalar @missing, " missing paths from ‘$sshHost’...\n";
|
||||
writeInt(5, $to); # == cmdExportPaths
|
||||
writeInt(0, $to); # obsolete
|
||||
writeStrings(\@missing, $to);
|
||||
importPaths(fileno($from), 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
# Only execute this file once per shell.
|
||||
if [ -n "$__ETC_PROFILE_NIX_SOURCED" ]; then return; fi
|
||||
__ETC_PROFILE_NIX_SOURCED=1
|
||||
|
||||
# Set up secure multi-user builds: non-root users build through the
|
||||
# Nix daemon.
|
||||
if [ "$USER" != root -o ! -w @localstatedir@/nix/db ]; then
|
||||
export NIX_REMOTE=daemon
|
||||
fi
|
||||
|
||||
export NIX_USER_PROFILE_DIR="@localstatedir@/nix/profiles/per-user/$USER"
|
||||
export NIX_PROFILES="@localstatedir@/nix/profiles/default $HOME/.nix-profile"
|
||||
|
||||
# Set up the per-user profile.
|
||||
mkdir -m 0755 -p $NIX_USER_PROFILE_DIR
|
||||
if ! test -O "$NIX_USER_PROFILE_DIR"; then
|
||||
echo "WARNING: bad ownership on $NIX_USER_PROFILE_DIR" >&2
|
||||
fi
|
||||
|
||||
if test -w $HOME; then
|
||||
if ! test -L $HOME/.nix-profile; then
|
||||
if test "$USER" != root; then
|
||||
ln -s $NIX_USER_PROFILE_DIR/profile $HOME/.nix-profile
|
||||
else
|
||||
# Root installs in the system-wide profile by default.
|
||||
ln -s @localstatedir@/nix/profiles/default $HOME/.nix-profile
|
||||
fi
|
||||
fi
|
||||
|
||||
# Subscribe the root user to the NixOS channel by default.
|
||||
if [ "$USER" = root -a ! -e $HOME/.nix-channels ]; then
|
||||
echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > $HOME/.nix-channels
|
||||
fi
|
||||
|
||||
# Create the per-user garbage collector roots directory.
|
||||
NIX_USER_GCROOTS_DIR=@localstatedir@/nix/gcroots/per-user/$USER
|
||||
mkdir -m 0755 -p $NIX_USER_GCROOTS_DIR
|
||||
if ! test -O "$NIX_USER_GCROOTS_DIR"; then
|
||||
echo "WARNING: bad ownership on $NIX_USER_GCROOTS_DIR" >&2
|
||||
fi
|
||||
|
||||
# Set up a default Nix expression from which to install stuff.
|
||||
if [ ! -e $HOME/.nix-defexpr -o -L $HOME/.nix-defexpr ]; then
|
||||
rm -f $HOME/.nix-defexpr
|
||||
mkdir -p $HOME/.nix-defexpr
|
||||
if [ "$USER" != root ]; then
|
||||
ln -s @localstatedir@/nix/profiles/per-user/root/channels $HOME/.nix-defexpr/channels_root
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
export NIX_SSL_CERT_FILE="@localstatedir@/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
|
||||
export NIX_PATH="@localstatedir@/nix/profiles/per-user/root/channels"
|
||||
export PATH="$HOME/.nix-profile/bin:$HOME/.nix-profile/lib/kde4/libexec:@localstatedir@/nix/profiles/default/bin:@localstatedir@/nix/profiles/default:@localstatedir@/nix/profiles/default/lib/kde4/libexec:$PATH"
|
||||
@@ -60,6 +60,12 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then
|
||||
# This part should be kept in sync with nixpkgs:nixos/modules/programs/environment.nix
|
||||
NIX_PROFILES="@localstatedir@/nix/profiles/default $NIX_USER_PROFILE_DIR"
|
||||
|
||||
for i in $NIX_PROFILES; do
|
||||
if [ -d "$i/lib/aspell" ]; then
|
||||
export ASPELL_CONF="dict-dir $i/lib/aspell"
|
||||
fi
|
||||
done
|
||||
|
||||
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
||||
if [ -e /etc/ssl/certs/ca-certificates.crt ]; then # NixOS, Ubuntu, Debian, Gentoo, Arch
|
||||
export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
|
||||
@@ -75,10 +81,10 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then
|
||||
export NIX_SSL_CERT_FILE="$NIX_LINK/etc/ca-bundle.crt"
|
||||
fi
|
||||
|
||||
if [ -n "${MANPATH}" ]; then
|
||||
if [ -n ${MANPATH} ]; then
|
||||
export MANPATH="$NIX_LINK/share/man:$MANPATH"
|
||||
fi
|
||||
|
||||
export PATH="$NIX_LINK/bin:$__savedpath"
|
||||
export PATH="$NIX_LINK/bin:$NIX_LINK/sbin:$__savedpath"
|
||||
unset __savedpath NIX_LINK NIX_USER_PROFILE_DIR NIX_PROFILES
|
||||
fi
|
||||
|
||||
31
shell.nix
31
shell.nix
@@ -1,15 +1,10 @@
|
||||
{ useClang ? false }:
|
||||
|
||||
with import <nixpkgs> {};
|
||||
|
||||
with import ./release-common.nix { inherit pkgs; };
|
||||
|
||||
(if useClang then clangStdenv else stdenv).mkDerivation {
|
||||
stdenv.mkDerivation {
|
||||
name = "nix";
|
||||
|
||||
buildInputs =
|
||||
[ curl bison flex libxml2 libxslt
|
||||
bzip2 xz brotli
|
||||
[ curl bison flex perl libxml2 libxslt bzip2 xz
|
||||
pkgconfig sqlite libsodium boehmgc
|
||||
docbook5 docbook5_xsl
|
||||
autoconf-archive
|
||||
@@ -18,18 +13,15 @@ with import ./release-common.nix { inherit pkgs; };
|
||||
customMemoryManagement = false;
|
||||
})
|
||||
autoreconfHook
|
||||
|
||||
# For nix-perl
|
||||
perl
|
||||
perlPackages.DBDSQLite
|
||||
];
|
||||
|
||||
# Tests
|
||||
git
|
||||
mercurial
|
||||
]
|
||||
++ lib.optional stdenv.isLinux libseccomp;
|
||||
|
||||
inherit configureFlags;
|
||||
configureFlags =
|
||||
[ "--disable-init-state"
|
||||
"--enable-gc"
|
||||
"--with-dbi=${perlPackages.DBI}/${perl.libPrefix}"
|
||||
"--with-dbd-sqlite=${perlPackages.DBDSQLite}/${perl.libPrefix}"
|
||||
];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
@@ -37,9 +29,6 @@ with import ./release-common.nix { inherit pkgs; };
|
||||
|
||||
shellHook =
|
||||
''
|
||||
export prefix=$(pwd)/inst
|
||||
configureFlags+=" --prefix=$prefix"
|
||||
PKG_CONFIG_PATH=$prefix/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
PATH=$prefix/bin:$PATH
|
||||
configureFlags+=" --prefix=$(pwd)/inst"
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -37,13 +37,6 @@ namespace {
|
||||
os.str(emptyStr);
|
||||
}
|
||||
|
||||
void do_pad( std::string & s,
|
||||
std::streamsize w,
|
||||
const char c,
|
||||
std::ios::fmtflags f,
|
||||
bool center)
|
||||
__attribute__ ((unused));
|
||||
|
||||
void do_pad( std::string & s,
|
||||
std::streamsize w,
|
||||
const char c,
|
||||
|
||||
@@ -1,252 +0,0 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <iomanip>
|
||||
#if __APPLE__
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "machines.hh"
|
||||
#include "shared.hh"
|
||||
#include "pathlocks.hh"
|
||||
#include "globals.hh"
|
||||
#include "serialise.hh"
|
||||
#include "store-api.hh"
|
||||
#include "derivations.hh"
|
||||
#include "local-store.hh"
|
||||
|
||||
using namespace nix;
|
||||
using std::cin;
|
||||
|
||||
static void handleAlarm(int sig) {
|
||||
}
|
||||
|
||||
std::string escapeUri(std::string uri)
|
||||
{
|
||||
std::replace(uri.begin(), uri.end(), '/', '_');
|
||||
return uri;
|
||||
}
|
||||
|
||||
static string currentLoad;
|
||||
|
||||
static AutoCloseFD openSlotLock(const Machine & m, unsigned long long slot)
|
||||
{
|
||||
return openLockFile(fmt("%s/%s-%d", currentLoad, escapeUri(m.storeUri), slot), true);
|
||||
}
|
||||
|
||||
int main (int argc, char * * argv)
|
||||
{
|
||||
return handleExceptions(argv[0], [&]() {
|
||||
initNix();
|
||||
|
||||
logger = makeJSONLogger(*logger);
|
||||
|
||||
/* Ensure we don't get any SSH passphrase or host key popups. */
|
||||
unsetenv("DISPLAY");
|
||||
unsetenv("SSH_ASKPASS");
|
||||
|
||||
if (argc != 2)
|
||||
throw UsageError("called without required arguments");
|
||||
|
||||
verbosity = (Verbosity) std::stoll(argv[1]);
|
||||
|
||||
FdSource source(STDIN_FILENO);
|
||||
|
||||
/* Read the parent's settings. */
|
||||
while (readInt(source)) {
|
||||
auto name = readString(source);
|
||||
auto value = readString(source);
|
||||
settings.set(name, value);
|
||||
}
|
||||
|
||||
settings.maxBuildJobs.set("1"); // hack to make tests with local?root= work
|
||||
|
||||
initPlugins();
|
||||
|
||||
auto store = openStore().cast<LocalStore>();
|
||||
|
||||
/* 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";
|
||||
|
||||
std::shared_ptr<Store> sshStore;
|
||||
AutoCloseFD bestSlotLock;
|
||||
|
||||
auto machines = getMachines();
|
||||
debug("got %d remote builders", machines.size());
|
||||
|
||||
if (machines.empty()) {
|
||||
std::cerr << "# decline-permanently\n";
|
||||
return;
|
||||
}
|
||||
|
||||
string drvPath;
|
||||
string storeUri;
|
||||
|
||||
while (true) {
|
||||
|
||||
try {
|
||||
auto s = readString(source);
|
||||
if (s != "try") return;
|
||||
} catch (EndOfFile &) { return; }
|
||||
|
||||
auto amWilling = readInt(source);
|
||||
auto neededSystem = readString(source);
|
||||
source >> drvPath;
|
||||
auto requiredFeatures = readStrings<std::set<std::string>>(source);
|
||||
|
||||
auto canBuildLocally = amWilling && (neededSystem == settings.thisSystem);
|
||||
|
||||
/* Error ignored here, will be caught later */
|
||||
mkdir(currentLoad.c_str(), 0777);
|
||||
|
||||
while (true) {
|
||||
bestSlotLock = -1;
|
||||
AutoCloseFD lock = openLockFile(currentLoad + "/main-lock", true);
|
||||
lockFile(lock.get(), ltWrite, true);
|
||||
|
||||
bool rightType = false;
|
||||
|
||||
Machine * bestMachine = nullptr;
|
||||
unsigned long long bestLoad = 0;
|
||||
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() &&
|
||||
m.allSupported(requiredFeatures) &&
|
||||
m.mandatoryMet(requiredFeatures)) {
|
||||
rightType = true;
|
||||
AutoCloseFD free;
|
||||
unsigned long long load = 0;
|
||||
for (unsigned long long slot = 0; slot < m.maxJobs; ++slot) {
|
||||
auto slotLock = openSlotLock(m, slot);
|
||||
if (lockFile(slotLock.get(), ltWrite, false)) {
|
||||
if (!free) {
|
||||
free = std::move(slotLock);
|
||||
}
|
||||
} else {
|
||||
++load;
|
||||
}
|
||||
}
|
||||
if (!free) {
|
||||
continue;
|
||||
}
|
||||
bool best = false;
|
||||
if (!bestSlotLock) {
|
||||
best = true;
|
||||
} else if (load / m.speedFactor < bestLoad / bestMachine->speedFactor) {
|
||||
best = true;
|
||||
} else if (load / m.speedFactor == bestLoad / bestMachine->speedFactor) {
|
||||
if (m.speedFactor > bestMachine->speedFactor) {
|
||||
best = true;
|
||||
} else if (m.speedFactor == bestMachine->speedFactor) {
|
||||
if (load < bestLoad) {
|
||||
best = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best) {
|
||||
bestLoad = load;
|
||||
bestSlotLock = std::move(free);
|
||||
bestMachine = &m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bestSlotLock) {
|
||||
if (rightType && !canBuildLocally)
|
||||
std::cerr << "# postpone\n";
|
||||
else
|
||||
std::cerr << "# decline\n";
|
||||
break;
|
||||
}
|
||||
|
||||
#if __APPLE__
|
||||
futimes(bestSlotLock.get(), NULL);
|
||||
#else
|
||||
futimens(bestSlotLock.get(), NULL);
|
||||
#endif
|
||||
|
||||
lock = -1;
|
||||
|
||||
try {
|
||||
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("connecting to '%s'", bestMachine->storeUri));
|
||||
|
||||
Store::Params storeParams;
|
||||
if (hasPrefix(bestMachine->storeUri, "ssh://")) {
|
||||
storeParams["max-connections"] ="1";
|
||||
storeParams["log-fd"] = "4";
|
||||
if (bestMachine->sshKey != "")
|
||||
storeParams["ssh-key"] = bestMachine->sshKey;
|
||||
}
|
||||
|
||||
sshStore = openStore(bestMachine->storeUri, storeParams);
|
||||
sshStore->connect();
|
||||
storeUri = bestMachine->storeUri;
|
||||
|
||||
} catch (std::exception & e) {
|
||||
printError("unable to open SSH connection to '%s': %s; trying other available machines...",
|
||||
bestMachine->storeUri, e.what());
|
||||
bestMachine->enabled = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
goto connected;
|
||||
}
|
||||
}
|
||||
|
||||
connected:
|
||||
std::cerr << "# accept\n" << storeUri << "\n";
|
||||
|
||||
auto inputs = readStrings<PathSet>(source);
|
||||
auto outputs = readStrings<PathSet>(source);
|
||||
|
||||
AutoCloseFD uploadLock = openLockFile(currentLoad + "/" + escapeUri(storeUri) + ".upload-lock", true);
|
||||
|
||||
{
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("waiting for the upload lock to '%s'", storeUri));
|
||||
|
||||
auto old = signal(SIGALRM, handleAlarm);
|
||||
alarm(15 * 60);
|
||||
if (!lockFile(uploadLock.get(), ltWrite, true))
|
||||
printError("somebody is hogging the upload lock for '%s', continuing...");
|
||||
alarm(0);
|
||||
signal(SIGALRM, old);
|
||||
}
|
||||
|
||||
auto substitute = settings.buildersUseSubstitutes ? Substitute : NoSubstitute;
|
||||
|
||||
{
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri));
|
||||
copyPaths(store, ref<Store>(sshStore), inputs, NoRepair, NoCheckSigs, substitute);
|
||||
}
|
||||
|
||||
uploadLock = -1;
|
||||
|
||||
BasicDerivation drv(readDerivation(store->realStoreDir + "/" + baseNameOf(drvPath)));
|
||||
drv.inputSrcs = inputs;
|
||||
|
||||
auto result = sshStore->buildDerivation(drvPath, drv);
|
||||
|
||||
if (!result.success())
|
||||
throw Error("build of '%s' on '%s' failed: %s", drvPath, storeUri, result.errorMsg);
|
||||
|
||||
PathSet missing;
|
||||
for (auto & path : outputs)
|
||||
if (!store->isValidPath(path)) missing.insert(path);
|
||||
|
||||
if (!missing.empty()) {
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri));
|
||||
store->locksHeld.insert(missing.begin(), missing.end()); /* FIXME: ugly */
|
||||
copyPaths(ref<Store>(sshStore), store, missing, NoRepair, NoCheckSigs, substitute);
|
||||
}
|
||||
|
||||
return;
|
||||
});
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
programs += build-remote
|
||||
|
||||
build-remote_DIR := $(d)
|
||||
|
||||
build-remote_INSTALL_DIR := $(libexecdir)/nix
|
||||
|
||||
build-remote_LIBS = libmain libutil libformat libstore
|
||||
|
||||
build-remote_SOURCES := $(d)/build-remote.cc
|
||||
@@ -12,7 +12,7 @@ static bool isDirectory (const Path & path)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(path.c_str(), &st) == -1)
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
throw SysError(format("getting status of ‘%1%’") % path);
|
||||
return S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
@@ -53,18 +53,18 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
|
||||
} else if (S_ISLNK(dstSt.st_mode)) {
|
||||
auto target = readLink(dstFile);
|
||||
if (!isDirectory(target))
|
||||
throw Error(format("collision between '%1%' and non-directory '%2%'")
|
||||
throw Error(format("collision between ‘%1%’ and non-directory ‘%2%’")
|
||||
% srcFile % target);
|
||||
if (unlink(dstFile.c_str()) == -1)
|
||||
throw SysError(format("unlinking '%1%'") % dstFile);
|
||||
throw SysError(format("unlinking ‘%1%’") % dstFile);
|
||||
if (mkdir(dstFile.c_str(), 0755) == -1)
|
||||
throw SysError(format("creating directory '%1%'"));
|
||||
throw SysError(format("creating directory ‘%1%’"));
|
||||
createLinks(target, dstFile, priorities[dstFile]);
|
||||
createLinks(srcFile, dstFile, priority);
|
||||
continue;
|
||||
}
|
||||
} else if (errno != ENOENT)
|
||||
throw SysError(format("getting status of '%1%'") % dstFile);
|
||||
throw SysError(format("getting status of ‘%1%’") % dstFile);
|
||||
} else {
|
||||
struct stat dstSt;
|
||||
auto res = lstat(dstFile.c_str(), &dstSt);
|
||||
@@ -74,18 +74,17 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
|
||||
auto prevPriority = priorities[dstFile];
|
||||
if (prevPriority == priority)
|
||||
throw Error(format(
|
||||
"Packages '%1%' and '%2%' have the same priority '%3%'"
|
||||
"use 'nix-env --set-flag priority NUMBER INSTALLED_PKGNAME' "
|
||||
"collision between ‘%1%’ and ‘%2%’; "
|
||||
"use ‘nix-env --set-flag priority NUMBER PKGNAME’ "
|
||||
"to change the priority of one of the conflicting packages"
|
||||
" ('0' being the highest priority)"
|
||||
) % srcFile % target % priority);
|
||||
) % srcFile % target);
|
||||
if (prevPriority < priority)
|
||||
continue;
|
||||
if (unlink(dstFile.c_str()) == -1)
|
||||
throw SysError(format("unlinking '%1%'") % dstFile);
|
||||
throw SysError(format("unlinking ‘%1%’") % dstFile);
|
||||
}
|
||||
} else if (errno != ENOENT)
|
||||
throw SysError(format("getting status of '%1%'") % dstFile);
|
||||
throw SysError(format("getting status of ‘%1%’") % dstFile);
|
||||
}
|
||||
createSymlink(srcFile, dstFile);
|
||||
priorities[dstFile] = priority;
|
||||
@@ -113,11 +112,11 @@ static void addPkg(const Path & pkgDir, int priority)
|
||||
if (!fd) {
|
||||
if (errno == ENOENT)
|
||||
return;
|
||||
throw SysError(format("opening '%1%'") % propagatedFN);
|
||||
throw SysError(format("opening ‘%1%’") % propagatedFN);
|
||||
}
|
||||
propagated = readFile(fd.get());
|
||||
propagated = readLine(fd.get());
|
||||
}
|
||||
for (const auto & p : tokenizeString<std::vector<string>>(propagated, " \n"))
|
||||
for (const auto & p : tokenizeString<std::vector<string>>(propagated, " "))
|
||||
if (done.find(p) == done.end())
|
||||
postponed.insert(p);
|
||||
}
|
||||
|
||||
141
src/download-via-ssh/download-via-ssh.cc
Normal file
141
src/download-via-ssh/download-via-ssh.cc
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "shared.hh"
|
||||
#include "util.hh"
|
||||
#include "serialise.hh"
|
||||
#include "archive.hh"
|
||||
#include "affinity.hh"
|
||||
#include "globals.hh"
|
||||
#include "serve-protocol.hh"
|
||||
#include "worker-protocol.hh"
|
||||
#include "store-api.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace nix;
|
||||
|
||||
// !!! TODO:
|
||||
// * Respect more than the first host
|
||||
// * use a database
|
||||
// * show progress
|
||||
|
||||
|
||||
static std::pair<FdSink, FdSource> connect(const string & conn)
|
||||
{
|
||||
Pipe to, from;
|
||||
to.create();
|
||||
from.create();
|
||||
startProcess([&]() {
|
||||
if (dup2(to.readSide, STDIN_FILENO) == -1)
|
||||
throw SysError("dupping stdin");
|
||||
if (dup2(from.writeSide, STDOUT_FILENO) == -1)
|
||||
throw SysError("dupping stdout");
|
||||
execlp("ssh", "ssh", "-x", "-T", conn.c_str(), "nix-store --serve", NULL);
|
||||
throw SysError("executing ssh");
|
||||
});
|
||||
// If child exits unexpectedly, we'll EPIPE or EOF early.
|
||||
// If we exit unexpectedly, child will EPIPE or EOF early.
|
||||
// So no need to keep track of it.
|
||||
|
||||
return std::pair<FdSink, FdSource>(to.writeSide.borrow(), from.readSide.borrow());
|
||||
}
|
||||
|
||||
|
||||
static void substitute(std::pair<FdSink, FdSource> & pipes, Path storePath, Path destPath)
|
||||
{
|
||||
pipes.first << cmdDumpStorePath << storePath;
|
||||
pipes.first.flush();
|
||||
restorePath(destPath, pipes.second);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
static void query(std::pair<FdSink, FdSource> & pipes)
|
||||
{
|
||||
for (string line; getline(std::cin, line);) {
|
||||
Strings tokenized = tokenizeString<Strings>(line);
|
||||
string cmd = tokenized.front();
|
||||
tokenized.pop_front();
|
||||
if (cmd == "have") {
|
||||
pipes.first
|
||||
<< cmdQueryValidPaths
|
||||
<< 0 // don't lock
|
||||
<< 0 // don't substitute
|
||||
<< tokenized;
|
||||
pipes.first.flush();
|
||||
PathSet paths = readStrings<PathSet>(pipes.second);
|
||||
for (auto & i : paths)
|
||||
std::cout << i << std::endl;
|
||||
} else if (cmd == "info") {
|
||||
pipes.first << cmdQueryPathInfos << tokenized;
|
||||
pipes.first.flush();
|
||||
while (1) {
|
||||
Path path = readString(pipes.second);
|
||||
if (path.empty()) break;
|
||||
assertStorePath(path);
|
||||
std::cout << path << std::endl;
|
||||
string deriver = readString(pipes.second);
|
||||
if (!deriver.empty()) assertStorePath(deriver);
|
||||
std::cout << deriver << std::endl;
|
||||
PathSet references = readStorePaths<PathSet>(pipes.second);
|
||||
std::cout << references.size() << std::endl;
|
||||
for (auto & i : references)
|
||||
std::cout << i << std::endl;
|
||||
std::cout << readLongLong(pipes.second) << std::endl;
|
||||
std::cout << readLongLong(pipes.second) << std::endl;
|
||||
}
|
||||
} else
|
||||
throw Error(format("unknown substituter query ‘%1%’") % cmd);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * * argv)
|
||||
{
|
||||
return handleExceptions(argv[0], [&]() {
|
||||
if (argc < 2)
|
||||
throw UsageError("download-via-ssh requires an argument");
|
||||
|
||||
initNix();
|
||||
|
||||
settings.update();
|
||||
|
||||
if (settings.sshSubstituterHosts.empty())
|
||||
return;
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
/* Pass on the location of the daemon client's SSH
|
||||
authentication socket. */
|
||||
string sshAuthSock = settings.get("ssh-auth-sock", string(""));
|
||||
if (sshAuthSock != "") setenv("SSH_AUTH_SOCK", sshAuthSock.c_str(), 1);
|
||||
|
||||
string host = settings.sshSubstituterHosts.front();
|
||||
std::pair<FdSink, FdSource> pipes = connect(host);
|
||||
|
||||
/* Exchange the greeting */
|
||||
pipes.first << SERVE_MAGIC_1;
|
||||
pipes.first.flush();
|
||||
unsigned int magic = readInt(pipes.second);
|
||||
if (magic != SERVE_MAGIC_2)
|
||||
throw Error("protocol mismatch");
|
||||
readInt(pipes.second); // Server version, unused for now
|
||||
pipes.first << SERVE_PROTOCOL_VERSION;
|
||||
pipes.first.flush();
|
||||
|
||||
string arg = argv[1];
|
||||
if (arg == "--query")
|
||||
query(pipes);
|
||||
else if (arg == "--substitute") {
|
||||
if (argc != 4)
|
||||
throw UsageError("download-via-ssh: --substitute takes exactly two arguments");
|
||||
Path storePath = argv[2];
|
||||
Path destPath = argv[3];
|
||||
printError(format("downloading ‘%1%’ via SSH from ‘%2%’...") % storePath % host);
|
||||
substitute(pipes, storePath, destPath);
|
||||
}
|
||||
else
|
||||
throw UsageError(format("download-via-ssh: unknown command ‘%1%’") % arg);
|
||||
});
|
||||
}
|
||||
11
src/download-via-ssh/local.mk
Normal file
11
src/download-via-ssh/local.mk
Normal file
@@ -0,0 +1,11 @@
|
||||
programs += download-via-ssh
|
||||
|
||||
download-via-ssh_DIR := $(d)
|
||||
|
||||
download-via-ssh_SOURCES := $(d)/download-via-ssh.cc
|
||||
|
||||
download-via-ssh_INSTALL_DIR := $(libexecdir)/nix/substituters
|
||||
|
||||
download-via-ssh_CXXFLAGS = -Isrc/nix-store
|
||||
|
||||
download-via-ssh_LIBS = libmain libstore libutil libformat
|
||||
@@ -19,7 +19,7 @@ static Strings parseAttrPath(const string & s)
|
||||
++i;
|
||||
while (1) {
|
||||
if (i == s.end())
|
||||
throw Error(format("missing closing quote in selection path '%1%'") % s);
|
||||
throw Error(format("missing closing quote in selection path ‘%1%’") % s);
|
||||
if (*i == '"') break;
|
||||
cur.push_back(*i++);
|
||||
}
|
||||
@@ -38,7 +38,7 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
|
||||
Strings tokens = parseAttrPath(attrPath);
|
||||
|
||||
Error attrError =
|
||||
Error(format("attribute selection path '%1%' does not match expression") % attrPath);
|
||||
Error(format("attribute selection path ‘%1%’ does not match expression") % attrPath);
|
||||
|
||||
Value * v = &vIn;
|
||||
|
||||
@@ -62,15 +62,15 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
|
||||
|
||||
if (v->type != tAttrs)
|
||||
throw TypeError(
|
||||
format("the expression selected by the selection path '%1%' should be a set but is %2%")
|
||||
format("the expression selected by the selection path ‘%1%’ should be a set but is %2%")
|
||||
% attrPath % showType(*v));
|
||||
|
||||
if (attr.empty())
|
||||
throw Error(format("empty attribute name in selection path '%1%'") % attrPath);
|
||||
throw Error(format("empty attribute name in selection path ‘%1%’") % attrPath);
|
||||
|
||||
Bindings::iterator a = v->attrs->find(state.symbols.create(attr));
|
||||
if (a == v->attrs->end())
|
||||
throw Error(format("attribute '%1%' in selection path '%2%' not found") % attr % attrPath);
|
||||
throw Error(format("attribute ‘%1%’ in selection path ‘%2%’ not found") % attr % attrPath);
|
||||
v = &*a->value;
|
||||
}
|
||||
|
||||
@@ -78,11 +78,11 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
|
||||
|
||||
if (!v->isList())
|
||||
throw TypeError(
|
||||
format("the expression selected by the selection path '%1%' should be a list but is %2%")
|
||||
format("the expression selected by the selection path ‘%1%’ should be a list but is %2%")
|
||||
% attrPath % showType(*v));
|
||||
|
||||
if (attrIndex >= v->listSize())
|
||||
throw Error(format("list index %1% in selection path '%2%' is out of range") % attrIndex % attrPath);
|
||||
throw Error(format("list index %1% in selection path ‘%2%’ is out of range") % attrIndex % attrPath);
|
||||
|
||||
v = v->listElems()[attrIndex];
|
||||
}
|
||||
|
||||
@@ -7,14 +7,13 @@
|
||||
namespace nix {
|
||||
|
||||
|
||||
/* Note: Various places expect the allocated memory to be zeroed. */
|
||||
static void * allocBytes(size_t n)
|
||||
{
|
||||
void * p;
|
||||
#if HAVE_BOEHMGC
|
||||
p = GC_malloc(n);
|
||||
#else
|
||||
p = calloc(n, 1);
|
||||
p = malloc(n);
|
||||
#endif
|
||||
if (!p) throw std::bad_alloc();
|
||||
return p;
|
||||
|
||||
@@ -75,19 +75,6 @@ public:
|
||||
|
||||
size_t capacity() { return capacity_; }
|
||||
|
||||
/* Returns the attributes in lexicographically sorted order. */
|
||||
std::vector<const Attr *> lexicographicOrder() const
|
||||
{
|
||||
std::vector<const Attr *> res;
|
||||
res.reserve(size_);
|
||||
for (size_t n = 0; n < size_; n++)
|
||||
res.emplace_back(&attrs[n]);
|
||||
std::sort(res.begin(), res.end(), [](const Attr * a, const Attr * b) {
|
||||
return (const string &) a->name < (const string &) b->name;
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
friend class EvalState;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#include "common-eval-args.hh"
|
||||
#include "shared.hh"
|
||||
#include "download.hh"
|
||||
#include "util.hh"
|
||||
#include "eval.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
MixEvalArgs::MixEvalArgs()
|
||||
{
|
||||
mkFlag()
|
||||
.longName("arg")
|
||||
.description("argument to be passed to Nix functions")
|
||||
.labels({"name", "expr"})
|
||||
.handler([&](std::vector<std::string> ss) { autoArgs[ss[0]] = 'E' + ss[1]; });
|
||||
|
||||
mkFlag()
|
||||
.longName("argstr")
|
||||
.description("string-valued argument to be passed to Nix functions")
|
||||
.labels({"name", "string"})
|
||||
.handler([&](std::vector<std::string> ss) { autoArgs[ss[0]] = 'S' + ss[1]; });
|
||||
|
||||
mkFlag()
|
||||
.shortName('I')
|
||||
.longName("include")
|
||||
.description("add a path to the list of locations used to look up <...> file names")
|
||||
.label("path")
|
||||
.handler([&](std::string s) { searchPath.push_back(s); });
|
||||
}
|
||||
|
||||
Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
|
||||
{
|
||||
Bindings * res = state.allocBindings(autoArgs.size());
|
||||
for (auto & i : autoArgs) {
|
||||
Value * v = state.allocValue();
|
||||
if (i.second[0] == 'E')
|
||||
state.mkThunk_(*v, state.parseExprFromString(string(i.second, 1), absPath(".")));
|
||||
else
|
||||
mkString(*v, string(i.second, 1));
|
||||
res->push_back(Attr(state.symbols.create(i.first), v));
|
||||
}
|
||||
res->sort();
|
||||
return res;
|
||||
}
|
||||
|
||||
Path lookupFileArg(EvalState & state, string s)
|
||||
{
|
||||
if (isUri(s))
|
||||
return getDownloader()->downloadCached(state.store, s, true);
|
||||
else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
||||
Path p = s.substr(1, s.size() - 2);
|
||||
return state.findFile(p);
|
||||
} else
|
||||
return absPath(s);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "args.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
class Store;
|
||||
class EvalState;
|
||||
class Bindings;
|
||||
|
||||
struct MixEvalArgs : virtual Args
|
||||
{
|
||||
MixEvalArgs();
|
||||
|
||||
Bindings * getAutoArgs(EvalState & state);
|
||||
|
||||
Strings searchPath;
|
||||
|
||||
private:
|
||||
|
||||
std::map<std::string, std::string> autoArgs;
|
||||
};
|
||||
|
||||
Path lookupFileArg(EvalState & state, string s);
|
||||
|
||||
}
|
||||
67
src/libexpr/common-opts.cc
Normal file
67
src/libexpr/common-opts.cc
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "common-opts.hh"
|
||||
#include "shared.hh"
|
||||
#include "download.hh"
|
||||
#include "util.hh"
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
bool parseAutoArgs(Strings::iterator & i,
|
||||
const Strings::iterator & argsEnd, std::map<string, string> & res)
|
||||
{
|
||||
string arg = *i;
|
||||
if (arg != "--arg" && arg != "--argstr") return false;
|
||||
|
||||
UsageError error(format("‘%1%’ requires two arguments") % arg);
|
||||
|
||||
if (++i == argsEnd) throw error;
|
||||
string name = *i;
|
||||
if (++i == argsEnd) throw error;
|
||||
string value = *i;
|
||||
|
||||
res[name] = (arg == "--arg" ? 'E' : 'S') + value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Bindings * evalAutoArgs(EvalState & state, std::map<string, string> & in)
|
||||
{
|
||||
Bindings * res = state.allocBindings(in.size());
|
||||
for (auto & i : in) {
|
||||
Value * v = state.allocValue();
|
||||
if (i.second[0] == 'E')
|
||||
state.mkThunk_(*v, state.parseExprFromString(string(i.second, 1), absPath(".")));
|
||||
else
|
||||
mkString(*v, string(i.second, 1));
|
||||
res->push_back(Attr(state.symbols.create(i.first), v));
|
||||
}
|
||||
res->sort();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool parseSearchPathArg(Strings::iterator & i,
|
||||
const Strings::iterator & argsEnd, Strings & searchPath)
|
||||
{
|
||||
if (*i != "-I") return false;
|
||||
if (++i == argsEnd) throw UsageError("‘-I’ requires an argument");
|
||||
searchPath.push_back(*i);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Path lookupFileArg(EvalState & state, string s)
|
||||
{
|
||||
if (isUri(s))
|
||||
return getDownloader()->downloadCached(state.store, s, true);
|
||||
else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
||||
Path p = s.substr(1, s.size() - 2);
|
||||
return state.findFile(p);
|
||||
} else
|
||||
return absPath(s);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
20
src/libexpr/common-opts.hh
Normal file
20
src/libexpr/common-opts.hh
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "eval.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
class Store;
|
||||
|
||||
/* Some common option parsing between nix-env and nix-instantiate. */
|
||||
bool parseAutoArgs(Strings::iterator & i,
|
||||
const Strings::iterator & argsEnd, std::map<string, string> & res);
|
||||
|
||||
Bindings * evalAutoArgs(EvalState & state, std::map<string, string> & in);
|
||||
|
||||
bool parseSearchPathArg(Strings::iterator & i,
|
||||
const Strings::iterator & argsEnd, Strings & searchPath);
|
||||
|
||||
Path lookupFileArg(EvalState & state, string s);
|
||||
|
||||
}
|
||||
@@ -33,7 +33,7 @@ void EvalState::forceValue(Value & v, const Pos & pos)
|
||||
v.type = tBlackhole;
|
||||
//checkInterrupt();
|
||||
expr->eval(*this, *env, v);
|
||||
} catch (...) {
|
||||
} catch (Error & e) {
|
||||
v.type = tThunk;
|
||||
v.thunk.env = env;
|
||||
v.thunk.expr = expr;
|
||||
|
||||
@@ -43,14 +43,13 @@ static char * dupString(const char * s)
|
||||
}
|
||||
|
||||
|
||||
/* Note: Various places expect the allocated memory to be zeroed. */
|
||||
static void * allocBytes(size_t n)
|
||||
{
|
||||
void * p;
|
||||
#if HAVE_BOEHMGC
|
||||
p = GC_malloc(n);
|
||||
#else
|
||||
p = calloc(n, 1);
|
||||
p = malloc(n);
|
||||
#endif
|
||||
if (!p) throw std::bad_alloc();
|
||||
return p;
|
||||
@@ -92,9 +91,13 @@ static void printValue(std::ostream & str, std::set<const Value *> & active, con
|
||||
break;
|
||||
case tAttrs: {
|
||||
str << "{ ";
|
||||
for (auto & i : v.attrs->lexicographicOrder()) {
|
||||
str << i->name << " = ";
|
||||
printValue(str, active, *i->value);
|
||||
typedef std::map<string, Value *> Sorted;
|
||||
Sorted sorted;
|
||||
for (auto & i : *v.attrs)
|
||||
sorted[i.name] = i.value;
|
||||
for (auto & i : sorted) {
|
||||
str << i.first << " = ";
|
||||
printValue(str, active, *i.second);
|
||||
str << "; ";
|
||||
}
|
||||
str << "}";
|
||||
@@ -150,7 +153,7 @@ string showType(const Value & v)
|
||||
switch (v.type) {
|
||||
case tInt: return "an integer";
|
||||
case tBool: return "a boolean";
|
||||
case tString: return v.string.context ? "a string with context" : "a string";
|
||||
case tString: return "a string";
|
||||
case tPath: return "a path";
|
||||
case tNull: return "null";
|
||||
case tAttrs: return "a set";
|
||||
@@ -203,7 +206,7 @@ void initGC()
|
||||
|
||||
GC_INIT();
|
||||
|
||||
GC_set_oom_fn(oomHandler);
|
||||
GC_oom_fn = oomHandler;
|
||||
|
||||
/* Set the initial heap size to something fairly big (25% of
|
||||
physical RAM, up to a maximum of 384 MiB) so that in most cases
|
||||
@@ -292,37 +295,21 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
|
||||
, sToString(symbols.create("__toString"))
|
||||
, sRight(symbols.create("right"))
|
||||
, sWrong(symbols.create("wrong"))
|
||||
, sStructuredAttrs(symbols.create("__structuredAttrs"))
|
||||
, sBuilder(symbols.create("builder"))
|
||||
, sArgs(symbols.create("args"))
|
||||
, sOutputHash(symbols.create("outputHash"))
|
||||
, sOutputHashAlgo(symbols.create("outputHashAlgo"))
|
||||
, sOutputHashMode(symbols.create("outputHashMode"))
|
||||
, repair(NoRepair)
|
||||
, store(store)
|
||||
, baseEnv(allocEnv(128))
|
||||
, staticBaseEnv(false, 0)
|
||||
{
|
||||
countCalls = getEnv("NIX_COUNT_CALLS", "0") != "0";
|
||||
|
||||
restricted = settings.get("restrict-eval", false);
|
||||
|
||||
assert(gcInitialised);
|
||||
|
||||
/* Initialise the Nix expression search path. */
|
||||
if (!settings.pureEval) {
|
||||
Strings paths = parseNixPath(getEnv("NIX_PATH", ""));
|
||||
for (auto & i : _searchPath) addToSearchPath(i);
|
||||
for (auto & i : paths) addToSearchPath(i);
|
||||
}
|
||||
addToSearchPath("nix=" + canonPath(settings.nixDataDir + "/nix/corepkgs"));
|
||||
|
||||
if (settings.restrictEval || settings.pureEval) {
|
||||
allowedPaths = PathSet();
|
||||
for (auto & i : searchPath) {
|
||||
auto r = resolveSearchPathElem(i);
|
||||
if (!r.first) continue;
|
||||
allowedPaths->insert(r.second);
|
||||
}
|
||||
}
|
||||
Strings paths = parseNixPath(getEnv("NIX_PATH", ""));
|
||||
for (auto & i : _searchPath) addToSearchPath(i);
|
||||
for (auto & i : paths) addToSearchPath(i);
|
||||
addToSearchPath("nix=" + settings.nixDataDir + "/nix/corepkgs");
|
||||
|
||||
clearValue(vEmptySet);
|
||||
vEmptySet.type = tAttrs;
|
||||
@@ -340,76 +327,36 @@ EvalState::~EvalState()
|
||||
|
||||
Path EvalState::checkSourcePath(const Path & path_)
|
||||
{
|
||||
if (!allowedPaths) return path_;
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (auto & i : *allowedPaths) {
|
||||
if (isDirOrInDir(path_, i)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
throw RestrictedPathError("access to path '%1%' is forbidden in restricted mode", path_);
|
||||
if (!restricted) return path_;
|
||||
|
||||
/* Resolve symlinks. */
|
||||
debug(format("checking access to '%s'") % path_);
|
||||
debug(format("checking access to ‘%s’") % path_);
|
||||
Path path = canonPath(path_, true);
|
||||
|
||||
for (auto & i : *allowedPaths) {
|
||||
if (isDirOrInDir(path, i))
|
||||
for (auto & i : searchPath) {
|
||||
auto r = resolveSearchPathElem(i);
|
||||
if (!r.first) continue;
|
||||
if (path == r.second || isInDir(path, r.second))
|
||||
return path;
|
||||
}
|
||||
|
||||
throw RestrictedPathError("access to path '%1%' is forbidden in restricted mode", path);
|
||||
/* To support import-from-derivation, allow access to anything in
|
||||
the store. FIXME: only allow access to paths that have been
|
||||
constructed by this evaluation. */
|
||||
if (store->isInStore(path)) return path;
|
||||
|
||||
#if 0
|
||||
/* Hack to support the chroot dependencies of corepkgs (see
|
||||
corepkgs/config.nix.in). */
|
||||
if (path == settings.nixPrefix && isStorePath(settings.nixPrefix))
|
||||
return path;
|
||||
#endif
|
||||
|
||||
throw RestrictedPathError(format("access to path ‘%1%’ is forbidden in restricted mode") % path_);
|
||||
}
|
||||
|
||||
|
||||
void EvalState::checkURI(const std::string & uri)
|
||||
{
|
||||
if (!settings.restrictEval) return;
|
||||
|
||||
/* 'uri' should be equal to a prefix, or in a subdirectory of a
|
||||
prefix. Thus, the prefix https://github.co does not permit
|
||||
access to https://github.com. Note: this allows 'http://' and
|
||||
'https://' as prefixes for any http/https URI. */
|
||||
for (auto & prefix : settings.allowedUris.get())
|
||||
if (uri == prefix ||
|
||||
(uri.size() > prefix.size()
|
||||
&& prefix.size() > 0
|
||||
&& hasPrefix(uri, prefix)
|
||||
&& (prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/')))
|
||||
return;
|
||||
|
||||
/* If the URI is a path, then check it against allowedPaths as
|
||||
well. */
|
||||
if (hasPrefix(uri, "/")) {
|
||||
checkSourcePath(uri);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasPrefix(uri, "file://")) {
|
||||
checkSourcePath(std::string(uri, 7));
|
||||
return;
|
||||
}
|
||||
|
||||
throw RestrictedPathError("access to URI '%s' is forbidden in restricted mode", uri);
|
||||
}
|
||||
|
||||
|
||||
Path EvalState::toRealPath(const Path & path, const PathSet & context)
|
||||
{
|
||||
// FIXME: check whether 'path' is in 'context'.
|
||||
return
|
||||
!context.empty() && store->isInStore(path)
|
||||
? store->toRealPath(path)
|
||||
: path;
|
||||
};
|
||||
|
||||
|
||||
Value * EvalState::addConstant(const string & name, Value & v)
|
||||
void EvalState::addConstant(const string & name, Value & v)
|
||||
{
|
||||
Value * v2 = allocValue();
|
||||
*v2 = v;
|
||||
@@ -417,18 +364,12 @@ Value * EvalState::addConstant(const string & name, Value & v)
|
||||
baseEnv.values[baseEnvDispl++] = v2;
|
||||
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
|
||||
baseEnv.values[0]->attrs->push_back(Attr(symbols.create(name2), v2));
|
||||
return v2;
|
||||
}
|
||||
|
||||
|
||||
Value * EvalState::addPrimOp(const string & name,
|
||||
void EvalState::addPrimOp(const string & name,
|
||||
unsigned int arity, PrimOpFun primOp)
|
||||
{
|
||||
if (arity == 0) {
|
||||
Value v;
|
||||
primOp(*this, noPos, nullptr, v);
|
||||
return addConstant(name, v);
|
||||
}
|
||||
Value * v = allocValue();
|
||||
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
|
||||
Symbol sym = symbols.create(name2);
|
||||
@@ -437,7 +378,6 @@ Value * EvalState::addPrimOp(const string & name,
|
||||
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl;
|
||||
baseEnv.values[baseEnvDispl++] = v;
|
||||
baseEnv.values[0]->attrs->push_back(Attr(sym, v));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
@@ -565,7 +505,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
||||
return j->value;
|
||||
}
|
||||
if (!env->prevWith)
|
||||
throwUndefinedVarError("undefined variable '%1%' at %2%", var.name, var.pos);
|
||||
throwUndefinedVarError("undefined variable ‘%1%’ at %2%", var.name, var.pos);
|
||||
for (unsigned int l = env->prevWith; l; --l, env = env->up) ;
|
||||
}
|
||||
}
|
||||
@@ -587,7 +527,9 @@ Env & EvalState::allocEnv(unsigned int size)
|
||||
Env * env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *));
|
||||
env->size = size;
|
||||
|
||||
/* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */
|
||||
/* Clear the values because maybeThunk() and lookupVar fromWith expect this. */
|
||||
for (unsigned i = 0; i < size; ++i)
|
||||
env->values[i] = 0;
|
||||
|
||||
return *env;
|
||||
}
|
||||
@@ -688,10 +630,8 @@ Value * ExprPath::maybeThunk(EvalState & state, Env & env)
|
||||
}
|
||||
|
||||
|
||||
void EvalState::evalFile(const Path & path_, Value & v)
|
||||
void EvalState::evalFile(const Path & path, Value & v)
|
||||
{
|
||||
auto path = checkSourcePath(path_);
|
||||
|
||||
FileEvalCache::iterator i;
|
||||
if ((i = fileEvalCache.find(path)) != fileEvalCache.end()) {
|
||||
v = i->second;
|
||||
@@ -704,12 +644,12 @@ void EvalState::evalFile(const Path & path_, Value & v)
|
||||
return;
|
||||
}
|
||||
|
||||
printTalkative("evaluating file '%1%'", path2);
|
||||
Activity act(*logger, lvlTalkative, format("evaluating file ‘%1%’") % path2);
|
||||
Expr * e = parseExprFromFile(checkSourcePath(path2));
|
||||
try {
|
||||
eval(e, v);
|
||||
} catch (Error & e) {
|
||||
addErrorPrefix(e, "while evaluating the file '%1%':\n", path2);
|
||||
addErrorPrefix(e, "while evaluating the file ‘%1%’:\n", path2);
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -859,7 +799,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||
Symbol nameSym = state.symbols.create(nameVal.string.s);
|
||||
Bindings::iterator j = v.attrs->find(nameSym);
|
||||
if (j != v.attrs->end())
|
||||
throwEvalError("dynamic attribute '%1%' at %2% already defined at %3%", nameSym, i.pos, *j->pos);
|
||||
throwEvalError("dynamic attribute ‘%1%’ at %2% already defined at %3%", nameSym, i.pos, *j->pos);
|
||||
|
||||
i.valueExpr->setName(nameSym);
|
||||
/* Keep sorted order so find can catch duplicates */
|
||||
@@ -947,7 +887,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||
} else {
|
||||
state.forceAttrs(*vAttrs, pos);
|
||||
if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
|
||||
throwEvalError("attribute '%1%' missing, at %2%", name, pos);
|
||||
throwEvalError("attribute ‘%1%’ missing, at %2%", name, pos);
|
||||
}
|
||||
vAttrs = j->value;
|
||||
pos2 = j->pos;
|
||||
@@ -958,7 +898,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
} catch (Error & e) {
|
||||
if (pos2 && pos2->file != state.sDerivationNix)
|
||||
addErrorPrefix(e, "while evaluating the attribute '%1%' at %2%:\n",
|
||||
addErrorPrefix(e, "while evaluating the attribute ‘%1%’ at %2%:\n",
|
||||
showAttrPath(state, env, attrPath), *pos2);
|
||||
throw;
|
||||
}
|
||||
@@ -1100,7 +1040,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
||||
for (auto & i : lambda.formals->formals) {
|
||||
Bindings::iterator j = arg.attrs->find(i.name);
|
||||
if (j == arg.attrs->end()) {
|
||||
if (!i.def) throwTypeError("%1% called without required argument '%2%', at %3%",
|
||||
if (!i.def) throwTypeError("%1% called without required argument ‘%2%’, at %3%",
|
||||
lambda, i.name, pos);
|
||||
env2.values[displ++] = i.def->maybeThunk(*this, env2);
|
||||
} else {
|
||||
@@ -1116,7 +1056,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
||||
user. */
|
||||
for (auto & i : *arg.attrs)
|
||||
if (lambda.formals->argNames.find(i.name) == lambda.formals->argNames.end())
|
||||
throwTypeError("%1% called with unexpected argument '%2%', at %3%", lambda, i.name, pos);
|
||||
throwTypeError("%1% called with unexpected argument ‘%2%’, at %3%", lambda, i.name, pos);
|
||||
abort(); // can't happen
|
||||
}
|
||||
}
|
||||
@@ -1174,7 +1114,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
||||
if (j != args.end())
|
||||
actualArgs->attrs->push_back(*j);
|
||||
else if (!i.def)
|
||||
throwTypeError("cannot auto-call a function that has an argument without a default value ('%1%')", i.name);
|
||||
throwTypeError("cannot auto-call a function that has an argument without a default value (‘%1%’)", i.name);
|
||||
}
|
||||
|
||||
actualArgs->attrs->sort();
|
||||
@@ -1403,7 +1343,7 @@ void EvalState::forceValueDeep(Value & v)
|
||||
try {
|
||||
recurse(*i.value);
|
||||
} catch (Error & e) {
|
||||
addErrorPrefix(e, "while evaluating the attribute '%1%' at %2%:\n", i.name, *i.pos);
|
||||
addErrorPrefix(e, "while evaluating the attribute ‘%1%’ at %2%:\n", i.name, *i.pos);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -1495,10 +1435,10 @@ string EvalState::forceStringNoCtx(Value & v, const Pos & pos)
|
||||
string s = forceString(v, pos);
|
||||
if (v.string.context) {
|
||||
if (pos)
|
||||
throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%'), at %3%",
|
||||
throwEvalError("the string ‘%1%’ is not allowed to refer to a store path (such as ‘%2%’), at %3%",
|
||||
v.string.s, v.string.context[0], pos);
|
||||
else
|
||||
throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
||||
throwEvalError("the string ‘%1%’ is not allowed to refer to a store path (such as ‘%2%’)",
|
||||
v.string.s, v.string.context[0]);
|
||||
}
|
||||
return s;
|
||||
@@ -1580,17 +1520,17 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
|
||||
string EvalState::copyPathToStore(PathSet & context, const Path & path)
|
||||
{
|
||||
if (nix::isDerivation(path))
|
||||
throwEvalError("file names are not allowed to end in '%1%'", drvExtension);
|
||||
throwEvalError("file names are not allowed to end in ‘%1%’", drvExtension);
|
||||
|
||||
Path dstPath;
|
||||
if (srcToStore[path] != "")
|
||||
dstPath = srcToStore[path];
|
||||
else {
|
||||
dstPath = settings.readOnlyMode
|
||||
? store->computeStorePathForPath(baseNameOf(path), checkSourcePath(path)).first
|
||||
? store->computeStorePathForPath(checkSourcePath(path)).first
|
||||
: store->addToStore(baseNameOf(path), checkSourcePath(path), true, htSHA256, defaultPathFilter, repair);
|
||||
srcToStore[path] = dstPath;
|
||||
printMsg(lvlChatty, format("copied source '%1%' -> '%2%'")
|
||||
printMsg(lvlChatty, format("copied source ‘%1%’ -> ‘%2%’")
|
||||
% path % dstPath);
|
||||
}
|
||||
|
||||
@@ -1603,7 +1543,7 @@ Path EvalState::coerceToPath(const Pos & pos, Value & v, PathSet & context)
|
||||
{
|
||||
string path = coerceToString(pos, v, context, false, false);
|
||||
if (path == "" || path[0] != '/')
|
||||
throwEvalError("string '%1%' doesn't represent an absolute path, at %2%", path, pos);
|
||||
throwEvalError("string ‘%1%’ doesn't represent an absolute path, at %2%", path, pos);
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -1709,13 +1649,10 @@ void EvalState::printStats()
|
||||
printMsg(v, format(" time elapsed: %1%") % cpuTime);
|
||||
printMsg(v, format(" size of a value: %1%") % sizeof(Value));
|
||||
printMsg(v, format(" size of an attr: %1%") % sizeof(Attr));
|
||||
printMsg(v, format(" environments allocated count: %1%") % nrEnvs);
|
||||
printMsg(v, format(" environments allocated bytes: %1%") % bEnvs);
|
||||
printMsg(v, format(" list elements count: %1%") % nrListElems);
|
||||
printMsg(v, format(" list elements bytes: %1%") % bLists);
|
||||
printMsg(v, format(" environments allocated: %1% (%2% bytes)") % nrEnvs % bEnvs);
|
||||
printMsg(v, format(" list elements: %1% (%2% bytes)") % nrListElems % bLists);
|
||||
printMsg(v, format(" list concatenations: %1%") % nrListConcats);
|
||||
printMsg(v, format(" values allocated count: %1%") % nrValues);
|
||||
printMsg(v, format(" values allocated bytes: %1%") % bValues);
|
||||
printMsg(v, format(" values allocated: %1% (%2% bytes)") % nrValues % bValues);
|
||||
printMsg(v, format(" sets allocated: %1% (%2% bytes)") % nrAttrsets % bAttrsets);
|
||||
printMsg(v, format(" right-biased unions: %1%") % nrOpUpdates);
|
||||
printMsg(v, format(" values copied in right-biased unions: %1%") % nrOpUpdateValuesCopied);
|
||||
|
||||
@@ -14,7 +14,6 @@ namespace nix {
|
||||
|
||||
class Store;
|
||||
class EvalState;
|
||||
enum RepairFlag : bool;
|
||||
|
||||
|
||||
typedef void (* PrimOpFun) (EvalState & state, const Pos & pos, Value * * args, Value & v);
|
||||
@@ -69,17 +68,16 @@ public:
|
||||
const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue,
|
||||
sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls,
|
||||
sFile, sLine, sColumn, sFunctor, sToString,
|
||||
sRight, sWrong, sStructuredAttrs, sBuilder, sArgs,
|
||||
sOutputHash, sOutputHashAlgo, sOutputHashMode;
|
||||
sRight, sWrong;
|
||||
Symbol sDerivationNix;
|
||||
|
||||
/* If set, force copying files to the Nix store even if they
|
||||
already exist there. */
|
||||
RepairFlag repair;
|
||||
bool repair = false;
|
||||
|
||||
/* The allowed filesystem paths in restricted or pure evaluation
|
||||
mode. */
|
||||
std::experimental::optional<PathSet> allowedPaths;
|
||||
/* If set, don't allow access to files outside of the Nix search
|
||||
path or to environment variables. */
|
||||
bool restricted;
|
||||
|
||||
Value vEmptySet;
|
||||
|
||||
@@ -111,17 +109,6 @@ public:
|
||||
|
||||
Path checkSourcePath(const Path & path);
|
||||
|
||||
void checkURI(const std::string & uri);
|
||||
|
||||
/* When using a diverted store and 'path' is in the Nix store, map
|
||||
'path' to the diverted location (e.g. /nix/store/foo is mapped
|
||||
to /home/alice/my-nix/nix/store/foo). However, this is only
|
||||
done if the context is not empty, since otherwise we're
|
||||
probably trying to read from the actual /nix/store. This is
|
||||
intended to distinguish between import-from-derivation and
|
||||
sources stored in the actual /nix/store. */
|
||||
Path toRealPath(const Path & path, const PathSet & context);
|
||||
|
||||
/* Parse a Nix expression from the specified file. */
|
||||
Expr * parseExprFromFile(const Path & path);
|
||||
Expr * parseExprFromFile(const Path & path, StaticEnv & staticEnv);
|
||||
@@ -130,8 +117,6 @@ public:
|
||||
Expr * parseExprFromString(const string & s, const Path & basePath, StaticEnv & staticEnv);
|
||||
Expr * parseExprFromString(const string & s, const Path & basePath);
|
||||
|
||||
Expr * parseStdin();
|
||||
|
||||
/* Evaluate an expression read from the given file to normal
|
||||
form. */
|
||||
void evalFile(const Path & path, Value & v);
|
||||
@@ -211,9 +196,9 @@ private:
|
||||
|
||||
void createBaseEnv();
|
||||
|
||||
Value * addConstant(const string & name, Value & v);
|
||||
void addConstant(const string & name, Value & v);
|
||||
|
||||
Value * addPrimOp(const string & name,
|
||||
void addPrimOp(const string & name,
|
||||
unsigned int arity, PrimOpFun primOp);
|
||||
|
||||
public:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user