Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b4577ac9d | ||
|
|
d704abc0f3 | ||
|
|
71e5b937fb | ||
|
|
0824f40760 | ||
|
|
a1bf934044 | ||
|
|
a6d52fcd95 | ||
|
|
8d22b26448 | ||
|
|
786046cf13 | ||
|
|
8906eda2f9 | ||
|
|
00903fa799 | ||
|
|
0cad1f8049 | ||
|
|
1c57ab8b31 | ||
|
|
ef7c2d8b3e | ||
|
|
4202b17666 | ||
|
|
10a6aa3ad4 | ||
|
|
458711e4ee | ||
|
|
9aac1861f7 | ||
|
|
94595f42eb | ||
|
|
2ef7e2e795 | ||
|
|
02a66b3fd7 | ||
|
|
caaaff3954 | ||
|
|
d2c0958e1e | ||
|
|
4f3cf06c97 | ||
|
|
39d1da7b51 | ||
|
|
0eb200e569 | ||
|
|
80ebd60e7c | ||
|
|
9a4706eb19 | ||
|
|
14080f3e4b | ||
|
|
6298afc047 | ||
|
|
36b9ce24b1 | ||
|
|
607d91517e | ||
|
|
743e310046 | ||
|
|
29c0199d5c | ||
|
|
5eb93556f1 | ||
|
|
f770b9e6c5 | ||
|
|
71a93a5f0e | ||
|
|
9be037448c | ||
|
|
f476535265 | ||
|
|
77ad443bd1 | ||
|
|
b8258a4475 | ||
|
|
52120123a5 | ||
|
|
68fd01f42a | ||
|
|
f696af0fab | ||
|
|
a9faa7bbce | ||
|
|
338880ee6f | ||
|
|
b07b3b0264 | ||
|
|
32ea8a9898 | ||
|
|
399397c907 | ||
|
|
8f67325a7c | ||
|
|
7431932b29 | ||
|
|
65bd82d42a | ||
|
|
9018deab6c | ||
|
|
d1e3bf01bc | ||
|
|
8063fc497a | ||
|
|
69b9d8fdbd | ||
|
|
f327970129 | ||
|
|
9533532ce2 | ||
|
|
bfb6c4876a | ||
|
|
c0d4173263 | ||
|
|
efd6a8c9f6 | ||
|
|
0ab4d905e7 | ||
|
|
27d6ed5c68 | ||
|
|
a0f0733413 | ||
|
|
afef347157 | ||
|
|
4c1c7e5812 | ||
|
|
cad40adce5 | ||
|
|
cf141abfe9 | ||
|
|
6c10bd7c5e | ||
|
|
279fa8f618 | ||
|
|
e0bd114e09 | ||
|
|
4921223160 | ||
|
|
b9b7bb1806 | ||
|
|
5deb7fbdfb | ||
|
|
33f2fbcb62 | ||
|
|
6ad10591ce | ||
|
|
36f7fcc157 | ||
|
|
8a74a125bc | ||
|
|
1d3529e93a | ||
|
|
9b4cd20752 | ||
|
|
58d2fac91d | ||
|
|
4390142315 | ||
|
|
bd09a4c967 | ||
|
|
4876bb012e | ||
|
|
d760c2638c | ||
|
|
22dfd023fa | ||
|
|
8a7f0dfd68 | ||
|
|
b39622a487 | ||
|
|
9ee15abe30 | ||
|
|
8fdd156a65 | ||
|
|
96c2ebf004 | ||
|
|
4384bbd2e1 | ||
|
|
7759a56bed | ||
|
|
8a2a3b6579 | ||
|
|
8a76bc9fb0 | ||
|
|
cdb346c65e | ||
|
|
5bc12454fd | ||
|
|
6f1743b1a5 | ||
|
|
a6ca68a70c | ||
|
|
c10ef2d134 | ||
|
|
3b52e54e31 | ||
|
|
85aeedb9bc | ||
|
|
d6bd51ffbe | ||
|
|
9a963c8adc | ||
|
|
95c66cc950 | ||
|
|
b83fb35f79 | ||
|
|
1f735a3440 | ||
|
|
dae5dc7ade | ||
|
|
5c28943e8f | ||
|
|
71039becd1 | ||
|
|
f6a224bd68 | ||
|
|
45b2f32cc1 | ||
|
|
fef8c3a5ab | ||
|
|
9155fbd386 | ||
|
|
af1218a86a | ||
|
|
992cda1b11 | ||
|
|
76f3ba42fd | ||
|
|
2dc8e19a17 | ||
|
|
f5a7739171 | ||
|
|
3f65504164 | ||
|
|
ff6953cb03 | ||
|
|
15c7a79ed3 | ||
|
|
5bf4085000 | ||
|
|
6a8cee19b3 | ||
|
|
1fc0fe1baf | ||
|
|
d4cac051f7 | ||
|
|
4b8c71b4ef | ||
|
|
e770f941d6 | ||
|
|
6dbc9e02ec | ||
|
|
1ea2aa9e99 | ||
|
|
f5b32ff47d | ||
|
|
01615b5f63 | ||
|
|
5db358d4d7 | ||
|
|
357d31b339 | ||
|
|
058d1950c0 | ||
|
|
a7dd26961d | ||
|
|
164487a5ba | ||
|
|
5f1a3201ec | ||
|
|
133a421bb4 | ||
|
|
2075ec83e3 | ||
|
|
51cf4455b2 | ||
|
|
8a87521636 | ||
|
|
055ab1fc8d | ||
|
|
14f7e1fc42 | ||
|
|
21ecd106ed | ||
|
|
f08449ccbd | ||
|
|
e4abf8610b | ||
|
|
b54f447df9 | ||
|
|
7888b2ba15 | ||
|
|
12c1776df9 | ||
|
|
c999ef70e8 | ||
|
|
cbc177ca01 | ||
|
|
1abda8e173 | ||
|
|
9ffc4f4363 | ||
|
|
57db2aa220 | ||
|
|
06f29fafe8 | ||
|
|
a3c4eb0964 | ||
|
|
bec3c31608 | ||
|
|
bdc4a0b54d | ||
|
|
a49514a2e2 | ||
|
|
aaf8a1c16b | ||
|
|
fd74296e2f | ||
|
|
4ba6bc184c | ||
|
|
3d91bfc8f8 | ||
|
|
42808fa281 | ||
|
|
12a4aea93d | ||
|
|
64f9b511be | ||
|
|
e5c3e054ec | ||
|
|
55b1146150 | ||
|
|
71a5161365 | ||
|
|
6e06a18d1b | ||
|
|
73332fd342 | ||
|
|
d711fe8f5e | ||
|
|
ce97523a7c | ||
|
|
5e4b2109b5 | ||
|
|
e12cf82782 | ||
|
|
eadb86f447 | ||
|
|
1d29db2a9f | ||
|
|
26221e44eb | ||
|
|
984c5cdc50 | ||
|
|
3b0f60e5c2 | ||
|
|
896428c818 | ||
|
|
34dfbd9394 | ||
|
|
30d19a2bdc | ||
|
|
3db950aab7 | ||
|
|
2bac04c5ff | ||
|
|
75837651f1 | ||
|
|
76cc8e97a2 | ||
|
|
50807f3dd5 | ||
|
|
f3dda728a4 | ||
|
|
d6d5885c15 | ||
|
|
2e8fd4c5cd | ||
|
|
cb4320c1a0 | ||
|
|
c8bb2371eb | ||
|
|
16c9935fa9 | ||
|
|
19eddecc0f | ||
|
|
b83801f8b3 | ||
|
|
14be783676 | ||
|
|
39e27a04b8 | ||
|
|
1ed55234d9 | ||
|
|
61af14a921 | ||
|
|
887bb5fa5a | ||
|
|
1993b10d11 | ||
|
|
0a2bee307b | ||
|
|
eda2f36c2a | ||
|
|
ccf31dbc25 | ||
|
|
db55940d9e | ||
|
|
b3491c781c | ||
|
|
6bd2c7bb38 | ||
|
|
1511aa9f48 | ||
|
|
f39979c6d3 | ||
|
|
7c9d0a5969 | ||
|
|
5845ffdf13 | ||
|
|
db21cfa688 | ||
|
|
467977f203 | ||
|
|
65e4dcd69b | ||
|
|
dd48c06bb6 | ||
|
|
9aed117395 | ||
|
|
e012c126db | ||
|
|
ff4de4cb27 | ||
|
|
2bc9c84327 | ||
|
|
ba63ec6f39 | ||
|
|
65f17cd330 | ||
|
|
0d4d92fcf9 | ||
|
|
a33b4bc01b | ||
|
|
39b3d9698e | ||
|
|
c48617671d | ||
|
|
d1e4b76a3a | ||
|
|
b65875f859 | ||
|
|
f90e9b65d6 | ||
|
|
7c4501886d | ||
|
|
f2b67fbf2a | ||
|
|
bf8cc4e9b6 | ||
|
|
7d148ad543 | ||
|
|
b64988bb35 | ||
|
|
b190f771e7 | ||
|
|
07d7e7df84 | ||
|
|
94378910fb | ||
|
|
a64da5915d | ||
|
|
f0f30f594c | ||
|
|
90aec21d76 | ||
|
|
898703e006 | ||
|
|
d8ddf994e7 | ||
|
|
7106bb0611 | ||
|
|
b755752f76 | ||
|
|
53dd97bb9d | ||
|
|
b8b571cfc1 | ||
|
|
bc51175dc0 | ||
|
|
da196ec68f | ||
|
|
c1323b53e3 | ||
|
|
1c88e100e7 | ||
|
|
feca5cb67f | ||
|
|
a80f11bf7b | ||
|
|
99c2c14f50 | ||
|
|
d68941d89d | ||
|
|
07c69aa03b | ||
|
|
b2798902ea | ||
|
|
920f5fd4dd | ||
|
|
7a411e01cf | ||
|
|
e0a068cb97 | ||
|
|
4ca5a9dcfd | ||
|
|
22b1a8d43f | ||
|
|
13493ef97c | ||
|
|
4441e4cc13 | ||
|
|
8d813fe3e0 | ||
|
|
a1c1bf3a56 | ||
|
|
12a888894b | ||
|
|
ea39c98d41 | ||
|
|
1529db702b | ||
|
|
3fac75bf29 | ||
|
|
46a56ea622 | ||
|
|
9c6328a7bf | ||
|
|
3d83188702 | ||
|
|
a010c0ae05 | ||
|
|
9233ac7c56 | ||
|
|
dad754843a | ||
|
|
000de699e9 | ||
|
|
71083f9e5e | ||
|
|
8972f7c14a | ||
|
|
6519f06f39 | ||
|
|
0705d04dfa | ||
|
|
9451ef3731 | ||
|
|
35d30d67eb | ||
|
|
deb8668a0e | ||
|
|
1f795f9f44 | ||
|
|
96dcc006e9 | ||
|
|
4bbcfaf87f | ||
|
|
ab2b3d6668 | ||
|
|
8a84bd8c8b | ||
|
|
4d652875bd | ||
|
|
fd6774e285 | ||
|
|
9b1866b721 | ||
|
|
035aeb9547 | ||
|
|
76f985b92d | ||
|
|
1e4a4a2e9f | ||
|
|
4ed2187377 | ||
|
|
1fc905ad4c | ||
|
|
c1f04fae35 | ||
|
|
60340ce3e2 | ||
|
|
1711679ea5 | ||
|
|
afa433e58c | ||
|
|
be1ff23352 | ||
|
|
000b5a000f | ||
|
|
7ea6ecf855 | ||
|
|
5114a07d95 | ||
|
|
fd89f97be9 | ||
|
|
5ce50cd99e | ||
|
|
6f0c6e20e0 | ||
|
|
b005e63ccf | ||
|
|
726f7f7fc9 | ||
|
|
da6b704b19 | ||
|
|
fa47279440 | ||
|
|
7a84143910 | ||
|
|
e659978ced | ||
|
|
17c71334e1 | ||
|
|
5badc8f975 | ||
|
|
9f3eb56b46 | ||
|
|
71b0a3a86b | ||
|
|
75ede65e3d | ||
|
|
c2699be93b | ||
|
|
336c4270c6 | ||
|
|
66d612f1da | ||
|
|
cffa7f80ab | ||
|
|
885bebf13b | ||
|
|
99897f6979 | ||
|
|
15d2d3c34e | ||
|
|
47bdc52c1b | ||
|
|
a8494de0be | ||
|
|
7bd8299c6c | ||
|
|
c33244d7c1 | ||
|
|
c4653afbcd | ||
|
|
e3e38a048e | ||
|
|
4b7c9f834c | ||
|
|
9bedd9b09b | ||
|
|
4646e94610 | ||
|
|
175935e053 | ||
|
|
e0953d53de | ||
|
|
1816ac0db1 | ||
|
|
dc7e8fae48 | ||
|
|
bb10010582 | ||
|
|
147deb236e | ||
|
|
bd91064150 | ||
|
|
a70d275f3d | ||
|
|
29e1ff675b | ||
|
|
f19b4abfb2 | ||
|
|
8c8750ae66 | ||
|
|
5451b8db9d | ||
|
|
b0bad3e615 | ||
|
|
d53735c823 | ||
|
|
b4e7eec16a | ||
|
|
1c972cba14 | ||
|
|
5d9cd27dce | ||
|
|
a596c525ad | ||
|
|
70cae879e3 | ||
|
|
2be7f79fd4 | ||
|
|
de8ed5c1d3 | ||
|
|
d66d9e8425 | ||
|
|
f3a5930488 | ||
|
|
e0def5bc4b | ||
|
|
0d1dafa0c4 | ||
|
|
db2ec59903 | ||
|
|
3688db3d43 | ||
|
|
73bf32ce94 | ||
|
|
de91a42c6e | ||
|
|
f46e329a13 | ||
|
|
f6716e95bb | ||
|
|
c2a8b5c42d | ||
|
|
a5e2c8e560 | ||
|
|
79ca503332 | ||
|
|
fcf57aad27 | ||
|
|
100961e370 | ||
|
|
f1151a3373 | ||
|
|
c23d67920e | ||
|
|
2a3b1df423 | ||
|
|
57d64d24aa | ||
|
|
57b82256b0 | ||
|
|
ed56ea980b | ||
|
|
27b7b94923 | ||
|
|
128538ef06 | ||
|
|
b76589206a | ||
|
|
a957893b26 | ||
|
|
7ba0e9cb48 | ||
|
|
153a943de7 | ||
|
|
6fec43ccb3 | ||
|
|
4d5c9d85ea | ||
|
|
df05f49dcd | ||
|
|
1b167c964f | ||
|
|
14fb7378df | ||
|
|
2c052278d2 | ||
|
|
8027083c3a | ||
|
|
8b88d25cda | ||
|
|
bbd45ac80f | ||
|
|
411b237ee5 | ||
|
|
3d97b8d1e7 | ||
|
|
bd0f362d2f | ||
|
|
f16b8786a2 | ||
|
|
2162a9c1c7 | ||
|
|
ccde347eb8 | ||
|
|
4579a44617 | ||
|
|
c9bd6a1de4 | ||
|
|
0ee1ca628a |
@@ -112,6 +112,8 @@ Makefile.config
|
||||
*.a
|
||||
*.o
|
||||
*.so
|
||||
*.dll
|
||||
*.exe
|
||||
*.dep
|
||||
*~
|
||||
*.pc
|
||||
|
||||
@@ -10,8 +10,10 @@ makefiles = \
|
||||
src/nix-instantiate/local.mk \
|
||||
src/nix-env/local.mk \
|
||||
src/nix-daemon/local.mk \
|
||||
src/nix-collect-garbage/local.mk \
|
||||
src/download-via-ssh/local.mk \
|
||||
src/nix-log2xml/local.mk \
|
||||
src/nix-prefetch-url/local.mk \
|
||||
src/bsdiff-4.3/local.mk \
|
||||
perl/local.mk \
|
||||
scripts/local.mk \
|
||||
@@ -25,7 +27,7 @@ makefiles = \
|
||||
|
||||
GLOBAL_CXXFLAGS += -std=c++0x -g -Wall
|
||||
|
||||
include Makefile.config
|
||||
-include Makefile.config
|
||||
|
||||
OPTIMIZE = 1
|
||||
|
||||
|
||||
+4
-1
@@ -3,10 +3,13 @@ CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
HAVE_OPENSSL = @HAVE_OPENSSL@
|
||||
HAVE_SODIUM = @HAVE_SODIUM@
|
||||
LIBCURL_LIBS = @LIBCURL_LIBS@
|
||||
OPENSSL_LIBS = @OPENSSL_LIBS@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
SODIUM_LIBS = @SODIUM_LIBS@
|
||||
SQLITE3_LIBS = @SQLITE3_LIBS@
|
||||
bash = @bash@
|
||||
bindir = @bindir@
|
||||
bsddiff_compat_include = @bsddiff_compat_include@
|
||||
|
||||
+36
-24
@@ -48,6 +48,7 @@ test "$localstatedir" = '${prefix}/var' && localstatedir=/nix/var
|
||||
|
||||
|
||||
# Solaris-specific stuff.
|
||||
AC_STRUCT_DIRENT_D_TYPE
|
||||
if test "$sys_name" = sunos; then
|
||||
# Solaris requires -lsocket -lnsl for network functions
|
||||
LIBS="-lsocket -lnsl $LIBS"
|
||||
@@ -76,17 +77,7 @@ static char buf[1024];]],
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
|
||||
# Check for chroot support (requires chroot() and bind mounts).
|
||||
AC_CHECK_FUNCS([chroot])
|
||||
AC_CHECK_FUNCS([unshare])
|
||||
AC_CHECK_FUNCS([statvfs])
|
||||
AC_CHECK_HEADERS([sched.h])
|
||||
AC_CHECK_HEADERS([sys/param.h])
|
||||
AC_CHECK_HEADERS([sys/mount.h], [], [],
|
||||
[#ifdef HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
])
|
||||
|
||||
|
||||
# Check for lutimes, optionally used for changing the mtime of
|
||||
@@ -94,10 +85,6 @@ AC_CHECK_HEADERS([sys/mount.h], [], [],
|
||||
AC_CHECK_FUNCS([lutimes])
|
||||
|
||||
|
||||
# Check for sched_setaffinity.
|
||||
AC_CHECK_FUNCS([sched_setaffinity])
|
||||
|
||||
|
||||
# Check whether the store optimiser can optimise symlinks.
|
||||
AC_MSG_CHECKING([whether it is possible to create a link to a symlink])
|
||||
ln -s bla tmp_link
|
||||
@@ -121,10 +108,6 @@ AC_CHECK_HEADER([err.h], [], [bsddiff_compat_include="-Icompat-include"])
|
||||
AC_SUBST([bsddiff_compat_include])
|
||||
|
||||
|
||||
# Check for <linux/fs.h> (for immutable file support).
|
||||
AC_CHECK_HEADERS([linux/fs.h])
|
||||
|
||||
|
||||
AC_DEFUN([NEED_PROG],
|
||||
[
|
||||
AC_PATH_PROG($1, $2)
|
||||
@@ -182,16 +165,12 @@ AC_ARG_WITH(store-dir, AC_HELP_STRING([--with-store-dir=PATH],
|
||||
AC_SUBST(storedir)
|
||||
|
||||
|
||||
# Look for OpenSSL, an optional dependency.
|
||||
# Look for OpenSSL, a required dependency.
|
||||
AC_PATH_PROG(openssl, openssl, openssl) # if not found, call openssl in $PATH
|
||||
AC_SUBST(openssl)
|
||||
AC_DEFINE_UNQUOTED(OPENSSL_PATH, ["$openssl"], [Path of the OpenSSL binary])
|
||||
|
||||
PKG_CHECK_MODULES([OPENSSL], [libcrypto],
|
||||
[AC_DEFINE([HAVE_OPENSSL], [1], [Whether to use OpenSSL.])
|
||||
CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"
|
||||
have_openssl=1], [have_openssl=])
|
||||
AC_SUBST(HAVE_OPENSSL, [$have_openssl])
|
||||
PKG_CHECK_MODULES([OPENSSL], [libcrypto], [CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"])
|
||||
|
||||
|
||||
# Look for libbz2, a required dependency.
|
||||
@@ -205,6 +184,22 @@ AC_CHECK_HEADERS([bzlib.h], [true],
|
||||
PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.6.19], [CXXFLAGS="$SQLITE3_CFLAGS $CXXFLAGS"])
|
||||
|
||||
|
||||
# Look for libcurl, a required dependency.
|
||||
PKG_CHECK_MODULES([LIBCURL], [libcurl], [CXXFLAGS="$LIBCURL_CFLAGS $CXXFLAGS"])
|
||||
|
||||
|
||||
# Look for libsodium, an optional dependency.
|
||||
PKG_CHECK_MODULES([SODIUM], [libsodium],
|
||||
[AC_DEFINE([HAVE_SODIUM], [1], [Whether to use libsodium for cryptography.])
|
||||
CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"
|
||||
have_sodium=1], [have_sodium=])
|
||||
AC_SUBST(HAVE_SODIUM, [$have_sodium])
|
||||
|
||||
|
||||
# Look for liblzma, a required dependency.
|
||||
PKG_CHECK_MODULES([LIBLZMA], [liblzma], [CXXFLAGS="$LIBLZMA_CFLAGS $CXXFLAGS"])
|
||||
|
||||
|
||||
# Whether to use the Boehm garbage collector.
|
||||
AC_ARG_ENABLE(gc, AC_HELP_STRING([--enable-gc],
|
||||
[enable garbage collection in the Nix expression evaluator (requires Boehm GC) [default=no]]),
|
||||
@@ -248,6 +243,23 @@ AC_MSG_RESULT(yes)
|
||||
AC_SUBST(perlFlags)
|
||||
|
||||
|
||||
# Check for otool, an optional dependency on Darwin.
|
||||
AC_PATH_PROG(otool, otool)
|
||||
AC_MSG_CHECKING([that otool works])
|
||||
case $host_os in
|
||||
darwin*)
|
||||
if test -z "$otool" || ! $otool --version 2>/dev/null; then
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([Can't get version from otool; do you need to install developer tools?])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT(not needed)
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# 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],
|
||||
|
||||
+20
-3
@@ -8,7 +8,7 @@ derivation {
|
||||
builder = perl;
|
||||
args = [ "-w" ./buildenv.pl ];
|
||||
|
||||
manifest = manifest;
|
||||
inherit manifest;
|
||||
|
||||
# !!! grmbl, need structured data for passing this in a clean way.
|
||||
derivations =
|
||||
@@ -23,6 +23,23 @@ derivation {
|
||||
# network traffic, so don't do that.
|
||||
preferLocalBuild = true;
|
||||
|
||||
# Don't build in a chroot because Nix's dependencies may not be there.
|
||||
__noChroot = true;
|
||||
# Also don't bother substituting.
|
||||
allowSubstitutes = false;
|
||||
|
||||
__sandboxProfile = ''
|
||||
(allow sysctl-read)
|
||||
(allow file-read*
|
||||
(literal "/usr/lib/libSystem.dylib")
|
||||
(literal "/usr/lib/libSystem.B.dylib")
|
||||
(literal "/usr/lib/libobjc.A.dylib")
|
||||
(literal "/usr/lib/libobjc.dylib")
|
||||
(literal "/usr/lib/libauto.dylib")
|
||||
(literal "/usr/lib/libc++abi.dylib")
|
||||
(literal "/usr/lib/libc++.1.dylib")
|
||||
(literal "/usr/lib/libDiagnosticMessagesClient.dylib")
|
||||
(subpath "/usr/lib/system")
|
||||
(subpath "/dev"))
|
||||
'';
|
||||
|
||||
inherit chrootDeps;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ foreach my $pkg (@pkgs) {
|
||||
|
||||
|
||||
# Symlink to the packages that have been "propagated" by packages
|
||||
# installed by the user (i.e., package X declares that it want Y
|
||||
# installed by the user (i.e., package X declares that it wants Y
|
||||
# installed as well). We do these later because they have a lower
|
||||
# priority in case of collisions.
|
||||
my $priorityCounter = 1000; # don't care about collisions
|
||||
|
||||
+11
-2
@@ -2,7 +2,7 @@ let
|
||||
fromEnv = var: def:
|
||||
let val = builtins.getEnv var; in
|
||||
if val != "" then val else def;
|
||||
in {
|
||||
in rec {
|
||||
perl = "@perl@";
|
||||
shell = "@bash@";
|
||||
coreutils = "@coreutils@";
|
||||
@@ -12,6 +12,15 @@ in {
|
||||
tar = "@tar@";
|
||||
tarFlags = "@tarFlags@";
|
||||
tr = "@tr@";
|
||||
curl = "@curl@";
|
||||
nixBinDir = fromEnv "NIX_BIN_DIR" "@bindir@";
|
||||
nixPrefix = "@prefix@";
|
||||
|
||||
# If Nix is installed in the Nix store, then automatically add it as
|
||||
# a dependency to the core packages. This ensures that they work
|
||||
# properly in a chroot.
|
||||
chrootDeps =
|
||||
if dirOf nixPrefix == builtins.storeDir then
|
||||
[ (builtins.storePath nixPrefix) ]
|
||||
else
|
||||
[ ];
|
||||
}
|
||||
|
||||
+13
-20
@@ -1,40 +1,33 @@
|
||||
with import <nix/config.nix>;
|
||||
|
||||
{system ? builtins.currentSystem, url, outputHash ? "", outputHashAlgo ? "", md5 ? "", sha1 ? "", sha256 ? "", executable ? false}:
|
||||
{ system ? builtins.currentSystem
|
||||
, url
|
||||
, outputHash ? ""
|
||||
, outputHashAlgo ? ""
|
||||
, md5 ? "", sha1 ? "", sha256 ? ""
|
||||
, executable ? false
|
||||
, unpack ? false
|
||||
, name ? baseNameOf (toString url)
|
||||
}:
|
||||
|
||||
assert (outputHash != "" && outputHashAlgo != "")
|
||||
|| md5 != "" || sha1 != "" || sha256 != "";
|
||||
|
||||
let
|
||||
|
||||
builder = builtins.toFile "fetchurl.sh"
|
||||
(''
|
||||
echo "downloading $url into $out"
|
||||
${curl} --fail --location --max-redirs 20 --insecure "$url" > "$out"
|
||||
'' + (if executable then "${coreutils}/chmod +x $out" else ""));
|
||||
|
||||
in
|
||||
|
||||
derivation {
|
||||
name = baseNameOf (toString url);
|
||||
builder = shell;
|
||||
args = [ "-e" builder ];
|
||||
builder = "builtin:fetchurl";
|
||||
|
||||
# New-style output content requirements.
|
||||
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 executable then "recursive" else "flat";
|
||||
|
||||
inherit system url;
|
||||
outputHashMode = if unpack || executable then "recursive" else "flat";
|
||||
|
||||
inherit name system url executable unpack;
|
||||
|
||||
# No need to double the amount of network traffic
|
||||
preferLocalBuild = true;
|
||||
|
||||
# Don't build in a chroot because Nix's dependencies may not be there.
|
||||
__noChroot = true;
|
||||
|
||||
impureEnvVars = [
|
||||
# We borrow these environment variables from the caller to allow
|
||||
# easy proxy configuration. This is impure, but a fixed-output
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
attrs @ { drvPath, outputs, ... }:
|
||||
attrs @ { drvPath, outputs, name, ... }:
|
||||
|
||||
let
|
||||
|
||||
commonAttrs = (builtins.listToAttrs outputsList) //
|
||||
{ all = map (x: x.value) outputsList;
|
||||
inherit drvPath;
|
||||
inherit drvPath name;
|
||||
type = "derivation";
|
||||
};
|
||||
|
||||
|
||||
+2
-3
@@ -41,9 +41,8 @@ derivation {
|
||||
args = [ "-e" builder ];
|
||||
inherit storePath hashAlgo compressionType;
|
||||
|
||||
# Don't build in a chroot because Nix's dependencies may not be there.
|
||||
__noChroot = true;
|
||||
|
||||
# Remote machines may not have ${nixBinDir} or ${coreutils} in the same prefixes
|
||||
preferLocalBuild = true;
|
||||
|
||||
inherit chrootDeps;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,5 @@ derivation {
|
||||
# No point in doing this remotely.
|
||||
preferLocalBuild = true;
|
||||
|
||||
# Don't build in a chroot because Nix's dependencies may not be there.
|
||||
__noChroot = true;
|
||||
inherit chrootDeps;
|
||||
}
|
||||
|
||||
@@ -224,43 +224,51 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>build-use-chroot</literal></term>
|
||||
<varlistentry><term><literal>build-use-sandbox</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal>, builds will be
|
||||
performed in a <emphasis>chroot environment</emphasis>, i.e., the
|
||||
build will be isolated from the normal file system hierarchy and
|
||||
will only see its dependencies in the Nix store, the temporary
|
||||
build directory, private versions of <filename>/proc</filename>,
|
||||
performed in a <emphasis>sandboxed environment</emphasis>, i.e.,
|
||||
they’re isolated from the normal file system hierarchy and will
|
||||
only see their dependencies in the Nix store, the temporary build
|
||||
directory, private versions of <filename>/proc</filename>,
|
||||
<filename>/dev</filename>, <filename>/dev/shm</filename> and
|
||||
<filename>/dev/pts</filename>, and the paths configured with the
|
||||
<link linkend='conf-build-chroot-dirs'><literal>build-chroot-dirs</literal>
|
||||
<filename>/dev/pts</filename> (on Linux), and the paths configured with the
|
||||
<link linkend='conf-build-sandbox-paths'><literal>build-sandbox-paths</literal>
|
||||
option</link>. This is useful to prevent undeclared dependencies
|
||||
on files in directories such as
|
||||
<filename>/usr/bin</filename>.</para>
|
||||
on files in directories such as <filename>/usr/bin</filename>. In
|
||||
addition, on Linux, builds run in private PID, mount, network, IPC
|
||||
and UTS namespaces to isolate them from other processes in the
|
||||
system (except that fixed-output derivations do not run in private
|
||||
network namespace to ensure they can access the network).</para>
|
||||
|
||||
<para>The use of a chroot requires that Nix is run as root (so you
|
||||
should use the <link linkend='conf-build-users-group'>“build
|
||||
users” feature</link> to perform the actual builds under different
|
||||
users than root). Currently, chroot builds only work on Linux
|
||||
because Nix uses “bind mounts” to make the Nix store and other
|
||||
directories available inside the chroot.</para>
|
||||
<para>Currently, sandboxing only work on Linux and Mac OS X. The use
|
||||
of a sandbox requires that Nix is run as root (so you should use
|
||||
the <link linkend='conf-build-users-group'>“build users”
|
||||
feature</link> to perform the actual builds under different users
|
||||
than root).</para>
|
||||
|
||||
<para>If this option is set to <literal>relaxed</literal>, then
|
||||
fixed-output derivations and derivations that have the
|
||||
<varname>__noChroot</varname> attribute set to
|
||||
<literal>true</literal> do not run in sandboxes.</para>
|
||||
|
||||
<para>The default is <literal>false</literal>.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-build-chroot-dirs"><term><literal>build-chroot-dirs</literal></term>
|
||||
<varlistentry xml:id="conf-build-sandbox-paths">
|
||||
<term><literal>build-sandbox-paths</literal></term>
|
||||
|
||||
<listitem><para>A list of paths bind-mounted into Nix chroot
|
||||
environments. Contrary to what the name suggests, the specified
|
||||
paths do not have to be directories; you can bind-mount other
|
||||
types of files as well. You can use the syntax
|
||||
<listitem><para>A list of paths bind-mounted into Nix sandbox
|
||||
environments. You can use the syntax
|
||||
<literal><replaceable>target</replaceable>=<replaceable>source</replaceable></literal>
|
||||
to mount a path in a different location in the chroot; for
|
||||
to mount a path in a different location in the sandbox; for
|
||||
instance, <literal>/bin=/nix-bin</literal> will mount the path
|
||||
<literal>/nix-bin</literal> as <literal>/bin</literal> inside the
|
||||
chroot.</para>
|
||||
sandbox.</para>
|
||||
|
||||
<para>Depending on how Nix was built, the default value for this option
|
||||
may be empty or provide <filename>/bin/sh</filename> as a
|
||||
@@ -269,10 +277,11 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-build-extra-chroot-dirs"><term><literal>build-extra-chroot-dirs</literal></term>
|
||||
<varlistentry xml:id="conf-build-extra-sandbox-paths">
|
||||
<term><literal>build-extra-sandbox-paths</literal></term>
|
||||
|
||||
<listitem><para>A list of additional paths appended to
|
||||
<option>build-chroot-dirs</option>. Useful if you want to extend
|
||||
<option>build-sandbox-paths</option>. Useful if you want to extend
|
||||
its default value.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
@@ -392,12 +401,32 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>signed-binary-caches</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>*</literal>, Nix will only
|
||||
download binaries if they are signed using one of the keys listed
|
||||
in <option>binary-cache-public-keys</option>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>binary-cache-public-keys</literal></term>
|
||||
|
||||
<listitem><para>A whitespace-separated list of public keys
|
||||
corresponding to the secret keys trusted to sign binary
|
||||
caches. For example:
|
||||
<literal>cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
|
||||
hydra.nixos.org-1:CNHJZBh9K4tP3EKF6FkkgeVYsS3ohTl+oS0Qa8bezVs=</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>binary-caches-parallel-connections</literal></term>
|
||||
|
||||
<listitem><para>The maximum number of parallel HTTP connections
|
||||
used by the binary cache substituter to get NAR info files. This
|
||||
number should be high to minimise latency. It defaults to
|
||||
150.</para></listitem>
|
||||
25.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
@@ -538,6 +567,69 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-restrict-eval"><term><literal>restrict-eval</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>If set to <literal>true</literal>, the Nix evaluator will
|
||||
not allow access to any files outside of the Nix search path (as
|
||||
set via the <envar>NIX_PATH</envar> environment variable or the
|
||||
<option>-I</option> option). The default is
|
||||
<literal>false</literal>.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-pre-build-hook"><term><literal>pre-build-hook</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
|
||||
<para>If set, the path to a program that can set extra
|
||||
derivation-specific settings for this system. This is used for settings
|
||||
that can't be captured by the derivation model itself and are too variable
|
||||
between different versions of the same system to be hard-coded into nix.
|
||||
</para>
|
||||
|
||||
<para>The hook is passed the derivation path and, if sandboxes are enabled,
|
||||
the sandbox directory. It can then modify the sandbox and send a series of
|
||||
commands to modify various settings to stdout. The currently recognized
|
||||
commands are:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry xml:id="extra-sandbox-paths">
|
||||
<term><literal>extra-sandbox-paths</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>Pass a list of files and directories to be included in the
|
||||
sandbox for this build. One entry per line, terminated by an empty
|
||||
line. Entries have the same format as
|
||||
<literal>build-sandbox-paths</literal>.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-build-repeat"><term><literal>build-repeat</literal></term>
|
||||
|
||||
<listitem><para>How many times to repeat builds to check whether
|
||||
they are deterministic. The default value is 0. If the value is
|
||||
non-zero, every build is repeated the specified number of
|
||||
times. If the contents of any of the runs differs from the
|
||||
previous ones, the build is rejected and the resulting store paths
|
||||
are not registered as “valid” in Nix’s database.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
@@ -36,8 +36,20 @@ nixpkgs=/home/eelco/Dev/nixpkgs-branch:/etc/nixos</screen>
|
||||
<literal><nixpkgs/<replaceable>path</replaceable>></literal> in
|
||||
<filename>/home/eelco/Dev/nixpkgs-branch/<replaceable>path</replaceable></filename>
|
||||
and
|
||||
<filename>/etc/nixos/nixpkgs/<replaceable>path</replaceable></filename>.
|
||||
</para>
|
||||
<filename>/etc/nixos/nixpkgs/<replaceable>path</replaceable></filename>.</para>
|
||||
|
||||
<para>If a path in the Nix search path starts with
|
||||
<literal>http://</literal> or <literal>https://</literal>, it is
|
||||
interpreted as the URL of a tarball that will be downloaded and
|
||||
unpacked to a temporary location. The tarball must consist of a
|
||||
single top-level directory. For example, setting
|
||||
<envar>NIX_PATH</envar> to
|
||||
|
||||
<screen>
|
||||
nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz</screen>
|
||||
|
||||
tells Nix to download the latest revision in the Nixpkgs/NixOS
|
||||
14.12 channel.</para>
|
||||
|
||||
<para>The search path can be extended using the <option
|
||||
linkend="opt-I">-I</option> option, which takes precedence over
|
||||
|
||||
@@ -58,6 +58,13 @@ and so on).</para>
|
||||
<command>nix-build</command> will use <filename>default.nix</filename>
|
||||
in the current directory, if it exists.</para>
|
||||
|
||||
<para>If an element of <replaceable>paths</replaceable> starts with
|
||||
<literal>http://</literal> or <literal>https://</literal>, it is
|
||||
interpreted as the URL of a tarball that will be downloaded and
|
||||
unpacked to a temporary location. The tarball must include a single
|
||||
top-level directory containing at least a file named
|
||||
<filename>default.nix</filename>.</para>
|
||||
|
||||
<para><command>nix-build</command> is essentially a wrapper around
|
||||
<link
|
||||
linkend="sec-nix-instantiate"><command>nix-instantiate</command></link>
|
||||
@@ -175,6 +182,15 @@ bar
|
||||
|
||||
</para>
|
||||
|
||||
<para>Build the GNU Hello package from the latest revision of the
|
||||
master branch of Nixpkgs:
|
||||
|
||||
<screen>
|
||||
$ nix-build https://github.com/NixOS/nixpkgs/archive/master.tar.gz -A hello
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<command>nix-channel</command>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--add</option> <replaceable>url</replaceable> <arg choice='opt'><replaceable>name</replaceable></arg></arg>
|
||||
<arg choice='plain'><option>--remove</option> <replaceable>url</replaceable></arg>
|
||||
<arg choice='plain'><option>--remove</option> <replaceable>name</replaceable></arg>
|
||||
<arg choice='plain'><option>--list</option></arg>
|
||||
<arg choice='plain'><option>--update</option> <arg rep='repeat'><replaceable>names</replaceable></arg></arg>
|
||||
<arg choice='plain'><option>--rollback</option> <arg choice='opt'><replaceable>generation</replaceable></arg></arg>
|
||||
@@ -129,7 +129,7 @@ $ nix-instantiate --eval -E '(import <nixpkgs> {}).lib.nixpkgsVersion'
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><filename>/nix/var/nix/profiles/<replaceable>username</replaceable>/channels</filename></term>
|
||||
<varlistentry><term><filename>/nix/var/nix/profiles/per-user/<replaceable>username</replaceable>/channels</filename></term>
|
||||
|
||||
<listitem><para><command>nix-channel</command> uses a
|
||||
<command>nix-env</command> profile to keep track of previous
|
||||
@@ -144,7 +144,7 @@ $ nix-instantiate --eval -E '(import <nixpkgs> {}).lib.nixpkgsVersion'
|
||||
<varlistentry><term><filename>~/.nix-defexpr/channels</filename></term>
|
||||
|
||||
<listitem><para>This is a symlink to
|
||||
<filename>/nix/var/nix/profiles/<replaceable>username</replaceable>/channels</filename>. It
|
||||
<filename>/nix/var/nix/profiles/per-user/<replaceable>username</replaceable>/channels</filename>. It
|
||||
ensures that <command>nix-env</command> can find your channels. In
|
||||
a multi-user installation, you may also have
|
||||
<filename>~/.nix-defexpr/channels_root</filename>, which links to
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
<arg choice='plain'><option>--print-dead</option></arg>
|
||||
<arg choice='plain'><option>--delete</option></arg>
|
||||
</group>
|
||||
<arg><option>--max-freed</option> <replaceable>bytes</replaceable></arg>
|
||||
<arg><option>--dry-run</option></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
<arg><option>--include-outputs</option></arg>
|
||||
<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>
|
||||
</arg>
|
||||
@@ -42,7 +43,7 @@
|
||||
|
||||
<para><command>nix-copy-closure</command> gives you an easy and
|
||||
efficient way to exchange software between machines. Given one or
|
||||
more Nix store paths <replaceable>paths</replaceable> on the local
|
||||
more Nix store <replaceable>paths</replaceable> on the local
|
||||
machine, <command>nix-copy-closure</command> computes the closure of
|
||||
those paths (i.e. all their dependencies in the Nix store), and copies
|
||||
all paths in the closure to the remote machine via the
|
||||
@@ -138,6 +139,12 @@ those paths. If this bothers you, use
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>-v</option></term>
|
||||
|
||||
<listitem><para>Show verbose output.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
@@ -154,7 +154,15 @@ also <xref linkend="sec-common-options" />.</phrase></para>
|
||||
<option>--install</option>, <option>--upgrade</option>, and
|
||||
<option>--query --available</option> operations to obtain
|
||||
derivations. The default is
|
||||
<filename>~/.nix-defexpr</filename>.</para></listitem>
|
||||
<filename>~/.nix-defexpr</filename>.</para>
|
||||
|
||||
<para>If the argument starts with <literal>http://</literal> or
|
||||
<literal>https://</literal>, it is interpreted as the URL of a
|
||||
tarball that will be downloaded and unpacked to a temporary
|
||||
location. The tarball must include a single top-level directory
|
||||
containing at least a file named <filename>default.nix</filename>.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
@@ -370,7 +378,7 @@ number of possible ways:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--prebuild-only</option> / <option>-b</option></term>
|
||||
<varlistentry><term><option>--prebuilt-only</option> / <option>-b</option></term>
|
||||
|
||||
<listitem><para>Use only derivations for which a substitute is
|
||||
registered, i.e., there is a pre-built binary available that can
|
||||
@@ -416,7 +424,7 @@ $ nix-env --install gcc-3.3.2
|
||||
installing `gcc-3.3.2'
|
||||
uninstalling `gcc-3.1'</screen>
|
||||
|
||||
Note the the previously installed version is removed, since
|
||||
Note the previously installed version is removed, since
|
||||
<option>--preserve-installed</option> was not specified.</para>
|
||||
|
||||
<para>To install an arbitrary version:
|
||||
@@ -496,6 +504,18 @@ the following paths will be substituted:
|
||||
|
||||
</para>
|
||||
|
||||
<para>To install Firefox from the latest revision in the Nixpkgs/NixOS
|
||||
14.12 channel:
|
||||
|
||||
<screen>
|
||||
$ nix-env -f https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz -iA firefox
|
||||
</screen>
|
||||
|
||||
(The GitHub repository <literal>nixpkgs-channels</literal> is updated
|
||||
automatically from the main <literal>nixpkgs</literal> repository
|
||||
after certain tests have succeeded and binaries have been built and
|
||||
uploaded to the binary cache at <uri>cache.nixos.org</uri>.)</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
</refsection>
|
||||
@@ -701,6 +721,44 @@ $ nix-env -e '.*' <lineannotation>(remove everything)</lineannotation></screen>
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
<refsection xml:id="rsec-nix-env-set"><title>Operation <option>--set</option></title>
|
||||
|
||||
<refsection><title>Synopsis</title>
|
||||
|
||||
<cmdsynopsis>
|
||||
<command>nix-env</command>
|
||||
<arg choice='plain'><option>--set</option></arg>
|
||||
<arg choice='plain'><replaceable>drvname</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsection>
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The <option>--set</option> operation modifies the current generation of a
|
||||
profile so that it contains exactly the specified derivation, and nothing else.
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<para>
|
||||
The following updates a profile such that its current generation will contain
|
||||
just Firefox:
|
||||
|
||||
<screen>
|
||||
$ nix-env -p /nix/var/nix/profiles/browser --set firefox</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
<refsection xml:id="rsec-nix-env-set-flag"><title>Operation <option>--set-flag</option></title>
|
||||
@@ -954,7 +1012,7 @@ user environment elements, etc. -->
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--prebuild-only</option> / <option>-b</option></term>
|
||||
<varlistentry><term><option>--prebuilt-only</option> / <option>-b</option></term>
|
||||
|
||||
<listitem><para>Show only derivations for which a substitute is
|
||||
registered, i.e., there is a pre-built binary available that can
|
||||
@@ -1091,54 +1149,103 @@ user environment elements, etc. -->
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<para>To show installed packages:
|
||||
|
||||
<screen>
|
||||
$ nix-env -q <lineannotation>(show installed derivations)</lineannotation>
|
||||
$ nix-env -q
|
||||
bison-1.875c
|
||||
docbook-xml-4.2
|
||||
firefox-1.0.4
|
||||
MPlayer-1.0pre7
|
||||
ORBit2-2.8.3
|
||||
...
|
||||
<replaceable>…</replaceable>
|
||||
</screen>
|
||||
|
||||
$ nix-env -qa <lineannotation>(show available derivations)</lineannotation>
|
||||
</para>
|
||||
|
||||
<para>To show available packages:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qa
|
||||
firefox-1.0.7
|
||||
GConf-2.4.0.1
|
||||
MPlayer-1.0pre7
|
||||
ORBit2-2.8.3
|
||||
...
|
||||
<replaceable>…</replaceable>
|
||||
</screen>
|
||||
|
||||
$ nix-env -qas <lineannotation>(show status of available derivations)</lineannotation>
|
||||
</para>
|
||||
|
||||
<para>To show the status of available packages:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qas
|
||||
-P- firefox-1.0.7 <lineannotation>(not installed but present)</lineannotation>
|
||||
--S GConf-2.4.0.1 <lineannotation>(not present, but there is a substitute for fast installation)</lineannotation>
|
||||
--S MPlayer-1.0pre3 <lineannotation>(i.e., this is not the installed MPlayer, even though the version is the same!)</lineannotation>
|
||||
IP- ORBit2-2.8.3 <lineannotation>(installed and by definition present)</lineannotation>
|
||||
...
|
||||
<replaceable>…</replaceable>
|
||||
</screen>
|
||||
|
||||
<lineannotation>(show available derivations in the Nix expression <!-- !!! <filename>-->foo.nix<!-- </filename> -->)</lineannotation>
|
||||
</para>
|
||||
|
||||
<para>To show available packages in the Nix expression <filename>foo.nix</filename>:
|
||||
|
||||
<screen>
|
||||
$ nix-env -f ./foo.nix -qa
|
||||
foo-1.2.3
|
||||
</screen>
|
||||
|
||||
$ nix-env -qc <lineannotation>(compare installed versions to what’s available)</lineannotation>
|
||||
</para>
|
||||
|
||||
<para>To compare installed versions to what’s available:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qc
|
||||
<replaceable>...</replaceable>
|
||||
acrobat-reader-7.0 - ? <lineannotation>(package is not available at all)</lineannotation>
|
||||
autoconf-2.59 = 2.59 <lineannotation>(same version)</lineannotation>
|
||||
firefox-1.0.4 < 1.0.7 <lineannotation>(a more recent version is available)</lineannotation>
|
||||
<replaceable>...</replaceable>
|
||||
</screen>
|
||||
|
||||
$ nix-env -qa '.*zip.*' <lineannotation>(show all packages with “zip” in the name)</lineannotation>
|
||||
</para>
|
||||
|
||||
<para>To show all packages with “<literal>zip</literal>” in the name:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qa '.*zip.*'
|
||||
bzip2-1.0.6
|
||||
gzip-1.6
|
||||
zip-3.0
|
||||
<replaceable>...</replaceable>
|
||||
<replaceable>…</replaceable>
|
||||
</screen>
|
||||
|
||||
$ nix-env -qa '.*(firefox|chromium).*' <lineannotation>(show all packages with “firefox” or “chromium” in the name)</lineannotation>
|
||||
</para>
|
||||
|
||||
<para>To show all packages with “<literal>firefox</literal>” or
|
||||
“<literal>chromium</literal>” in the name:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qa '.*(firefox|chromium).*'
|
||||
chromium-37.0.2062.94
|
||||
chromium-beta-38.0.2125.24
|
||||
firefox-32.0.3
|
||||
firefox-with-plugins-13.0.1
|
||||
<replaceable>...</replaceable>
|
||||
<replaceable>…</replaceable>
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>To show all packages in the latest revision of the Nixpkgs
|
||||
repository:
|
||||
|
||||
<screen>
|
||||
$ nix-env -f https://github.com/NixOS/nixpkgs/archive/master.tar.gz -qa
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
</refsection>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-nix-prefetch-url">
|
||||
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-prefetch-url</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
@@ -20,6 +20,7 @@
|
||||
<cmdsynopsis>
|
||||
<command>nix-prefetch-url</command>
|
||||
<arg><option>--type</option> <replaceable>hashAlgo</replaceable></arg>
|
||||
<arg><option>--print-path</option></arg>
|
||||
<arg choice='plain'><replaceable>url</replaceable></arg>
|
||||
<arg><replaceable>hash</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
@@ -54,8 +55,8 @@ error if signaled if the actual hash of the file does not match the
|
||||
specified hash.</para>
|
||||
|
||||
<para>This command prints the hash on standard output. Additionally,
|
||||
if the environment variable <envar>PRINT_PATH</envar> is set, the path
|
||||
of the downloaded file in the Nix store is also printed.</para>
|
||||
if the option <option>--print-path</option> is used, the path of the
|
||||
downloaded file in the Nix store is also printed.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
@@ -63,7 +64,7 @@ of the downloaded file in the Nix store is also printed.</para>
|
||||
<refsection><title>Options</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
|
||||
<varlistentry><term><option>--type</option> <replaceable>hashAlgo</replaceable></term>
|
||||
|
||||
<listitem><para>Use the specified cryptographic hash algorithm,
|
||||
@@ -73,6 +74,35 @@ of the downloaded file in the Nix store is also printed.</para>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--print-path</option></term>
|
||||
|
||||
<listitem><para>Print the store path of the downloaded file on
|
||||
standard output.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--unpack</option></term>
|
||||
|
||||
<listitem><para>Unpack the archive (which must be a tarball or zip
|
||||
file) and add the result to the Nix store. The resulting hash can
|
||||
be used with functions such as Nixpkgs’s
|
||||
<varname>fetchzip</varname> or
|
||||
<varname>fetchFromGitHub</varname>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--name</option></term>
|
||||
|
||||
<listitem><para>Override the name of the file in the Nix store. By
|
||||
default, this is
|
||||
<literal><replaceable>hash</replaceable>-<replaceable>basename</replaceable></literal>,
|
||||
where <replaceable>basename</replaceable> is the last component of
|
||||
<replaceable>url</replaceable>. Overriding the name is necessary
|
||||
when <replaceable>basename</replaceable> contains characters that
|
||||
are not allowed in Nix store paths.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
@@ -81,14 +111,19 @@ of the downloaded file in the Nix store is also printed.</para>
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<screen>
|
||||
$ nix-prefetch-url ftp://ftp.nluug.nl/pub/gnu/make/make-3.80.tar.bz2
|
||||
0bbd1df101bc0294d440471e50feca71
|
||||
$ nix-prefetch-url ftp://ftp.gnu.org/pub/gnu/hello/hello-2.10.tar.gz
|
||||
0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i
|
||||
|
||||
$ PRINT_PATH=1 nix-prefetch-url ftp://ftp.nluug.nl/pub/gnu/make/make-3.80.tar.bz2
|
||||
0bbd1df101bc0294d440471e50feca71
|
||||
/nix/store/wvyz8ifdn7wyz1p3pqyn0ra45ka2l492-make-3.80.tar.bz2</screen>
|
||||
$ nix-prefetch-url --print-path mirror://gnu/hello/hello-2.10.tar.gz
|
||||
0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i
|
||||
/nix/store/3x7dwzq014bblazs7kq20p9hyzz0qh8g-hello-2.10.tar.gz
|
||||
|
||||
$ nix-prefetch-url --unpack --print-path https://github.com/NixOS/patchelf/archive/0.8.tar.gz
|
||||
079agjlv0hrv7fxnx9ngipx14gyncbkllxrp9cccnh3a50fxcmy7
|
||||
/nix/store/19zrmhm3m40xxaw81c8cqm6aljgrnwj2-0.8.tar.gz
|
||||
</screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
</refentry>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
<arg><option>--manifest</option></arg>
|
||||
<arg><option>--manifest-path</option> <replaceable>filename</replaceable></arg>
|
||||
<arg><option>--url-prefix</option> <replaceable>url</replaceable></arg>
|
||||
<arg><option>--key-file</option> <replaceable>path</replaceable></arg>
|
||||
<arg choice='plain' rep='repeat'><replaceable>paths</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
@@ -43,7 +44,7 @@ source and instead download binaries from the cache
|
||||
automatically.</para>
|
||||
|
||||
<para><command>nix-push</command> performs the following actions.
|
||||
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem><para>Each path in <replaceable>paths</replaceable> is
|
||||
@@ -101,9 +102,9 @@ automatically.</para>
|
||||
<varlistentry><term><option>--bzip2</option></term>
|
||||
|
||||
<listitem><para>Compress NARs using <command>bzip2</command>
|
||||
instead of <command>xz -9</command>. The latter compresses about
|
||||
30% better on typical archives, decompresses about twice as fast,
|
||||
but compresses a lot slower and is not supported by Nix prior to
|
||||
instead of <command>xz</command>. The latter compresses about 30%
|
||||
better on typical archives, decompresses about twice as fast, but
|
||||
compresses a lot slower and is not supported by Nix prior to
|
||||
version 1.2.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
@@ -155,6 +156,19 @@ automatically.</para>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--key-file</option> <replaceable>path</replaceable></term>
|
||||
|
||||
<listitem><para>Sign the binary cache using the secret key stored
|
||||
in <replaceable>path</replaceable>. This secret key must have been
|
||||
created using <command
|
||||
linkend="rsec-nix-store-generate-binary-cache-key">nix-store
|
||||
--generate-binary-cache-key</command>. Users of this binary cache
|
||||
should add the corresponding public key to the option
|
||||
<option>binary-cache-public-keys</option> in
|
||||
<filename>nix.conf</filename>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
@@ -203,6 +217,40 @@ $ nix-pull http://example.org/cache
|
||||
|
||||
to cause the binaries to be used by subsequent Nix operations.</para>
|
||||
|
||||
<para>To generate a signed binary cache, you must first generate a key
|
||||
pair, in this example called <literal>cache.example.org-1</literal>,
|
||||
storing the secret key in <filename>./sk</filename> and the public key
|
||||
in <filename>./pk</filename>:
|
||||
|
||||
<screen>
|
||||
$ nix-store --generate-binary-cache-key cache.example.org-1 sk pk
|
||||
|
||||
$ cat sk
|
||||
cache.example.org-1:jcMRQYFo8pQKzTtimpQLIPeHkMYZjfhB24hGfwF+u9PuX8H8FO7q564+X3G/JDlqqIqGar3OXRRwS9N3Wh3vbw==
|
||||
|
||||
$ cat pk
|
||||
cache.example.org-1:7l/B/BTu6ueuPl9xvyQ5aqiKhmq9zl0UcEvTd1od728=
|
||||
</screen>
|
||||
|
||||
You can then generate a binary cache signed with the secret key:
|
||||
|
||||
<screen>
|
||||
$ nix-push --dest /tmp/cache --key-file ./sk $(type -p firefox)
|
||||
</screen>
|
||||
|
||||
Users who wish to verify the integrity of binaries downloaded from
|
||||
your cache would add the following to their
|
||||
<filename>nix.conf</filename>:
|
||||
|
||||
<programlisting>
|
||||
binary-caches = http://cache.example.org
|
||||
signed-binary-caches = *
|
||||
binary-cache-public-keys = cache.example.org-1:7l/B/BTu6ueuPl9xvyQ5aqiKhmq9zl0UcEvTd1od728=
|
||||
</programlisting>
|
||||
|
||||
Nix will then ignore any binary that has a missing, incorrect or
|
||||
unrecognised signature.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
@@ -224,7 +272,7 @@ Priority: 10
|
||||
The properties that are currently supported are:
|
||||
|
||||
<variablelist>
|
||||
|
||||
|
||||
<varlistentry><term><literal>StoreDir</literal></term>
|
||||
|
||||
<listitem><para>The path of the Nix store to which this binary
|
||||
@@ -303,12 +351,13 @@ NarHash: sha256:0s491y1h9hxj5ghiizlxk7ax6jwbha00zwn7lpyd5xg5bhf60vzg
|
||||
NarSize: 109521136
|
||||
References: 2ma2k0ys8knh4an48n28vigcmc2z8773-linux-headers-2.6.23.16 ...
|
||||
Deriver: 7akyyc87ka32xwmqza9dvyg5pwx3j212-glibc-2.7.drv
|
||||
Sig: cache.example.org-1:WepnSp2UT0odDpR3NRjPVhJBHmdBgSBSTbHpdh4SCz92nGXwFY82bkPEmISoC0hGqBXDXEmB6y3Ohgna3mMgDg==
|
||||
</screen>
|
||||
|
||||
The fields are as follows:
|
||||
|
||||
<variablelist>
|
||||
|
||||
|
||||
<varlistentry><term><literal>StorePath</literal></term>
|
||||
|
||||
<listitem><para>The full store path, including the name part
|
||||
@@ -381,6 +430,22 @@ The fields are as follows:
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>Sig</literal></term>
|
||||
|
||||
<listitem><para>A signature of the the form
|
||||
<literal><replaceable>key-name</replaceable>:<replaceable>sig</replaceable></literal>,
|
||||
where <replaceable>key-name</replaceable> is the symbolic name of
|
||||
the key pair used to sign and verify the cache
|
||||
(e.g. <literal>cache.example.org-1</literal>), and
|
||||
<replaceable>sig</replaceable> is the actual signature, computed
|
||||
over the <varname>StorePath</varname>, <varname>NarHash</varname>,
|
||||
<varname>NarSize</varname> and <varname>References</varname>
|
||||
fields using the <link
|
||||
xlink:href="http://ed25519.cr.yp.to/">Ed25519 public-key signature
|
||||
system</link>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
<replaceable>attrPath</replaceable>
|
||||
</arg>
|
||||
<arg><option>--command</option> <replaceable>cmd</replaceable></arg>
|
||||
<arg><option>--run</option> <replaceable>cmd</replaceable></arg>
|
||||
<arg><option>--exclude</option> <replaceable>regexp</replaceable></arg>
|
||||
<arg><option>--pure</option></arg>
|
||||
<group choice='req'>
|
||||
@@ -60,6 +61,13 @@ derivation for development.</para>
|
||||
<filename>shell.nix</filename> if it exists, and
|
||||
<filename>default.nix</filename> otherwise.</para>
|
||||
|
||||
<para>If <replaceable>path</replaceable> starts with
|
||||
<literal>http://</literal> or <literal>https://</literal>, it is
|
||||
interpreted as the URL of a tarball that will be downloaded and
|
||||
unpacked to a temporary location. The tarball must include a single
|
||||
top-level directory containing at least a file named
|
||||
<filename>default.nix</filename>.</para>
|
||||
|
||||
<para>If the derivation defines the variable
|
||||
<varname>shellHook</varname>, it will be evaluated after
|
||||
<literal>$stdenv/setup</literal> has been sourced. Since this hook is
|
||||
@@ -92,11 +100,24 @@ also <xref linkend="sec-common-options" />.</phrase></para>
|
||||
<varlistentry><term><option>--command</option> <replaceable>cmd</replaceable></term>
|
||||
|
||||
<listitem><para>In the environment of the derivation, run the
|
||||
shell command <replaceable>cmd</replaceable> instead of starting
|
||||
an interactive shell. However, if you end the shell command with
|
||||
<literal>return</literal>, you still get an interactive shell.
|
||||
This can be useful for doing any additional
|
||||
initialisation.</para></listitem>
|
||||
shell command <replaceable>cmd</replaceable>. This command is
|
||||
executed in an interactive shell. (Use <option>--run</option> to
|
||||
use a non-interactive shell instead.) However, a call to
|
||||
<literal>exit</literal> is implicitly added to the command, so the
|
||||
shell will exit after running the command. To prevent this, add
|
||||
<literal>return</literal> at the end; e.g. <literal>--command
|
||||
"echo Hello; return"</literal> will print <literal>Hello</literal>
|
||||
and then drop you into the interactive shell. This can be useful
|
||||
for doing any additional initialisation.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--run</option> <replaceable>cmd</replaceable></term>
|
||||
|
||||
<listitem><para>Like <option>--command</option>, but executes the
|
||||
command in a non-interactive shell. This means (among other
|
||||
things) that if you hit Ctrl-C while the command is running, the
|
||||
shell exits.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
@@ -135,6 +156,15 @@ also <xref linkend="sec-common-options" />.</phrase></para>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>-i</option> <replaceable>interpreter</replaceable></term>
|
||||
|
||||
<listitem><para>The chained script interpreter to be invoked by
|
||||
<command>nix-shell</command>. Only applicable in
|
||||
<literal>#!</literal>-scripts (described <link
|
||||
linkend="ssec-nix-shell-shebang">below</link>).</para>
|
||||
|
||||
</listitem></varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
<para>The following common options are supported:</para>
|
||||
@@ -146,6 +176,22 @@ also <xref linkend="sec-common-options" />.</phrase></para>
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Environment variables</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><envar>NIX_BUILD_SHELL</envar></term>
|
||||
|
||||
<listitem><para>Shell used to start the interactive environment.
|
||||
Defaults to the <command>bash</command> found in <envar>PATH</envar>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<para>To build the dependencies of the package Pan, and start an
|
||||
@@ -184,6 +230,133 @@ $ nix-shell -p sqlite xorg.libX11
|
||||
… -L/nix/store/j1zg5v…-sqlite-3.8.0.2/lib -L/nix/store/0gmcz9…-libX11-1.6.1/lib …
|
||||
</screen>
|
||||
|
||||
The <command>-p</command> flag looks up Nixpkgs in the Nix search
|
||||
path. You can override it by passing <option>-I</option> or setting
|
||||
<envar>NIX_PATH</envar>. For example, the following gives you a shell
|
||||
containing the Pan package from a specific revision of Nixpkgs:
|
||||
|
||||
<screen>
|
||||
$ nix-shell -p pan -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/8a3eea054838b55aca962c3fbde9c83c102b8bf2.tar.gz
|
||||
|
||||
[nix-shell:~]$ pan --version
|
||||
Pan 0.139
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection xml:id="ssec-nix-shell-shebang"><title>Use as a <literal>#!</literal>-interpreter</title>
|
||||
|
||||
<para>You can use <command>nix-shell</command> as a script interpreter
|
||||
to allow scripts written in arbitrary languages to obtain their own
|
||||
dependencies via Nix. This is done by starting the script with the
|
||||
following lines:
|
||||
|
||||
<programlisting>
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i <replaceable>real-interpreter</replaceable> -p <replaceable>packages</replaceable>
|
||||
</programlisting>
|
||||
|
||||
where <replaceable>real-interpreter</replaceable> is the “real” script
|
||||
interpreter that will be invoked by <command>nix-shell</command> after
|
||||
it has obtained the dependencies and initialised the environment, and
|
||||
<replaceable>packages</replaceable> are the attribute names of the
|
||||
dependencies in Nixpkgs.</para>
|
||||
|
||||
<para>The lines starting with <literal>#! nix-shell</literal> specify
|
||||
<command>nix-shell</command> options (see above). Note that you cannot
|
||||
write <literal>#1 /usr/bin/env nix-shell -i ...</literal> because
|
||||
many operating systems only allow one argument in
|
||||
<literal>#!</literal> lines.</para>
|
||||
|
||||
<para>For example, here is a Python script that depends on Python and
|
||||
the <literal>prettytable</literal> package:
|
||||
|
||||
<programlisting>
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i python -p python pythonPackages.prettytable
|
||||
|
||||
import prettytable
|
||||
|
||||
# Print a simple table.
|
||||
t = prettytable.PrettyTable(["N", "N^2"])
|
||||
for n in range(1, 10): t.add_row([n, n * n])
|
||||
print t
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Similarly, the following is a Perl script that specifies that it
|
||||
requires Perl and the <literal>HTML::TokeParser::Simple</literal> and
|
||||
<literal>LWP</literal> packages:
|
||||
|
||||
<programlisting>
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i perl -p perl perlPackages.HTMLTokeParserSimple perlPackages.LWP
|
||||
|
||||
use HTML::TokeParser::Simple;
|
||||
|
||||
# Fetch nixos.org and print all hrefs.
|
||||
my $p = HTML::TokeParser::Simple->new(url => 'http://nixos.org/');
|
||||
|
||||
while (my $token = $p->get_tag("a")) {
|
||||
my $href = $token->get_attr("href");
|
||||
print "$href\n" if $href;
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Finally, the following Haskell script uses a specific branch of
|
||||
Nixpkgs/NixOS (the 14.12 stable branch):
|
||||
|
||||
<programlisting><![CDATA[
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i runghc -p haskellPackages.ghc haskellPackages.HTTP haskellPackages.tagsoup
|
||||
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz
|
||||
|
||||
import Network.HTTP
|
||||
import Text.HTML.TagSoup
|
||||
|
||||
-- Fetch nixos.org and print all hrefs.
|
||||
main = do
|
||||
resp <- Network.HTTP.simpleHTTP (getRequest "http://nixos.org/")
|
||||
body <- getResponseBody resp
|
||||
let tags = filter (isTagOpenName "a") $ parseTags body
|
||||
let tags' = map (fromAttrib "href") tags
|
||||
mapM_ putStrLn $ filter (/= "") tags'
|
||||
]]></programlisting>
|
||||
|
||||
If you want to be even more precise, you can specify a specific
|
||||
revision of Nixpkgs:
|
||||
|
||||
<programlisting>
|
||||
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/0672315759b3e15e2121365f067c1c8c56bb4722.tar.gz
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The examples above all used <option>-p</option> to get
|
||||
dependencies from Nixpkgs. You can also use a Nix expression to build
|
||||
your own dependencies. For example, the Python example could have been
|
||||
written as:
|
||||
|
||||
<programlisting>
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell deps.nix -i python
|
||||
</programlisting>
|
||||
|
||||
where the file <filename>deps.nix</filename> in the same directory
|
||||
as the <literal>#!</literal>-script contains:
|
||||
|
||||
<programlisting>
|
||||
with import <nixpkgs> {};
|
||||
|
||||
runCommand "dummy" { buildInputs = [ python pythonPackages.prettytable ]; } ""
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
@@ -194,6 +194,25 @@ printed.)</para>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--check</option></term>
|
||||
|
||||
<listitem><para>This option allows you to check whether a
|
||||
derivation is deterministic. It rebuilds the specified derivation
|
||||
and checks whether the result is bitwise-identical with the
|
||||
existing outputs, printing an error if that’s not the case. The
|
||||
outputs of the specified derivation must already exist. When used
|
||||
with <option>-K</option>, if an output path is not identical to
|
||||
the corresponding output from the previous build, the new output
|
||||
path is left in
|
||||
<filename>/nix/store/<replaceable>name</replaceable>-check.</filename></para>
|
||||
|
||||
<para>See also the <option>build-repeat</option> configuration
|
||||
option, which repeats a derivation a number of times and prevents
|
||||
its outputs from being registered as “valid” in the Nix store
|
||||
unless they are identical.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
@@ -212,6 +231,14 @@ $ nix-store -r $(nix-instantiate ./test.nix)
|
||||
This is essentially what <link
|
||||
linkend="sec-nix-build"><command>nix-build</command></link> does.</para>
|
||||
|
||||
<para>To test whether a previously-built derivation is deterministic:
|
||||
|
||||
<screen>
|
||||
$ nix-build -r '<nixpkgs>' -A hello --check -K
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
@@ -1338,6 +1365,56 @@ $ nix-store --clear-failed-paths *
|
||||
</refsection>
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
<refsection xml:id='rsec-nix-store-generate-binary-cache-key'><title>Operation <option>--generate-binary-cache-key</option></title>
|
||||
|
||||
<refsection>
|
||||
<title>Synopsis</title>
|
||||
<cmdsynopsis>
|
||||
<command>nix-store</command>
|
||||
<arg choice='plain'>
|
||||
<option>--generate-binary-cache-key</option>
|
||||
<option>key-name</option>
|
||||
<option>secret-key-file</option>
|
||||
<option>public-key-file</option>
|
||||
</arg>
|
||||
</cmdsynopsis>
|
||||
</refsection>
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>This command generates an <link
|
||||
xlink:href="http://ed25519.cr.yp.to/">Ed25519 key pair</link> that can
|
||||
be used to create a signed binary cache. It takes three mandatory
|
||||
parameters:
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem><para>A key name, such as
|
||||
<literal>cache.example.org-1</literal>, that is used to look up keys
|
||||
on the client when it verifies signatures. It can be anything, but
|
||||
it’s suggested to use the host name of your cache
|
||||
(e.g. <literal>cache.example.org</literal>) with a suffix denoting
|
||||
the number of the key (to be incremented every time you need to
|
||||
revoke a key).</para></listitem>
|
||||
|
||||
<listitem><para>The file name where the secret key is to be
|
||||
stored.</para></listitem>
|
||||
|
||||
<listitem><para>The file name where the public key is to be
|
||||
stored.</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
For an example, see the manual page for <command
|
||||
linkend="sec-nix-push">nix-push</command>.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
<refsection condition="manpage"><title>Environment variables</title>
|
||||
|
||||
@@ -40,7 +40,7 @@ allowedReferences = [];
|
||||
recursively. For example,
|
||||
|
||||
<programlisting>
|
||||
allowedReferences = [ foobar ];
|
||||
allowedRequisites = [ foobar ];
|
||||
</programlisting>
|
||||
|
||||
enforces that the output of a derivation cannot have any other
|
||||
@@ -90,6 +90,33 @@ derivation {
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><varname>impureEnvVars</varname></term>
|
||||
|
||||
<listitem><para>This attribute allows you to specify a list of
|
||||
environment variables that should be passed from the environment
|
||||
of the calling user to the builder. Usually, the environment is
|
||||
cleared completely when the builder is executed, but with this
|
||||
attribute you can allow specific environment variables to be
|
||||
passed unmodified. For example, <function>fetchurl</function> in
|
||||
Nixpkgs has the line
|
||||
|
||||
<programlisting>
|
||||
impureEnvVars = [ "http_proxy" "https_proxy" <replaceable>...</replaceable> ];
|
||||
</programlisting>
|
||||
|
||||
to make it use the proxy server configuration specified by the
|
||||
user in the environment variables <envar>http_proxy</envar> and
|
||||
friends.</para>
|
||||
|
||||
<para>This attribute is only allowed in <link
|
||||
linkend="fixed-output-drvs">fixed-output derivations</link>, where
|
||||
impurities such as these are okay since (the hash of) the output
|
||||
is known in advance. It is ignored for all other
|
||||
derivations.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="fixed-output-drvs">
|
||||
<term><varname>outputHash</varname></term>
|
||||
<term><varname>outputHashAlgo</varname></term>
|
||||
@@ -215,29 +242,29 @@ stdenv.mkDerivation {
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><varname>impureEnvVars</varname></term>
|
||||
<varlistentry><term><varname>passAsFile</varname></term>
|
||||
|
||||
<listitem><para>This attribute allows you to specify a list of
|
||||
environment variables that should be passed from the environment
|
||||
of the calling user to the builder. Usually, the environment is
|
||||
cleared completely when the builder is executed, but with this
|
||||
attribute you can allow specific environment variables to be
|
||||
passed unmodified. For example, <function>fetchurl</function> in
|
||||
Nixpkgs has the line
|
||||
<listitem><para>A list of names of attributes that should be
|
||||
passed via files rather than environment variables. For example,
|
||||
if you have
|
||||
|
||||
<programlisting>
|
||||
impureEnvVars = [ "http_proxy" "https_proxy" <replaceable>...</replaceable> ];
|
||||
</programlisting>
|
||||
<programlisting>
|
||||
passAsFile = ["big"];
|
||||
big = "a very long string";
|
||||
</programlisting>
|
||||
|
||||
to make it use the proxy server configuration specified by the
|
||||
user in the environment variables <envar>http_proxy</envar> and
|
||||
friends.</para>
|
||||
|
||||
<para>This attribute is only allowed in <link
|
||||
linkend="fixed-output-drvs">fixed-output derivations</link>, where
|
||||
impurities such as these are okay since (the hash of) the output
|
||||
is known in advance. It is ignored for all other
|
||||
derivations.</para></listitem>
|
||||
then when the builder runs, the environment variable
|
||||
<envar>bigPath</envar> will contain the absolute path to a
|
||||
temporary file containing <literal>a very long
|
||||
string</literal>. That is, for any attribute
|
||||
<replaceable>x</replaceable> listed in
|
||||
<varname>passAsFile</varname>, Nix will pass an environment
|
||||
variable <envar><replaceable>x</replaceable>Path</envar> holding
|
||||
the path of the file containing the value of attribute
|
||||
<replaceable>x</replaceable>. This is useful when you need to pass
|
||||
large strings to a builder, since most operating systems impose a
|
||||
limit on the size of the environment (typically, a few hundred
|
||||
kilobyte).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
@@ -39,6 +39,28 @@ available as <function>builtins.derivation</function>.</para>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.all</function>
|
||||
<replaceable>pred</replaceable> <replaceable>list</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if the function
|
||||
<replaceable>pred</replaceable> returns <literal>true</literal>
|
||||
for all elements of <replaceable>list</replaceable>,
|
||||
and <literal>false</literal> otherwise.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.any</function>
|
||||
<replaceable>pred</replaceable> <replaceable>list</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if the function
|
||||
<replaceable>pred</replaceable> returns <literal>true</literal>
|
||||
for at least one element of <replaceable>list</replaceable>,
|
||||
and <literal>false</literal> otherwise.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.attrNames</function>
|
||||
<replaceable>set</replaceable></term>
|
||||
|
||||
@@ -211,6 +233,45 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.fetchurl</function>
|
||||
<replaceable>url</replaceable></term>
|
||||
|
||||
<listitem><para>Download the specified URL and return the path of
|
||||
the downloaded file. This function is not available if <link
|
||||
linkend="conf-restrict-eval">restricted evaluation mode</link> is
|
||||
enabled.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>fetchTarball</function>
|
||||
<replaceable>url</replaceable></term>
|
||||
|
||||
<listitem><para>Download the specified URL, unpack it and return
|
||||
the path of the unpacked tree. The file must be a tape archive
|
||||
(<filename>.tar</filename>) compressed with
|
||||
<literal>gzip</literal>, <literal>bzip2</literal> or
|
||||
<literal>xz</literal>. The top-level path component of the files
|
||||
in the tarball is removed, so it is best if the tarball contains a
|
||||
single directory at top level. The typical use of the function is
|
||||
to obtain external Nix expression dependencies, such as a
|
||||
particular version of Nixpkgs, e.g.
|
||||
|
||||
<programlisting>
|
||||
with import (fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz) {};
|
||||
|
||||
stdenv.mkDerivation { … }
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>This function is not available if <link
|
||||
linkend="conf-restrict-eval">restricted evaluation mode</link> is
|
||||
enabled.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.filter</function>
|
||||
<replaceable>f</replaceable> <replaceable>xs</replaceable></term>
|
||||
|
||||
@@ -274,6 +335,37 @@ stdenv.mkDerivation {
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.foldl’</function>
|
||||
<replaceable>op</replaceable> <replaceable>nul</replaceable> <replaceable>list</replaceable></term>
|
||||
|
||||
<listitem><para>Reduce a list by applying a binary operator, from
|
||||
left to right, e.g. <literal>foldl’ op nul [x0 x1 x2 ...] = op (op
|
||||
(op nul x0) x1) x2) ...</literal>. The operator is applied
|
||||
strictly, i.e., its arguments are evaluated first. For example,
|
||||
<literal>foldl’ (x: y: x + y) 0 [1 2 3]</literal> evaluates to
|
||||
6.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.functionArgs</function>
|
||||
<replaceable>f</replaceable></term>
|
||||
|
||||
<listitem><para>
|
||||
Return a set containing the names of the formal arguments expected
|
||||
by the function <replaceable>f</replaceable>.
|
||||
The value of each attribute is a Boolean denoting whether the corresponding
|
||||
argument has a default value. For instance,
|
||||
<literal>functionArgs ({ x, y ? 123}: ...) = { x = false; y = true; }</literal>.
|
||||
</para>
|
||||
|
||||
<para>"Formal argument" here refers to the attributes pattern-matched by
|
||||
the function. Plain lambdas are not included, e.g.
|
||||
<literal>functionArgs (x: ...) = { }</literal>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.fromJSON</function> <replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Convert a JSON string to a Nix
|
||||
@@ -290,6 +382,24 @@ builtins.fromJSON ''{"x": [1, 2, 3], "y": null}''
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.genList</function>
|
||||
<replaceable>generator</replaceable> <replaceable>length</replaceable></term>
|
||||
|
||||
<listitem><para>Generate list of size
|
||||
<replaceable>length</replaceable>, with each element
|
||||
<replaceable>i></replaceable> equal to the value returned by
|
||||
<replaceable>generator</replaceable> <literal>i</literal>. For
|
||||
example,
|
||||
|
||||
<programlisting>
|
||||
builtins.genList (x: x * x) 5
|
||||
</programlisting>
|
||||
|
||||
returns the list <literal>[ 0 1 4 9 16 ]</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.getAttr</function>
|
||||
<replaceable>s</replaceable> <replaceable>set</replaceable></term>
|
||||
|
||||
@@ -624,7 +734,7 @@ in config.someSetting</programlisting>
|
||||
./A</literal> will return the set
|
||||
|
||||
<programlisting>
|
||||
{ A = "regular"; B = "directory"; }</programlisting>
|
||||
{ B = "regular"; C = "directory"; }</programlisting>
|
||||
|
||||
The possible values for the file type are
|
||||
<literal>"regular"</literal>, <literal>"directory"</literal>,
|
||||
@@ -659,6 +769,23 @@ removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ]</programlisting>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.replaceStrings</function>
|
||||
<replaceable>from</replaceable> <replaceable>to</replaceable> <replaceable>s</replaceable></term>
|
||||
|
||||
<listitem><para>Given string <replaceable>s</replaceable>, replace
|
||||
every occurrence of the strings in <replaceable>from</replaceable>
|
||||
with the corresponding string in
|
||||
<replaceable>to</replaceable>. For example,
|
||||
|
||||
<programlisting>
|
||||
builtins.replaceStrings ["oo" "a"] ["a" "i"] "foobar"
|
||||
</programlisting>
|
||||
|
||||
evaluates to <literal>"fabir"</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.seq</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
|
||||
@@ -670,6 +797,29 @@ removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ]</programlisting>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.sort</function>
|
||||
<replaceable>comparator</replaceable> <replaceable>list</replaceable></term>
|
||||
|
||||
<listitem><para>Return <replaceable>list</replaceable> in sorted
|
||||
order. It repeatedly calls the function
|
||||
<replaceable>comparator</replaceable> with two elements. The
|
||||
comparator should return <literal>true</literal> if the first
|
||||
element is less than the second, and <literal>false</literal>
|
||||
otherwise. For example,
|
||||
|
||||
<programlisting>
|
||||
builtins.sort builtins.lessThan [ 483 249 526 147 42 77 ]
|
||||
</programlisting>
|
||||
|
||||
produces the list <literal>[ 42 77 147 249 483 526
|
||||
]</literal>.</para>
|
||||
|
||||
<para>This is a stable sort: it preserves the relative order of
|
||||
elements deemed equal by the comparator.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.stringLength</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
|
||||
@@ -155,7 +155,14 @@ stdenv.mkDerivation {
|
||||
expression that contained it. For instance, if a Nix expression in
|
||||
<filename>/foo/bar/bla.nix</filename> refers to
|
||||
<filename>../xyzzy/fnord.nix</filename>, the absolute path is
|
||||
<filename>/foo/xyzzy/fnord.nix</filename>.</para></listitem>
|
||||
<filename>/foo/xyzzy/fnord.nix</filename>.</para>
|
||||
|
||||
<para>If the first component of a path is a <literal>~</literal>,
|
||||
it is interpreted as if the rest of the path were relative to the
|
||||
user's home directory. e.g. <filename>~/foo</filename> would be
|
||||
equivalent to <filename>/home/edolstra/foo</filename> for a user
|
||||
whose home directory is <filename>/home/edolstra</filename>.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para><emphasis>Booleans</emphasis> with values
|
||||
<literal>true</literal> and
|
||||
|
||||
@@ -28,6 +28,7 @@ $ chown alice /nix
|
||||
|
||||
</para>
|
||||
|
||||
<!--
|
||||
<para>You can also manually download and install a binary package.
|
||||
Binary packages of the latest stable release are available for Fedora,
|
||||
Debian, Ubuntu, Mac OS X and various other systems from the <link
|
||||
@@ -53,12 +54,12 @@ $ dpkg -i nix_1.8-1_amd64.deb</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>For other platforms, including Mac OS X and other Linux
|
||||
distributions, you can download a binary tarball that contains Nix and
|
||||
all its dependencies. (This is what the install script at
|
||||
<uri>https://nixos.org/nix/install</uri> uses.) You should unpack it
|
||||
somewhere (e.g. in <filename>/tmp</filename>), and then run the script
|
||||
named <command>install</command> inside the binary tarball:
|
||||
<para>You can also download a binary tarball that contains Nix and all
|
||||
its dependencies. (This is what the install script at
|
||||
<uri>https://nixos.org/nix/install</uri> does automatically.) You
|
||||
should unpack it somewhere (e.g. in <filename>/tmp</filename>), and
|
||||
then run the script named <command>install</command> inside the binary
|
||||
tarball:
|
||||
|
||||
<screen>
|
||||
alice$ cd /tmp
|
||||
@@ -77,6 +78,15 @@ other auxiliary data, if desired:
|
||||
<screen>
|
||||
$ rm -rf /nix</screen>
|
||||
|
||||
</para>
|
||||
-->
|
||||
|
||||
<para>You can uninstall Nix simply by running:
|
||||
|
||||
<screen>
|
||||
$ rm -rf /nix
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -30,13 +30,13 @@
|
||||
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
|
||||
<listitem><para>The Perl DBI, DBD::SQLite, and WWW::Curl 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.hpl.hp.com/personal/Hans_Boehm/gc/">Boehm
|
||||
xlink:href="http://www.hboehm.info/gc/">Boehm
|
||||
garbage collector</link> to reduce the evaluator’s memory
|
||||
consumption (optional). To enable it, install
|
||||
<literal>pkgconfig</literal> and the Boehm garbage collector, and
|
||||
@@ -70,4 +70,4 @@
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -197,7 +197,7 @@ collection</emphasis> (Nixpkgs).</para>
|
||||
<simplesect><title>Managing build environments</title>
|
||||
|
||||
<para>Nix is extremely useful for developers as it makes it easy to
|
||||
automatically set up the the build environment for a package. Given a
|
||||
automatically set up the build environment for a package. Given a
|
||||
Nix expression that describes the dependencies of your package, the
|
||||
command <command>nix-shell</command> will build or download those
|
||||
dependencies if they’re not already in your Nix store, and then start
|
||||
|
||||
@@ -4,10 +4,8 @@
|
||||
version="5.0">
|
||||
|
||||
<info>
|
||||
|
||||
<title>Nix Package Manager Guide</title>
|
||||
|
||||
<edition>Version <xi:include href="version.txt" parse="text" /></edition>
|
||||
<subtitle>Version <xi:include href="version.txt" parse="text" /></subtitle>
|
||||
|
||||
<author>
|
||||
<personname>
|
||||
|
||||
@@ -36,7 +36,7 @@ it’s much more convenient to use the Nixpkgs
|
||||
<emphasis>channel</emphasis>, since it makes it easy to stay up to
|
||||
date with new versions of Nixpkgs. (Channels are described in more
|
||||
detail in <xref linkend="sec-channels"/>.) Nixpkgs is automatically
|
||||
added to your list of “subscribed” channels when when you install
|
||||
added to your list of “subscribed” channels when you install
|
||||
Nix. If this is not the case for some reason, you can add it as
|
||||
follows:
|
||||
|
||||
|
||||
@@ -120,8 +120,7 @@ can also see all available generations:
|
||||
<screen>
|
||||
$ nix-env --list-generations</screen></para>
|
||||
|
||||
<para>Actually, there is another level of indirection not shown in the
|
||||
figure above. You generally wouldn’t have
|
||||
<para>You generally wouldn’t have
|
||||
<filename>/nix/var/nix/profiles/<replaceable>some-profile</replaceable>/bin</filename>
|
||||
in your <envar>PATH</envar>. Rather, there is a symlink
|
||||
<filename>~/.nix-profile</filename> that points to your current
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
</partintro>
|
||||
-->
|
||||
|
||||
<xi:include href="rl-1.11.xml" />
|
||||
<xi:include href="rl-1.10.xml" />
|
||||
<xi:include href="rl-1.9.xml" />
|
||||
<xi:include href="rl-1.8.xml" />
|
||||
<xi:include href="rl-1.7.xml" />
|
||||
<xi:include href="rl-1.6.1.xml" />
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
version="5.0"
|
||||
xml:id="ch-relnotes-0.10.1">
|
||||
|
||||
<title>Release 0.10.1 (October 11, 2006)</title>
|
||||
<title>Release 0.10.1 (2006-10-11)</title>
|
||||
|
||||
<para>This release fixes two somewhat obscure bugs that occur when
|
||||
evaluating Nix expressions that are stored inside the Nix store
|
||||
(<literal>NIX-67</literal>). These do not affect most users.</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ch-relnotes-0.10">
|
||||
|
||||
<title>Release 0.10 (October 6, 2006)</title>
|
||||
<title>Release 0.10 (2006-10-06)</title>
|
||||
|
||||
<note><para>This version of Nix uses Berkeley DB 4.4 instead of 4.3.
|
||||
The database is upgraded automatically, but you should be careful not
|
||||
@@ -320,4 +320,4 @@ irreversible.</para></warning>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-0.11">
|
||||
|
||||
<title>Release 0.11 (December 31, 2007)</title>
|
||||
<title>Release 0.11 (2007-12-31)</title>
|
||||
|
||||
<para>Nix 0.11 has many improvements over the previous stable release.
|
||||
The most important improvement is secure multi-user support. It also
|
||||
@@ -258,4 +258,4 @@ on Nix. Here is an (incomplete) list:</para>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-0.12">
|
||||
|
||||
<title>Release 0.12 (November 20, 2008)</title>
|
||||
<title>Release 0.12 (2008-11-20)</title>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
@@ -172,4 +172,4 @@ the following paths will be downloaded/copied (30.02 MiB):
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-0.13">
|
||||
|
||||
<title>Release 0.13 (November 5, 2009)</title>
|
||||
<title>Release 0.13 (2009-11-05)</title>
|
||||
|
||||
<para>This is primarily a bug fix release. It has some new
|
||||
features:</para>
|
||||
@@ -103,4 +103,4 @@ features:</para>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-0.14"><title>Release 0.14 (February 4, 2010)</title>
|
||||
xml:id="ssec-relnotes-0.14">
|
||||
|
||||
<title>Release 0.14 (2010-02-04)</title>
|
||||
|
||||
<para>This release has the following improvements:</para>
|
||||
|
||||
@@ -41,4 +43,4 @@
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-0.15">
|
||||
|
||||
<title>Release 0.15 (March 17, 2010)</title>
|
||||
<title>Release 0.15 (2010-03-17)</title>
|
||||
|
||||
<para>This is a bug-fix release. Among other things, it fixes
|
||||
building on Mac OS X (Snow Leopard), and improves the contents of
|
||||
<filename>/etc/passwd</filename> and <filename>/etc/group</filename>
|
||||
in <literal>chroot</literal> builds.</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-0.16">
|
||||
|
||||
<title>Release 0.16 (August 17, 2010)</title>
|
||||
<title>Release 0.16 (2010-08-17)</title>
|
||||
|
||||
<para>This release has the following improvements:</para>
|
||||
|
||||
@@ -52,4 +52,4 @@
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ch-relnotes-0.6">
|
||||
|
||||
<title>Release 0.6 (November 14, 2004)</title>
|
||||
<title>Release 0.6 (2004-11-14)</title>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
@@ -119,4 +119,4 @@
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ch-relnotes-0.7">
|
||||
|
||||
<title>Release 0.7 (January 12, 2005)</title>
|
||||
<title>Release 0.7 (2005-01-12)</title>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
@@ -32,4 +32,4 @@
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ch-relnotes-0.8.1">
|
||||
|
||||
<title>Release 0.8.1 (April 13, 2005)</title>
|
||||
<title>Release 0.8.1 (2005-04-13)</title>
|
||||
|
||||
<para>This is a bug fix release.</para>
|
||||
|
||||
@@ -18,4 +18,4 @@
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ch-relnotes-0.8">
|
||||
|
||||
<title>Release 0.8 (April 11, 2005)</title>
|
||||
<title>Release 0.8 (2005-04-11)</title>
|
||||
|
||||
<para>NOTE: the hashing scheme in Nix 0.8 changed (as detailed below).
|
||||
As a result, <command>nix-pull</command> manifests and channels built
|
||||
@@ -243,4 +243,4 @@ $ nix-env -f .../i686-linux.nix -i -E 'x: x.firefoxWrapper'</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
version="5.0"
|
||||
xml:id="ch-relnotes-0.9.1">
|
||||
|
||||
<title>Release 0.9.1 (September 20, 2005)</title>
|
||||
<title>Release 0.9.1 (2005-09-20)</title>
|
||||
|
||||
<para>This bug fix release addresses a problem with the ATerm library
|
||||
when the <option>--with-aterm</option> flag in
|
||||
<command>configure</command> was <emphasis>not</emphasis> used.</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ch-relnotes-0.9.2">
|
||||
|
||||
<title>Release 0.9.2 (September 21, 2005)</title>
|
||||
<title>Release 0.9.2 (2005-09-21)</title>
|
||||
|
||||
<para>This bug fix release fixes two problems on Mac OS X:
|
||||
|
||||
@@ -25,4 +25,4 @@
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ch-relnotes-0.9">
|
||||
|
||||
<title>Release 0.9 (September 16, 2005)</title>
|
||||
<title>Release 0.9 (2005-09-16)</title>
|
||||
|
||||
<para>NOTE: this version of Nix uses Berkeley DB 4.3 instead of 4.2.
|
||||
The database is upgraded automatically, but you should be careful not
|
||||
@@ -95,4 +95,4 @@ svnService = derivation {
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.0">
|
||||
|
||||
<title>Release 1.0 (May 11, 2012)</title>
|
||||
<title>Release 1.0 (2012-05-11)</title>
|
||||
|
||||
<para>There have been numerous improvements and bug fixes since the
|
||||
previous release. Here are the most significant:</para>
|
||||
@@ -116,4 +116,4 @@ previous release. Here are the most significant:</para>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.1">
|
||||
|
||||
<title>Release 1.1 (July 18, 2012)</title>
|
||||
<title>Release 1.1 (2012-07-18)</title>
|
||||
|
||||
<para>This release has the following improvements:</para>
|
||||
|
||||
@@ -97,4 +97,4 @@
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<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.10">
|
||||
|
||||
<title>Release 1.10 (2015-09-03)</title>
|
||||
|
||||
<para>This is primarily a bug fix release. It also has a number of new
|
||||
features:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>A number of builtin functions have been added to reduce
|
||||
Nixpkgs/NixOS evaluation time and memory consumption:
|
||||
<function>all</function>,
|
||||
<function>any</function>,
|
||||
<function>concatStringsSep</function>,
|
||||
<function>foldl’</function>,
|
||||
<function>genList</function>,
|
||||
<function>replaceStrings</function>,
|
||||
<function>sort</function>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The garbage collector is more robust when the disk is full.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Nix supports a new API for building derivations that doesn’t
|
||||
require a <literal>.drv</literal> file to be present on disk; it
|
||||
only requires an in-memory representation of the derivation. This
|
||||
is used by the Hydra continuous build system to make remote builds
|
||||
more efficient.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The function <literal><nix/fetchurl.nix></literal> now
|
||||
uses a <emphasis>builtin</emphasis> builder (i.e. it doesn’t
|
||||
require starting an external process; the download is performed by
|
||||
Nix itself). This ensures that derivation paths don’t change when
|
||||
Nix is upgraded, and obviates the need for ugly hacks to support
|
||||
chroot execution.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><option>--version -v</option> now prints some configuration
|
||||
information, in particular what compile-time optional features are
|
||||
enabled, and the paths of various directories.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Build users have their supplementary groups set correctly.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>This release has contributions from Eelco Dolstra, Guillaume
|
||||
Maudoux, Iwan Aucamp, Jaka Hudoklin, Kirill Elagin, Ludovic Courtès,
|
||||
Manolis Ragkousis, Nicolas B. Pierron and Shea Levy.</para>
|
||||
|
||||
</section>
|
||||
@@ -0,0 +1,141 @@
|
||||
<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">
|
||||
|
||||
<title>Release 1.11 (2016-01-19)</title>
|
||||
|
||||
<para>This is primarily a bug fix release. It also has a number of new
|
||||
features:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para><command>nix-prefetch-url</command> can now download URLs
|
||||
specified in a Nix expression. For example,
|
||||
|
||||
<screen>
|
||||
$ nix-prefetch-url -A hello.src
|
||||
</screen>
|
||||
|
||||
will prefetch the file specified by the
|
||||
<function>fetchurl</function> call in the attribute
|
||||
<literal>hello.src</literal> from the Nix expression in the
|
||||
current directory, and print the cryptographic hash of the
|
||||
resulting file on stdout. This differs from <literal>nix-build -A
|
||||
hello.src</literal> in that it doesn't verify the hash, and is
|
||||
thus useful when you’re updating a Nix expression.</para>
|
||||
|
||||
<para>You can also prefetch the result of functions that unpack a
|
||||
tarball, such as <function>fetchFromGitHub</function>. For example:
|
||||
|
||||
<screen>
|
||||
$ nix-prefetch-url --unpack https://github.com/NixOS/patchelf/archive/0.8.tar.gz
|
||||
</screen>
|
||||
|
||||
or from a Nix expression:
|
||||
|
||||
<screen>
|
||||
$ nix-prefetch-url -A nix-repl.src
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The builtin function
|
||||
<function><nix/fetchurl.nix></function> now supports
|
||||
downloading and unpacking NARs. This removes the need to have
|
||||
multiple downloads in the Nixpkgs stdenv bootstrap process (like a
|
||||
separate busybox binary for Linux, or curl/mkdir/sh/bzip2 for
|
||||
Darwin). Now all those files can be combined into a single NAR,
|
||||
optionally compressed using <command>xz</command>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Nix now supports SHA-512 hashes for verifying fixed-output
|
||||
derivations, and in <function>builtins.hashString</function>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
The new flag <option>--option build-repeat
|
||||
<replaceable>N</replaceable></option> will cause every build to
|
||||
be executed <replaceable>N</replaceable>+1 times. If the build
|
||||
output differs between any round, the build is rejected, and the
|
||||
output paths are not registered as valid. This is primarily
|
||||
useful to verify build determinism. (We already had a
|
||||
<option>--check</option> option to repeat a previously succeeded
|
||||
build. However, with <option>--check</option>, non-deterministic
|
||||
builds are registered in the DB. Preventing that is useful for
|
||||
Hydra to ensure that non-deterministic builds don't end up
|
||||
getting published to the binary cache.)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
The options <option>--check</option> and <option>--option
|
||||
build-repeat <replaceable>N</replaceable></option>, if they
|
||||
detect a difference between two runs of the same derivation and
|
||||
<option>-K</option> is given, will make the output of the other
|
||||
run available under
|
||||
<filename><replaceable>store-path</replaceable>-check</filename>. This
|
||||
makes it easier to investigate the non-determinism using tools
|
||||
like <command>diffoscope</command>, e.g.,
|
||||
|
||||
<screen>
|
||||
$ nix-build pkgs/stdenv/linux -A stage1.pkgs.zlib --check -K
|
||||
error: derivation ‘/nix/store/l54i8wlw2265…-zlib-1.2.8.drv’ may not
|
||||
be deterministic: output ‘/nix/store/11a27shh6n2i…-zlib-1.2.8’
|
||||
differs from ‘/nix/store/11a27shh6n2i…-zlib-1.2.8-check’
|
||||
|
||||
$ diffoscope /nix/store/11a27shh6n2i…-zlib-1.2.8 /nix/store/11a27shh6n2i…-zlib-1.2.8-check
|
||||
…
|
||||
├── lib/libz.a
|
||||
│ ├── metadata
|
||||
│ │ @@ -1,15 +1,15 @@
|
||||
│ │ -rw-r--r-- 30001/30000 3096 Jan 12 15:20 2016 adler32.o
|
||||
…
|
||||
│ │ +rw-r--r-- 30001/30000 3096 Jan 12 15:28 2016 adler32.o
|
||||
…
|
||||
</screen>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Improved FreeBSD support.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><command>nix-env -qa --xml --meta</command> now prints
|
||||
license information.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The maximum number of parallel TCP connections that the
|
||||
binary cache substituter will use has been decreased from 150 to
|
||||
25. This should prevent upsetting some broken NAT routers, and
|
||||
also improves performance.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>All "chroot"-containing strings got renamed to "sandbox".
|
||||
In particular, some Nix options got renamed, but the old names
|
||||
are still accepted as lower-priority aliases.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>This release has contributions from Anders Claesson, Anthony
|
||||
Cowley, Bjørn Forsman, Brian McKenna, Danny Wilson, davidak, Eelco Dolstra,
|
||||
Fabian Schmitthenner, FrankHB, Ilya Novoselov, janus, Jim Garrison, John
|
||||
Ericson, Jude Taylor, Ludovic Courtès, Manuel Jacob, Mathnerd314,
|
||||
Pascal Wittmann, Peter Simons, Philip Potter, Preston Bennes, Rommel
|
||||
M. Martinez, Sander van der Burg, Shea Levy, Tim Cuthbertson, Tuomas
|
||||
Tynkkynen, Utku Demir and Vladimír Čunát.</para>
|
||||
|
||||
</section>
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.2">
|
||||
|
||||
<title>Release 1.2 (December 6, 2012)</title>
|
||||
<title>Release 1.2 (2012-12-06)</title>
|
||||
|
||||
<para>This release has the following improvements and changes:</para>
|
||||
|
||||
@@ -154,4 +154,4 @@ $ mount -o remount,ro,bind /nix/store
|
||||
<para>This release has contributions from Eelco Dolstra, Florian
|
||||
Friesdorf, Mats Erik Andersson and Shea Levy.</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.3">
|
||||
|
||||
<title>Release 1.3 (January 4, 2013)</title>
|
||||
<title>Release 1.3 (2013-01-04)</title>
|
||||
|
||||
<para>This is primarily a bug fix release. When this version is first
|
||||
run on Linux, it removes any immutable bits from the Nix store and
|
||||
@@ -16,4 +16,4 @@ efficient.)</para>
|
||||
<para>This release has contributions from Eelco Dolstra and Stuart
|
||||
Pernsteiner.</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.4">
|
||||
|
||||
<title>Release 1.4 (February 26, 2013)</title>
|
||||
<title>Release 1.4 (2013-02-26)</title>
|
||||
|
||||
<para>This release fixes a security bug in multi-user operation. It
|
||||
was possible for derivations to cause the mode of files outside of the
|
||||
@@ -36,4 +36,4 @@ xlink:href="https://github.com/NixOS/nix/commit/5526a282b5b44e9296e61e07d7d2626a
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.5.1">
|
||||
|
||||
<title>Release 1.5.1 (February 28, 2013)</title>
|
||||
<title>Release 1.5.1 (2013-02-28)</title>
|
||||
|
||||
<para>The bug fix to the bug fix had a bug itself, of course. But
|
||||
this time it will work for sure!</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.5.2">
|
||||
|
||||
<title>Release 1.5.2 (May 13, 2013)</title>
|
||||
<title>Release 1.5.2 (2013-05-13)</title>
|
||||
|
||||
<para>This is primarily a bug fix release. It has contributions from
|
||||
Eelco Dolstra, Lluís Batlle i Rossell and Shea Levy.</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.5">
|
||||
|
||||
<title>Release 1.5 (February 27, 2013)</title>
|
||||
<title>Release 1.5 (2013-02-27)</title>
|
||||
|
||||
<para>This is a brown paper bag release to fix a regression introduced
|
||||
by the hard link security fix in 1.4.</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.6.1">
|
||||
|
||||
<title>Release 1.6.1 (October 28, 2013)</title>
|
||||
<title>Release 1.6.1 (2013-10-28)</title>
|
||||
|
||||
<para>This is primarily a bug fix release. Changes of interest
|
||||
are:</para>
|
||||
@@ -66,4 +66,4 @@ are:</para>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.6.0">
|
||||
|
||||
<title>Release 1.6 (September 10, 2013)</title>
|
||||
<title>Release 1.6 (2013-09-10)</title>
|
||||
|
||||
<para>In addition to the usual bug fixes, this release has several new
|
||||
features:</para>
|
||||
@@ -124,4 +124,4 @@ in pkgs.bar
|
||||
Florian Friesdorf, Gergely Risko, Ivan Kozik, Ludovic Courtès and Shea
|
||||
Levy.</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.7">
|
||||
|
||||
<title>Release 1.7 (April 11, 2014)</title>
|
||||
<title>Release 1.7 (2014-04-11)</title>
|
||||
|
||||
<para>In addition to the usual bug fixes, this release has the
|
||||
following new features:</para>
|
||||
@@ -260,4 +260,4 @@ error: attribute `nixUnstabl' missing, at /etc/nixos/configurations/misc/eelco/m
|
||||
Eelco Dolstra, Ian-Woo Kim, Ludovic Courtès, Maxim Ivanov, Petr
|
||||
Rockai, Ricardo M. Correia and Shea Levy.</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-1.8">
|
||||
|
||||
<title>Release 1.8 (December 14, 2014)</title>
|
||||
<title>Release 1.8 (2014-12-14)</title>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
@@ -60,7 +60,7 @@ $ nix-store -l $(which xterm)
|
||||
<listitem><para><command>nix-copy-closure</command> now uses
|
||||
<command>nix-store --serve</command> on the remote side to send or
|
||||
receive closures. This fixes a race condition between
|
||||
<command>nix-copy-closureE</command> and the garbage
|
||||
<command>nix-copy-closure</command> and the garbage
|
||||
collector.</para></listitem>
|
||||
|
||||
<listitem><para>Derivations can specify the new special attribute
|
||||
@@ -113,4 +113,11 @@ $ nix-store -l $(which xterm)
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>This release has contributions from Adam Szkoda, Aristid
|
||||
Breitkreuz, Bob van der Linden, Charles Strahan, darealshinji, Eelco
|
||||
Dolstra, Gergely Risko, Joel Taylor, Ludovic Courtès, Marko Durkovic,
|
||||
Mikey Ariel, Paul Colomiets, Ricardo M. Correia, Ricky Elrod, Robert
|
||||
Helgesson, Rob Vermaas, Russell O'Connor, Shea Levy, Shell Turner,
|
||||
Sönke Hahn, Steve Purcell, Vladimír Čunát and Wout Mertens.</para>
|
||||
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
<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.9">
|
||||
|
||||
<title>Release 1.9 (2015-06-12)</title>
|
||||
|
||||
<para>In addition to the usual bug fixes, this release has the
|
||||
following new features:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>Signed binary cache support. You can enable signature
|
||||
checking by adding the following to <filename>nix.conf</filename>:
|
||||
|
||||
<programlisting>
|
||||
signed-binary-caches = *
|
||||
binary-cache-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
|
||||
</programlisting>
|
||||
|
||||
This will prevent Nix from downloading any binary from the cache
|
||||
that is not signed by one of the keys listed in
|
||||
<option>binary-cache-public-keys</option>.</para>
|
||||
|
||||
<para>Signature checking is only supported if you built Nix with
|
||||
the <literal>libsodium</literal> package.</para>
|
||||
|
||||
<para>Note that while Nix has had experimental support for signed
|
||||
binary caches since version 1.7, this release changes the
|
||||
signature format in a backwards-incompatible way.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>Automatic downloading of Nix expression tarballs. In various
|
||||
places, you can now specify the URL of a tarball containing Nix
|
||||
expressions (such as Nixpkgs), which will be downloaded and
|
||||
unpacked automatically. For example:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>In <command>nix-env</command>:
|
||||
|
||||
<screen>
|
||||
$ nix-env -f https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz -iA firefox
|
||||
</screen>
|
||||
|
||||
This installs Firefox from the latest tested and built revision
|
||||
of the NixOS 14.12 channel.</para></listitem>
|
||||
|
||||
<listitem><para>In <command>nix-build</command> and
|
||||
<command>nix-shell</command>:
|
||||
|
||||
<screen>
|
||||
$ nix-build https://github.com/NixOS/nixpkgs/archive/master.tar.gz -A hello
|
||||
</screen>
|
||||
|
||||
This builds GNU Hello from the latest revision of the Nixpkgs
|
||||
master branch.</para></listitem>
|
||||
|
||||
<listitem><para>In the Nix search path (as specified via
|
||||
<envar>NIX_PATH</envar> or <option>-I</option>). For example, to
|
||||
start a shell containing the Pan package from a specific version
|
||||
of Nixpkgs:
|
||||
|
||||
<screen>
|
||||
$ nix-shell -p pan -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/8a3eea054838b55aca962c3fbde9c83c102b8bf2.tar.gz
|
||||
</screen>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>In <command>nixos-rebuild</command> (on NixOS):
|
||||
|
||||
<screen>
|
||||
$ nixos-rebuild test -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-unstable.tar.gz
|
||||
</screen>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>In Nix expressions, via the new builtin function <function>fetchTarball</function>:
|
||||
|
||||
<programlisting>
|
||||
with import (fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz) {}; …
|
||||
</programlisting>
|
||||
|
||||
(This is not allowed in restricted mode.)</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para><command>nix-shell</command> improvements:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para><command>nix-shell</command> now has a flag
|
||||
<option>--run</option> to execute a command in the
|
||||
<command>nix-shell</command> environment,
|
||||
e.g. <literal>nix-shell --run make</literal>. This is like
|
||||
the existing <option>--command</option> flag, except that it
|
||||
uses a non-interactive shell (ensuring that hitting Ctrl-C won’t
|
||||
drop you into the child shell).</para></listitem>
|
||||
|
||||
<listitem><para><command>nix-shell</command> can now be used as
|
||||
a <literal>#!</literal>-interpreter. This allows you to write
|
||||
scripts that dynamically fetch their own dependencies. For
|
||||
example, here is a Haskell script that, when invoked, first
|
||||
downloads GHC and the Haskell packages on which it depends:
|
||||
|
||||
<programlisting>
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i runghc -p haskellPackages.ghc haskellPackages.HTTP
|
||||
|
||||
import Network.HTTP
|
||||
|
||||
main = do
|
||||
resp <- Network.HTTP.simpleHTTP (getRequest "http://nixos.org/")
|
||||
body <- getResponseBody resp
|
||||
print (take 100 body)
|
||||
</programlisting>
|
||||
|
||||
Of course, the dependencies are cached in the Nix store, so the
|
||||
second invocation of this script will be much
|
||||
faster.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>Chroot improvements:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>Chroot builds are now supported on Mac OS X
|
||||
(using its sandbox mechanism).</para></listitem>
|
||||
|
||||
<listitem><para>If chroots are enabled, they are now used for
|
||||
all derivations, including fixed-output derivations (such as
|
||||
<function>fetchurl</function>). The latter do have network
|
||||
access, but can no longer access the host filesystem. If you
|
||||
need the old behaviour, you can set the option
|
||||
<option>build-use-chroot</option> to
|
||||
<literal>relaxed</literal>.</para></listitem>
|
||||
|
||||
<listitem><para>On Linux, if chroots are enabled, builds are
|
||||
performed in a private PID namespace once again. (This
|
||||
functionality was lost in Nix 1.8.)</para></listitem>
|
||||
|
||||
<listitem><para>Store paths listed in
|
||||
<option>build-chroot-dirs</option> are now automatically
|
||||
expanded to their closure. For instance, if you want
|
||||
<filename>/nix/store/…-bash/bin/sh</filename> mounted in your
|
||||
chroot as <filename>/bin/sh</filename>, you only need to say
|
||||
<literal>build-chroot-dirs =
|
||||
/bin/sh=/nix/store/…-bash/bin/sh</literal>; it is no longer
|
||||
necessary to specify the dependencies of Bash.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem><para>The new derivation attribute
|
||||
<varname>passAsFile</varname> allows you to specify that the
|
||||
contents of derivation attributes should be passed via files rather
|
||||
than environment variables. This is useful if you need to pass very
|
||||
long strings that exceed the size limit of the environment. The
|
||||
Nixpkgs function <function>writeTextFile</function> uses
|
||||
this.</para></listitem>
|
||||
|
||||
<listitem><para>You can now use <literal>~</literal> in Nix file
|
||||
names to refer to your home directory, e.g. <literal>import
|
||||
~/.nixpkgs/config.nix</literal>.</para></listitem>
|
||||
|
||||
<listitem><para>Nix has a new option <option>restrict-eval</option>
|
||||
that allows limiting what paths the Nix evaluator has access to. By
|
||||
passing <literal>--option restrict-eval true</literal> to Nix, the
|
||||
evaluator will throw an exception if an attempt is made to access
|
||||
any file outside of the Nix search path. This is primarily intended
|
||||
for Hydra to ensure that a Hydra jobset only refers to its declared
|
||||
inputs (and is therefore reproducible).</para></listitem>
|
||||
|
||||
<listitem><para><command>nix-env</command> now only creates a new
|
||||
“generation” symlink in <filename>/nix/var/nix/profiles</filename>
|
||||
if something actually changed.</para></listitem>
|
||||
|
||||
<listitem><para>The environment variable <envar>NIX_PAGER</envar>
|
||||
can now be set to override <envar>PAGER</envar>. You can set it to
|
||||
<literal>cat</literal> to disable paging for Nix commands
|
||||
only.</para></listitem>
|
||||
|
||||
<listitem><para>Failing <literal><...></literal>
|
||||
lookups now show position information.</para></listitem>
|
||||
|
||||
<listitem><para>Improved Boehm GC use: we disabled scanning for
|
||||
interior pointers, which should reduce the “<literal>Repeated
|
||||
allocation of very large block</literal>” warnings and associated
|
||||
retention of memory.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>This release has contributions from aszlig, Benjamin Staffin,
|
||||
Charles Strahan, Christian Theune, Daniel Hahler, Danylo Hlynskyi
|
||||
Daniel Peebles, Dan Peebles, Domen Kožar, Eelco Dolstra, Harald van
|
||||
Dijk, Hoang Xuan Phu, Jaka Hudoklin, Jeff Ramnani, j-keck, Linquize,
|
||||
Luca Bruno, Michael Merickel, Oliver Dunkl, Rob Vermaas, Rok Garbas,
|
||||
Shea Levy, Tobias Geerinckx-Rice and William A. Kennington III.</para>
|
||||
|
||||
</section>
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
ifeq ($(MAKECMDGOALS), dist)
|
||||
dist-files += $(shell git ls-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
|
||||
|
||||
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), $(eval $(call install-file-in, $(i), $(includedir)/nix, 0644)))
|
||||
$(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)))
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
FROM busybox
|
||||
|
||||
RUN set -x \
|
||||
&& wget -O- http://nixos.org/releases/nix/nix-1.9/nix-1.9-x86_64-linux.tar.bz2 | \
|
||||
bzcat - | tar xf - \
|
||||
&& echo "nixbld:x:30000:nixbld1,nixbld10,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9" >> /etc/group \
|
||||
&& for i in $(seq 1 9); do echo "nixbld$i:x:3000$i:30000:::" >> /etc/passwd; done \
|
||||
&& sed -i 's/\$HOME\/\.nix-profile\/etc\/ssl\/certs\/ca-bundle\.crt/\$HOME\/\.nix-profile\/etc\/ca-bundle\.crt/g' nix-1.9-x86_64-linux/install \
|
||||
&& mkdir -m 0755 /nix && USER=root sh nix-1.9-x86_64-linux/install \
|
||||
&& echo ". /root/.nix-profile/etc/profile.d/nix.sh" >> /etc/profile \
|
||||
&& rm -r /nix-1.9-x86_64-linux
|
||||
|
||||
ONBUILD ENV \
|
||||
ENV=/etc/profile \
|
||||
PATH=/root/.nix-profile/bin:/root/.nix-profile/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
|
||||
GIT_SSL_CAINFO=/root/.nix-profile/etc/ca-bundle.crt \
|
||||
SSL_CERT_FILE=/root/.nix-profile/etc/ca-bundle.crt
|
||||
|
||||
ENV \
|
||||
ENV=/etc/profile \
|
||||
PATH=/root/.nix-profile/bin:/root/.nix-profile/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
|
||||
GIT_SSL_CAINFO=/root/.nix-profile/etc/ca-bundle.crt \
|
||||
SSL_CERT_FILE=/root/.nix-profile/etc/ca-bundle.crt
|
||||
+10
-10
@@ -9,16 +9,16 @@
|
||||
;;; Code:
|
||||
|
||||
(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)
|
||||
'("\\_<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,37 +0,0 @@
|
||||
" Vim syntax file
|
||||
" Language: nix
|
||||
" Maintainer: Marc Weber <marco-oweber@gmx.de>
|
||||
" Modify and commit if you feel that way
|
||||
" Last Change: 2007 Dec
|
||||
|
||||
" Quit when a (custom) syntax file was already loaded
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
syn keyword nixKeyword let throw inherit import true false null with
|
||||
syn keyword nixConditional if else then
|
||||
syn keyword nixBrace ( ) { } =
|
||||
syn keyword nixBuiltin __currentSystem __currentTime __isFunction __getEnv __trace __toPath __pathExists
|
||||
\ __readFile __toXML __toFile __filterSource __attrNames __getAttr __hasAttr __isAttrs __listToAttrs __isList
|
||||
\ __head __tail __add __sub __lessThan __substring __stringLength
|
||||
|
||||
syn match nixAttr "\w\+\ze\s*="
|
||||
syn match nixFuncArg "\zs\w\+\ze\s*:"
|
||||
syn region nixStringParam start=+\${+ end=+}+
|
||||
syn region nixMultiLineComment start=+/\*+ skip=+\\"+ end=+\*/+
|
||||
syn match nixEndOfLineComment "#.*$"
|
||||
syn region nixStringIndented start=+''+ skip=+'''\|''${\|"+ end=+''+ contains=nixStringParam
|
||||
syn region nixString start=+"+ skip=+\\"+ end=+"+ contains=nixStringParam
|
||||
|
||||
hi def link nixKeyword Keyword
|
||||
hi def link nixConditional Conditional
|
||||
hi def link nixBrace Special
|
||||
hi def link nixString String
|
||||
hi def link nixStringIndented String
|
||||
hi def link nixBuiltin Special
|
||||
hi def link nixStringParam Macro
|
||||
hi def link nixMultiLineComment Comment
|
||||
hi def link nixEndOfLineComment Comment
|
||||
hi def link nixAttr Identifier
|
||||
hi def link nixFuncArg Identifier
|
||||
@@ -61,7 +61,9 @@ ifeq ($(BUILD_SHARED_LIBS), 1)
|
||||
endif
|
||||
ifneq ($(OS), Darwin)
|
||||
ifneq ($(OS), SunOS)
|
||||
GLOBAL_LDFLAGS += -Wl,--no-copy-dt-needed-entries
|
||||
ifneq ($(OS), FreeBSD)
|
||||
GLOBAL_LDFLAGS += -Wl,--no-copy-dt-needed-entries
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
SET_RPATH_TO_LIBS ?= 1
|
||||
|
||||
@@ -26,6 +26,7 @@ Requires: gzip
|
||||
Requires: xz
|
||||
BuildRequires: bzip2-devel
|
||||
BuildRequires: sqlite-devel
|
||||
BuildRequires: libcurl-devel
|
||||
|
||||
# Hack to make that shitty RPM scanning hack shut up.
|
||||
Provides: perl(Nix::SSH)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package Nix::Config;
|
||||
|
||||
use MIME::Base64;
|
||||
|
||||
$version = "@PACKAGE_VERSION@";
|
||||
|
||||
$binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
@@ -19,24 +21,33 @@ $useBindings = "@perlbindings@" eq "yes";
|
||||
|
||||
%config = ();
|
||||
|
||||
%binaryCachePublicKeys = ();
|
||||
|
||||
$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;
|
||||
}
|
||||
return;
|
||||
} 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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package Nix::Crypto;
|
||||
|
||||
use strict;
|
||||
use MIME::Base64;
|
||||
use Nix::Store;
|
||||
use Nix::Config;
|
||||
use IPC::Open2;
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(signString isValidSignature);
|
||||
|
||||
sub signString {
|
||||
my ($privateKeyFile, $s) = @_;
|
||||
my $hash = hashString("sha256", 0, $s);
|
||||
my ($from, $to);
|
||||
my $pid = open2($from, $to, $Nix::Config::openssl, "rsautl", "-sign", "-inkey", $privateKeyFile);
|
||||
print $to $hash;
|
||||
close $to;
|
||||
local $/ = undef;
|
||||
my $sig = <$from>;
|
||||
close $from;
|
||||
waitpid($pid, 0);
|
||||
die "$0: OpenSSL returned exit code $? while signing hash\n" if $? != 0;
|
||||
my $sig64 = encode_base64($sig, "");
|
||||
return $sig64;
|
||||
}
|
||||
|
||||
sub isValidSignature {
|
||||
my ($publicKeyFile, $sig64, $s) = @_;
|
||||
my ($from, $to);
|
||||
my $pid = open2($from, $to, $Nix::Config::openssl, "rsautl", "-verify", "-inkey", $publicKeyFile, "-pubin");
|
||||
print $to decode_base64($sig64);
|
||||
close $to;
|
||||
my $decoded = <$from>;
|
||||
close $from;
|
||||
waitpid($pid, 0);
|
||||
return 0 if $? != 0;
|
||||
my $hash = hashString("sha256", 0, $s);
|
||||
return $decoded eq $hash;
|
||||
}
|
||||
|
||||
1;
|
||||
+41
-18
@@ -8,11 +8,12 @@ use Cwd;
|
||||
use File::stat;
|
||||
use File::Path;
|
||||
use Fcntl ':flock';
|
||||
use MIME::Base64;
|
||||
use Nix::Config;
|
||||
use Nix::Crypto;
|
||||
use Nix::Store;
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(readManifest writeManifest updateManifestDB addPatch deleteOldManifests parseNARInfo);
|
||||
our @EXPORT = qw(readManifest writeManifest updateManifestDB addPatch deleteOldManifests parseNARInfo fingerprintPath);
|
||||
|
||||
|
||||
sub addNAR {
|
||||
@@ -376,7 +377,6 @@ EOF
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Delete all old manifests downloaded from a given URL.
|
||||
sub deleteOldManifests {
|
||||
my ($url, $curUrlFile) = @_;
|
||||
@@ -394,12 +394,29 @@ sub deleteOldManifests {
|
||||
}
|
||||
|
||||
|
||||
# Return a fingerprint of a store path to be used in binary cache
|
||||
# signatures. It contains the store path, the base-32 SHA-256 hash of
|
||||
# the contents of the path, and the references.
|
||||
sub fingerprintPath {
|
||||
my ($storePath, $narHash, $narSize, $references) = @_;
|
||||
die if substr($storePath, 0, length($Nix::Config::storeDir)) ne $Nix::Config::storeDir;
|
||||
die if substr($narHash, 0, 7) ne "sha256:";
|
||||
# Convert hash from base-16 to base-32, if necessary.
|
||||
$narHash = "sha256:" . convertHash("sha256", substr($narHash, 7), 1)
|
||||
if length($narHash) == 71;
|
||||
die if length($narHash) != 59;
|
||||
foreach my $ref (@{$references}) {
|
||||
die if substr($ref, 0, length($Nix::Config::storeDir)) ne $Nix::Config::storeDir;
|
||||
}
|
||||
return "1;" . $storePath . ";" . $narHash . ";" . $narSize . ";" . join(",", @{$references});
|
||||
}
|
||||
|
||||
|
||||
# Parse a NAR info file.
|
||||
sub parseNARInfo {
|
||||
my ($storePath, $content, $requireValidSig, $location) = @_;
|
||||
|
||||
my ($storePath2, $url, $fileHash, $fileSize, $narHash, $narSize, $deriver, $system, $sig);
|
||||
my $signedData = "";
|
||||
my $compression = "bzip2";
|
||||
my @refs;
|
||||
|
||||
@@ -415,8 +432,7 @@ sub parseNARInfo {
|
||||
elsif ($1 eq "References") { @refs = split / /, $2; }
|
||||
elsif ($1 eq "Deriver") { $deriver = $2; }
|
||||
elsif ($1 eq "System") { $system = $2; }
|
||||
elsif ($1 eq "Signature") { $sig = $2; last; }
|
||||
$signedData .= "$line\n";
|
||||
elsif ($1 eq "Sig") { $sig = $2; }
|
||||
}
|
||||
|
||||
return undef if $storePath ne $storePath2 || !defined $url || !defined $narHash;
|
||||
@@ -434,30 +450,37 @@ sub parseNARInfo {
|
||||
};
|
||||
|
||||
if ($requireValidSig) {
|
||||
# FIXME: might be useful to support multiple signatures per .narinfo.
|
||||
|
||||
if (!defined $sig) {
|
||||
warn "NAR info file ‘$location’ lacks a signature; ignoring\n";
|
||||
return undef;
|
||||
}
|
||||
my ($sigVersion, $keyName, $sig64) = split ";", $sig;
|
||||
$sigVersion //= 0;
|
||||
if ($sigVersion != 1) {
|
||||
warn "NAR info file ‘$location’ has unsupported version $sigVersion; ignoring\n";
|
||||
return undef;
|
||||
}
|
||||
my ($keyName, $sig64) = split ":", $sig;
|
||||
return undef unless defined $keyName && defined $sig64;
|
||||
my $publicKeyFile = $Nix::Config::config{"binary-cache-public-key-$keyName"};
|
||||
if (!defined $publicKeyFile) {
|
||||
|
||||
my $publicKey = $Nix::Config::binaryCachePublicKeys{$keyName};
|
||||
if (!defined $publicKey) {
|
||||
warn "NAR info file ‘$location’ is signed by unknown key ‘$keyName’; ignoring\n";
|
||||
return undef;
|
||||
}
|
||||
if (! -f $publicKeyFile) {
|
||||
die "binary cache public key file ‘$publicKeyFile’ does not exist\n";
|
||||
|
||||
my $fingerprint;
|
||||
eval {
|
||||
$fingerprint = fingerprintPath(
|
||||
$storePath, $narHash, $narSize,
|
||||
[ map { "$Nix::Config::storeDir/$_" } @refs ]);
|
||||
};
|
||||
if ($@) {
|
||||
warn "cannot compute fingerprint of ‘$location’; ignoring\n";
|
||||
return undef;
|
||||
}
|
||||
if (!isValidSignature($publicKeyFile, $sig64, $signedData)) {
|
||||
warn "NAR info file ‘$location’ has an invalid signature; ignoring\n";
|
||||
|
||||
if (!checkSignature($publicKey, decode_base64($sig64), $fingerprint)) {
|
||||
warn "NAR info file ‘$location’ has an incorrect signature; ignoring\n";
|
||||
return undef;
|
||||
}
|
||||
|
||||
$res->{signedBy} = $keyName;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,15 @@ our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
|
||||
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
||||
|
||||
our @EXPORT = qw(
|
||||
setVerbosity
|
||||
isValidPath queryReferences queryPathInfo queryDeriver queryPathHash
|
||||
queryPathFromHashPart
|
||||
topoSortPaths computeFSClosure followLinksToStorePath exportPaths importPaths
|
||||
hashPath hashFile hashString
|
||||
hashPath hashFile hashString convertHash
|
||||
signString checkSignature
|
||||
addToStore makeFixedOutputPath
|
||||
derivationFromPath
|
||||
addTempRoot
|
||||
);
|
||||
|
||||
our $VERSION = '0.15';
|
||||
|
||||
+95
-19
@@ -11,6 +11,10 @@
|
||||
#include <misc.hh>
|
||||
#include <util.hh>
|
||||
|
||||
#if HAVE_SODIUM
|
||||
#include <sodium.h>
|
||||
#endif
|
||||
|
||||
|
||||
using namespace nix;
|
||||
|
||||
@@ -25,7 +29,7 @@ void doInit()
|
||||
settings.lockCPU = false;
|
||||
store = openStore();
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,13 +48,18 @@ void init()
|
||||
doInit();
|
||||
|
||||
|
||||
void setVerbosity(int level)
|
||||
CODE:
|
||||
verbosity = (Verbosity) level;
|
||||
|
||||
|
||||
int isValidPath(char * path)
|
||||
CODE:
|
||||
try {
|
||||
doInit();
|
||||
RETVAL = store->isValidPath(path);
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
@@ -65,7 +74,7 @@ SV * queryReferences(char * path)
|
||||
for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i)
|
||||
XPUSHs(sv_2mortal(newSVpv(i->c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +86,7 @@ SV * queryPathHash(char * path)
|
||||
string s = "sha256:" + printHash32(hash);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +98,7 @@ SV * queryDeriver(char * path)
|
||||
if (deriver == "") XSRETURN_UNDEF;
|
||||
XPUSHs(sv_2mortal(newSVpv(deriver.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +120,7 @@ SV * queryPathInfo(char * path, int base32)
|
||||
av_push(arr, newSVpv(i->c_str(), 0));
|
||||
XPUSHs(sv_2mortal(newRV((SV *) arr)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +131,7 @@ SV * queryPathFromHashPart(char * hashPart)
|
||||
Path path = store->queryPathFromHashPart(hashPart);
|
||||
XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +145,7 @@ SV * computeFSClosure(int flipDirection, int includeOutputs, ...)
|
||||
for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i)
|
||||
XPUSHs(sv_2mortal(newSVpv(i->c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -150,7 +159,7 @@ SV * topoSortPaths(...)
|
||||
for (Paths::iterator i = sorted.begin(); i != sorted.end(); ++i)
|
||||
XPUSHs(sv_2mortal(newSVpv(i->c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +169,7 @@ SV * followLinksToStorePath(char * path)
|
||||
doInit();
|
||||
RETVAL = newSVpv(followLinksToStorePath(path).c_str(), 0);
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
@@ -175,7 +184,7 @@ void exportPaths(int fd, int sign, ...)
|
||||
FdSink sink(fd);
|
||||
exportPaths(*store, paths, sign, sink);
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +195,7 @@ void importPaths(int fd)
|
||||
FdSource source(fd);
|
||||
store->importPaths(false, source);
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +206,7 @@ SV * hashPath(char * algo, int base32, char * path)
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -208,7 +217,7 @@ SV * hashFile(char * algo, int base32, char * path)
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -219,18 +228,75 @@ SV * hashString(char * algo, int base32, char * s)
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * convertHash(char * algo, char * s, int toBase32)
|
||||
PPCODE:
|
||||
try {
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
SV * signString(SV * secretKey_, char * msg)
|
||||
PPCODE:
|
||||
try {
|
||||
#if HAVE_SODIUM
|
||||
STRLEN secretKeyLen;
|
||||
unsigned char * secretKey = (unsigned char *) SvPV(secretKey_, secretKeyLen);
|
||||
if (secretKeyLen != crypto_sign_SECRETKEYBYTES)
|
||||
throw Error("secret key is not valid");
|
||||
|
||||
unsigned char sig[crypto_sign_BYTES];
|
||||
unsigned long long sigLen;
|
||||
crypto_sign_detached(sig, &sigLen, (unsigned char *) msg, strlen(msg), secretKey);
|
||||
XPUSHs(sv_2mortal(newSVpv((char *) sig, sigLen)));
|
||||
#else
|
||||
throw Error("Nix was not compiled with libsodium, required for signed binary cache support");
|
||||
#endif
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
int checkSignature(SV * publicKey_, SV * sig_, char * msg)
|
||||
CODE:
|
||||
try {
|
||||
#if HAVE_SODIUM
|
||||
STRLEN publicKeyLen;
|
||||
unsigned char * publicKey = (unsigned char *) SvPV(publicKey_, publicKeyLen);
|
||||
if (publicKeyLen != crypto_sign_PUBLICKEYBYTES)
|
||||
throw Error("public key is not valid");
|
||||
|
||||
STRLEN sigLen;
|
||||
unsigned char * sig = (unsigned char *) SvPV(sig_, sigLen);
|
||||
if (sigLen != crypto_sign_BYTES)
|
||||
throw Error("signature is not valid");
|
||||
|
||||
RETVAL = crypto_sign_verify_detached(sig, (unsigned char *) msg, strlen(msg), publicKey) == 0;
|
||||
#else
|
||||
throw Error("Nix was not compiled with libsodium, required for signed binary cache support");
|
||||
#endif
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
}
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
|
||||
SV * addToStore(char * srcPath, int recursive, char * algo)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
Path path = store->addToStore(srcPath, recursive, parseHashType(algo));
|
||||
Path path = store->addToStore(baseNameOf(srcPath), srcPath, recursive, parseHashType(algo));
|
||||
XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -243,7 +309,7 @@ SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
|
||||
parseHash16or32(ht, hash), name);
|
||||
XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -286,7 +352,17 @@ SV * derivationFromPath(char * drvPath)
|
||||
|
||||
RETVAL = newRV_noinc((SV *)hash);
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
croak("%s", e.what());
|
||||
}
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
|
||||
void addTempRoot(char * storePath)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
store->addTempRoot(storePath);
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
+9
-6
@@ -5,8 +5,7 @@ nix_perl_sources := \
|
||||
$(d)/lib/Nix/SSH.pm \
|
||||
$(d)/lib/Nix/CopyClosure.pm \
|
||||
$(d)/lib/Nix/Config.pm.in \
|
||||
$(d)/lib/Nix/Utils.pm \
|
||||
$(d)/lib/Nix/Crypto.pm
|
||||
$(d)/lib/Nix/Utils.pm
|
||||
|
||||
nix_perl_modules := $(nix_perl_sources:.in=)
|
||||
|
||||
@@ -23,16 +22,20 @@ ifeq ($(perlbindings), yes)
|
||||
|
||||
Store_SOURCES := $(Store_DIR)/Store.cc
|
||||
|
||||
Store_LIBS = libstore libutil
|
||||
|
||||
Store_CXXFLAGS = \
|
||||
-I$(shell $(perl) -e 'use Config; print $$Config{archlibexp};')/CORE \
|
||||
-D_FILE_OFFSET_BITS=64 -Wno-unused-variable -Wno-literal-suffix -Wno-reserved-user-defined-literal
|
||||
-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_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})
|
||||
Store_LDFLAGS += $(shell find ${archlib} -name ${libperl})
|
||||
endif
|
||||
|
||||
Store_ALLOW_UNDEFINED = 1
|
||||
|
||||
+54
-38
@@ -23,8 +23,8 @@ let
|
||||
inherit officialRelease;
|
||||
|
||||
buildInputs =
|
||||
[ curl bison flex perl libxml2 libxslt bzip2
|
||||
tetex dblatex nukeReferences pkgconfig sqlite
|
||||
[ curl bison flex perl libxml2 libxslt bzip2 xz
|
||||
dblatex (dblatex.tex or tetex) nukeReferences pkgconfig sqlite libsodium
|
||||
docbook5 docbook5_xsl
|
||||
] ++ lib.optional (!lib.inNixShell) git;
|
||||
|
||||
@@ -36,7 +36,9 @@ let
|
||||
|
||||
postUnpack = ''
|
||||
# Clean up when building from a working tree.
|
||||
(cd $sourceRoot && (git ls-files -o | xargs -r rm -v))
|
||||
if [[ -d $sourceRoot/.git ]]; then
|
||||
git -C $sourceRoot clean -fd
|
||||
fi
|
||||
'';
|
||||
|
||||
preConfigure = ''
|
||||
@@ -74,13 +76,16 @@ let
|
||||
|
||||
build = pkgs.lib.genAttrs systems (system:
|
||||
|
||||
with import <nixpkgs> { inherit system; };
|
||||
# FIXME: temporarily use a different branch for the Darwin build.
|
||||
with import (if system == "x86_64-darwin" then <nixpkgs-darwin> else <nixpkgs>) { inherit system; };
|
||||
|
||||
releaseTools.nixBuild {
|
||||
name = "nix";
|
||||
src = tarball;
|
||||
|
||||
buildInputs = [ curl perl bzip2 openssl pkgconfig sqlite boehmgc ];
|
||||
buildInputs =
|
||||
[ curl perl bzip2 xz openssl pkgconfig sqlite boehmgc ]
|
||||
++ lib.optional stdenv.isLinux libsodium;
|
||||
|
||||
configureFlags = ''
|
||||
--disable-init-state
|
||||
@@ -91,14 +96,6 @@ let
|
||||
--sysconfdir=/etc
|
||||
'';
|
||||
|
||||
# Provide a default value for the ‘build-chroot-dirs’ setting
|
||||
# that includes /bin/sh pointing to bash.
|
||||
preHook = lib.optionalString stdenv.isLinux (
|
||||
let sh = stdenv.shell; in
|
||||
''
|
||||
export DEFAULT_CHROOT_DIRS="/bin/sh=${sh} $(tr '\n' ' ' < ${writeReferencesToFile sh})"
|
||||
'');
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
makeFlags = "profiledir=$(out)/etc/profile.d";
|
||||
@@ -114,7 +111,8 @@ let
|
||||
|
||||
binaryTarball = pkgs.lib.genAttrs systems (system:
|
||||
|
||||
with import <nixpkgs> { inherit system; };
|
||||
# FIXME: temporarily use a different branch for the Darwin build.
|
||||
with import (if system == "x86_64-darwin" then <nixpkgs-darwin> else <nixpkgs>) { inherit system; };
|
||||
|
||||
let
|
||||
toplevel = builtins.getAttr system jobs.build;
|
||||
@@ -156,7 +154,7 @@ let
|
||||
src = tarball;
|
||||
|
||||
buildInputs =
|
||||
[ curl perl bzip2 openssl pkgconfig sqlite
|
||||
[ curl perl bzip2 openssl pkgconfig sqlite xz libsodium
|
||||
# These are for "make check" only:
|
||||
graphviz libxml2 libxslt
|
||||
];
|
||||
@@ -181,23 +179,33 @@ let
|
||||
};
|
||||
|
||||
|
||||
rpm_fedora20i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora20i386);
|
||||
rpm_fedora20x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora20x86_64);
|
||||
rpm_fedora18i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora18i386) [];
|
||||
rpm_fedora18x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora18x86_64) [];
|
||||
rpm_fedora19i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora19i386) [];
|
||||
rpm_fedora19x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora19x86_64) [];
|
||||
rpm_fedora20i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora20i386) [];
|
||||
rpm_fedora20x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora20x86_64) [];
|
||||
rpm_fedora21i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora21i386) [ "libsodium-devel" ];
|
||||
rpm_fedora21x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora21x86_64) [ "libsodium-devel" ];
|
||||
|
||||
|
||||
deb_debian7i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.debian7i386);
|
||||
deb_debian7x86_64 = makeDeb_x86_64 (diskImageFunsFun: diskImageFunsFun.debian7x86_64);
|
||||
deb_debian7i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.debian7i386) [];
|
||||
deb_debian7x86_64 = makeDeb_x86_64 (diskImageFunsFun: diskImageFunsFun.debian7x86_64) [];
|
||||
deb_debian8i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.debian8i386) [ "libsodium-dev" ];
|
||||
deb_debian8x86_64 = makeDeb_x86_64 (diskImageFunsFun: diskImageFunsFun.debian8x86_64) [ "libsodium-dev" ];
|
||||
|
||||
deb_ubuntu1210i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1210i386);
|
||||
deb_ubuntu1210x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1210x86_64);
|
||||
deb_ubuntu1304i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1304i386);
|
||||
deb_ubuntu1304x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1304x86_64);
|
||||
deb_ubuntu1310i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1310i386);
|
||||
deb_ubuntu1310x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1310x86_64);
|
||||
deb_ubuntu1404i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1404i386);
|
||||
deb_ubuntu1404x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1404x86_64);
|
||||
deb_ubuntu1410i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1410i386);
|
||||
deb_ubuntu1410x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1410x86_64);
|
||||
deb_ubuntu1210i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1210i386) [];
|
||||
deb_ubuntu1210x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1210x86_64) [];
|
||||
deb_ubuntu1304i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1304i386) [];
|
||||
deb_ubuntu1304x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1304x86_64) [];
|
||||
deb_ubuntu1310i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1310i386) [];
|
||||
deb_ubuntu1310x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1310x86_64) [];
|
||||
deb_ubuntu1404i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1404i386) [];
|
||||
deb_ubuntu1404x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1404x86_64) [];
|
||||
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" ];
|
||||
deb_ubuntu1504x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1504x86_64) [ "libsodium-dev" ];
|
||||
|
||||
|
||||
# System tests.
|
||||
@@ -245,12 +253,14 @@ let
|
||||
binaryTarball.x86_64-linux
|
||||
deb_debian7i386
|
||||
deb_debian7x86_64
|
||||
deb_ubuntu1404i386
|
||||
deb_ubuntu1404x86_64
|
||||
deb_ubuntu1410i386
|
||||
deb_ubuntu1410x86_64
|
||||
deb_ubuntu1404i386 # LTS
|
||||
deb_ubuntu1404x86_64 # LTS
|
||||
deb_ubuntu1504i386
|
||||
deb_ubuntu1504x86_64
|
||||
rpm_fedora20i386
|
||||
rpm_fedora20x86_64
|
||||
rpm_fedora21i386
|
||||
rpm_fedora21x86_64
|
||||
tests.remoteBuilds
|
||||
tests.nix-copy-closure
|
||||
tests.binaryTarball
|
||||
@@ -264,7 +274,7 @@ let
|
||||
makeRPM_x86_64 = makeRPM "x86_64-linux";
|
||||
|
||||
makeRPM =
|
||||
system: diskImageFun:
|
||||
system: diskImageFun: extraPackages:
|
||||
|
||||
with import <nixpkgs> { inherit system; };
|
||||
|
||||
@@ -272,7 +282,9 @@ let
|
||||
name = "nix-rpm";
|
||||
src = jobs.tarball;
|
||||
diskImage = (diskImageFun vmTools.diskImageFuns)
|
||||
{ extraPackages = [ "perl-DBD-SQLite" "perl-devel" "sqlite" "sqlite-devel" "bzip2-devel" "emacs" "perl-WWW-Curl" ]; };
|
||||
{ extraPackages =
|
||||
[ "perl-DBD-SQLite" "perl-devel" "sqlite" "sqlite-devel" "bzip2-devel" "emacs" "perl-WWW-Curl" "libcurl-devel" "openssl-devel" "xz-devel" ]
|
||||
++ extraPackages; };
|
||||
memSize = 1024;
|
||||
meta.schedulingPriority = 50;
|
||||
postRPMInstall = "cd /tmp/rpmout/BUILD/nix-* && make installcheck";
|
||||
@@ -283,7 +295,7 @@ let
|
||||
makeDeb_x86_64 = makeDeb "x86_64-linux";
|
||||
|
||||
makeDeb =
|
||||
system: diskImageFun:
|
||||
system: diskImageFun: extraPackages:
|
||||
|
||||
with import <nixpkgs> { inherit system; };
|
||||
|
||||
@@ -291,11 +303,15 @@ let
|
||||
name = "nix-deb";
|
||||
src = jobs.tarball;
|
||||
diskImage = (diskImageFun vmTools.diskImageFuns)
|
||||
{ extraPackages = [ "libdbd-sqlite3-perl" "libsqlite3-dev" "libbz2-dev" "libwww-curl-perl" ]; };
|
||||
{ extraPackages =
|
||||
[ "libdbd-sqlite3-perl" "libsqlite3-dev" "libbz2-dev" "libwww-curl-perl" "libcurl-dev" "libcurl3-nss" "libssl-dev" "liblzma-dev" ]
|
||||
++ extraPackages; };
|
||||
memSize = 1024;
|
||||
meta.schedulingPriority = 50;
|
||||
configureFlags = "--sysconfdir=/etc";
|
||||
debRequires = [ "curl" "libdbd-sqlite3-perl" "libsqlite3-0" "libbz2-1.0" "bzip2" "xz-utils" "libwww-curl-perl" ];
|
||||
debRequires =
|
||||
[ "curl" "libdbd-sqlite3-perl" "libsqlite3-0" "libbz2-1.0" "bzip2" "xz-utils" "libwww-curl-perl" "libssl1.0.0" "liblzma5" ]
|
||||
++ lib.optionals (lib.elem "libsodium-dev" extraPackages) [ "libsodium13" ] ;
|
||||
debMaintainer = "Eelco Dolstra <eelco.dolstra@logicblox.com>";
|
||||
doInstallCheck = true;
|
||||
};
|
||||
|
||||
@@ -82,7 +82,7 @@ if (defined $conf && -e $conf) {
|
||||
push @machines,
|
||||
{ hostName => $tokens[0]
|
||||
, systemTypes => [ split(/,/, $tokens[1]) ]
|
||||
, sshKeys => $tokens[2]
|
||||
, sshKey => $tokens[2]
|
||||
, maxJobs => int($tokens[3])
|
||||
, speedFactor => 1.0 * (defined $tokens[4] ? int($tokens[4]) : 1)
|
||||
, supportedFeatures => [ @supportedFeatures, @mandatoryFeatures ]
|
||||
@@ -201,7 +201,7 @@ REQ: while (1) {
|
||||
|
||||
|
||||
# Connect to the selected machine.
|
||||
my @sshOpts = ("-i", $machine->{sshKeys});
|
||||
my @sshOpts = ("-i", $machine->{sshKey});
|
||||
$hostName = $machine->{hostName};
|
||||
eval {
|
||||
($from, $to) = connectToRemoteNix($hostName, \@sshOpts, "2>&4");
|
||||
|
||||
@@ -9,6 +9,7 @@ my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
binmode STDERR, ":encoding(utf8)";
|
||||
|
||||
my @remoteStoresAll = split ':', ($ENV{"NIX_OTHER_STORES"} or "");
|
||||
|
||||
@@ -93,7 +94,7 @@ elsif ($ARGV[0] eq "--substitute") {
|
||||
my ($store, $sourcePath) = findStorePath $storePath;
|
||||
die unless $store;
|
||||
print STDERR "\n*** Copying ‘$storePath’ from ‘$sourcePath’\n\n";
|
||||
system("$binDir/nix-store --dump $sourcePath | $binDir/nix-store --restore $destPath") == 0
|
||||
system("@coreutils@/cp", "-rpd", $sourcePath, $destPath) == 0
|
||||
or die "cannot copy ‘$sourcePath’ to ‘$storePath’";
|
||||
print "\n"; # no hash to verify
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ Nix::Config::readConfig;
|
||||
my @caches;
|
||||
my $gotCaches = 0;
|
||||
|
||||
my $maxParallelRequests = int($Nix::Config::config{"binary-caches-parallel-connections"} // 150);
|
||||
my $maxParallelRequests = int($Nix::Config::config{"binary-caches-parallel-connections"} // 25);
|
||||
$maxParallelRequests = 1 if $maxParallelRequests < 1;
|
||||
|
||||
my $ttlNegative = 24 * 3600; # when to purge negative lookups from the database
|
||||
@@ -47,11 +47,17 @@ $caBundle = "/etc/ssl/certs/ca-certificates.crt" if !$caBundle && -f "/etc/ssl/c
|
||||
|
||||
my $userName = getpwuid($<) || $ENV{"USER"} or die "cannot figure out user name";
|
||||
|
||||
my $userAgent = "Nix/$Nix::Config::version";
|
||||
|
||||
sub isTrue {
|
||||
my ($x) = @_;
|
||||
return $x eq "true" || $x eq "1";
|
||||
}
|
||||
|
||||
# FIXME: this should be cache URLs required to have valid signatures,
|
||||
# or "*" to require signatures on all binary caches.
|
||||
# FIXME: should binary caches using a key in
|
||||
# ‘binary-cache-public-keys’ be trusted by default?
|
||||
my $requireSignedBinaryCaches = ($Nix::Config::config{"signed-binary-caches"} // "0") ne "0";
|
||||
|
||||
my $curlConnectTimeout = int(
|
||||
@@ -74,8 +80,13 @@ sub addRequest {
|
||||
$curl->setopt(CURLOPT_WRITEDATA, $fh);
|
||||
$curl->setopt(CURLOPT_FOLLOWLOCATION, 1);
|
||||
$curl->setopt(CURLOPT_CAINFO, $caBundle) if defined $caBundle;
|
||||
$curl->setopt(CURLOPT_SSL_VERIFYPEER, 0) unless isTrue($Nix::Config::config{"verify-https-binary-caches"} // "1");
|
||||
$curl->setopt(CURLOPT_USERAGENT, "Nix/$Nix::Config::version");
|
||||
|
||||
unless (isTrue($Nix::Config::config{"verify-https-binary-caches"} // "1")) {
|
||||
$curl->setopt(CURLOPT_SSL_VERIFYPEER, 0);
|
||||
$curl->setopt(CURLOPT_SSL_VERIFYHOST, 0);
|
||||
}
|
||||
|
||||
$curl->setopt(CURLOPT_USERAGENT, $userAgent);
|
||||
$curl->setopt(CURLOPT_NOBODY, 1) if $head;
|
||||
$curl->setopt(CURLOPT_FAILONERROR, 1);
|
||||
$curl->setopt(CURLOPT_CONNECTTIMEOUT, $curlConnectTimeout);
|
||||
@@ -555,7 +566,7 @@ sub downloadBinary {
|
||||
die if $requireSignedBinaryCaches && !defined $info->{signedBy};
|
||||
print STDERR "\n*** Downloading ‘$url’ ", ($requireSignedBinaryCaches ? "(signed by ‘$info->{signedBy}’) " : ""), "to ‘$storePath’...\n";
|
||||
checkURL $url;
|
||||
if (system("$Nix::Config::curl --fail --location --insecure --connect-timeout $curlConnectTimeout '$url' $decompressor | $Nix::Config::binDir/nix-store --restore $destPath") != 0) {
|
||||
if (system("$Nix::Config::curl --fail --location --connect-timeout $curlConnectTimeout -A '$userAgent' '$url' $decompressor | $Nix::Config::binDir/nix-store --restore $destPath") != 0) {
|
||||
warn "download of ‘$url’ failed" . ($! ? ": $!" : "") . "\n";
|
||||
next;
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@ my $logFile = "$Nix::Config::logDir/downloads";
|
||||
# estimating the expected download size.
|
||||
my $fast = 1;
|
||||
|
||||
# ‘--insecure’ is fine because Nix verifies the hash of the result.
|
||||
my $curl = "$Nix::Config::curl --fail --location --insecure";
|
||||
my $curl = "$Nix::Config::curl --fail --location";
|
||||
|
||||
|
||||
# Open the manifest cache and update it if necessary.
|
||||
|
||||
@@ -41,7 +41,7 @@ mkdir -p $dest/store
|
||||
|
||||
echo -n "copying Nix to $dest/store..." >&2
|
||||
|
||||
for i in $(cd $self/store && echo *); do
|
||||
for i in $(cd $self/store >/dev/null && echo *); do
|
||||
echo -n "." >&2
|
||||
i_tmp="$dest/store/$i.$$"
|
||||
if [ -e "$i_tmp" ]; then
|
||||
@@ -75,7 +75,7 @@ fi
|
||||
# Install an SSL certificate bundle.
|
||||
if [ -z "$SSL_CERT_FILE" -o ! -f "$SSL_CERT_FILE" ]; then
|
||||
$nix/bin/nix-env -i "$cacert"
|
||||
export SSL_CERT_FILE="$HOME/.nix-profile/etc/ca-bundle.crt"
|
||||
export SSL_CERT_FILE="$HOME/.nix-profile/etc/ssl/certs/ca-bundle.crt"
|
||||
fi
|
||||
|
||||
# Subscribe the user to the Nixpkgs channel and fetch it.
|
||||
|
||||
+2
-2
@@ -1,11 +1,9 @@
|
||||
nix_bin_scripts := \
|
||||
$(d)/nix-build \
|
||||
$(d)/nix-channel \
|
||||
$(d)/nix-collect-garbage \
|
||||
$(d)/nix-copy-closure \
|
||||
$(d)/nix-generate-patches \
|
||||
$(d)/nix-install-package \
|
||||
$(d)/nix-prefetch-url \
|
||||
$(d)/nix-pull \
|
||||
$(d)/nix-push
|
||||
|
||||
@@ -19,6 +17,7 @@ nix_substituters := \
|
||||
nix_noinst_scripts := \
|
||||
$(d)/build-remote.pl \
|
||||
$(d)/find-runtime-roots.pl \
|
||||
$(d)/resolve-system-dependencies.pl \
|
||||
$(d)/nix-http-export.cgi \
|
||||
$(d)/nix-profile.sh \
|
||||
$(d)/nix-reduce-build \
|
||||
@@ -31,6 +30,7 @@ profiledir = $(sysconfdir)/profile.d
|
||||
$(eval $(call install-file-as, $(d)/nix-profile.sh, $(profiledir)/nix.sh, 0644))
|
||||
$(eval $(call install-program-in, $(d)/find-runtime-roots.pl, $(libexecdir)/nix))
|
||||
$(eval $(call install-program-in, $(d)/build-remote.pl, $(libexecdir)/nix))
|
||||
$(eval $(call install-program-in, $(d)/resolve-system-dependencies.pl, $(libexecdir)/nix))
|
||||
$(foreach prog, $(nix_substituters), $(eval $(call install-program-in, $(prog), $(libexecdir)/nix/substituters)))
|
||||
$(eval $(call install-symlink, nix-build, $(bindir)/nix-shell))
|
||||
|
||||
|
||||
+69
-5
@@ -5,6 +5,9 @@ use strict;
|
||||
use Nix::Config;
|
||||
use Nix::Store;
|
||||
use Nix::Utils;
|
||||
use File::Basename;
|
||||
use Text::ParseWords;
|
||||
use Cwd;
|
||||
|
||||
binmode STDERR, ":encoding(utf8)";
|
||||
|
||||
@@ -14,6 +17,7 @@ my $runEnv = $0 =~ /nix-shell$/;
|
||||
my $pure = 0;
|
||||
my $fromArgs = 0;
|
||||
my $packages = 0;
|
||||
my $interactive = 1;
|
||||
|
||||
my @instArgs = ();
|
||||
my @buildArgs = ();
|
||||
@@ -25,6 +29,9 @@ my @envExclude = ();
|
||||
|
||||
my $myName = $runEnv ? "nix-shell" : "nix-build";
|
||||
|
||||
my $inShebang = 0;
|
||||
my $script;
|
||||
my @savedArgs;
|
||||
|
||||
my $tmpDir = mkTempDir($myName);
|
||||
|
||||
@@ -35,6 +42,30 @@ my $drvLink = "$tmpDir/derivation";
|
||||
$SIG{'INT'} = sub { exit 1 };
|
||||
|
||||
|
||||
# Heuristic to see if we're invoked as a shebang script, namely, if we
|
||||
# have a single argument, it's the name of an executable file, and it
|
||||
# starts with "#!".
|
||||
if ($runEnv && defined $ARGV[0] && $ARGV[0] !~ /nix-shell/) {
|
||||
$script = $ARGV[0];
|
||||
if (-f $script && -x $script) {
|
||||
open SCRIPT, "<$script" or die "$0: cannot open ‘$script’: $!\n";
|
||||
my $first = <SCRIPT>;
|
||||
if ($first =~ /^\#\!/) {
|
||||
$inShebang = 1;
|
||||
@savedArgs = @ARGV; shift @savedArgs;
|
||||
@ARGV = ();
|
||||
while (<SCRIPT>) {
|
||||
chomp;
|
||||
if (/^\#\!\s*nix-shell (.*)$/) {
|
||||
push @ARGV, shellwords(/ /, $1);
|
||||
}
|
||||
}
|
||||
}
|
||||
close SCRIPT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (my $n = 0; $n < scalar @ARGV; $n++) {
|
||||
my $arg = $ARGV[$n];
|
||||
|
||||
@@ -131,10 +162,11 @@ for (my $n = 0; $n < scalar @ARGV; $n++) {
|
||||
$runEnv = 1;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--command") {
|
||||
elsif ($arg eq "--command" || $arg eq "--run") {
|
||||
$n++;
|
||||
die "$0: ‘$arg’ requires an argument\n" unless $n < scalar @ARGV;
|
||||
$envCommand = "$ARGV[$n]\nexit $!";
|
||||
$envCommand = "$ARGV[$n]\nexit";
|
||||
$interactive = 0 if $arg eq "--run";
|
||||
}
|
||||
|
||||
elsif ($arg eq "--exclude") {
|
||||
@@ -155,15 +187,39 @@ for (my $n = 0; $n < scalar @ARGV; $n++) {
|
||||
$packages = 1;
|
||||
}
|
||||
|
||||
elsif ($inShebang && $arg eq "-i") {
|
||||
$n++;
|
||||
die "$0: ‘$arg’ requires an argument\n" unless $n < scalar @ARGV;
|
||||
my $interpreter = $ARGV[$n];
|
||||
# Überhack to support Perl. Perl examines the shebang and
|
||||
# executes it unless it contains the string "perl" or "indir",
|
||||
# or (undocumented) argv[0] does not contain "perl". Exploit
|
||||
# the latter by doing "exec -a".
|
||||
my $execArgs = $interpreter =~ /perl/ ? "-a PERL" : "";
|
||||
sub shellEscape {
|
||||
my $s = $_;
|
||||
$s =~ s/'/'\\''/g;
|
||||
return "'" . $s . "'";
|
||||
}
|
||||
$envCommand = "exec $execArgs $interpreter $script ${\(join ' ', (map shellEscape, @savedArgs))}";
|
||||
}
|
||||
|
||||
elsif (substr($arg, 0, 1) eq "-") {
|
||||
push @buildArgs, $arg;
|
||||
}
|
||||
|
||||
elsif ($arg eq "-Q" || $arg eq "--no-build-output") {
|
||||
push @buildArgs, $arg;
|
||||
push @instArgs, $arg;
|
||||
}
|
||||
|
||||
else {
|
||||
push @exprs, $arg;
|
||||
}
|
||||
}
|
||||
|
||||
die "$0: ‘-p’ and ‘-E’ are mutually exclusive\n" if $packages && $fromArgs;
|
||||
|
||||
if ($packages) {
|
||||
push @instArgs, "--expr";
|
||||
@exprs = (
|
||||
@@ -182,6 +238,11 @@ foreach my $expr (@exprs) {
|
||||
# Instantiate.
|
||||
my @drvPaths;
|
||||
if ($expr !~ /^\/.*\.drv$/) {
|
||||
# If we're in a #! script, interpret filenames relative to the
|
||||
# script.
|
||||
$expr = dirname(Cwd::abs_path($script)) . "/" . $expr
|
||||
if $inShebang && !$packages && $expr !~ /^\//;
|
||||
|
||||
# !!! would prefer the perl 5.8.0 pipe open feature here.
|
||||
my $pid = open(DRVPATHS, "-|") || exec "$Nix::Config::binDir/nix-instantiate", "--add-root", $drvLink, "--indirect", @instArgs, $expr;
|
||||
while (<DRVPATHS>) {chomp; push @drvPaths, $_;}
|
||||
@@ -209,7 +270,7 @@ foreach my $expr (@exprs) {
|
||||
my $tmp = $ENV{"TMPDIR"} // $ENV{"XDG_RUNTIME_DIR"} // "/tmp";
|
||||
if ($pure) {
|
||||
foreach my $name (keys %ENV) {
|
||||
next if grep { $_ eq $name } ("HOME", "USER", "LOGNAME", "DISPLAY", "PATH", "TERM", "IN_NIX_SHELL", "TZ", "PAGER");
|
||||
next if grep { $_ eq $name } ("HOME", "USER", "LOGNAME", "DISPLAY", "PATH", "TERM", "IN_NIX_SHELL", "TZ", "PAGER", "NIX_BUILD_SHELL");
|
||||
delete $ENV{$name};
|
||||
}
|
||||
# NixOS hack: prevent /etc/bashrc from sourcing /etc/profile.
|
||||
@@ -232,17 +293,20 @@ foreach my $expr (@exprs) {
|
||||
($pure ? '' : 'p=$PATH; ' ) .
|
||||
'dontAddDisableDepTrack=1; ' .
|
||||
'[ -e $stdenv/setup ] && source $stdenv/setup; ' .
|
||||
'if [ "$(type -t runHook)" = function ]; then runHook shellHook; fi; ' .
|
||||
($pure ? '' : 'PATH=$PATH:$p; unset p; ') .
|
||||
'set +e; ' .
|
||||
'[ -n "$PS1" ] && PS1="\n\[\033[1;32m\][nix-shell:\w]$\[\033[0m\] "; ' .
|
||||
'if [ "$(type -t runHook)" = function ]; then runHook shellHook; fi; ' .
|
||||
'unset NIX_ENFORCE_PURITY; ' .
|
||||
'unset NIX_INDENT_MAKE; ' .
|
||||
'shopt -u nullglob; ' .
|
||||
'unset TZ; ' . (defined $ENV{'TZ'} ? "export TZ='${ENV{'TZ'}}'; " : '') .
|
||||
$envCommand);
|
||||
$ENV{BASH_ENV} = $rcfile;
|
||||
exec($ENV{NIX_BUILD_SHELL} // "bash", "--rcfile", $rcfile);
|
||||
my @args = ($ENV{NIX_BUILD_SHELL} // "bash");
|
||||
push @args, "--rcfile" if $interactive;
|
||||
push @args, $rcfile;
|
||||
exec @args;
|
||||
die;
|
||||
}
|
||||
|
||||
|
||||
+54
-35
@@ -6,6 +6,7 @@ use File::Basename;
|
||||
use File::Path qw(mkpath);
|
||||
use Nix::Config;
|
||||
use Nix::Manifest;
|
||||
use File::Temp qw(tempdir);
|
||||
|
||||
binmode STDERR, ":encoding(utf8)";
|
||||
|
||||
@@ -98,42 +99,14 @@ sub update {
|
||||
my $url = $channels{$name};
|
||||
my $origUrl = "$url/MANIFEST";
|
||||
|
||||
# Check if $url is a redirect. If so, follow it now to ensure
|
||||
# consistency if the redirection is changed between
|
||||
# downloading the manifest and the tarball.
|
||||
my $headers = `$Nix::Config::curl --silent --head '$url'`;
|
||||
# We want to download the url to a file to see if it's a tarball while also checking if we
|
||||
# got redirected in the process, so that we can grab the various parts of a nix channel
|
||||
# definition from a consistent location if the redirect changes mid-download.
|
||||
my $tmpdir = tempdir( CLEANUP => 1 );
|
||||
my $filename;
|
||||
($url, $filename) = `cd $tmpdir && $Nix::Config::curl --silent --write-out '%{url_effective}\n%{filename_effective}' -L '$url' -O`;
|
||||
chomp $url;
|
||||
die "$0: unable to check ‘$url’\n" if $? != 0;
|
||||
$headers =~ s/\r//g;
|
||||
$url = $1 if $headers =~ /^Location:\s*(.*)\s*$/m;
|
||||
|
||||
# Check if the channel advertises a binary cache.
|
||||
my $binaryCacheURL = `$Nix::Config::curl --silent '$url'/binary-cache-url`;
|
||||
my $extraAttrs = "";
|
||||
my $getManifest = ($Nix::Config::config{"force-manifest"} // "false") eq "true";
|
||||
if ($? == 0 && $binaryCacheURL ne "") {
|
||||
$extraAttrs .= "binaryCacheURL = \"$binaryCacheURL\"; ";
|
||||
deleteOldManifests($origUrl, undef);
|
||||
} else {
|
||||
$getManifest = 1;
|
||||
}
|
||||
|
||||
if ($getManifest) {
|
||||
# No binary cache, so pull the channel manifest.
|
||||
mkdir $manifestDir, 0755 unless -e $manifestDir;
|
||||
die "$0: you do not have write permission to ‘$manifestDir’!\n" unless -W $manifestDir;
|
||||
$ENV{'NIX_ORIG_URL'} = $origUrl;
|
||||
system("$Nix::Config::binDir/nix-pull", "--skip-wrong-store", "$url/MANIFEST") == 0
|
||||
or die "cannot pull manifest from ‘$url’\n";
|
||||
}
|
||||
|
||||
# Download the channel tarball.
|
||||
my $fullURL = "$url/nixexprs.tar.xz";
|
||||
system("$Nix::Config::curl --fail --silent --head '$fullURL' > /dev/null") == 0 or
|
||||
$fullURL = "$url/nixexprs.tar.bz2";
|
||||
print STDERR "downloading Nix expressions from ‘$fullURL’...\n";
|
||||
my ($hash, $path) = `PRINT_PATH=1 QUIET=1 $Nix::Config::binDir/nix-prefetch-url '$fullURL'`;
|
||||
die "cannot fetch ‘$fullURL’\n" if $? != 0;
|
||||
chomp $path;
|
||||
|
||||
# If the URL contains a version number, append it to the name
|
||||
# attribute (so that "nix-env -q" on the channels profile
|
||||
@@ -141,6 +114,52 @@ sub update {
|
||||
my $cname = $name;
|
||||
$cname .= $1 if basename($url) =~ /(-\d.*)$/;
|
||||
|
||||
my $path;
|
||||
my $ret = -1;
|
||||
if (-e "$tmpdir/$filename" && $filename =~ /\.tar\.(gz|bz2|xz)$/) {
|
||||
# Get our temporary download into the store.
|
||||
(my $hash, $path) = `PRINT_PATH=1 QUIET=1 $Nix::Config::binDir/nix-prefetch-url 'file://$tmpdir/$filename'`;
|
||||
chomp $path;
|
||||
|
||||
# Try unpacking the expressions to see if they'll be valid for us to process later.
|
||||
# Like anything in nix, this will cache the result so we don't do it again outside of the loop below.
|
||||
$ret = system("$Nix::Config::binDir/nix-build --no-out-link -E 'import <nix/unpack-channel.nix> " .
|
||||
"{ name = \"$cname\"; channelName = \"$name\"; src = builtins.storePath \"$path\"; }'");
|
||||
}
|
||||
|
||||
# The URL doesn't unpack directly, so let's try treating it like a full channel folder with files in it
|
||||
my $extraAttrs = "";
|
||||
if ($ret != 0) {
|
||||
# Check if the channel advertises a binary cache.
|
||||
my $binaryCacheURL = `$Nix::Config::curl --silent '$url'/binary-cache-url`;
|
||||
my $getManifest = ($Nix::Config::config{"force-manifest"} // "false") eq "true";
|
||||
if ($? == 0 && $binaryCacheURL ne "") {
|
||||
$extraAttrs .= "binaryCacheURL = \"$binaryCacheURL\"; ";
|
||||
deleteOldManifests($origUrl, undef);
|
||||
} else {
|
||||
$getManifest = 1;
|
||||
}
|
||||
|
||||
if ($getManifest) {
|
||||
# No binary cache, so pull the channel manifest.
|
||||
mkdir $manifestDir, 0755 unless -e $manifestDir;
|
||||
die "$0: you do not have write permission to ‘$manifestDir’!\n" unless -W $manifestDir;
|
||||
$ENV{'NIX_ORIG_URL'} = $origUrl;
|
||||
system("$Nix::Config::binDir/nix-pull", "--skip-wrong-store", "$url/MANIFEST") == 0
|
||||
or die "cannot pull manifest from ‘$url’\n";
|
||||
}
|
||||
|
||||
# Download the channel tarball.
|
||||
my $fullURL = "$url/nixexprs.tar.xz";
|
||||
system("$Nix::Config::curl --fail --silent --head '$fullURL' > /dev/null") == 0 or
|
||||
$fullURL = "$url/nixexprs.tar.bz2";
|
||||
print STDERR "downloading Nix expressions from ‘$fullURL’...\n";
|
||||
(my $hash, $path) = `PRINT_PATH=1 QUIET=1 $Nix::Config::binDir/nix-prefetch-url '$fullURL'`;
|
||||
die "cannot fetch ‘$fullURL’\n" if $? != 0;
|
||||
chomp $path;
|
||||
}
|
||||
|
||||
# Regardless of where it came from, add the expression representing this channel to accumulated expression
|
||||
$exprs .= "'f: f { name = \"$cname\"; channelName = \"$name\"; src = builtins.storePath \"$path\"; $extraAttrs }' ";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use Nix::Config;
|
||||
|
||||
my $profilesDir = "@localstatedir@/nix/profiles";
|
||||
|
||||
|
||||
# Process the command line arguments.
|
||||
my @args = ();
|
||||
my $arg;
|
||||
|
||||
my $removeOld = 0;
|
||||
my $gen;
|
||||
my $dryRun = 0;
|
||||
|
||||
while ($arg = shift) {
|
||||
if ($arg eq "--delete-old" || $arg eq "-d") {
|
||||
$removeOld = 1;
|
||||
$gen = "old";
|
||||
} elsif ($arg eq "--delete-older-than") {
|
||||
$removeOld = 1;
|
||||
$gen = shift;
|
||||
} elsif ($arg eq "--dry-run") {
|
||||
$dryRun = 1;
|
||||
} elsif ($arg eq "--help") {
|
||||
exec "man nix-collect-garbage" or die;
|
||||
} else {
|
||||
push @args, $arg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# If `-d' was specified, remove all old generations of all profiles.
|
||||
# Of course, this makes rollbacks to before this point in time
|
||||
# impossible.
|
||||
|
||||
sub removeOldGenerations;
|
||||
sub removeOldGenerations {
|
||||
my $dir = shift;
|
||||
|
||||
my $dh;
|
||||
opendir $dh, $dir or die;
|
||||
|
||||
foreach my $name (sort (readdir $dh)) {
|
||||
next if $name eq "." || $name eq "..";
|
||||
$name = $dir . "/" . $name;
|
||||
if (-l $name && (readlink($name) =~ /link/)) {
|
||||
print STDERR "removing old generations of profile $name\n";
|
||||
|
||||
system("$Nix::Config::binDir/nix-env", "-p", $name, "--delete-generations", $gen, $dryRun ? "--dry-run" : ());
|
||||
}
|
||||
elsif (! -l $name && -d $name) {
|
||||
removeOldGenerations $name;
|
||||
}
|
||||
}
|
||||
|
||||
closedir $dh or die;
|
||||
}
|
||||
|
||||
removeOldGenerations $profilesDir if $removeOld;
|
||||
|
||||
|
||||
# Run the actual garbage collector.
|
||||
exec "$Nix::Config::binDir/nix-store", "--gc", @args unless $dryRun;
|
||||
@@ -1,5 +1,6 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use utf8;
|
||||
use strict;
|
||||
use Nix::SSH;
|
||||
use Nix::Config;
|
||||
@@ -25,6 +26,7 @@ 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.
|
||||
@@ -61,6 +63,10 @@ while (@ARGV) {
|
||||
elsif ($arg eq "--use-substitutes" || $arg eq "-s") {
|
||||
$useSubstitutes = 1;
|
||||
}
|
||||
elsif ($arg eq "-v") {
|
||||
$verbosity++;
|
||||
setVerbosity($verbosity);
|
||||
}
|
||||
elsif (!defined $sshHost) {
|
||||
$sshHost = $arg;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ sub barf {
|
||||
my $pkgFile = $source;
|
||||
if ($fromURL) {
|
||||
$pkgFile = "$tmpDir/tmp.nixpkg";
|
||||
system("@curl@", "--silent", $source, "-o", $pkgFile) == 0
|
||||
system("@curl@", "-L", "--silent", $source, "-o", $pkgFile) == 0
|
||||
or barf "curl failed: $?";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use utf8;
|
||||
use strict;
|
||||
use File::Basename;
|
||||
use File::stat;
|
||||
use Nix::Store;
|
||||
use Nix::Config;
|
||||
use Nix::Utils;
|
||||
|
||||
binmode STDERR, ":encoding(utf8)";
|
||||
|
||||
|
||||
my $hashType = $ENV{'NIX_HASH_ALGO'} || "sha256"; # obsolete
|
||||
my $cacheDir = $ENV{'NIX_DOWNLOAD_CACHE'};
|
||||
|
||||
my @args;
|
||||
my $arg;
|
||||
while ($arg = shift) {
|
||||
if ($arg eq "--help") {
|
||||
exec "man nix-prefetch-url" or die;
|
||||
} elsif ($arg eq "--type") {
|
||||
$hashType = shift;
|
||||
die "$0: ‘$arg’ requires an argument\n" unless defined $hashType;
|
||||
} elsif (substr($arg, 0, 1) eq "-") {
|
||||
die "$0: unknown flag ‘$arg’\n";
|
||||
} else {
|
||||
push @args, $arg;
|
||||
}
|
||||
}
|
||||
|
||||
my $url = $args[0];
|
||||
my $expHash = $args[1];
|
||||
|
||||
|
||||
if (!defined $url || $url eq "") {
|
||||
print STDERR <<EOF
|
||||
Usage: nix-prefetch-url URL [EXPECTED-HASH]
|
||||
EOF
|
||||
;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $tmpDir = mkTempDir("nix-prefetch-url");
|
||||
|
||||
# Hack to support the mirror:// scheme from Nixpkgs.
|
||||
if ($url =~ /^mirror:\/\//) {
|
||||
system("$Nix::Config::binDir/nix-build '<nixpkgs>' -A resolveMirrorURLs --argstr url '$url' -o $tmpDir/urls > /dev/null") == 0
|
||||
or die "$0: nix-build failed; maybe \$NIX_PATH is not set properly\n";
|
||||
my @expanded = split ' ', readFile("$tmpDir/urls");
|
||||
die "$0: cannot resolve ‘$url’" unless scalar @expanded > 0;
|
||||
print STDERR "$url expands to $expanded[0]\n";
|
||||
$url = $expanded[0];
|
||||
}
|
||||
|
||||
# Handle escaped characters in the URI. `+', `=' and `?' are the only
|
||||
# characters that are valid in Nix store path names but have a special
|
||||
# meaning in URIs.
|
||||
my $name = basename $url;
|
||||
die "cannot figure out file name for ‘$url’\n" if $name eq "";
|
||||
$name =~ s/%2b/+/g;
|
||||
$name =~ s/%3d/=/g;
|
||||
$name =~ s/%3f/?/g;
|
||||
|
||||
my $finalPath;
|
||||
my $hash;
|
||||
|
||||
# If the hash was given, a file with that hash may already be in the
|
||||
# store.
|
||||
if (defined $expHash) {
|
||||
$finalPath = makeFixedOutputPath(0, $hashType, $expHash, $name);
|
||||
if (isValidPath($finalPath)) { $hash = $expHash; } else { $finalPath = undef; }
|
||||
}
|
||||
|
||||
# If we don't know the hash or a file with that hash doesn't exist,
|
||||
# download the file and add it to the store.
|
||||
if (!defined $finalPath) {
|
||||
|
||||
my $tmpFile = "$tmpDir/$name";
|
||||
|
||||
# Optionally do timestamp-based caching of the download.
|
||||
# Actually, the only thing that we cache in $NIX_DOWNLOAD_CACHE is
|
||||
# the hash and the timestamp of the file at $url. The caching of
|
||||
# the file *contents* is done in Nix store, where it can be
|
||||
# garbage-collected independently.
|
||||
my ($cachedTimestampFN, $cachedHashFN, @cacheFlags);
|
||||
if (defined $cacheDir) {
|
||||
my $urlHash = hashString("sha256", 1, $url);
|
||||
writeFile "$cacheDir/$urlHash.url", $url;
|
||||
$cachedHashFN = "$cacheDir/$urlHash.$hashType";
|
||||
$cachedTimestampFN = "$cacheDir/$urlHash.stamp";
|
||||
@cacheFlags = ("--time-cond", $cachedTimestampFN) if -f $cachedHashFN && -f $cachedTimestampFN;
|
||||
}
|
||||
|
||||
# Perform the download.
|
||||
my @curlFlags = ("curl", $url, "-o", $tmpFile, "--fail", "--location", "--max-redirs", "20", "--disable-epsv", "--cookie-jar", "$tmpDir/cookies", "--remote-time", (split " ", ($ENV{NIX_CURL_FLAGS} || "")));
|
||||
(system $Nix::Config::curl @curlFlags, @cacheFlags) == 0 or die "$0: download of ‘$url’ failed\n";
|
||||
|
||||
if (defined $cacheDir && ! -e $tmpFile) {
|
||||
# Curl didn't create $tmpFile, so apparently there's no newer
|
||||
# file on the server.
|
||||
$hash = readFile $cachedHashFN or die;
|
||||
$finalPath = makeFixedOutputPath(0, $hashType, $hash, $name);
|
||||
unless (isValidPath $finalPath) {
|
||||
print STDERR "cached contents of ‘$url’ disappeared, redownloading...\n";
|
||||
$finalPath = undef;
|
||||
(system $Nix::Config::curl @curlFlags) == 0 or die "$0: download of ‘$url’ failed\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!defined $finalPath) {
|
||||
|
||||
# Compute the hash.
|
||||
$hash = hashFile($hashType, $hashType ne "md5", $tmpFile);
|
||||
|
||||
if (defined $cacheDir) {
|
||||
writeFile $cachedHashFN, $hash;
|
||||
my $st = stat($tmpFile) or die;
|
||||
open STAMP, ">$cachedTimestampFN" or die; close STAMP;
|
||||
utime($st->atime, $st->mtime, $cachedTimestampFN) or die;
|
||||
}
|
||||
|
||||
# Add the downloaded file to the Nix store.
|
||||
$finalPath = addToStore($tmpFile, 0, $hashType);
|
||||
}
|
||||
|
||||
die "$0: hash mismatch for ‘$url’\n" if defined $expHash && $expHash ne $hash;
|
||||
}
|
||||
|
||||
print STDERR "path is ‘$finalPath’\n" unless $ENV{'QUIET'};
|
||||
print "$hash\n";
|
||||
print "$finalPath\n" if $ENV{'PRINT_PATH'};
|
||||
@@ -21,11 +21,15 @@ if [ -n "$HOME" ]; then
|
||||
export NIX_PATH=${NIX_PATH:+$NIX_PATH:}nixpkgs=$HOME/.nix-defexpr/channels/nixpkgs
|
||||
|
||||
# Set $SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
||||
if [ -e /etc/ssl/certs/ca-bundle.crt ]; then # Fedora, NixOS
|
||||
export SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt
|
||||
elif [ -e /etc/ssl/certs/ca-certificates.crt ]; then # Ubuntu, Debian
|
||||
if [ -e /etc/ssl/certs/ca-certificates.crt ]; then # NixOS, Ubuntu, Debian, Gentoo, Arch
|
||||
export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
|
||||
elif [ -e "$NIX_LINK/etc/ca-bundle.crt" ]; then # fall back to Nix profile
|
||||
elif [ -e /etc/ssl/certs/ca-bundle.crt ]; then # Old NixOS
|
||||
export SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt
|
||||
elif [ -e /etc/pki/tls/certs/ca-bundle.crt ]; then # Fedora, CentOS
|
||||
export SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt
|
||||
elif [ -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" ]; then # fall back to cacert in Nix profile
|
||||
export SSL_CERT_FILE="$NIX_LINK/etc/ssl/certs/ca-bundle.crt"
|
||||
elif [ -e "$NIX_LINK/etc/ca-bundle.crt" ]; then # old cacert in Nix profile
|
||||
export SSL_CERT_FILE="$NIX_LINK/etc/ca-bundle.crt"
|
||||
fi
|
||||
fi
|
||||
|
||||
+17
-12
@@ -6,11 +6,11 @@ use File::Basename;
|
||||
use File::Path qw(mkpath);
|
||||
use File::stat;
|
||||
use File::Copy;
|
||||
use MIME::Base64;
|
||||
use Nix::Config;
|
||||
use Nix::Store;
|
||||
use Nix::Manifest;
|
||||
use Nix::Utils;
|
||||
use Nix::Crypto;
|
||||
|
||||
binmode STDERR, ":encoding(utf8)";
|
||||
|
||||
@@ -27,9 +27,9 @@ my $writeManifest = 0;
|
||||
my $manifestPath;
|
||||
my $archivesURL;
|
||||
my $link = 0;
|
||||
my $privateKeyFile;
|
||||
my $keyName;
|
||||
my $secretKeyFile;
|
||||
my @roots;
|
||||
my @buildArgs;
|
||||
|
||||
for (my $n = 0; $n < scalar @ARGV; $n++) {
|
||||
my $arg = $ARGV[$n];
|
||||
@@ -61,14 +61,14 @@ for (my $n = 0; $n < scalar @ARGV; $n++) {
|
||||
$archivesURL = $ARGV[$n];
|
||||
} elsif ($arg eq "--link") {
|
||||
$link = 1;
|
||||
} elsif ($arg eq "--key") {
|
||||
} elsif ($arg eq "--key-file") {
|
||||
$n++;
|
||||
die "$0: ‘$arg’ requires an argument\n" unless $n < scalar @ARGV;
|
||||
$privateKeyFile = $ARGV[$n];
|
||||
} elsif ($arg eq "--key-name") {
|
||||
$secretKeyFile = $ARGV[$n];
|
||||
} elsif ($arg eq "--max-jobs" || $arg eq "-j") {
|
||||
$n++;
|
||||
die "$0: ‘$arg’ requires an argument\n" unless $n < scalar @ARGV;
|
||||
$keyName = $ARGV[$n];
|
||||
push @buildArgs, ($arg, $ARGV[$n]);
|
||||
} elsif (substr($arg, 0, 1) eq "-") {
|
||||
die "$0: unknown flag ‘$arg’\n";
|
||||
} else {
|
||||
@@ -110,7 +110,7 @@ my %narFiles;
|
||||
foreach my $storePath (@storePaths) {
|
||||
my $pathHash = substr(basename($storePath), 0, 32);
|
||||
my $narInfoFile = "$destDir/$pathHash.narinfo";
|
||||
if (-e $narInfoFile) {
|
||||
if (!$force && -e $narInfoFile) {
|
||||
my $narInfo = parseNARInfo($storePath, readFile($narInfoFile), 0, $narInfoFile) or die "cannot read ‘$narInfoFile’\n";
|
||||
my $narFile = "$destDir/$narInfo->{url}";
|
||||
if (-e $narFile) {
|
||||
@@ -158,7 +158,7 @@ close NIX;
|
||||
# Build the Nix expression.
|
||||
print STDERR "building compressed archives...\n";
|
||||
my @narPaths;
|
||||
my $pid = open(READ, "$Nix::Config::binDir/nix-build $nixExpr -o $tmpDir/result |")
|
||||
my $pid = open(READ, "-|", "$Nix::Config::binDir/nix-build", $nixExpr, "-o", "$tmpDir/result", @buildArgs)
|
||||
or die "cannot run nix-build";
|
||||
while (<READ>) {
|
||||
chomp;
|
||||
@@ -257,9 +257,14 @@ for (my $n = 0; $n < scalar @storePaths2; $n++) {
|
||||
}
|
||||
}
|
||||
|
||||
if (defined $privateKeyFile && defined $keyName) {
|
||||
my $sig = signString($privateKeyFile, $info);
|
||||
$info .= "Signature: 1;$keyName;$sig\n";
|
||||
if (defined $secretKeyFile) {
|
||||
my $s = readFile $secretKeyFile;
|
||||
chomp $s;
|
||||
my ($keyName, $secretKey) = split ":", $s;
|
||||
die "invalid secret key file ‘$secretKeyFile’\n" unless defined $keyName && defined $secretKey;
|
||||
my $fingerprint = fingerprintPath($storePath, $narHash, $narSize, $refs);
|
||||
my $sig = encode_base64(signString(decode_base64($secretKey), $fingerprint), "");
|
||||
$info .= "Sig: $keyName:$sig\n";
|
||||
}
|
||||
|
||||
my $pathHash = substr(basename($storePath), 0, 32);
|
||||
|
||||
Executable
+122
@@ -0,0 +1,122 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use utf8;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Cwd qw(realpath);
|
||||
use Errno;
|
||||
use File::Basename qw(dirname);
|
||||
use File::Path qw(make_path);
|
||||
use File::Spec::Functions qw(catfile);
|
||||
use List::Util qw(reduce);
|
||||
use IPC::Open3;
|
||||
use Nix::Config;
|
||||
use Nix::Store qw(derivationFromPath);
|
||||
use POSIX qw(uname);
|
||||
use Storable qw(lock_retrieve lock_store);
|
||||
|
||||
my ($sysname, undef, $version, undef, $machine) = uname;
|
||||
$sysname =~ /Darwin/ or die "This tool is only meant to be used on Darwin systems.";
|
||||
|
||||
my $cache = "$Nix::Config::stateDir/dependency-maps/$machine-$sysname-$version.map";
|
||||
|
||||
make_path dirname($cache);
|
||||
|
||||
our $DEPS;
|
||||
eval {
|
||||
$DEPS = lock_retrieve($cache);
|
||||
};
|
||||
|
||||
if($!{ENOENT}) {
|
||||
lock_store {}, $cache;
|
||||
$DEPS = {};
|
||||
} elsif($@) {
|
||||
die "Unable to obtain a lock on dependency-map file $cache: $@";
|
||||
}
|
||||
|
||||
sub mkset(@) {
|
||||
my %set;
|
||||
@set{@_} = ();
|
||||
\%set
|
||||
}
|
||||
|
||||
sub union($$) {
|
||||
my ($set1, $set2) = @_;
|
||||
my %new = (%$set1, %$set2);
|
||||
\%new
|
||||
}
|
||||
|
||||
sub cache_filepath($) {
|
||||
my $fp = shift;
|
||||
$fp =~ s/-/--/g;
|
||||
$fp =~ s/\//-/g;
|
||||
$fp =~ s/^-//g;
|
||||
catfile $cache, $fp
|
||||
}
|
||||
|
||||
sub resolve_tree {
|
||||
sub resolve_tree_inner {
|
||||
my ($lib, $TREE) = @_;
|
||||
return if (defined $TREE->{$lib});
|
||||
$TREE->{$lib} = mkset(@{cache_get($lib)});
|
||||
foreach my $dep (keys %{$TREE->{$lib}}) {
|
||||
resolve_tree_inner($dep, $TREE);
|
||||
}
|
||||
values %$TREE
|
||||
}
|
||||
|
||||
reduce { union($a, $b) } {}, resolve_tree_inner(@_)
|
||||
}
|
||||
|
||||
sub cache_get {
|
||||
my $key = shift;
|
||||
if (defined $DEPS->{$key}) {
|
||||
$DEPS->{$key}
|
||||
} else {
|
||||
cache_insert($key);
|
||||
cache_get($key)
|
||||
}
|
||||
}
|
||||
|
||||
sub cache_insert($) {
|
||||
my $key = shift;
|
||||
print STDERR "Finding dependencies for $key...\n";
|
||||
my @deps = find_deps($key);
|
||||
$DEPS->{$key} = \@deps;
|
||||
}
|
||||
|
||||
sub find_deps($) {
|
||||
my $lib = shift;
|
||||
my($chld_in, $chld_out, $chld_err);
|
||||
my $pid = open3($chld_in, $chld_out, $chld_err, "@otool@", "-L", "-arch", "x86_64", $lib);
|
||||
waitpid($pid, 0);
|
||||
my $line = readline $chld_out;
|
||||
if($? == 0 and $line !~ /not an object file/) {
|
||||
my @libs;
|
||||
while(<$chld_out>) {
|
||||
my $dep = (split /\s+/)[1];
|
||||
push @libs, $dep unless $dep eq $lib or $dep =~ /\@rpath/;
|
||||
}
|
||||
@libs
|
||||
} elsif (-l $lib) {
|
||||
(realpath($lib))
|
||||
} else {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
if (defined $ARGV[0]) {
|
||||
my $deps = derivationFromPath($ARGV[0])->{"env"}->{"__impureHostDeps"};
|
||||
if (defined $deps) {
|
||||
my @files = split(/\s+/, $deps);
|
||||
my $depcache = {};
|
||||
my $depset = reduce { union($a, $b) } (map { resolve_tree($_, $depcache) } @files);
|
||||
print "extra-chroot-dirs\n";
|
||||
print join("\n", keys %$depset);
|
||||
print "\n";
|
||||
}
|
||||
lock_store($DEPS, $cache);
|
||||
} else {
|
||||
print STDERR "Usage: $0 path/to/derivation.drv\n";
|
||||
exit 1
|
||||
}
|
||||
@@ -43,8 +43,7 @@ static std::pair<FdSink, FdSource> connect(const string & conn)
|
||||
|
||||
static void substitute(std::pair<FdSink, FdSource> & pipes, Path storePath, Path destPath)
|
||||
{
|
||||
writeInt(cmdDumpStorePath, pipes.first);
|
||||
writeString(storePath, pipes.first);
|
||||
pipes.first << cmdDumpStorePath << storePath;
|
||||
pipes.first.flush();
|
||||
restorePath(destPath, pipes.second);
|
||||
std::cout << std::endl;
|
||||
@@ -58,17 +57,17 @@ static void query(std::pair<FdSink, FdSource> & pipes)
|
||||
string cmd = tokenized.front();
|
||||
tokenized.pop_front();
|
||||
if (cmd == "have") {
|
||||
writeInt(cmdQueryValidPaths, pipes.first);
|
||||
writeInt(0, pipes.first); // don't lock
|
||||
writeInt(0, pipes.first); // don't substitute
|
||||
writeStrings(tokenized, pipes.first);
|
||||
pipes.first
|
||||
<< cmdQueryValidPaths
|
||||
<< 0 // don't lock
|
||||
<< 0 // don't substitute
|
||||
<< tokenized;
|
||||
pipes.first.flush();
|
||||
PathSet paths = readStrings<PathSet>(pipes.second);
|
||||
foreach (PathSet::iterator, i, paths)
|
||||
std::cout << *i << std::endl;
|
||||
for (auto & i : paths)
|
||||
std::cout << i << std::endl;
|
||||
} else if (cmd == "info") {
|
||||
writeInt(cmdQueryPathInfos, pipes.first);
|
||||
writeStrings(tokenized, pipes.first);
|
||||
pipes.first << cmdQueryPathInfos << tokenized;
|
||||
pipes.first.flush();
|
||||
while (1) {
|
||||
Path path = readString(pipes.second);
|
||||
@@ -80,8 +79,8 @@ static void query(std::pair<FdSink, FdSource> & pipes)
|
||||
std::cout << deriver << std::endl;
|
||||
PathSet references = readStorePaths<PathSet>(pipes.second);
|
||||
std::cout << references.size() << std::endl;
|
||||
foreach (PathSet::iterator, i, references)
|
||||
std::cout << *i << 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;
|
||||
}
|
||||
@@ -116,13 +115,13 @@ int main(int argc, char * * argv)
|
||||
std::pair<FdSink, FdSource> pipes = connect(host);
|
||||
|
||||
/* Exchange the greeting */
|
||||
writeInt(SERVE_MAGIC_1, pipes.first);
|
||||
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
|
||||
writeInt(SERVE_PROTOCOL_VERSION, pipes.first);
|
||||
pipes.first << SERVE_PROTOCOL_VERSION;
|
||||
pipes.first.flush();
|
||||
|
||||
string arg = argv[1];
|
||||
|
||||
@@ -42,11 +42,10 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
|
||||
|
||||
Value * v = &vIn;
|
||||
|
||||
foreach (Strings::iterator, i, tokens) {
|
||||
for (auto & attr : tokens) {
|
||||
|
||||
/* Is *i an index (integer) or a normal attribute name? */
|
||||
/* Is i an index (integer) or a normal attribute name? */
|
||||
enum { apAttr, apIndex } apType = apAttr;
|
||||
string attr = *i;
|
||||
unsigned int attrIndex;
|
||||
if (string2Int(attr, attrIndex)) apType = apIndex;
|
||||
|
||||
@@ -77,15 +76,15 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
|
||||
|
||||
else if (apType == apIndex) {
|
||||
|
||||
if (v->type != tList)
|
||||
if (!v->isList())
|
||||
throw TypeError(
|
||||
format("the expression selected by the selection path ‘%1%’ should be a list but is %2%")
|
||||
% attrPath % showType(*v));
|
||||
|
||||
if (attrIndex >= v->list.length)
|
||||
if (attrIndex >= v->listSize())
|
||||
throw Error(format("list index %1% in selection path ‘%2%’ is out of range") % attrIndex % attrPath);
|
||||
|
||||
v = v->list.elems[attrIndex];
|
||||
v = v->listElems()[attrIndex];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "attr-set.hh"
|
||||
#include "eval.hh"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
static void * allocBytes(size_t n)
|
||||
{
|
||||
void * p;
|
||||
#if HAVE_BOEHMGC
|
||||
p = GC_malloc(n);
|
||||
#else
|
||||
p = malloc(n);
|
||||
#endif
|
||||
if (!p) throw std::bad_alloc();
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate a new array of attributes for an attribute set with a specific
|
||||
capacity. The space is implicitly reserved after the Bindings
|
||||
structure. */
|
||||
Bindings * EvalState::allocBindings(Bindings::size_t capacity)
|
||||
{
|
||||
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings(capacity);
|
||||
}
|
||||
|
||||
|
||||
void EvalState::mkAttrs(Value & v, unsigned int capacity)
|
||||
{
|
||||
if (capacity == 0) {
|
||||
v = vEmptySet;
|
||||
return;
|
||||
}
|
||||
clearValue(v);
|
||||
v.type = tAttrs;
|
||||
v.attrs = allocBindings(capacity);
|
||||
nrAttrsets++;
|
||||
nrAttrsInAttrsets += capacity;
|
||||
}
|
||||
|
||||
|
||||
/* Create a new attribute named 'name' on an existing attribute set stored
|
||||
in 'vAttrs' and return the newly allocated Value which is associated with
|
||||
this attribute. */
|
||||
Value * EvalState::allocAttr(Value & vAttrs, const Symbol & name)
|
||||
{
|
||||
Value * v = allocValue();
|
||||
vAttrs.attrs->push_back(Attr(name, v));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
void Bindings::sort()
|
||||
{
|
||||
std::sort(begin(), end());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include "nixexpr.hh"
|
||||
#include "symbol-table.hh"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
class EvalState;
|
||||
struct Value;
|
||||
|
||||
/* Map one attribute name to its value. */
|
||||
struct Attr
|
||||
{
|
||||
Symbol name;
|
||||
Value * value;
|
||||
Pos * pos;
|
||||
Attr(Symbol name, Value * value, Pos * pos = &noPos)
|
||||
: name(name), value(value), pos(pos) { };
|
||||
Attr() : pos(&noPos) { };
|
||||
bool operator < (const Attr & a) const
|
||||
{
|
||||
return name < a.name;
|
||||
}
|
||||
};
|
||||
|
||||
/* Bindings contains all the attributes of an attribute set. It is defined
|
||||
by its size and its capacity, the capacity being the number of Attr
|
||||
elements allocated after this structure, while the size corresponds to
|
||||
the number of elements already inserted in this structure. */
|
||||
class Bindings
|
||||
{
|
||||
public:
|
||||
typedef uint32_t size_t;
|
||||
|
||||
private:
|
||||
size_t size_, capacity_;
|
||||
Attr attrs[0];
|
||||
|
||||
Bindings(size_t capacity) : size_(0), capacity_(capacity) { }
|
||||
Bindings(const Bindings & bindings) = delete;
|
||||
|
||||
public:
|
||||
size_t size() const { return size_; }
|
||||
|
||||
bool empty() const { return !size_; }
|
||||
|
||||
typedef Attr * iterator;
|
||||
|
||||
void push_back(const Attr & attr)
|
||||
{
|
||||
assert(size_ < capacity_);
|
||||
attrs[size_++] = attr;
|
||||
}
|
||||
|
||||
iterator find(const Symbol & name)
|
||||
{
|
||||
Attr key(name, 0);
|
||||
iterator i = std::lower_bound(begin(), end(), key);
|
||||
if (i != end() && i->name == name) return i;
|
||||
return end();
|
||||
}
|
||||
|
||||
iterator begin() { return &attrs[0]; }
|
||||
iterator end() { return &attrs[size_]; }
|
||||
|
||||
Attr & operator[](size_t pos)
|
||||
{
|
||||
return attrs[pos];
|
||||
}
|
||||
|
||||
void sort();
|
||||
|
||||
size_t capacity() { return capacity_; }
|
||||
|
||||
friend class EvalState;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "common-opts.hh"
|
||||
#include "../libmain/shared.hh"
|
||||
#include "shared.hh"
|
||||
#include "download.hh"
|
||||
#include "util.hh"
|
||||
|
||||
|
||||
@@ -53,7 +54,9 @@ bool parseSearchPathArg(Strings::iterator & i,
|
||||
|
||||
Path lookupFileArg(EvalState & state, string s)
|
||||
{
|
||||
if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
||||
if (isUri(s))
|
||||
return downloadFileCached(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
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
LocalNoInlineNoReturn(void throwEvalError(const char * s))
|
||||
LocalNoInlineNoReturn(void throwEvalError(const char * s, const Pos & pos))
|
||||
{
|
||||
throw EvalError(s);
|
||||
throw EvalError(format(s) % pos);
|
||||
}
|
||||
|
||||
LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v))
|
||||
@@ -24,7 +24,7 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v, const
|
||||
}
|
||||
|
||||
|
||||
void EvalState::forceValue(Value & v)
|
||||
void EvalState::forceValue(Value & v, const Pos & pos)
|
||||
{
|
||||
if (v.type == tThunk) {
|
||||
Env * env = v.thunk.env;
|
||||
@@ -43,7 +43,7 @@ void EvalState::forceValue(Value & v)
|
||||
else if (v.type == tApp)
|
||||
callFunction(*v.app.left, *v.app.right, v, noPos);
|
||||
else if (v.type == tBlackhole)
|
||||
throwEvalError("infinite recursion encountered");
|
||||
throwEvalError("infinite recursion encountered, at %1%", pos);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ inline void EvalState::forceAttrs(Value & v, const Pos & pos)
|
||||
inline void EvalState::forceList(Value & v)
|
||||
{
|
||||
forceValue(v);
|
||||
if (v.type != tList)
|
||||
if (!v.isList())
|
||||
throwTypeError("value is %1% while a list was expected", v);
|
||||
}
|
||||
|
||||
@@ -74,9 +74,8 @@ inline void EvalState::forceList(Value & v)
|
||||
inline void EvalState::forceList(Value & v, const Pos & pos)
|
||||
{
|
||||
forceValue(v);
|
||||
if (v.type != tList)
|
||||
if (!v.isList())
|
||||
throwTypeError("value is %1% while a list was expected, at %2%", v, pos);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+294
-189
@@ -21,9 +21,6 @@
|
||||
|
||||
#else
|
||||
|
||||
#define GC_STRDUP strdup
|
||||
#define GC_MALLOC malloc
|
||||
|
||||
#define NEW new
|
||||
|
||||
#endif
|
||||
@@ -32,14 +29,36 @@
|
||||
namespace nix {
|
||||
|
||||
|
||||
void Bindings::sort()
|
||||
static char * dupString(const char * s)
|
||||
{
|
||||
std::sort(begin(), end());
|
||||
char * t;
|
||||
#if HAVE_BOEHMGC
|
||||
t = GC_strdup(s);
|
||||
#else
|
||||
t = strdup(s);
|
||||
#endif
|
||||
if (!t) throw std::bad_alloc();
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
static void * allocBytes(size_t n)
|
||||
{
|
||||
void * p;
|
||||
#if HAVE_BOEHMGC
|
||||
p = GC_malloc(n);
|
||||
#else
|
||||
p = malloc(n);
|
||||
#endif
|
||||
if (!p) throw std::bad_alloc();
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static void printValue(std::ostream & str, std::set<const Value *> & active, const Value & v)
|
||||
{
|
||||
checkInterrupt();
|
||||
|
||||
if (active.find(&v) != active.end()) {
|
||||
str << "<CYCLE>";
|
||||
return;
|
||||
@@ -73,8 +92,8 @@ static void printValue(std::ostream & str, std::set<const Value *> & active, con
|
||||
str << "{ ";
|
||||
typedef std::map<string, Value *> Sorted;
|
||||
Sorted sorted;
|
||||
foreach (Bindings::iterator, i, *v.attrs)
|
||||
sorted[i->name] = i->value;
|
||||
for (auto & i : *v.attrs)
|
||||
sorted[i.name] = i.value;
|
||||
for (auto & i : sorted) {
|
||||
str << i.first << " = ";
|
||||
printValue(str, active, *i.second);
|
||||
@@ -83,10 +102,12 @@ static void printValue(std::ostream & str, std::set<const Value *> & active, con
|
||||
str << "}";
|
||||
break;
|
||||
}
|
||||
case tList:
|
||||
case tList1:
|
||||
case tList2:
|
||||
case tListN:
|
||||
str << "[ ";
|
||||
for (unsigned int n = 0; n < v.list.length; ++n) {
|
||||
printValue(str, active, *v.list.elems[n]);
|
||||
for (unsigned int n = 0; n < v.listSize(); ++n) {
|
||||
printValue(str, active, *v.listElems()[n]);
|
||||
str << " ";
|
||||
}
|
||||
str << "]";
|
||||
@@ -132,7 +153,7 @@ string showType(const Value & v)
|
||||
case tPath: return "a path";
|
||||
case tNull: return "null";
|
||||
case tAttrs: return "a set";
|
||||
case tList: return "a list";
|
||||
case tList1: case tList2: case tListN: return "a list";
|
||||
case tThunk: return "a thunk";
|
||||
case tApp: return "a function application";
|
||||
case tLambda: return "a function";
|
||||
@@ -168,6 +189,61 @@ static Symbol getName(const AttrName & name, EvalState & state, Env & env)
|
||||
}
|
||||
|
||||
|
||||
static bool gcInitialised = false;
|
||||
|
||||
void initGC()
|
||||
{
|
||||
if (gcInitialised) return;
|
||||
|
||||
#if HAVE_BOEHMGC
|
||||
/* Initialise the Boehm garbage collector. */
|
||||
GC_set_all_interior_pointers(0);
|
||||
|
||||
GC_INIT();
|
||||
|
||||
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
|
||||
we don't need to garbage collect at all. (Collection has a
|
||||
fairly significant overhead.) The heap size can be overridden
|
||||
through libgc's GC_INITIAL_HEAP_SIZE environment variable. We
|
||||
should probably also provide a nix.conf setting for this. Note
|
||||
that GC_expand_hp() causes a lot of virtual, but not physical
|
||||
(resident) memory to be allocated. This might be a problem on
|
||||
systems that don't overcommit. */
|
||||
if (!getenv("GC_INITIAL_HEAP_SIZE")) {
|
||||
size_t size = 32 * 1024 * 1024;
|
||||
#if HAVE_SYSCONF && defined(_SC_PAGESIZE) && defined(_SC_PHYS_PAGES)
|
||||
size_t maxSize = 384 * 1024 * 1024;
|
||||
long pageSize = sysconf(_SC_PAGESIZE);
|
||||
long pages = sysconf(_SC_PHYS_PAGES);
|
||||
if (pageSize != -1)
|
||||
size = (pageSize * pages) / 4; // 25% of RAM
|
||||
if (size > maxSize) size = maxSize;
|
||||
#endif
|
||||
debug(format("setting initial heap size to %1% bytes") % size);
|
||||
GC_expand_hp(size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
gcInitialised = true;
|
||||
}
|
||||
|
||||
|
||||
/* Very hacky way to parse $NIX_PATH, which is colon-separated, but
|
||||
can contain URLs (e.g. "nixpkgs=https://bla...:foo=https://"). */
|
||||
static Strings parseNixPath(const string & in)
|
||||
{
|
||||
string marker = "\001//";
|
||||
auto res = tokenizeString<Strings>(replaceStrings(in, "://", marker), ":");
|
||||
for (auto & s : res)
|
||||
s = replaceStrings(s, marker, "://");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
EvalState::EvalState(const Strings & _searchPath)
|
||||
: sWith(symbols.create("<with>"))
|
||||
, sOutPath(symbols.create("outPath"))
|
||||
@@ -185,61 +261,26 @@ EvalState::EvalState(const Strings & _searchPath)
|
||||
, sLine(symbols.create("line"))
|
||||
, sColumn(symbols.create("column"))
|
||||
, sFunctor(symbols.create("__functor"))
|
||||
, repair(false)
|
||||
, sToString(symbols.create("__toString"))
|
||||
, baseEnv(allocEnv(128))
|
||||
, staticBaseEnv(false, 0)
|
||||
, baseEnvDispl(0)
|
||||
{
|
||||
nrEnvs = nrValuesInEnvs = nrValues = nrListElems = 0;
|
||||
nrAttrsets = nrAttrsInAttrsets = nrOpUpdates = nrOpUpdateValuesCopied = 0;
|
||||
nrListConcats = nrPrimOpCalls = nrFunctionCalls = 0;
|
||||
countCalls = getEnv("NIX_COUNT_CALLS", "0") != "0";
|
||||
|
||||
#if HAVE_BOEHMGC
|
||||
static bool gcInitialised = false;
|
||||
if (!gcInitialised) {
|
||||
restricted = settings.get("restrict-eval", false);
|
||||
|
||||
/* Initialise the Boehm garbage collector. This isn't
|
||||
necessary on most platforms, but for portability we do it
|
||||
anyway. */
|
||||
GC_INIT();
|
||||
|
||||
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 we don't need to garbage collect at all. (Collection
|
||||
has a fairly significant overhead.) The heap size can be
|
||||
overridden through libgc's GC_INITIAL_HEAP_SIZE environment
|
||||
variable. We should probably also provide a nix.conf
|
||||
setting for this. Note that GC_expand_hp() causes a lot of
|
||||
virtual, but not physical (resident) memory to be
|
||||
allocated. This might be a problem on systems that don't
|
||||
overcommit. */
|
||||
if (!getenv("GC_INITIAL_HEAP_SIZE")) {
|
||||
size_t size = 32 * 1024 * 1024;
|
||||
#if HAVE_SYSCONF && defined(_SC_PAGESIZE) && defined(_SC_PHYS_PAGES)
|
||||
size_t maxSize = 384 * 1024 * 1024;
|
||||
long pageSize = sysconf(_SC_PAGESIZE);
|
||||
long pages = sysconf(_SC_PHYS_PAGES);
|
||||
if (pageSize != -1)
|
||||
size = (pageSize * pages) / 4; // 25% of RAM
|
||||
if (size > maxSize) size = maxSize;
|
||||
#endif
|
||||
debug(format("setting initial heap size to %1% bytes") % size);
|
||||
GC_expand_hp(size);
|
||||
}
|
||||
|
||||
gcInitialised = true;
|
||||
}
|
||||
#endif
|
||||
assert(gcInitialised);
|
||||
|
||||
/* Initialise the Nix expression search path. */
|
||||
Strings paths = tokenizeString<Strings>(getEnv("NIX_PATH", ""), ":");
|
||||
Strings paths = parseNixPath(getEnv("NIX_PATH", ""));
|
||||
for (auto & i : _searchPath) addToSearchPath(i, true);
|
||||
for (auto & i : paths) addToSearchPath(i);
|
||||
addToSearchPath("nix=" + settings.nixDataDir + "/nix/corepkgs");
|
||||
|
||||
clearValue(vEmptySet);
|
||||
vEmptySet.type = tAttrs;
|
||||
vEmptySet.attrs = allocBindings(0);
|
||||
|
||||
createBaseEnv();
|
||||
}
|
||||
|
||||
@@ -250,6 +291,33 @@ EvalState::~EvalState()
|
||||
}
|
||||
|
||||
|
||||
Path EvalState::checkSourcePath(const Path & path_)
|
||||
{
|
||||
if (!restricted) return path_;
|
||||
|
||||
/* Resolve symlinks. */
|
||||
Path path = canonPath(path_, true);
|
||||
|
||||
for (auto & i : searchPath)
|
||||
if (path == i.second || isInDir(path, i.second))
|
||||
return 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 (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::addConstant(const string & name, Value & v)
|
||||
{
|
||||
Value * v2 = allocValue();
|
||||
@@ -291,11 +359,6 @@ LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2))
|
||||
throw EvalError(format(s) % s2);
|
||||
}
|
||||
|
||||
LocalNoInlineNoReturn(void throwEvalError(const char * s, const Pos & pos))
|
||||
{
|
||||
throw EvalError(format(s) % pos);
|
||||
}
|
||||
|
||||
LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2, const Pos & pos))
|
||||
{
|
||||
throw EvalError(format(s) % s2 % pos);
|
||||
@@ -359,7 +422,7 @@ LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2,
|
||||
|
||||
void mkString(Value & v, const char * s)
|
||||
{
|
||||
mkStringNoCopy(v, GC_STRDUP(s));
|
||||
mkStringNoCopy(v, dupString(s));
|
||||
}
|
||||
|
||||
|
||||
@@ -369,9 +432,9 @@ void mkString(Value & v, const string & s, const PathSet & context)
|
||||
if (!context.empty()) {
|
||||
unsigned int n = 0;
|
||||
v.string.context = (const char * *)
|
||||
GC_MALLOC((context.size() + 1) * sizeof(char *));
|
||||
foreach (PathSet::const_iterator, i, context)
|
||||
v.string.context[n++] = GC_STRDUP(i->c_str());
|
||||
allocBytes((context.size() + 1) * sizeof(char *));
|
||||
for (auto & i : context)
|
||||
v.string.context[n++] = dupString(i.c_str());
|
||||
v.string.context[n] = 0;
|
||||
}
|
||||
}
|
||||
@@ -379,7 +442,7 @@ void mkString(Value & v, const string & s, const PathSet & context)
|
||||
|
||||
void mkPath(Value & v, const char * s)
|
||||
{
|
||||
mkPathNoCopy(v, GC_STRDUP(s));
|
||||
mkPathNoCopy(v, dupString(s));
|
||||
}
|
||||
|
||||
|
||||
@@ -412,7 +475,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
||||
Value * EvalState::allocValue()
|
||||
{
|
||||
nrValues++;
|
||||
return (Value *) GC_MALLOC(sizeof(Value));
|
||||
return (Value *) allocBytes(sizeof(Value));
|
||||
}
|
||||
|
||||
|
||||
@@ -422,10 +485,10 @@ Env & EvalState::allocEnv(unsigned int size)
|
||||
|
||||
nrEnvs++;
|
||||
nrValuesInEnvs += size;
|
||||
Env * env = (Env *) GC_MALLOC(sizeof(Env) + size * sizeof(Value *));
|
||||
Env * env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *));
|
||||
env->size = size;
|
||||
|
||||
/* Clear the values because maybeThunk() and lookupVar fromWith expects this. */
|
||||
/* Clear the values because maybeThunk() and lookupVar fromWith expect this. */
|
||||
for (unsigned i = 0; i < size; ++i)
|
||||
env->values[i] = 0;
|
||||
|
||||
@@ -433,37 +496,19 @@ Env & EvalState::allocEnv(unsigned int size)
|
||||
}
|
||||
|
||||
|
||||
Value * EvalState::allocAttr(Value & vAttrs, const Symbol & name)
|
||||
{
|
||||
Value * v = allocValue();
|
||||
vAttrs.attrs->push_back(Attr(name, v));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
Bindings * EvalState::allocBindings(Bindings::size_t capacity)
|
||||
{
|
||||
return new (GC_MALLOC(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings(capacity);
|
||||
}
|
||||
|
||||
|
||||
void EvalState::mkList(Value & v, unsigned int length)
|
||||
void EvalState::mkList(Value & v, unsigned int size)
|
||||
{
|
||||
clearValue(v);
|
||||
v.type = tList;
|
||||
v.list.length = length;
|
||||
v.list.elems = length ? (Value * *) GC_MALLOC(length * sizeof(Value *)) : 0;
|
||||
nrListElems += length;
|
||||
}
|
||||
|
||||
|
||||
void EvalState::mkAttrs(Value & v, unsigned int expected)
|
||||
{
|
||||
clearValue(v);
|
||||
v.type = tAttrs;
|
||||
v.attrs = allocBindings(expected);
|
||||
nrAttrsets++;
|
||||
nrAttrsInAttrsets += expected;
|
||||
if (size == 1)
|
||||
v.type = tList1;
|
||||
else if (size == 2)
|
||||
v.type = tList2;
|
||||
else {
|
||||
v.type = tListN;
|
||||
v.bigList.size = size;
|
||||
v.bigList.elems = size ? (Value * *) allocBytes(size * sizeof(Value *)) : 0;
|
||||
}
|
||||
nrListElems += size;
|
||||
}
|
||||
|
||||
|
||||
@@ -555,7 +600,7 @@ void EvalState::evalFile(const Path & path, Value & v)
|
||||
}
|
||||
|
||||
startNest(nest, lvlTalkative, format("evaluating file ‘%1%’") % path2);
|
||||
Expr * e = parseExprFromFile(path2);
|
||||
Expr * e = parseExprFromFile(checkSourcePath(path2));
|
||||
try {
|
||||
eval(e, v);
|
||||
} catch (Error & e) {
|
||||
@@ -651,15 +696,15 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||
environment, while the inherited attributes are evaluated
|
||||
in the original environment. */
|
||||
unsigned int displ = 0;
|
||||
foreach (AttrDefs::iterator, i, attrs) {
|
||||
for (auto & i : attrs) {
|
||||
Value * vAttr;
|
||||
if (hasOverrides && !i->second.inherited) {
|
||||
if (hasOverrides && !i.second.inherited) {
|
||||
vAttr = state.allocValue();
|
||||
mkThunk(*vAttr, env2, i->second.e);
|
||||
mkThunk(*vAttr, env2, i.second.e);
|
||||
} else
|
||||
vAttr = i->second.e->maybeThunk(state, i->second.inherited ? env : env2);
|
||||
vAttr = i.second.e->maybeThunk(state, i.second.inherited ? env : env2);
|
||||
env2.values[displ++] = vAttr;
|
||||
v.attrs->push_back(Attr(i->first, vAttr, &i->second.pos));
|
||||
v.attrs->push_back(Attr(i.first, vAttr, &i.second.pos));
|
||||
}
|
||||
|
||||
/* If the rec contains an attribute called `__overrides', then
|
||||
@@ -690,25 +735,25 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||
}
|
||||
|
||||
else
|
||||
foreach (AttrDefs::iterator, i, attrs)
|
||||
v.attrs->push_back(Attr(i->first, i->second.e->maybeThunk(state, env), &i->second.pos));
|
||||
for (auto & i : attrs)
|
||||
v.attrs->push_back(Attr(i.first, i.second.e->maybeThunk(state, env), &i.second.pos));
|
||||
|
||||
/* Dynamic attrs apply *after* rec and __overrides. */
|
||||
foreach (DynamicAttrDefs::iterator, i, dynamicAttrs) {
|
||||
for (auto & i : dynamicAttrs) {
|
||||
Value nameVal;
|
||||
i->nameExpr->eval(state, *dynamicEnv, nameVal);
|
||||
state.forceValue(nameVal);
|
||||
i.nameExpr->eval(state, *dynamicEnv, nameVal);
|
||||
state.forceValue(nameVal, i.pos);
|
||||
if (nameVal.type == tNull)
|
||||
continue;
|
||||
state.forceStringNoCtx(nameVal);
|
||||
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);
|
||||
i.valueExpr->setName(nameSym);
|
||||
/* Keep sorted order so find can catch duplicates */
|
||||
v.attrs->push_back(Attr(nameSym, i->valueExpr->maybeThunk(state, *dynamicEnv), &i->pos));
|
||||
v.attrs->push_back(Attr(nameSym, i.valueExpr->maybeThunk(state, *dynamicEnv), &i.pos));
|
||||
v.attrs->sort(); // FIXME: inefficient
|
||||
}
|
||||
}
|
||||
@@ -725,8 +770,8 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
|
||||
while the inherited attributes are evaluated in the original
|
||||
environment. */
|
||||
unsigned int displ = 0;
|
||||
foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs)
|
||||
env2.values[displ++] = i->second.e->maybeThunk(state, i->second.inherited ? env : env2);
|
||||
for (auto & i : attrs->attrs)
|
||||
env2.values[displ++] = i.second.e->maybeThunk(state, i.second.inherited ? env : env2);
|
||||
|
||||
body->eval(state, env2, v);
|
||||
}
|
||||
@@ -735,19 +780,36 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
|
||||
void ExprList::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
state.mkList(v, elems.size());
|
||||
for (unsigned int n = 0; n < v.list.length; ++n)
|
||||
v.list.elems[n] = elems[n]->maybeThunk(state, env);
|
||||
for (unsigned int n = 0; n < elems.size(); ++n)
|
||||
v.listElems()[n] = elems[n]->maybeThunk(state, env);
|
||||
}
|
||||
|
||||
|
||||
void ExprVar::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
Value * v2 = state.lookupVar(&env, *this, false);
|
||||
state.forceValue(*v2);
|
||||
state.forceValue(*v2, pos);
|
||||
v = *v2;
|
||||
}
|
||||
|
||||
|
||||
static string showAttrPath(EvalState & state, Env & env, const AttrPath & attrPath)
|
||||
{
|
||||
std::ostringstream out;
|
||||
bool first = true;
|
||||
for (auto & i : attrPath) {
|
||||
if (!first) out << '.'; else first = false;
|
||||
try {
|
||||
out << getName(i, state, env);
|
||||
} catch (Error & e) {
|
||||
assert(!i.symbol.set());
|
||||
out << "\"${" << *i.expr << "}\"";
|
||||
}
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
unsigned long nrLookups = 0;
|
||||
|
||||
void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||
@@ -760,12 +822,12 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
try {
|
||||
|
||||
foreach (AttrPath::const_iterator, i, attrPath) {
|
||||
for (auto & i : attrPath) {
|
||||
nrLookups++;
|
||||
Bindings::iterator j;
|
||||
Symbol name = getName(*i, state, env);
|
||||
Symbol name = getName(i, state, env);
|
||||
if (def) {
|
||||
state.forceValue(*vAttrs);
|
||||
state.forceValue(*vAttrs, pos);
|
||||
if (vAttrs->type != tAttrs ||
|
||||
(j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
|
||||
{
|
||||
@@ -774,28 +836,20 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||
}
|
||||
} else {
|
||||
state.forceAttrs(*vAttrs, pos);
|
||||
if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) {
|
||||
AttrPath staticPath;
|
||||
AttrPath::const_iterator j;
|
||||
for (j = attrPath.begin(); j != i; ++j)
|
||||
staticPath.push_back(AttrName(getName(*j, state, env)));
|
||||
staticPath.push_back(AttrName(getName(*j, state, env)));
|
||||
for (j = j + 1; j != attrPath.end(); ++j)
|
||||
staticPath.push_back(*j);
|
||||
throwEvalError("attribute ‘%1%’ missing, at %2%", showAttrPath(staticPath), pos);
|
||||
}
|
||||
if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
|
||||
throwEvalError("attribute ‘%1%’ missing, at %2%", name, pos);
|
||||
}
|
||||
vAttrs = j->value;
|
||||
pos2 = j->pos;
|
||||
if (state.countCalls && pos2) state.attrSelects[*pos2]++;
|
||||
}
|
||||
|
||||
state.forceValue(*vAttrs);
|
||||
state.forceValue(*vAttrs, ( pos2 != NULL ? *pos2 : this->pos ) );
|
||||
|
||||
} catch (Error & e) {
|
||||
if (pos2 && pos2->file != state.sDerivationNix)
|
||||
addErrorPrefix(e, "while evaluating the attribute ‘%1%’ at %2%:\n",
|
||||
showAttrPath(attrPath), *pos2);
|
||||
showAttrPath(state, env, attrPath), *pos2);
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -810,10 +864,10 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
e->eval(state, env, vTmp);
|
||||
|
||||
foreach (AttrPath::const_iterator, i, attrPath) {
|
||||
for (auto & i : attrPath) {
|
||||
state.forceValue(*vAttrs);
|
||||
Bindings::iterator j;
|
||||
Symbol name = getName(*i, state, env);
|
||||
Symbol name = getName(i, state, env);
|
||||
if (vAttrs->type != tAttrs ||
|
||||
(j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
|
||||
{
|
||||
@@ -892,10 +946,10 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
||||
if (fun.type == tAttrs) {
|
||||
auto found = fun.attrs->find(sFunctor);
|
||||
if (found != fun.attrs->end()) {
|
||||
forceValue(*found->value);
|
||||
forceValue(*found->value, pos);
|
||||
Value * v2 = allocValue();
|
||||
callFunction(*found->value, fun, *v2, pos);
|
||||
forceValue(*v2);
|
||||
forceValue(*v2, pos);
|
||||
return callFunction(*v2, arg, v, pos);
|
||||
}
|
||||
}
|
||||
@@ -926,12 +980,12 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
||||
there is no matching actual argument but the formal
|
||||
argument has a default, use the default. */
|
||||
unsigned int attrsUsed = 0;
|
||||
foreach (Formals::Formals_::iterator, i, lambda.formals->formals) {
|
||||
Bindings::iterator j = arg.attrs->find(i->name);
|
||||
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%",
|
||||
lambda, i->name, pos);
|
||||
env2.values[displ++] = i->def->maybeThunk(*this, env2);
|
||||
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 {
|
||||
attrsUsed++;
|
||||
env2.values[displ++] = j->value;
|
||||
@@ -943,9 +997,9 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
||||
if (!lambda.formals->ellipsis && attrsUsed != arg.attrs->size()) {
|
||||
/* Nope, so show the first unexpected argument to the
|
||||
user. */
|
||||
foreach (Bindings::iterator, 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);
|
||||
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);
|
||||
abort(); // can't happen
|
||||
}
|
||||
}
|
||||
@@ -979,6 +1033,17 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
||||
{
|
||||
forceValue(fun);
|
||||
|
||||
if (fun.type == tAttrs) {
|
||||
auto found = fun.attrs->find(sFunctor);
|
||||
if (found != fun.attrs->end()) {
|
||||
forceValue(*found->value);
|
||||
Value * v = allocValue();
|
||||
callFunction(*found->value, fun, *v, noPos);
|
||||
forceValue(*v);
|
||||
return autoCallFunction(args, *v, res);
|
||||
}
|
||||
}
|
||||
|
||||
if (fun.type != tLambda || !fun.lambda.fun->matchAttrs) {
|
||||
res = fun;
|
||||
return;
|
||||
@@ -987,12 +1052,12 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
||||
Value * actualArgs = allocValue();
|
||||
mkAttrs(*actualArgs, fun.lambda.fun->formals->formals.size());
|
||||
|
||||
foreach (Formals::Formals_::iterator, i, fun.lambda.fun->formals->formals) {
|
||||
Bindings::iterator j = args.find(i->name);
|
||||
for (auto & i : fun.lambda.fun->formals->formals) {
|
||||
Bindings::iterator j = args.find(i.name);
|
||||
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);
|
||||
else if (!i.def)
|
||||
throwTypeError("cannot auto-call a function that has an argument without a default value (‘%1%’)", i.name);
|
||||
}
|
||||
|
||||
actualArgs->attrs->sort();
|
||||
@@ -1120,20 +1185,21 @@ void EvalState::concatLists(Value & v, unsigned int nrLists, Value * * lists, co
|
||||
unsigned int len = 0;
|
||||
for (unsigned int n = 0; n < nrLists; ++n) {
|
||||
forceList(*lists[n], pos);
|
||||
unsigned int l = lists[n]->list.length;
|
||||
unsigned int l = lists[n]->listSize();
|
||||
len += l;
|
||||
if (l) nonEmpty = lists[n];
|
||||
}
|
||||
|
||||
if (nonEmpty && len == nonEmpty->list.length) {
|
||||
if (nonEmpty && len == nonEmpty->listSize()) {
|
||||
v = *nonEmpty;
|
||||
return;
|
||||
}
|
||||
|
||||
mkList(v, len);
|
||||
auto out = v.listElems();
|
||||
for (unsigned int n = 0, pos = 0; n < nrLists; ++n) {
|
||||
unsigned int l = lists[n]->list.length;
|
||||
memcpy(v.list.elems + pos, lists[n]->list.elems, l * sizeof(Value *));
|
||||
unsigned int l = lists[n]->listSize();
|
||||
memcpy(out + pos, lists[n]->listElems(), l * sizeof(Value *));
|
||||
pos += l;
|
||||
}
|
||||
}
|
||||
@@ -1148,9 +1214,9 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
||||
bool first = !forceString;
|
||||
ValueType firstType = tString;
|
||||
|
||||
foreach (vector<Expr *>::iterator, i, *es) {
|
||||
for (auto & i : *es) {
|
||||
Value vTmp;
|
||||
(*i)->eval(state, env, vTmp);
|
||||
i->eval(state, env, vTmp);
|
||||
|
||||
/* If the first element is a path, then the result will also
|
||||
be a path, we don't copy anything (yet - that's done later,
|
||||
@@ -1174,7 +1240,8 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
||||
else if (firstType == tPath) {
|
||||
if (!context.empty())
|
||||
throwEvalError("a string that refers to a store path cannot be appended to a path, at %1%", pos);
|
||||
mkPath(v, s.str().c_str());
|
||||
auto path = canonPath(s.str());
|
||||
mkPath(v, path.c_str());
|
||||
} else
|
||||
mkString(v, s.str(), context);
|
||||
}
|
||||
@@ -1199,13 +1266,18 @@ void EvalState::forceValueDeep(Value & v)
|
||||
forceValue(v);
|
||||
|
||||
if (v.type == tAttrs) {
|
||||
foreach (Bindings::iterator, i, *v.attrs)
|
||||
recurse(*i->value);
|
||||
for (auto & i : *v.attrs)
|
||||
try {
|
||||
recurse(*i.value);
|
||||
} catch (Error & e) {
|
||||
addErrorPrefix(e, "while evaluating the attribute ‘%1%’ at %2%:\n", i.name, *i.pos);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
else if (v.type == tList) {
|
||||
for (unsigned int n = 0; n < v.list.length; ++n)
|
||||
recurse(*v.list.elems[n]);
|
||||
else if (v.isList()) {
|
||||
for (unsigned int n = 0; n < v.listSize(); ++n)
|
||||
recurse(*v.listElems()[n]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1215,7 +1287,7 @@ void EvalState::forceValueDeep(Value & v)
|
||||
|
||||
NixInt EvalState::forceInt(Value & v, const Pos & pos)
|
||||
{
|
||||
forceValue(v);
|
||||
forceValue(v, pos);
|
||||
if (v.type != tInt)
|
||||
throwTypeError("value is %1% while an integer was expected, at %2%", v, pos);
|
||||
return v.integer;
|
||||
@@ -1231,17 +1303,23 @@ bool EvalState::forceBool(Value & v)
|
||||
}
|
||||
|
||||
|
||||
bool EvalState::isFunctor(Value & fun)
|
||||
{
|
||||
return fun.type == tAttrs && fun.attrs->find(sFunctor) != fun.attrs->end();
|
||||
}
|
||||
|
||||
|
||||
void EvalState::forceFunction(Value & v, const Pos & pos)
|
||||
{
|
||||
forceValue(v);
|
||||
if (v.type != tLambda && v.type != tPrimOp && v.type != tPrimOpApp)
|
||||
if (v.type != tLambda && v.type != tPrimOp && v.type != tPrimOpApp && !isFunctor(v))
|
||||
throwTypeError("value is %1% while a function was expected, at %2%", v, pos);
|
||||
}
|
||||
|
||||
|
||||
string EvalState::forceString(Value & v, const Pos & pos)
|
||||
{
|
||||
forceValue(v);
|
||||
forceValue(v, pos);
|
||||
if (v.type != tString) {
|
||||
if (pos)
|
||||
throwTypeError("value is %1% while a string was expected, at %2%", v, pos);
|
||||
@@ -1312,7 +1390,14 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
|
||||
}
|
||||
|
||||
if (v.type == tAttrs) {
|
||||
Bindings::iterator i = v.attrs->find(sOutPath);
|
||||
auto i = v.attrs->find(sToString);
|
||||
if (i != v.attrs->end()) {
|
||||
forceValue(*i->value, pos);
|
||||
Value v1;
|
||||
callFunction(*i->value, v, v1, pos);
|
||||
return coerceToString(pos, v1, context, coerceMore, copyToStore);
|
||||
}
|
||||
i = v.attrs->find(sOutPath);
|
||||
if (i == v.attrs->end()) throwTypeError("cannot coerce a set to a string, at %1%", pos);
|
||||
return coerceToString(pos, *i->value, context, coerceMore, copyToStore);
|
||||
}
|
||||
@@ -1326,17 +1411,17 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
|
||||
shell scripting convenience, just like `null'. */
|
||||
if (v.type == tBool && v.boolean) return "1";
|
||||
if (v.type == tBool && !v.boolean) return "";
|
||||
if (v.type == tInt) return int2String(v.integer);
|
||||
if (v.type == tInt) return std::to_string(v.integer);
|
||||
if (v.type == tNull) return "";
|
||||
|
||||
if (v.type == tList) {
|
||||
if (v.isList()) {
|
||||
string result;
|
||||
for (unsigned int n = 0; n < v.list.length; ++n) {
|
||||
result += coerceToString(pos, *v.list.elems[n],
|
||||
for (unsigned int n = 0; n < v.listSize(); ++n) {
|
||||
result += coerceToString(pos, *v.listElems()[n],
|
||||
context, coerceMore, copyToStore);
|
||||
if (n < v.list.length - 1
|
||||
if (n < v.listSize() - 1
|
||||
/* !!! not quite correct */
|
||||
&& (v.list.elems[n]->type != tList || v.list.elems[n]->list.length != 0))
|
||||
&& (!v.listElems()[n]->isList() || v.listElems()[n]->listSize() != 0))
|
||||
result += " ";
|
||||
}
|
||||
return result;
|
||||
@@ -1357,8 +1442,8 @@ string EvalState::copyPathToStore(PathSet & context, const Path & path)
|
||||
dstPath = srcToStore[path];
|
||||
else {
|
||||
dstPath = settings.readOnlyMode
|
||||
? computeStorePathForPath(path).first
|
||||
: store->addToStore(path, true, htSHA256, defaultPathFilter, repair);
|
||||
? computeStorePathForPath(checkSourcePath(path)).first
|
||||
: store->addToStore(baseNameOf(path), checkSourcePath(path), true, htSHA256, defaultPathFilter, repair);
|
||||
srcToStore[path] = dstPath;
|
||||
printMsg(lvlChatty, format("copied source ‘%1%’ -> ‘%2%’")
|
||||
% path % dstPath);
|
||||
@@ -1407,10 +1492,12 @@ bool EvalState::eqValues(Value & v1, Value & v2)
|
||||
case tNull:
|
||||
return true;
|
||||
|
||||
case tList:
|
||||
if (v1.list.length != v2.list.length) return false;
|
||||
for (unsigned int n = 0; n < v1.list.length; ++n)
|
||||
if (!eqValues(*v1.list.elems[n], *v2.list.elems[n])) return false;
|
||||
case tList1:
|
||||
case tList2:
|
||||
case tListN:
|
||||
if (v1.listSize() != v2.listSize()) return false;
|
||||
for (unsigned int n = 0; n < v1.listSize(); ++n)
|
||||
if (!eqValues(*v1.listElems()[n], *v2.listElems()[n])) return false;
|
||||
return true;
|
||||
|
||||
case tAttrs: {
|
||||
@@ -1466,6 +1553,7 @@ 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: %1% (%2% bytes)") % nrEnvs % bEnvs);
|
||||
printMsg(v, format(" list elements: %1% (%2% bytes)") % nrListElems % bLists);
|
||||
printMsg(v, format(" list concatenations: %1%") % nrListConcats);
|
||||
@@ -1482,31 +1570,38 @@ void EvalState::printStats()
|
||||
printMsg(v, format(" number of function calls: %1%") % nrFunctionCalls);
|
||||
printMsg(v, format(" total allocations: %1% bytes") % (bEnvs + bLists + bValues + bAttrsets));
|
||||
|
||||
#if HAVE_BOEHMGC
|
||||
GC_word heapSize, totalBytes;
|
||||
GC_get_heap_usage_safe(&heapSize, 0, 0, 0, &totalBytes);
|
||||
printMsg(v, format(" current Boehm heap size: %1% bytes") % heapSize);
|
||||
printMsg(v, format(" total Boehm heap allocations: %1% bytes") % totalBytes);
|
||||
#endif
|
||||
|
||||
if (countCalls) {
|
||||
v = lvlInfo;
|
||||
|
||||
printMsg(v, format("calls to %1% primops:") % primOpCalls.size());
|
||||
typedef std::multimap<unsigned int, Symbol> PrimOpCalls_;
|
||||
PrimOpCalls_ primOpCalls_;
|
||||
foreach (PrimOpCalls::iterator, i, primOpCalls)
|
||||
primOpCalls_.insert(std::pair<unsigned int, Symbol>(i->second, i->first));
|
||||
foreach_reverse (PrimOpCalls_::reverse_iterator, i, primOpCalls_)
|
||||
for (auto & i : primOpCalls)
|
||||
primOpCalls_.insert(std::pair<unsigned int, Symbol>(i.second, i.first));
|
||||
for (auto i = primOpCalls_.rbegin(); i != primOpCalls_.rend(); ++i)
|
||||
printMsg(v, format("%1$10d %2%") % i->first % i->second);
|
||||
|
||||
printMsg(v, format("calls to %1% functions:") % functionCalls.size());
|
||||
typedef std::multimap<unsigned int, ExprLambda *> FunctionCalls_;
|
||||
FunctionCalls_ functionCalls_;
|
||||
foreach (FunctionCalls::iterator, i, functionCalls)
|
||||
functionCalls_.insert(std::pair<unsigned int, ExprLambda *>(i->second, i->first));
|
||||
foreach_reverse (FunctionCalls_::reverse_iterator, i, functionCalls_)
|
||||
for (auto & i : functionCalls)
|
||||
functionCalls_.insert(std::pair<unsigned int, ExprLambda *>(i.second, i.first));
|
||||
for (auto i = functionCalls_.rbegin(); i != functionCalls_.rend(); ++i)
|
||||
printMsg(v, format("%1$10d %2%") % i->first % i->second->showNamePos());
|
||||
|
||||
printMsg(v, format("evaluations of %1% attributes:") % attrSelects.size());
|
||||
typedef std::multimap<unsigned int, Pos> AttrSelects_;
|
||||
AttrSelects_ attrSelects_;
|
||||
foreach (AttrSelects::iterator, i, attrSelects)
|
||||
attrSelects_.insert(std::pair<unsigned int, Pos>(i->second, i->first));
|
||||
foreach_reverse (AttrSelects_::reverse_iterator, i, attrSelects_)
|
||||
for (auto & i : attrSelects)
|
||||
attrSelects_.insert(std::pair<unsigned int, Pos>(i.second, i.first));
|
||||
for (auto i = attrSelects_.rbegin(); i != attrSelects_.rend(); ++i)
|
||||
printMsg(v, format("%1$10d %2%") % i->first % i->second);
|
||||
|
||||
}
|
||||
@@ -1543,12 +1638,22 @@ size_t valueSize(Value & v)
|
||||
sz += doString(v.path);
|
||||
break;
|
||||
case tAttrs:
|
||||
for (auto & i : *v.attrs)
|
||||
sz += doValue(*i.value);
|
||||
if (seen.find(v.attrs) == seen.end()) {
|
||||
seen.insert(v.attrs);
|
||||
sz += sizeof(Bindings) + sizeof(Attr) * v.attrs->capacity();
|
||||
for (auto & i : *v.attrs)
|
||||
sz += doValue(*i.value);
|
||||
}
|
||||
break;
|
||||
case tList:
|
||||
for (unsigned int n = 0; n < v.list.length; ++n)
|
||||
sz += doValue(*v.list.elems[n]);
|
||||
case tList1:
|
||||
case tList2:
|
||||
case tListN:
|
||||
if (seen.find(v.listElems()) == seen.end()) {
|
||||
seen.insert(v.listElems());
|
||||
sz += v.listSize() * sizeof(Value *);
|
||||
for (unsigned int n = 0; n < v.listSize(); ++n)
|
||||
sz += doValue(*v.listElems()[n]);
|
||||
}
|
||||
break;
|
||||
case tThunk:
|
||||
sz += doEnv(*v.thunk.env);
|
||||
@@ -1580,7 +1685,7 @@ size_t valueSize(Value & v)
|
||||
if (seen.find(&env) != seen.end()) return 0;
|
||||
seen.insert(&env);
|
||||
|
||||
size_t sz = sizeof(Env);
|
||||
size_t sz = sizeof(Env) + sizeof(Value *) * env.size;
|
||||
|
||||
for (unsigned int i = 0; i < env.size; ++i)
|
||||
if (env.values[i])
|
||||
|
||||
+32
-79
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "attr-set.hh"
|
||||
#include "value.hh"
|
||||
#include "nixexpr.hh"
|
||||
#include "symbol-table.hh"
|
||||
@@ -18,68 +19,6 @@ namespace nix {
|
||||
class EvalState;
|
||||
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Symbol name;
|
||||
Value * value;
|
||||
Pos * pos;
|
||||
Attr(Symbol name, Value * value, Pos * pos = &noPos)
|
||||
: name(name), value(value), pos(pos) { };
|
||||
Attr() : pos(&noPos) { };
|
||||
bool operator < (const Attr & a) const
|
||||
{
|
||||
return name < a.name;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Bindings
|
||||
{
|
||||
public:
|
||||
typedef uint32_t size_t;
|
||||
|
||||
private:
|
||||
size_t size_, capacity;
|
||||
Attr attrs[0];
|
||||
|
||||
Bindings(uint32_t capacity) : size_(0), capacity(capacity) { }
|
||||
Bindings(const Bindings & bindings) = delete;
|
||||
|
||||
public:
|
||||
size_t size() const { return size_; }
|
||||
|
||||
bool empty() const { return !size_; }
|
||||
|
||||
typedef Attr * iterator;
|
||||
|
||||
void push_back(const Attr & attr)
|
||||
{
|
||||
assert(size_ < capacity);
|
||||
attrs[size_++] = attr;
|
||||
}
|
||||
|
||||
iterator find(const Symbol & name)
|
||||
{
|
||||
Attr key(name, 0);
|
||||
iterator i = std::lower_bound(begin(), end(), key);
|
||||
if (i != end() && i->name == name) return i;
|
||||
return end();
|
||||
}
|
||||
|
||||
iterator begin() { return &attrs[0]; }
|
||||
iterator end() { return &attrs[size_]; }
|
||||
|
||||
Attr & operator[](size_t pos)
|
||||
{
|
||||
return attrs[pos];
|
||||
}
|
||||
|
||||
void sort();
|
||||
|
||||
friend class EvalState;
|
||||
};
|
||||
|
||||
|
||||
typedef void (* PrimOpFun) (EvalState & state, const Pos & pos, Value * * args, Value & v);
|
||||
|
||||
|
||||
@@ -119,6 +58,10 @@ std::ostream & operator << (std::ostream & str, const Value & v);
|
||||
typedef list<std::pair<string, Path> > SearchPath;
|
||||
|
||||
|
||||
/* Initialise the Boehm GC, if applicable. */
|
||||
void initGC();
|
||||
|
||||
|
||||
class EvalState
|
||||
{
|
||||
public:
|
||||
@@ -126,12 +69,18 @@ public:
|
||||
|
||||
const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue,
|
||||
sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls,
|
||||
sFile, sLine, sColumn, sFunctor;
|
||||
sFile, sLine, sColumn, sFunctor, sToString;
|
||||
Symbol sDerivationNix;
|
||||
|
||||
/* If set, force copying files to the Nix store even if they
|
||||
already exist there. */
|
||||
bool repair;
|
||||
bool repair = false;
|
||||
|
||||
/* If set, don't allow access to files outside of the Nix search
|
||||
path or to environment variables. */
|
||||
bool restricted;
|
||||
|
||||
Value vEmptySet;
|
||||
|
||||
private:
|
||||
SrcToStore srcToStore;
|
||||
@@ -153,6 +102,8 @@ public:
|
||||
|
||||
void addToSearchPath(const string & s, bool warn = false);
|
||||
|
||||
Path checkSourcePath(const Path & path);
|
||||
|
||||
/* Parse a Nix expression from the specified file. */
|
||||
Expr * parseExprFromFile(const Path & path);
|
||||
Expr * parseExprFromFile(const Path & path, StaticEnv & staticEnv);
|
||||
@@ -169,7 +120,7 @@ public:
|
||||
|
||||
/* Look up a file in the search path. */
|
||||
Path findFile(const string & path);
|
||||
Path findFile(SearchPath & searchPath, const string & path);
|
||||
Path findFile(SearchPath & searchPath, const string & path, const Pos & pos = noPos);
|
||||
|
||||
/* Evaluate an expression to normal form, storing the result in
|
||||
value `v'. */
|
||||
@@ -185,7 +136,7 @@ public:
|
||||
of the evaluation of the thunk. If `v' is a delayed function
|
||||
application, call the function and overwrite `v' with the
|
||||
result. Otherwise, this is a no-op. */
|
||||
inline void forceValue(Value & v);
|
||||
inline void forceValue(Value & v, const Pos & pos = noPos);
|
||||
|
||||
/* Force a value, then recursively force list elements and
|
||||
attributes. */
|
||||
@@ -232,7 +183,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
unsigned int baseEnvDispl;
|
||||
unsigned int baseEnvDispl = 0;
|
||||
|
||||
void createBaseEnv();
|
||||
|
||||
@@ -262,6 +213,8 @@ public:
|
||||
elements and attributes are compared recursively. */
|
||||
bool eqValues(Value & v1, Value & v2);
|
||||
|
||||
bool isFunctor(Value & fun);
|
||||
|
||||
void callFunction(Value & fun, Value & arg, Value & v, const Pos & pos);
|
||||
void callPrimOp(Value & fun, Value & arg, Value & v, const Pos & pos);
|
||||
|
||||
@@ -278,7 +231,7 @@ public:
|
||||
Bindings * allocBindings(Bindings::size_t capacity);
|
||||
|
||||
void mkList(Value & v, unsigned int length);
|
||||
void mkAttrs(Value & v, unsigned int expected);
|
||||
void mkAttrs(Value & v, unsigned int capacity);
|
||||
void mkThunk_(Value & v, Expr * expr);
|
||||
void mkPos(Value & v, Pos * pos);
|
||||
|
||||
@@ -289,17 +242,17 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
unsigned long nrEnvs;
|
||||
unsigned long nrValuesInEnvs;
|
||||
unsigned long nrValues;
|
||||
unsigned long nrListElems;
|
||||
unsigned long nrAttrsets;
|
||||
unsigned long nrAttrsInAttrsets;
|
||||
unsigned long nrOpUpdates;
|
||||
unsigned long nrOpUpdateValuesCopied;
|
||||
unsigned long nrListConcats;
|
||||
unsigned long nrPrimOpCalls;
|
||||
unsigned long nrFunctionCalls;
|
||||
unsigned long nrEnvs = 0;
|
||||
unsigned long nrValuesInEnvs = 0;
|
||||
unsigned long nrValues = 0;
|
||||
unsigned long nrListElems = 0;
|
||||
unsigned long nrAttrsets = 0;
|
||||
unsigned long nrAttrsInAttrsets = 0;
|
||||
unsigned long nrOpUpdates = 0;
|
||||
unsigned long nrOpUpdateValuesCopied = 0;
|
||||
unsigned long nrListConcats = 0;
|
||||
unsigned long nrPrimOpCalls = 0;
|
||||
unsigned long nrFunctionCalls = 0;
|
||||
|
||||
bool countCalls;
|
||||
|
||||
|
||||
+19
-19
@@ -39,9 +39,9 @@ DrvInfo::Outputs DrvInfo::queryOutputs()
|
||||
state->forceList(*i->value, *i->pos);
|
||||
|
||||
/* For each output... */
|
||||
for (unsigned int j = 0; j < i->value->list.length; ++j) {
|
||||
for (unsigned int j = 0; j < i->value->listSize(); ++j) {
|
||||
/* Evaluate the corresponding set. */
|
||||
string name = state->forceStringNoCtx(*i->value->list.elems[j], *i->pos);
|
||||
string name = state->forceStringNoCtx(*i->value->listElems()[j], *i->pos);
|
||||
Bindings::iterator out = attrs->find(state->symbols.create(name));
|
||||
if (out == attrs->end()) continue; // FIXME: throw error?
|
||||
state->forceAttrs(*out->value);
|
||||
@@ -85,8 +85,8 @@ StringSet DrvInfo::queryMetaNames()
|
||||
{
|
||||
StringSet res;
|
||||
if (!getMeta()) return res;
|
||||
foreach (Bindings::iterator, i, *meta)
|
||||
res.insert(i->name);
|
||||
for (auto & i : *meta)
|
||||
res.insert(i.name);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -94,16 +94,16 @@ StringSet DrvInfo::queryMetaNames()
|
||||
bool DrvInfo::checkMeta(Value & v)
|
||||
{
|
||||
state->forceValue(v);
|
||||
if (v.type == tList) {
|
||||
for (unsigned int n = 0; n < v.list.length; ++n)
|
||||
if (!checkMeta(*v.list.elems[n])) return false;
|
||||
if (v.isList()) {
|
||||
for (unsigned int n = 0; n < v.listSize(); ++n)
|
||||
if (!checkMeta(*v.listElems()[n])) return false;
|
||||
return true;
|
||||
}
|
||||
else if (v.type == tAttrs) {
|
||||
Bindings::iterator i = v.attrs->find(state->sOutPath);
|
||||
if (i != v.attrs->end()) return false;
|
||||
foreach (Bindings::iterator, i, *v.attrs)
|
||||
if (!checkMeta(*i->value)) return false;
|
||||
for (auto & i : *v.attrs)
|
||||
if (!checkMeta(*i.value)) return false;
|
||||
return true;
|
||||
}
|
||||
else return v.type == tInt || v.type == tBool || v.type == tString;
|
||||
@@ -255,13 +255,13 @@ static void getDerivations(EvalState & state, Value & vIn,
|
||||
precedence). */
|
||||
typedef std::map<string, Symbol> SortedSymbols;
|
||||
SortedSymbols attrs;
|
||||
foreach (Bindings::iterator, i, *v.attrs)
|
||||
attrs.insert(std::pair<string, Symbol>(i->name, i->name));
|
||||
for (auto & i : *v.attrs)
|
||||
attrs.insert(std::pair<string, Symbol>(i.name, i.name));
|
||||
|
||||
foreach (SortedSymbols::iterator, i, attrs) {
|
||||
startNest(nest, lvlDebug, format("evaluating attribute ‘%1%’") % i->first);
|
||||
string pathPrefix2 = addToPath(pathPrefix, i->first);
|
||||
Value & v2(*v.attrs->find(i->second)->value);
|
||||
for (auto & i : attrs) {
|
||||
startNest(nest, lvlDebug, format("evaluating attribute ‘%1%’") % i.first);
|
||||
string pathPrefix2 = addToPath(pathPrefix, i.first);
|
||||
Value & v2(*v.attrs->find(i.second)->value);
|
||||
if (combineChannels)
|
||||
getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
|
||||
else if (getDerivation(state, v2, pathPrefix2, drvs, done, ignoreAssertionFailures)) {
|
||||
@@ -277,13 +277,13 @@ static void getDerivations(EvalState & state, Value & vIn,
|
||||
}
|
||||
}
|
||||
|
||||
else if (v.type == tList) {
|
||||
for (unsigned int n = 0; n < v.list.length; ++n) {
|
||||
else if (v.isList()) {
|
||||
for (unsigned int n = 0; n < v.listSize(); ++n) {
|
||||
startNest(nest, lvlDebug,
|
||||
format("evaluating list element"));
|
||||
string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str());
|
||||
if (getDerivation(state, *v.list.elems[n], pathPrefix2, drvs, done, ignoreAssertionFailures))
|
||||
getDerivations(state, *v.list.elems[n], pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
|
||||
if (getDerivation(state, *v.listElems()[n], pathPrefix2, drvs, done, ignoreAssertionFailures))
|
||||
getDerivations(state, *v.listElems()[n], pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user