Compare commits

..

65 Commits

Author SHA1 Message Date
Eelco Dolstra
9d13ba6dc1 Bump version 2018-05-04 12:33:35 +02:00
Eelco Dolstra
f97e3a24ff Don't set a CA assertion for paths with references
Really fixes #2133.

(cherry picked from commit c717d8e3bd)
2018-05-03 14:50:28 +02:00
Will Dietz
686241825c build.cc: fix bind-mount of /dev/{pts,ptmx} fallback
Don't bind-mount these to themselves,
mount them into the chroot directory.

Fixes pty issues when using sandbox on CentOS 7.4.
(build of perlPackages.IOTty fails before this change)

(cherry picked from commit 6d9129014d)
2018-05-03 13:59:24 +02:00
Eelco Dolstra
8eceb32e0a LocalStore::addValidPath(): Throw error when the CA assertion is wrong
Closes #2133.

(cherry picked from commit 80a7b16593)
2018-05-03 13:59:04 +02:00
Danylo Hlynskyi
3c6dd39750 nix-collect-garbage: little doc fix
This removes confusing documentation. It's better to remove doc than add implementation, because Nix 1.12 will surely have new GC interface anyway.

Fixes https://github.com/NixOS/nix/issues/641

(cherry picked from commit ac22d77fd1)
2018-05-03 13:58:53 +02:00
Eelco Dolstra
1a67d4155f Fix bzip2 compression of files > 4 GiB
Bzip2's 'avail_in' parameter is declared as an unsigned int, so
assigning a size_t length to it led to silent truncation.

Fixes #2111.

(cherry picked from commit 4a2c948943)
2018-05-03 13:27:56 +02:00
Eelco Dolstra
444b921fcb Fix #1921
(cherry picked from commit d34fa2bcc3)
Signed-off-by: Domen Kožar <domen@dev.si>
2018-04-20 12:47:14 +01:00
Shea Levy
dab3a9d37b Export required C++ version in pkgconfig.
(cherry picked from commit a38fe5c1a8)
2018-04-20 11:13:56 +02:00
Shea Levy
51415f1004 Make prim_exec and prim_importNative available to plugins
(cherry picked from commit fd98fca7bb)
2018-04-20 11:13:56 +02:00
Eelco Dolstra
338a3cc0cb Merge pull request #2093 from grahamc/re-backport-multi-user-linux
Re backport multi user linux, but default to no daemon on Linux
2018-04-20 00:37:22 +02:00
Graham Christensen
572192ec52 installer: allow opting in / out to the daemon installer
By passing --daemon or --no-daemon, the installer can be forced to
select one or the other installation options, despite what the
automatic detection can provide.

This commit can be backported to 2.0-maintenance because it explicitly
turns off the daemon installation for Linux under systemd.

(cherry picked from commit 17b158af85)
2018-04-19 13:56:00 -04:00
Graham Christensen
fa44fa36d1 Revert "Revert "Merge pull request #2027 from grahamc/backport-linux-multi-user""
This reverts commit 4a7b3d1f4c.
2018-04-19 13:55:37 -04:00
Shea Levy
0ccf36be35 ssh-ng: Don't forward options to the daemon.
This can be iterated on and currently leaves out settings we know we
want to forward, but it fixes #1713 and fixes #1935 and isn't
fundamentally broken like the status quo. Future changes are suggested
in a comment.

(cherry picked from commit 088ef81759)
2018-04-19 11:46:25 -04:00
Eelco Dolstra
c67476fb7a Bump version to 2.0.1 2018-04-19 16:28:28 +02:00
Asad Saeeduddin
e30bd3502e Wrap thread local in function for Cygwin
Fixes #1826. See #1352 for a previous instance of a similar change.

(cherry picked from commit be54f4a0b6)
2018-04-19 16:28:07 +02:00
Eelco Dolstra
5a01ff6b47 Fix tests.evalNixOS
This failed because NixOS' release.nix calls builtins.fetchGit.

(cherry picked from commit a99027d587)
2018-04-19 16:18:59 +02:00
Eelco Dolstra
f7454db452 Remove Fedora / Ubuntu releases that are no longer in Nixpkgs
(cherry picked from commit ed87fd17dd)
2018-04-19 14:49:58 +02:00
Eelco Dolstra
497325a75d Remove some release-critical jobs
The release does not in fact depend on Ubuntu/Fedora builds (we don't
publish the build results).

(cherry picked from commit 92aee1b7d6)
2018-04-19 14:49:49 +02:00
Shea Levy
b61ea7b24e initPlugins: Fix dlopen error message.
(cherry picked from commit dc0a542c9f)
2018-04-18 17:47:59 +02:00
Eelco Dolstra
b1ade66815 Handle arguments in $EDITOR
Fixes #2079.

(cherry picked from commit a4aac7f88c)
2018-04-18 17:47:33 +02:00
Félix Baylac-Jacqué
5be4f48c2d nix repl: Fix multiline SIGINT handling.
Fixes #2076

(cherry picked from commit a91fb422fe)
2018-04-18 17:47:21 +02:00
Eelco Dolstra
effbbca812 Fix #2057
(cherry picked from commit 1839a5542a)
2018-04-11 11:47:43 +02:00
Shea Levy
f226d56d25 nix-daemon: Exit successfully when interrupted.
Fixes #2058.

(cherry picked from commit 346c0ac361)
2018-04-11 11:47:43 +02:00
Andrew Dunham
2463b4eb07 Fix missing $DESTDIR when installing programs
(cherry picked from commit f8ab9cef6c)
2018-04-11 11:47:43 +02:00
Samuel Dionne-Riel
b8a5acc203 nix-shell: Fixes use with ruby shebangs.
The ported code in 80ebc553ec was incorrectly ported.

```
-            $envCommand = "exec $execArgs $interpreter -e 'load(\"$script\")' -- ${\(join ' ', (map shellEscape, @savedArgs))}";
...
+                    envCommand = (format("exec %1% %2% -e 'load(\"%3%\") -- %4%") % execArgs % interpreter % script % joined.str()).str();
```

The single-quote finishing the small ruby snippet was lost in
translation.

(cherry picked from commit 399f43c3d5)
2018-04-11 11:47:43 +02:00
zimbatm
1e17079915 nix copy: add an example with S3
I couldn't find a good example how to use it with non-us-east-1 buckets.

(cherry picked from commit 865ca2402f)
2018-04-11 11:47:43 +02:00
Eelco Dolstra
3556a7c254 Remove reference to non-existent manpages
(cherry picked from commit 446bb88f13)
2018-04-11 11:47:43 +02:00
Eelco Dolstra
d0699defd6 Process --option use-case-hack properly
Fixes https://github.com/NixOS/nix/issues/2009.

(cherry picked from commit 2b61c74922)
2018-04-11 11:47:43 +02:00
Eelco Dolstra
247630287b ValidPathInfo::isContentAddressed(): Ensure there are no references
(cherry picked from commit 9d1220a01d)
2018-04-11 11:47:43 +02:00
Tuomas Tynkkynen
59c54f877c release.nix: Use pkgs.closureInfo for binaryTarball
pathsFromGraph is legacy since Nix 2.0.

(cherry picked from commit cc6712ae90)
2018-04-11 11:47:43 +02:00
Eelco Dolstra
4a7b3d1f4c Revert "Merge pull request #2027 from grahamc/backport-linux-multi-user"
This reverts commit a198670ab2,
reversing changes made to
a1cc741d9c. For the stable release
branch, we can't really change the fundamental behaviour of the
installer (i.e. by doing a multi-user install on Linux).
2018-04-11 11:47:43 +02:00
Shea Levy
33dc83821d Document fetchGit.
Fixes #1981.

(cherry picked from commit 6856fe62b0)
2018-04-11 11:47:43 +02:00
Dmitry Kalinkin
26bc4b9557 doc: don't mention obsolete ssh-substituter-hosts
#1840

(cherry picked from commit e2f56c1333)
2018-04-11 11:47:42 +02:00
Corey O'Connor
7a35b10ade manual: correct repeated "--deriver". Add missing single char option aliases.
(cherry picked from commit 22b144fea6)
2018-04-11 11:47:42 +02:00
Eelco Dolstra
ccb81b2622 Remove unused channel-cache directory
(cherry picked from commit 03d8136b02)
2018-04-11 11:47:42 +02:00
Eelco Dolstra
073dac149b Don't retry on CURLE_SSL_CACERT_BADFILE
The certificates won't get any better if we retry.

(cherry picked from commit eb75bc5afb)
2018-04-11 11:47:42 +02:00
Eelco Dolstra
225ae5b62a Filter ANSI colors when not writing to a terminal
Fixes https://github.com/NixOS/nixpkgs/issues/37114.

(cherry picked from commit 4868721506)
2018-04-11 11:47:42 +02:00
Will Dietz
434cdab511 nix-daemon: preserve errno in signal handler (thanks tsan)
(cherry picked from commit d98755b0c2)
2018-04-11 11:47:42 +02:00
Eelco Dolstra
ac5a36c2f3 build-remote: Don't substitute the build result
(cherry picked from commit 7afdc8d4a1)
2018-04-11 11:47:42 +02:00
Eelco Dolstra
25b24a5542 Typo
(cherry picked from commit 6e60141a80)
2018-04-11 11:47:42 +02:00
Guillaume Maudoux
4c737abe3e fetchGit: Fix debug message
(cherry picked from commit 80735c4cc9)
2018-04-11 11:47:42 +02:00
Eelco Dolstra
dd214bb087 Fix double free in Store::queryPathInfo()
It was holding on to a Value* (i.e. a std::shared_ptr<ValidPathInfo>*)
outside of the pathInfoCache lock, so the std::shared_ptr could be
destroyed between the release of the lock and the decrement of the
std::shared_ptr refcount. This can happen if more than
'path-info-cache-size' paths are added in the meantime, *or* if
clearPathInfoCache() is called. The hydra-queue-runner queue monitor
thread periodically calls the later, so is likely to trigger a crash.

Fixes https://github.com/NixOS/hydra/issues/542.

(cherry picked from commit 24b739817f)
2018-04-11 11:47:42 +02:00
Eelco Dolstra
d306287abd Fix #1957
(cherry picked from commit 16551f54c9)
2018-04-11 11:47:41 +02:00
Will Dietz
33bfcbdbdd release.nix: don't try to use nix-2.0 branch, no longer exists
Probably should point at the 18.03 release branch once that's made.

(cherry picked from commit e9a5ce9b07)
2018-04-11 11:47:41 +02:00
Eelco Dolstra
2bbea0d96f Fix error message
(cherry picked from commit 939cf4cceb)
2018-04-11 11:47:41 +02:00
Michael Fiano
d64618de01 nix-channel grammar and punctuation
Minor changes to the nix-channel manpage for my first contribution

(cherry picked from commit ad97d1a786)
2018-04-11 11:47:41 +02:00
Will Dietz
5df25a35b7 fetchGit: use "HEAD" as default ref
(cherry picked from commit e89d02bf03)
2018-04-11 11:47:41 +02:00
Shea Levy
7e989da790 Actually fix nixDataDir in non-canonical path
(cherry picked from commit 14ca85688c)
2018-04-11 11:47:41 +02:00
Tuomas Tynkkynen
77a2cd2f5e libexpr: Fix prim_replaceStrings() to work on an empty source string
Otherwise, running e.g.

nix-instantiate --eval -E --strict 'builtins.replaceStrings [""] ["X"] "abc"'

would just hang in an infinite loop.

Found by afl-fuzz.

First attempt of this was reverted in e2d71bd186 because it caused
another infinite loop, which is fixed now and a test added.

(cherry picked from commit 77e9e1ed91)
2018-04-11 11:47:41 +02:00
Eelco Dolstra
d0665a22cc nix run: Fix segfault on macOS
Note that clearenv() is not available on macOS.

Fixes #1907.

(cherry picked from commit 24ec750003)
2018-04-11 11:47:41 +02:00
Will Dietz
bdd88cabd3 nix search: explicitly handle empty search string, fixes #1893
This is important since this is given as an example.
Other patterns containing "empty search string" will still
be handled differently on different platforms ("asdf|")
but that's less of an issue.

(cherry picked from commit 009cf9cd23)
2018-04-11 11:47:41 +02:00
Will Dietz
e9c5be6fe7 nix search: fix bug where we wrote to cache when shouldn't, breaking
This is exposed by the tests added previously,
and resolves the error reported in #1892:
"expected JSON value".

(cherry picked from commit 3cac8734ac)
2018-04-11 11:47:41 +02:00
Eelco Dolstra
0995763eb1 Fix downloadCached() with a chroot store
E.g.

  nix run --store ~/my-nix -f channel:nixos-17.03 hello -c hello

This problem was mentioned in #1897.

(cherry picked from commit 64e486ab63)
2018-04-11 11:47:41 +02:00
Eelco Dolstra
741a9e9ec3 Fix example in release notes
(cherry picked from commit 39b4177500)
2018-04-11 11:47:40 +02:00
Eelco Dolstra
af81bb7845 Doh
(cherry picked from commit 2691d51a33)
2018-04-11 11:47:40 +02:00
Linus Heckemann
3b9eb5385f Fix #1762
nix-store --export, nix-store --dump, and nix dump-path would previously
fail silently if writing the data out failed, because
 a) FdSink::write ignored exceptions, and
 b) the commands relied on FdSink's destructor, which ignores
    exceptions, to flush the data out.

This could cause rather opaque issues with installing nixos, because
nix-store --export would happily proceed even if it couldn't write its
data out (e.g. if nix-store --import on the other side of the pipe
failed).

This commit adds tests that expose these issues in the nix-store
commands, and fixes them for all three.

(cherry picked from commit 78ac3eb4eb)
2018-04-11 11:47:40 +02:00
Daniel Peebles
d8141deebe Merge pull request #2067 from LnL7/darwin-daemon-keepalive
launchd: enable keepalive for the nix-daemon service
2018-04-10 15:39:12 -04:00
Daiderd Jordan
3cc790bd20 launchd: enable keepalive for the nix-daemon service
Without this the daemon won't be restarted if the process ever dies, for
example when sending a SIGHUP to reload nix.conf.

(cherry picked from commit 05cb8e5c5a)
2018-04-10 21:35:51 +02:00
Graham Christensen
a198670ab2 Merge pull request #2027 from grahamc/backport-linux-multi-user
Backport #2026: Expand the multi-user installer to support Linuxes with systemd
2018-03-30 16:04:17 -04:00
Graham Christensen
b037be7e33 macos: Handle when a build user doesn't have a user ID
(cherry picked from commit 4eb40c72ed)
2018-03-30 15:17:03 -04:00
Graham Christensen
985f0dafe8 Use a looser comparison for the 'user note' check
We use grep instead of an equality check because it is difficult
to extract _just_ the user's note, instead it is prefixed with
some plist junk. This was causing the user note to always be set,
even if there was no reason for it.

(cherry picked from commit f06f8102bd)
2018-03-30 15:17:03 -04:00
Graham Christensen
1b493df892 Check for the existence of a profile target before seeing if it mentions Nix
Grep would ignore files that didn't exist, but would complain
about files in a directory if the directory didn't exist. Simply check
for the directory first, prior to grepping it.

(cherry picked from commit 4ba91f5bae)
2018-03-30 15:17:03 -04:00
Graham Christensen
fb6a41a227 Expand the multi-user installer to support Linuxes with systemd
- darwin installer: delete hardware report, not necessary
 - moves os-specific code from the darwin installer to to `poly_*`
   functions
 - adds profile.d support to the profile targets, which automatically
   handles many distros which don't have a /etc/bashrc but do have an
   /etc/profile.d
 - /bin/bash -> /usr/bin/env bash
 - document why each excluded shellcheck check is excluded
 - rename the multi-user to Daemon-based

(cherry picked from commit 2921165a9d)
2018-03-30 15:16:59 -04:00
Dmitry Kalinkin
a1cc741d9c Fix a small typo in the release notes
(cherry picked from commit d9d8a84a96)
2018-02-24 10:26:27 -05:00
Michael Weiss
bc0899dcc1 doc: Fix a URL in the release notes for Nix 2.0
(cherry picked from commit bd94e63853)
2018-02-24 10:22:47 -05:00
260 changed files with 14734 additions and 20325 deletions

9
.gitignore vendored
View File

@@ -13,6 +13,9 @@ perl/Makefile.config
/corepkgs/config.nix
# /corepkgs/buildenv/
/corepkgs/buildenv/builder.pl
# /corepkgs/channels/
/corepkgs/channels/unpack.sh
@@ -69,6 +72,9 @@ perl/Makefile.config
# /src/nix-channel/
/src/nix-channel/nix-channel
# /src/buildenv/
/src/buildenv/buildenv
# /src/nix-build/
/src/nix-build/nix-build
@@ -81,9 +87,6 @@ perl/Makefile.config
/tests/common.sh
/tests/dummy
/tests/result*
/tests/restricted-innocent
/tests/shell
/tests/shell.drv
# /tests/lang/
/tests/lang/*.out

View File

@@ -1 +0,0 @@
2.3

View File

@@ -1,11 +1,23 @@
makefiles = \
local.mk \
src/boost/format/local.mk \
src/libutil/local.mk \
src/libstore/local.mk \
src/libmain/local.mk \
src/libexpr/local.mk \
src/nix/local.mk \
src/nix-store/local.mk \
src/nix-instantiate/local.mk \
src/nix-env/local.mk \
src/nix-daemon/local.mk \
src/nix-collect-garbage/local.mk \
src/nix-copy-closure/local.mk \
src/nix-prefetch-url/local.mk \
src/buildenv/local.mk \
src/resolve-system-dependencies/local.mk \
src/nix-channel/local.mk \
src/nix-build/local.mk \
src/build-remote/local.mk \
scripts/local.mk \
corepkgs/local.mk \
misc/systemd/local.mk \
@@ -15,7 +27,7 @@ makefiles = \
tests/local.mk \
tests/plugins/local.mk
GLOBAL_CXXFLAGS += -g -Wall -include config.h
GLOBAL_CXXFLAGS += -std=c++14 -g -Wall -include config.h
-include Makefile.config

View File

@@ -1,6 +1,4 @@
AR = @AR@
BDW_GC_LIBS = @BDW_GC_LIBS@
BUILD_SHARED_LIBS = @BUILD_SHARED_LIBS@
CC = @CC@
CFLAGS = @CFLAGS@
CXX = @CXX@
@@ -8,6 +6,7 @@ CXXFLAGS = @CXXFLAGS@
ENABLE_S3 = @ENABLE_S3@
HAVE_SODIUM = @HAVE_SODIUM@
HAVE_READLINE = @HAVE_READLINE@
HAVE_BROTLI = @HAVE_BROTLI@
HAVE_SECCOMP = @HAVE_SECCOMP@
LIBCURL_LIBS = @LIBCURL_LIBS@
OPENSSL_LIBS = @OPENSSL_LIBS@
@@ -17,9 +16,9 @@ SODIUM_LIBS = @SODIUM_LIBS@
LIBLZMA_LIBS = @LIBLZMA_LIBS@
SQLITE3_LIBS = @SQLITE3_LIBS@
LIBBROTLI_LIBS = @LIBBROTLI_LIBS@
EDITLINE_LIBS = @EDITLINE_LIBS@
bash = @bash@
bindir = @bindir@
brotli = @brotli@
lsof = @lsof@
datadir = @datadir@
datarootdir = @datarootdir@

983
config/config.guess vendored

File diff suppressed because it is too large Load Diff

1976
config/config.sub vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
AC_INIT(nix, m4_esyscmd([bash -c "echo -n $(cat ./.version)$VERSION_SUFFIX"]))
AC_INIT(nix, m4_esyscmd([bash -c "echo -n $(cat ./version)$VERSION_SUFFIX"]))
AC_CONFIG_SRCDIR(README.md)
AC_CONFIG_AUX_DIR(config)
@@ -62,9 +62,8 @@ CXXFLAGS=
AC_PROG_CC
AC_PROG_CXX
AC_PROG_CPP
AX_CXX_COMPILE_STDCXX_17
AX_CXX_COMPILE_STDCXX_11
AC_CHECK_TOOL([AR], [ar])
# Use 64-bit file system calls so that we can support files > 2 GiB.
AC_SYS_LARGEFILE
@@ -128,6 +127,8 @@ NEED_PROG(bzip2, bzip2)
NEED_PROG(gzip, gzip)
NEED_PROG(xz, xz)
AC_PATH_PROG(dot, dot)
AC_PATH_PROG(pv, pv, pv)
AC_PATH_PROGS(brotli, brotli bro, bro)
AC_PATH_PROG(lsof, lsof, lsof)
@@ -151,9 +152,9 @@ PKG_CHECK_MODULES([OPENSSL], [libcrypto], [CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"]
# Look for libbz2, a required dependency.
AC_CHECK_LIB([bz2], [BZ2_bzWriteOpen], [true],
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See https://web.archive.org/web/20180624184756/http://www.bzip.org/.])])
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See http://www.bzip.org/.])])
AC_CHECK_HEADERS([bzlib.h], [true],
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See https://web.archive.org/web/20180624184756/http://www.bzip.org/.])])
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See http://www.bzip.org/.])])
# Look for SQLite, a required dependency.
@@ -163,8 +164,6 @@ PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.6.19], [CXXFLAGS="$SQLITE3_CFLAGS $CX
# Look for libcurl, a required dependency.
PKG_CHECK_MODULES([LIBCURL], [libcurl], [CXXFLAGS="$LIBCURL_CFLAGS $CXXFLAGS"])
# Look for editline, a required dependency.
PKG_CHECK_MODULES([EDITLINE], [libeditline], [CXXFLAGS="$EDITLINE_CFLAGS $CXXFLAGS"])
# Look for libsodium, an optional dependency.
PKG_CHECK_MODULES([SODIUM], [libsodium],
@@ -180,9 +179,12 @@ AC_CHECK_LIB([lzma], [lzma_stream_encoder_mt],
[AC_DEFINE([HAVE_LZMA_MT], [1], [xz multithreaded compression support])])
# Look for libbrotli{enc,dec}.
PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec], [CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"])
# Look for libbrotli{enc,dec}, optional dependencies
PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec],
[AC_DEFINE([HAVE_BROTLI], [1], [Whether to use libbrotli.])
CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"]
have_brotli=1], [have_brotli=])
AC_SUBST(HAVE_BROTLI, [$have_brotli])
# Look for libseccomp, required for Linux sandboxing.
if test "$sys_name" = linux; then
@@ -213,7 +215,7 @@ AC_SUBST(ENABLE_S3, [$enable_s3])
AC_LANG_POP(C++)
if test -n "$enable_s3"; then
declare -a aws_version_tokens=($(printf '#include <aws/core/VersionConfig.h>\nAWS_SDK_VERSION_STRING' | $CPP $CPPFLAGS - | grep -v '^#.*' | sed 's/"//g' | tr '.' ' '))
declare -a aws_version_tokens=($(printf '#include <aws/core/VersionConfig.h>\nAWS_SDK_VERSION_STRING' | $CPP - | grep -v '^#.*' | sed 's/"//g' | tr '.' ' '))
AC_DEFINE_UNQUOTED([AWS_VERSION_MAJOR], ${aws_version_tokens@<:@0@:>@}, [Major version of aws-sdk-cpp.])
AC_DEFINE_UNQUOTED([AWS_VERSION_MINOR], ${aws_version_tokens@<:@1@:>@}, [Minor version of aws-sdk-cpp.])
fi
@@ -230,6 +232,12 @@ if test "$gc" = yes; then
fi
AC_ARG_ENABLE(init-state, AC_HELP_STRING([--disable-init-state],
[do not initialise DB etc. in `make install']),
init_state=$enableval, init_state=yes)
#AM_CONDITIONAL(INIT_STATE, test "$init_state" = "yes")
# documentation generation switch
AC_ARG_ENABLE(doc-gen, AC_HELP_STRING([--disable-doc-gen],
[disable documentation generation]),
@@ -252,6 +260,11 @@ if test "$(uname)" = "Darwin"; then
fi
# Figure out the extension of dynamic libraries.
eval dynlib_suffix=$shrext_cmds
AC_SUBST(dynlib_suffix)
# Do we have GNU tar?
AC_MSG_CHECKING([if you have a recent GNU tar])
if $tar --version 2> /dev/null | grep -q GNU && tar cvf /dev/null --warning=no-timestamp ./config.log > /dev/null; then
@@ -268,15 +281,6 @@ AC_ARG_WITH(sandbox-shell, AC_HELP_STRING([--with-sandbox-shell=PATH],
sandbox_shell=$withval)
AC_SUBST(sandbox_shell)
AC_ARG_ENABLE(shared, AC_HELP_STRING([--enable-shared],
[Build shared libraries for Nix [default=yes]]),
shared=$enableval, shared=yes)
if test "$shared" = yes; then
AC_SUBST(BUILD_SHARED_LIBS, 1, [Whether to build shared libraries.])
else
AC_SUBST(BUILD_SHARED_LIBS, 0, [Whether to build shared libraries.])
fi
# Expand all variables in config.status.
test "$prefix" = NONE && prefix=$ac_default_prefix

View File

@@ -1,9 +1,11 @@
with import <nix/config.nix>;
{ derivations, manifest }:
derivation {
name = "user-environment";
system = "builtin";
builder = "builtin:buildenv";
system = builtins.currentSystem;
builder = nixLibexecDir + "/nix/buildenv";
inherit manifest;
@@ -22,4 +24,21 @@ derivation {
# 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;
}

View File

@@ -1,14 +1,10 @@
{ system ? "" # obsolete
, url
, hash ? "" # an SRI ash
# Legacy hash specification
, md5 ? "", sha1 ? "", sha256 ? "", sha512 ? ""
, outputHash ?
if hash != "" then hash else if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256
if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256
, outputHashAlgo ?
if hash != "" then "" else if sha512 != "" then "sha512" else if sha1 != "" then "sha1" else if md5 != "" then "md5" else "sha256"
if sha512 != "" then "sha512" else if sha1 != "" then "sha1" else if md5 != "" then "md5" else "sha256"
, executable ? false
, unpack ? false
, name ? baseNameOf (toString url)

View File

@@ -1,7 +1,6 @@
<part xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="part-advanced-topics"
version="5.0">
<title>Advanced Topics</title>

View File

@@ -81,7 +81,6 @@ or a newline, e.g.
<para>Each machine specification consists of the following elements,
separated by spaces. Only the first element is required.
To leave a field at its default, set it to <literal>-</literal>.
<orderedlist>
@@ -180,8 +179,4 @@ builders = @/etc/nix/machines
causes the list of machines in <filename>/etc/nix/machines</filename>
to be included. (This is the default.)</para>
<para>If you want the builders to use caches, you likely want to set
the option <link linkend='conf-builders-use-substitutes'><literal>builders-use-substitutes</literal></link>
in your local <filename>nix.conf</filename>.</para>
</chapter>

View File

@@ -123,7 +123,7 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-auto-optimise-store"><term><literal>auto-optimise-store</literal></term>
<varlistentry><term><literal>auto-optimise-store</literal></term>
<listitem><para>If set to <literal>true</literal>, Nix
automatically detects files in the store that have identical
@@ -135,6 +135,7 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-builders">
<term><literal>builders</literal></term>
<listitem>
@@ -145,7 +146,7 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-builders-use-substitutes"><term><literal>builders-use-substitutes</literal></term>
<varlistentry><term><literal>builders-use-substitutes</literal></term>
<listitem><para>If set to <literal>true</literal>, Nix will instruct
remote build machines to use their own binary substitutes if available. In
@@ -158,6 +159,7 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-build-users-group"><term><literal>build-users-group</literal></term>
<listitem><para>This options specifies the Unix group containing
@@ -199,7 +201,7 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-compress-build-log"><term><literal>compress-build-log</literal></term>
<varlistentry><term><literal>compress-build-log</literal></term>
<listitem><para>If set to <literal>true</literal> (the default),
build logs written to <filename>/nix/var/log/nix/drvs</filename>
@@ -208,6 +210,7 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-connect-timeout"><term><literal>connect-timeout</literal></term>
<listitem>
@@ -240,6 +243,7 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-extra-sandbox-paths">
<term><literal>extra-sandbox-paths</literal></term>
@@ -250,26 +254,7 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-extra-platforms"><term><literal>extra-platforms</literal></term>
<listitem><para>Platforms other than the native one which
this machine is capable of building for. This can be useful for
supporting additional architectures on compatible machines:
i686-linux can be built on x86_64-linux machines (and the default
for this setting reflects this); armv7 is backwards-compatible with
armv6 and armv5tel; some aarch64 machines can also natively run
32-bit ARM code; and qemu-user may be used to support non-native
platforms (though this may be slow and buggy). Most values for this
are not enabled by default because build systems will often
misdetect the target platform and generate incompatible code, so you
may wish to cross-check the results of using this option against
proper natively-built versions of your
derivations.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-extra-substituters"><term><literal>extra-substituters</literal></term>
<varlistentry><term><literal>extra-substituters</literal></term>
<listitem><para>Additional binary caches appended to those
specified in <option>substituters</option>. When used by
@@ -279,7 +264,8 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-fallback"><term><literal>fallback</literal></term>
<varlistentry><term><literal>fallback</literal></term>
<listitem><para>If set to <literal>true</literal>, Nix will fall
back to building from source if a binary substitute fails. This
@@ -288,7 +274,8 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-fsync-metadata"><term><literal>fsync-metadata</literal></term>
<varlistentry><term><literal>fsync-metadata</literal></term>
<listitem><para>If set to <literal>true</literal>, changes to the
Nix store metadata (in <filename>/nix/var/nix/db</filename>) are
@@ -298,6 +285,7 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-hashed-mirrors"><term><literal>hashed-mirrors</literal></term>
<listitem><para>A list of web servers used by
@@ -326,7 +314,7 @@ builtins.fetchurl {
</varlistentry>
<varlistentry xml:id="conf-http-connections"><term><literal>http-connections</literal></term>
<varlistentry><term><literal>http-connections</literal></term>
<listitem><para>The maximum number of parallel TCP connections
used to fetch files from binary caches and by other downloads. It
@@ -335,7 +323,7 @@ builtins.fetchurl {
</varlistentry>
<varlistentry xml:id="conf-keep-build-log"><term><literal>keep-build-log</literal></term>
<varlistentry><term><literal>keep-build-log</literal></term>
<listitem><para>If set to <literal>true</literal> (the default),
Nix will write the build log of a derivation (i.e. the standard
@@ -360,9 +348,11 @@ builtins.fetchurl {
options a store path was built), so by default this option is on.
Turn it off to save a bit of disk space (or a lot if
<literal>keep-outputs</literal> is also turned on).</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-keep-env-derivations"><term><literal>keep-env-derivations</literal></term>
<varlistentry><term><literal>keep-env-derivations</literal></term>
<listitem><para>If <literal>false</literal> (default), derivations
are not stored in Nix user environments. That is, the derivation
@@ -385,6 +375,7 @@ builtins.fetchurl {
</varlistentry>
<varlistentry xml:id="conf-keep-outputs"><term><literal>keep-outputs</literal></term>
<listitem><para>If <literal>true</literal>, the garbage collector
@@ -398,8 +389,10 @@ builtins.fetchurl {
only at build time (e.g., the C compiler, or source tarballs
downloaded from the network). To prevent it from doing so, set
this option to <literal>true</literal>.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-max-build-log-size"><term><literal>max-build-log-size</literal></term>
<listitem>
@@ -413,27 +406,20 @@ builtins.fetchurl {
</varlistentry>
<varlistentry xml:id="conf-max-free"><term><literal>max-free</literal></term>
<listitem><para>This option defines after how many free bytes to stop collecting
garbage once the <literal>min-free</literal> condition gets triggered.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-max-jobs"><term><literal>max-jobs</literal></term>
<listitem><para>This option defines the maximum number of jobs
that Nix will try to build in parallel. The default is
<literal>1</literal>. The special value <literal>auto</literal>
causes Nix to use the number of CPUs in your system. <literal>0</literal>
is useful when using remote builders to prevent any local builds (except for
<literal>preferLocalBuild</literal> derivation attribute which executes locally
regardless). It can be
causes Nix to use the number of CPUs in your system. It can be
overridden using the <option
linkend='opt-max-jobs'>--max-jobs</option> (<option>-j</option>)
command line switch.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-max-silent-time"><term><literal>max-silent-time</literal></term>
<listitem>
@@ -454,48 +440,8 @@ builtins.fetchurl {
</varlistentry>
<varlistentry xml:id="conf-min-free"><term><literal>min-free</literal></term>
<listitem>
<para>When the disk reaches <literal>min-free</literal> bytes of free disk space during a build, nix
will start to garbage-collection until <literal>max-free</literal> bytes are available on the disk.
A value of <literal>0</literal> (the default) means that this feature is disabled.</para>
</listitem>
</varlistentry>
<varlistentry xml:id="conf-narinfo-cache-negative-ttl"><term><literal>narinfo-cache-negative-ttl</literal></term>
<listitem>
<para>The TTL in seconds for negative lookups. If a store path is
queried from a substituter but was not found, there will be a
negative lookup cached in the local disk cache database for the
specified duration.</para>
</listitem>
</varlistentry>
<varlistentry xml:id="conf-narinfo-cache-positive-ttl"><term><literal>narinfo-cache-positive-ttl</literal></term>
<listitem>
<para>The TTL in seconds for positive lookups. If a store path is
queried from a substituter, the result of the query will be cached
in the local disk cache database including some of the NAR
metadata. The default TTL is a month, setting a shorter TTL for
positive lookups can be useful for binary caches that have
frequent garbage collection, in which case having a more frequent
cache invalidation would prevent trying to pull the path again and
failing with a hash mismatch if the build isn't reproducible.
</para>
</listitem>
</varlistentry>
<varlistentry xml:id="conf-netrc-file"><term><literal>netrc-file</literal></term>
<varlistentry><term><literal>netrc-file</literal></term>
<listitem><para>If set to an absolute path to a <filename>netrc</filename>
file, Nix will use the HTTP authentication credentials in this file when
@@ -513,12 +459,7 @@ password <replaceable>my-password</replaceable>
For the exact syntax, see <link
xlink:href="https://ec.haxx.se/usingcurl-netrc.html">the
<literal>curl</literal> documentation.</link></para>
<note><para>This must be an absolute path, and <literal>~</literal>
is not resolved. For example, <filename>~/.netrc</filename> won't
resolve to your home directory's <filename>.netrc</filename>.</para></note>
</listitem>
<literal>curl</literal> documentation.</link></para></listitem>
</varlistentry>
@@ -554,6 +495,7 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-pre-build-hook"><term><literal>pre-build-hook</literal></term>
<listitem>
@@ -589,6 +531,7 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-repeat"><term><literal>repeat</literal></term>
<listitem><para>How many times to repeat builds to check whether
@@ -600,7 +543,8 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-require-sigs"><term><literal>require-sigs</literal></term>
<varlistentry><term><literal>require-sigs</literal></term>
<listitem><para>If set to <literal>true</literal> (the default),
any non-content-addressed path added or copied to the Nix store
@@ -629,7 +573,7 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-sandbox"><term><literal>sandbox</literal></term>
<varlistentry><term><literal>sandbox</literal></term>
<listitem><para>If set to <literal>true</literal>, builds will be
performed in a <emphasis>sandboxed environment</emphasis>, i.e.,
@@ -657,13 +601,13 @@ password <replaceable>my-password</replaceable>
<varname>__noChroot</varname> attribute set to
<literal>true</literal> do not run in sandboxes.</para>
<para>The default is <literal>true</literal> on Linux and
<literal>false</literal> on all other platforms.</para>
<para>The default is <literal>false</literal>.</para>
</listitem>
</varlistentry>
<varlistentry xml:id="conf-sandbox-dev-shm-size"><term><literal>sandbox-dev-shm-size</literal></term>
<listitem><para>This option determines the maximum size of the
@@ -700,7 +644,7 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-secret-key-files"><term><literal>secret-key-files</literal></term>
<varlistentry><term><literal>secret-key-files</literal></term>
<listitem><para>A whitespace-separated list of files containing
secret (private) keys. These are used to sign locally-built
@@ -721,7 +665,7 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-substitute"><term><literal>substitute</literal></term>
<varlistentry><term><literal>substitute</literal></term>
<listitem><para>If set to <literal>true</literal> (default), Nix
will use binary substitutes if available. This option can be
@@ -729,7 +673,8 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-substituters"><term><literal>substituters</literal></term>
<varlistentry><term><literal>substituters</literal></term>
<listitem><para>A list of URLs of substituters, separated by
whitespace. The default is
@@ -737,7 +682,8 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-system"><term><literal>system</literal></term>
<varlistentry><term><literal>system</literal></term>
<listitem><para>This option specifies the canonical Nix system
name of the current installation, such as
@@ -758,33 +704,6 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-system-features"><term><literal>system-features</literal></term>
<listitem><para>A set of system “features” supported by this
machine, e.g. <literal>kvm</literal>. Derivations can express a
dependency on such features through the derivation attribute
<varname>requiredSystemFeatures</varname>. For example, the
attribute
<programlisting>
requiredSystemFeatures = [ "kvm" ];
</programlisting>
ensures that the derivation can only be built on a machine with
the <literal>kvm</literal> feature.</para>
<para>This setting by default includes <literal>kvm</literal> if
<filename>/dev/kvm</filename> is accessible, and the
pseudo-features <literal>nixos-test</literal>,
<literal>benchmark</literal> and <literal>big-parallel</literal>
that are used in Nixpkgs to route builds to specific
machines.</para>
</listitem>
</varlistentry>
<varlistentry xml:id="conf-timeout"><term><literal>timeout</literal></term>
<listitem>
@@ -804,7 +723,8 @@ requiredSystemFeatures = [ "kvm" ];
</varlistentry>
<varlistentry xml:id="conf-trusted-public-keys"><term><literal>trusted-public-keys</literal></term>
<varlistentry><term><literal>trusted-public-keys</literal></term>
<listitem><para>A whitespace-separated list of public keys. When
paths are copied from another Nix store (such as a binary cache),
@@ -814,7 +734,8 @@ requiredSystemFeatures = [ "kvm" ];
</varlistentry>
<varlistentry xml:id="conf-trusted-substituters"><term><literal>trusted-substituters</literal></term>
<varlistentry><term><literal>trusted-substituters</literal></term>
<listitem><para>A list of URLs of substituters, separated by
whitespace. These are not used by default, but can be enabled by
@@ -826,6 +747,7 @@ requiredSystemFeatures = [ "kvm" ];
</varlistentry>
<varlistentry xml:id="conf-trusted-users"><term><literal>trusted-users</literal></term>
<listitem>
@@ -850,179 +772,11 @@ requiredSystemFeatures = [ "kvm" ];
</varlistentry>
</variablelist>
</para>
<refsection>
<title>Deprecated Settings</title>
<para>
<variablelist>
<varlistentry xml:id="conf-binary-caches">
<term><literal>binary-caches</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>binary-caches</literal> is now an alias to
<xref linkend="conf-substituters" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-binary-cache-public-keys">
<term><literal>binary-cache-public-keys</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>binary-cache-public-keys</literal> is now an alias to
<xref linkend="conf-trusted-public-keys" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-compress-log">
<term><literal>build-compress-log</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-compress-log</literal> is now an alias to
<xref linkend="conf-compress-build-log" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-cores">
<term><literal>build-cores</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-cores</literal> is now an alias to
<xref linkend="conf-cores" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-extra-chroot-dirs">
<term><literal>build-extra-chroot-dirs</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-extra-chroot-dirs</literal> is now an alias to
<xref linkend="conf-extra-sandbox-paths" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-extra-sandbox-paths">
<term><literal>build-extra-sandbox-paths</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-extra-sandbox-paths</literal> is now an alias to
<xref linkend="conf-extra-sandbox-paths" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-fallback">
<term><literal>build-fallback</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-fallback</literal> is now an alias to
<xref linkend="conf-fallback" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-max-jobs">
<term><literal>build-max-jobs</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-max-jobs</literal> is now an alias to
<xref linkend="conf-max-jobs" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-max-log-size">
<term><literal>build-max-log-size</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-max-log-size</literal> is now an alias to
<xref linkend="conf-max-build-log-size" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-max-silent-time">
<term><literal>build-max-silent-time</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-max-silent-time</literal> is now an alias to
<xref linkend="conf-max-silent-time" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-repeat">
<term><literal>build-repeat</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-repeat</literal> is now an alias to
<xref linkend="conf-repeat" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-timeout">
<term><literal>build-timeout</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-timeout</literal> is now an alias to
<xref linkend="conf-timeout" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-use-chroot">
<term><literal>build-use-chroot</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-use-chroot</literal> is now an alias to
<xref linkend="conf-sandbox" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-use-sandbox">
<term><literal>build-use-sandbox</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-use-sandbox</literal> is now an alias to
<xref linkend="conf-sandbox" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-build-use-substitutes">
<term><literal>build-use-substitutes</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>build-use-substitutes</literal> is now an alias to
<xref linkend="conf-substitute" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-gc-keep-derivations">
<term><literal>gc-keep-derivations</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>gc-keep-derivations</literal> is now an alias to
<xref linkend="conf-keep-derivations" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-gc-keep-outputs">
<term><literal>gc-keep-outputs</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>gc-keep-outputs</literal> is now an alias to
<xref linkend="conf-keep-outputs" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-env-keep-derivations">
<term><literal>env-keep-derivations</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>env-keep-derivations</literal> is now an alias to
<xref linkend="conf-keep-env-derivations" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-extra-binary-caches">
<term><literal>extra-binary-caches</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>extra-binary-caches</literal> is now an alias to
<xref linkend="conf-extra-substituters" />.</para></listitem>
</varlistentry>
<varlistentry xml:id="conf-trusted-binary-caches">
<term><literal>trusted-binary-caches</literal></term>
<listitem><para><emphasis>Deprecated:</emphasis>
<literal>trusted-binary-caches</literal> is now an alias to
<xref linkend="conf-trusted-substituters" />.</para></listitem>
</varlistentry>
</variablelist>
</para>
</refsection>
</refsection>
</refentry>

View File

@@ -52,15 +52,10 @@ nixpkgs=/home/eelco/Dev/nixpkgs-branch:/etc/nixos</screen>
<envar>NIX_PATH</envar> to
<screen>
nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-15.09.tar.gz</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
15.09 channel.</para>
<para>A following shorthand can be used to refer to the official channels:
<screen>nixpkgs=channel:nixos-15.09</screen>
</para>
14.12 channel.</para>
<para>The search path can be extended using the <option
linkend="opt-I">-I</option> option, which takes precedence over

View File

@@ -95,6 +95,15 @@ those paths. If this bothers you, use
</varlistentry>
<!--
<varlistentry><term><option>- -show-progress</option></term>
<listitem><para>Show the progress of each path's transfer as it's made.
This requires the <command>pv</command> utility to be in <envar>PATH</envar>.</para></listitem>
</varlistentry>
-->
<varlistentry><term><option>--include-outputs</option></term>
<listitem><para>Also copy the outputs of store derivations

View File

@@ -456,7 +456,7 @@ $ nix-env -f ~/foo.nix -i '.*'</screen>
from another profile:
<screen>
$ nix-env -i --from-profile /nix/var/nix/profiles/foo gcc</screen>
$ nix-env -i --from-profile /nix/var/nix/profiles/foo -i gcc</screen>
</para>
@@ -1346,12 +1346,11 @@ $ nix-env --list-generations
<para>This operation deletes the specified generations of the current
profile. The generations can be a list of generation numbers, the
special value <literal>old</literal> to delete all non-current
generations, a value such as <literal>30d</literal> to delete all
generations, or a value such as <literal>30d</literal> to delete all
generations older than the specified number of days (except for the
generation that was active at that point in time), or a value such as.
<literal>+5</literal> to only keep the specified items older than the
current generation. Periodically deleting old generations is important
to make garbage collection effective.</para>
generation that was active at that point in time).
Periodically deleting old generations is important to make garbage
collection effective.</para>
</refsection>
@@ -1360,8 +1359,6 @@ to make garbage collection effective.</para>
<screen>
$ nix-env --delete-generations 3 4 8
$ nix-env --delete-generations +5
$ nix-env --delete-generations 30d
$ nix-env -p other_profile --delete-generations old</screen>
@@ -1461,7 +1458,7 @@ error: no generation older than the current (91) exists</screen>
<refsection condition="manpage"><title>Environment variables</title>
<variablelist>
<varlistentry><term><envar>NIX_PROFILE</envar></term>
<listitem><para>Location of the Nix profile. Defaults to the
@@ -1475,6 +1472,6 @@ error: no generation older than the current (91) exists</screen>
</variablelist>
</refsection>
</refentry>

View File

@@ -154,9 +154,7 @@ input.</para>
<listitem><para>When used with <option>--eval</option>, perform
evaluation in read/write mode so nix language features that
require it will still work (at the cost of needing to do
instantiation of every evaluated derivation). If this option is
not enabled, there may be uninstantiated store paths in the final
output.</para>
instantiation of every evaluated derivation).</para>
</listitem>

View File

@@ -32,7 +32,6 @@
<arg><option>--run</option> <replaceable>cmd</replaceable></arg>
<arg><option>--exclude</option> <replaceable>regexp</replaceable></arg>
<arg><option>--pure</option></arg>
<arg><option>--keep</option> <replaceable>name</replaceable></arg>
<group choice='req'>
<arg choice='plain'>
<group choice='req'>
@@ -166,13 +165,6 @@ also <xref linkend="sec-common-options" />.</phrase></para>
</listitem></varlistentry>
<varlistentry><term><option>--keep</option> <replaceable>name</replaceable></term>
<listitem><para>When a <option>--pure</option> shell is started,
keep the listed environment variables.</para></listitem>
</varlistentry>
</variablelist>
<para>The following common options are supported:</para>
@@ -317,28 +309,13 @@ while (my $token = $p->get_tag("a")) {
</para>
<para>Sometimes you need to pass a simple Nix expression to customize
a package like Terraform:
<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 bash -p "terraform.withPlugins (plugins: [ plugins.openstack ])"
terraform apply
]]></programlisting>
<note><para>You must use double quotes (<literal>"</literal>) when
passing a simple Nix expression in a nix-shell shebang.</para></note>
</para>
<para>Finally, using the merging of multiple nix-shell shebangs the
following Haskell script uses a specific branch of Nixpkgs/NixOS (the
18.03 stable branch):
<programlisting><![CDATA[
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p "haskellPackages.ghcWithPackages (ps: [ps.HTTP ps.tagsoup])"
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-18.03.tar.gz
#! 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

View File

@@ -204,7 +204,7 @@ printed.)</para>
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>
<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
@@ -275,7 +275,7 @@ as a means of providing Nix store access to a restricted ssh user.
<listitem><para>Allow the connected client to request the realization
of derivations. In effect, this can be used to make the host act
as a remote builder.</para></listitem>
as a build slave.</para></listitem>
</varlistentry>
@@ -679,18 +679,6 @@ query is applied to the target of the symlink.</para>
</varlistentry>
<varlistentry><term><option>--graphml</option></term>
<listitem><para>Prints the references graph of the store paths
<replaceable>paths</replaceable> in the <link
xlink:href="http://graphml.graphdrawing.org/">GraphML</link> file format.
This can be used to visualise dependency graphs. To obtain a
build-time dependency graph, apply this to a store derivation. To
obtain a runtime dependency graph, apply it to an output
path.</para></listitem>
</varlistentry>
<varlistentry><term><option>--binding</option> <replaceable>name</replaceable></term>
<term><option>-b</option> <replaceable>name</replaceable></term>
@@ -1282,7 +1270,6 @@ ktorrent-2.2.1/NEWS
<cmdsynopsis>
<command>nix-store</command>
<arg choice='plain'><option>--dump-db</option></arg>
<arg rep='repeat'><replaceable>paths</replaceable></arg>
</cmdsynopsis>
</refsection>
@@ -1293,13 +1280,6 @@ Nix database to standard output. It can be loaded into an empty Nix
store using <option>--load-db</option>. This is useful for making
backups and when migrating to different database schemas.</para>
<para>By default, <option>--dump-db</option> will dump the entire Nix
database. When one or more store paths is passed, only the subset of
the Nix database for those store paths is dumped. As with
<option>--export</option>, the user is responsible for passing all the
store paths for a closure. See <option>--export</option> for an
example.</para>
</refsection>
</refsection>

View File

@@ -8,9 +8,6 @@
<arg choice='plain'><option>-v</option></arg>
</group>
</arg>
<arg>
<arg choice='plain'><option>--quiet</option></arg>
</arg>
<arg>
<group choice='plain'>
<arg choice='plain'><option>--no-build-output</option></arg>

View File

@@ -75,23 +75,6 @@
</varlistentry>
<varlistentry><term><option>--quiet</option></term>
<listitem>
<para>Decreases the level of verbosity of diagnostic messages
printed on standard error. This is the inverse option to
<option>-v</option> / <option>--verbose</option>.
</para>
<para>This option may be specified repeatedly. See the previous
verbosity levels list.</para>
</listitem>
</varlistentry>
<varlistentry><term><option>--no-build-output</option> / <option>-Q</option></term>
<listitem><para>By default, output written by builders to standard

View File

@@ -50,40 +50,6 @@ allowedRequisites = [ foobar ];
</varlistentry>
<varlistentry><term><varname>disallowedReferences</varname></term>
<listitem><para>The optional attribute
<varname>disallowedReferences</varname> specifies a list of illegal
references (dependencies) of the output of the builder. For
example,
<programlisting>
disallowedReferences = [ foo ];
</programlisting>
enforces that the output of a derivation cannot have a direct runtime
dependencies on the derivation <varname>foo</varname>.</para></listitem>
</varlistentry>
<varlistentry><term><varname>disallowedRequisites</varname></term>
<listitem><para>This attribute is similar to
<varname>disallowedReferences</varname>, but it specifies illegal
requisites for the whole closure, so all the dependencies
recursively. For example,
<programlisting>
disallowedRequisites = [ foobar ];
</programlisting>
enforces that the output of a derivation cannot have any
runtime dependency on <varname>foobar</varname> or any other derivation
depending recursively on <varname>foobar</varname>.</para></listitem>
</varlistentry>
<varlistentry><term><varname>exportReferencesGraph</varname></term>
@@ -146,13 +112,7 @@ impureEnvVars = [ "http_proxy" "https_proxy" <replaceable>...</replaceable> ];
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>
<warning><para><varname>impureEnvVars</varname> implementation takes
environment variables from the current builder process. When a daemon is
building its environmental variables are used. Without the daemon, the
environmental variables come from the environment of the
<command>nix-build</command>.</para></warning></listitem>
derivations.</para></listitem>
</varlistentry>
@@ -216,7 +176,7 @@ fetchurl {
<programlisting>
{ stdenv, curl }: # The <command>curl</command> program is used for downloading.
{ url, sha256 }:
{ url, md5 }:
stdenv.mkDerivation {
name = baseNameOf (toString url);
@@ -224,10 +184,10 @@ stdenv.mkDerivation {
buildInputs = [ curl ];
# This is a fixed-output derivation; the output must be a regular
# file with SHA256 hash <varname>sha256</varname>.
# file with MD5 hash <varname>md5</varname>.
outputHashMode = "flat";
outputHashAlgo = "sha256";
outputHash = sha256;
outputHashAlgo = "md5";
outputHash = md5;
inherit url;
}
@@ -237,8 +197,8 @@ stdenv.mkDerivation {
<para>The <varname>outputHashAlgo</varname> attribute specifies
the hash algorithm used to compute the hash. It can currently be
<literal>"sha1"</literal>, <literal>"sha256"</literal> or
<literal>"sha512"</literal>.</para>
<literal>"md5"</literal>, <literal>"sha1"</literal> or
<literal>"sha256"</literal>.</para>
<para>The <varname>outputHashMode</varname> attribute determines
how the hash is computed. It must be one of the following two
@@ -251,7 +211,7 @@ stdenv.mkDerivation {
<listitem><para>The output must be a non-executable regular
file. If it isnt, the build fails. The hash is simply
computed over the contents of that file (so its equal to what
Unix commands like <command>sha256sum</command> or
Unix commands like <command>md5sum</command> or
<command>sha1sum</command> produce).</para>
<para>This is the default.</para></listitem>
@@ -312,7 +272,9 @@ big = "a very long string";
<varlistentry><term><varname>preferLocalBuild</varname></term>
<listitem><para>If this attribute is set to
<literal>true</literal> and <link
<literal>true</literal>, it has two effects. First, the
derivation will always be built, not substituted, even if a
substitute is available. Second, if <link
linkend="chap-distributed-builds">distributed building is
enabled</link>, then, if possible, the derivaton will be built
locally instead of forwarded to a remote machine. This is
@@ -322,19 +284,6 @@ big = "a very long string";
</varlistentry>
<varlistentry><term><varname>allowSubstitutes</varname></term>
<listitem><para>If this attribute is set to
<literal>false</literal>, then Nix will always build this
derivation; it will not try to substitute its outputs. This is
useful for very trivial derivations (such as
<function>writeText</function> in Nixpkgs) that are cheaper to
build than to substitute from a binary cache.</para></listitem>
</varlistentry>
</variablelist>
</section>

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,7 @@ encountered</quote>).</para></footnote>.</para>
</simplesect>
<simplesect xml:id="sect-let-expressions"><title>Let-expressions</title>
<simplesect><title>Let-expressions</title>
<para>A let-expression allows you define local variables for an
expression. For instance,

View File

@@ -1,6 +1,5 @@
<appendix xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="part-glossary">
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Glossary</title>
@@ -86,48 +85,29 @@
<glossentry xml:id="gloss-reference"><glossterm>reference</glossterm>
<glossdef>
<para>A store path <varname>P</varname> is said to have a
reference to a store path <varname>Q</varname> if the store object
at <varname>P</varname> contains the path <varname>Q</varname>
somewhere. The <emphasis>references</emphasis> of a store path are
the set of store paths to which it has a reference.
</para>
<para>A derivation can reference other derivations and sources
(but not output paths), whereas an output path only references other
output paths.
</para>
</glossdef>
<glossdef><para>A store path <varname>P</varname> is said to have a
reference to a store path <varname>Q</varname> if the store object
at <varname>P</varname> contains the path <varname>Q</varname>
somewhere. This implies than an execution involving
<varname>P</varname> potentially needs <varname>Q</varname> to be
present. The <emphasis>references</emphasis> of a store path are
the set of store paths to which it has a reference.</para></glossdef>
</glossentry>
<glossentry xml:id="gloss-reachable"><glossterm>reachable</glossterm>
<glossdef><para>A store path <varname>Q</varname> is reachable from
another store path <varname>P</varname> if <varname>Q</varname> is in the
<link linkend="gloss-closure">closure</link> of the
<link linkend="gloss-reference">references</link> relation.
</para></glossdef>
</glossentry>
<glossentry xml:id="gloss-closure"><glossterm>closure</glossterm>
<glossdef><para>The closure of a store path is the set of store
paths that are directly or indirectly “reachable” from that store
path; that is, its the closure of the path under the <link
linkend="gloss-reference">references</link> relation. For a package, the
closure of its derivation is equivalent to the build-time
dependencies, while the closure of its output path is equivalent to its
runtime dependencies. For correct deployment it is necessary to deploy whole
closures, since otherwise at runtime files could be missing. The command
<command>nix-store -qR</command> prints out closures of store paths.
</para>
<para>As an example, if the store object at path <varname>P</varname> contains
a reference to path <varname>Q</varname>, then <varname>Q</varname> is
in the closure of <varname>P</varname>. Further, if <varname>Q</varname>
references <varname>R</varname> then <varname>R</varname> is also in
the closure of <varname>P</varname>.
</para></glossdef>
linkend="gloss-reference">references</link> relation. For instance,
if the store object at path <varname>P</varname> contains a
reference to path <varname>Q</varname>, then <varname>Q</varname> is
in the closure of <varname>P</varname>. For correct deployment it
is necessary to deploy whole closures, since otherwise at runtime
files could be missing. The command <command>nix-store
-qR</command> prints out closures of store paths.</para></glossdef>
</glossentry>
@@ -167,7 +147,7 @@
linkend="sec-profiles" />.</para>
</glossdef>
</glossentry>

View File

@@ -30,7 +30,7 @@ To build Nix itself in this shell:
[nix-shell]$ configurePhase
[nix-shell]$ make
</screen>
To install it in <literal>$(pwd)/inst</literal> and test it:
To install it in <literal>$(pwd)/nix</literal> and test it:
<screen>
[nix-shell]$ make install
[nix-shell]$ make installcheck

View File

@@ -21,51 +21,4 @@ in your <filename>~/.profile</filename> (or similar), like this:</para>
<screen>
source <replaceable>prefix</replaceable>/etc/profile.d/nix.sh</screen>
<section xml:id="sec-nix-ssl-cert-file">
<title><envar>NIX_SSL_CERT_FILE</envar></title>
<para>If you need to specify a custom certificate bundle to account
for an HTTPS-intercepting man in the middle proxy, you must specify
the path to the certificate bundle in the environment variable
<envar>NIX_SSL_CERT_FILE</envar>.</para>
<para>If you don't specify a <envar>NIX_SSL_CERT_FILE</envar>
manually, Nix will install and use its own certificate
bundle.</para>
<procedure>
<step><para>Set the environment variable and install Nix</para>
<screen>
$ export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crt
$ sh &lt;(curl https://nixos.org/nix/install)
</screen></step>
<step><para>In the shell profile and rc files (for example,
<filename>/etc/bashrc</filename>, <filename>/etc/zshrc</filename>),
add the following line:</para>
<programlisting>
export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crt
</programlisting>
</step>
</procedure>
<note><para>You must not add the export and then do the install, as
the Nix installer will detect the presense of Nix configuration, and
abort.</para></note>
<section xml:id="sec-nix-ssl-cert-file-with-nix-daemon-and-macos">
<title><envar>NIX_SSL_CERT_FILE</envar> with macOS and the Nix daemon</title>
<para>On macOS you must specify the environment variable for the Nix
daemon service, then restart it:</para>
<screen>
$ sudo launchctl setenv NIX_SSL_CERT_FILE /etc/ssl/my-certificate-bundle.crt
$ sudo launchctl kickstart -k system/org.nixos.nix-daemon
</screen>
</section>
</section>
</chapter>
</chapter>

View File

@@ -6,30 +6,13 @@
<title>Installing a Binary Distribution</title>
<para>If you are using Linux or macOS, the easiest way to install Nix
is to run the following command:
<para>If you are using Linux or macOS, the easiest way to install
Nix is to run the following command:
<screen>
$ sh &lt;(curl https://nixos.org/nix/install)
$ bash &lt;(curl https://nixos.org/nix/install)
</screen>
As of Nix 2.1.0, the Nix installer will always default to creating a
single-user installation, however opting in to the multi-user
installation is highly recommended.
</para>
<section xml:id="sect-single-user-installation">
<title>Single User Installation</title>
<para>
To explicitly select a single-user installation on your system:
<screen>
sh &lt;(curl https://nixos.org/nix/install) --no-daemon
</screen>
</para>
<para>
This will perform a single-user installation of Nix, meaning that
<filename>/nix</filename> is owned by the invoking user. You should
run this under your usual user account, <emphasis>not</emphasis> as
@@ -50,8 +33,51 @@ and <filename>.profile</filename> to source
the <command>NIX_INSTALLER_NO_MODIFY_PROFILE</command> environment
variable before executing the install script to disable this
behaviour.
</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, macOS and various other systems from the <link
xlink:href="http://nixos.org/nix/download.html">Nix homepage</link>.
You can also get builds of the latest development release from our
<link
xlink:href="http://hydra.nixos.org/job/nix/master/release/latest-finished#tabs-constituents">continuous
build system</link>.</para>
<para>For Fedora, RPM packages are available. These can be installed
or upgraded using <command>rpm -U</command>. For example,
<screen>
$ rpm -U nix-1.8-1.i386.rpm</screen>
</para>
<para>For Debian and Ubuntu, you can download a Deb package and
install it like this:
<screen>
$ dpkg -i nix_1.8-1_amd64.deb</screen>
</para>
-->
<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
alice$ tar xfj nix-1.8-x86_64-darwin.tar.bz2
alice$ cd nix-1.8-x86_64-darwin
alice$ ./install
</screen>
</para>
<para>You can uninstall Nix simply by running:
@@ -60,131 +86,5 @@ $ rm -rf /nix
</screen>
</para>
</section>
<section xml:id="sect-multi-user-installation">
<title>Multi User Installation</title>
<para>
The multi-user Nix installation creates system users, and a system
service for the Nix daemon.
</para>
<itemizedlist>
<title>Supported Systems</title>
<listitem>
<para>Linux running systemd, with SELinux disabled</para>
</listitem>
<listitem><para>macOS</para></listitem>
</itemizedlist>
<para>
You can instruct the installer to perform a multi-user
installation on your system:
<screen>
sh &lt;(curl https://nixos.org/nix/install) --daemon
</screen>
</para>
<para>
The multi-user installation of Nix will create build users between
the user IDs 30001 and 30032, and a group with the group ID 30000.
You should run this under your usual user account,
<emphasis>not</emphasis> as root. The script will invoke
<command>sudo</command> as needed.
</para>
<note><para>
If you need Nix to use a different group ID or user ID set, you
will have to download the tarball manually and <link
linkend="sect-nix-install-binary-tarball">edit the install
script</link>.
</para></note>
<para>
The installer will modify <filename>/etc/bashrc</filename>, and
<filename>/etc/zshrc</filename> if they exist. The installer will
first back up these files with a
<literal>.backup-before-nix</literal> extension. The installer
will also create <filename>/etc/profile.d/nix.sh</filename>.
</para>
<para>You can uninstall Nix with the following commands:
<screen>
sudo rm -rf /etc/profile/nix.sh /etc/nix /nix ~root/.nix-profile ~root/.nix-defexpr ~root/.nix-channels ~/.nix-profile ~/.nix-defexpr ~/.nix-channels
# If you are on Linux with systemd, you will need to run:
sudo systemctl stop nix-daemon.socket
sudo systemctl stop nix-daemon.service
sudo systemctl disable nix-daemon.socket
sudo systemctl disable nix-daemon.service
sudo systemctl daemon-reload
# If you are on macOS, you will need to run:
sudo launchctl unload /Library/LaunchDaemons/org.nixos.nix-daemon.plist
sudo rm /Library/LaunchDaemons/org.nixos.nix-daemon.plist
</screen>
There may also be references to Nix in
<filename>/etc/profile</filename>,
<filename>/etc/bashrc</filename>, and
<filename>/etc/zshrc</filename> which you may remove.
</para>
</section>
<section xml:id="sect-nix-install-pinned-version-url">
<title>Installing a pinned Nix version from a URL</title>
<para>
NixOS.org hosts version-specific installation URLs for all Nix
versions since 1.11.16, at
<literal>https://nixos.org/releases/nix/nix-VERSION/install</literal>.
</para>
<para>
These install scripts can be used the same as the main
NixOS.org installation script:
<screen>
sh &lt;(curl https://nixos.org/nix/install)
</screen>
</para>
<para>
In the same directory of the install script are sha256 sums, and
gpg signature files.
</para>
</section>
<section xml:id="sect-nix-install-binary-tarball">
<title>Installing from a binary tarball</title>
<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
alice$ tar xfj nix-1.8-x86_64-darwin.tar.bz2
alice$ cd nix-1.8-x86_64-darwin
alice$ ./install
</screen>
</para>
<para>
If you need to edit the multi-user installation script to use
different group ID or a different user ID range, modify the
variables set in the file named
<filename>install-multi-user</filename>.
</para>
</section>
</chapter>

View File

@@ -9,9 +9,6 @@
<itemizedlist>
<listitem><para>GNU Make.</para></listitem>
<listitem><para>Bash Shell. The <literal>./configure</literal> script
relies on bashisms, so Bash is required.</para></listitem>
<listitem><para>A version of GCC or Clang that supports C++14.</para></listitem>
@@ -25,27 +22,12 @@
If your distribution does not provide it, you can get it from <link
xlink:href="https://www.openssl.org"/>.</para></listitem>
<listitem><para>The <literal>libbrotlienc</literal> and
<literal>libbrotlidec</literal> libraries to provide implementation
of the Brotli compression algorithm. They are available for download
from the official repository <link
xlink:href="https://github.com/google/brotli" />.</para></listitem>
<listitem><para>The bzip2 compressor program and the
<literal>libbz2</literal> library. Thus you must have bzip2
installed, including development headers and libraries. If your
distribution does not provide these, you can obtain bzip2 from <link
xlink:href="https://web.archive.org/web/20180624184756/http://www.bzip.org/"
/>.</para></listitem>
xlink:href="http://www.bzip.org/"/>.</para></listitem>
<listitem><para><literal>liblzma</literal>, which is provided by
XZ Utils. If your distribution does not provide this, you can
get it from <link xlink:href="https://tukaani.org/xz/"/>.</para></listitem>
<listitem><para>cURL and its library. If your distribution does not
provide it, you can get it from <link
xlink:href="https://curl.haxx.se/"/>.</para></listitem>
<listitem><para>The SQLite embedded database library, version 3.6.19
or higher. If your distribution does not provide it, please install
it from <link xlink:href="http://www.sqlite.org/" />.</para></listitem>
@@ -58,10 +40,6 @@
pass the flag <option>--enable-gc</option> to
<command>configure</command>.</para></listitem>
<listitem><para>The <literal>boost</literal> library of version
1.66.0 or higher. It can be obtained from the official web site
<link xlink:href="https://www.boost.org/" />.</para></listitem>
<listitem><para>The <command>xmllint</command> and
<command>xsltproc</command> programs to build this manual and the
man-pages. These are part of the <literal>libxml2</literal> and
@@ -87,15 +65,6 @@
modify the parser or when you are building from the Git
repository.</para></listitem>
<listitem><para>The <literal>libseccomp</literal> is used to provide
syscall filtering on Linux. This is an optional dependency and can
be disabled passing a <option>--disable-seccomp-sandboxing</option>
option to the <command>configure</command> script (Not recommended
unless your system doesn't support
<literal>libseccomp</literal>). To get the library, visit <link
xlink:href="https://github.com/seccomp/libseccomp"
/>.</para></listitem>
</itemizedlist>
</section>

View File

@@ -10,7 +10,7 @@
<itemizedlist>
<listitem><para>Linux (i686, x86_64, aarch64).</para></listitem>
<listitem><para>Linux (i686, x86_64).</para></listitem>
<listitem><para>macOS (x86_64).</para></listitem>

View File

@@ -1,22 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="ch-upgrading-nix">
<title>Upgrading Nix</title>
<para>
Multi-user Nix users on macOS can upgrade Nix by running:
<command>sudo -i sh -c 'nix-channel --update &amp;&amp;
nix-env -iA nixpkgs.nix &amp;&amp;
launchctl remove org.nixos.nix-daemon &amp;&amp;
launchctl load /Library/LaunchDaemons/org.nixos.nix-daemon.plist'</command>
</para>
<para>
Single-user installations of Nix should run this:
<command>nix-channel --update; nix-env -iA nixpkgs.nix</command>
</para>
</chapter>

View File

@@ -60,8 +60,7 @@ This is because tools such as compilers dont search in per-packages
directories such as
<filename>/nix/store/5lbfaxb722zp…-openssl-0.9.8d/include</filename>,
so if a package builds correctly on your system, this is because you
specified the dependency explicitly. This takes care of the build-time
dependencies.</para>
specified the dependency explicitly.</para>
<para>Once a package is built, runtime dependencies are found by
scanning binaries for the hash parts of Nix store paths (such as
@@ -262,6 +261,12 @@ xlink:href="http://nixos.org/">NixOS homepage</link>.</para>
xlink:href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">GNU
LGPLv2.1 or (at your option) any later version</link>.</para>
<para>Nix uses the <link
xlink:href="https://github.com/arangodb/linenoise-ng">linenoise-ng
library</link>, which has the following license:</para>
<programlisting><xi:include href="../../../src/linenoise/LICENSE" parse="text" /></programlisting>
</simplesect>

View File

@@ -32,7 +32,6 @@
<xi:include href="introduction/introduction.xml" />
<xi:include href="installation/installation.xml" />
<xi:include href="installation/upgrading.xml" />
<xi:include href="packages/package-management.xml" />
<xi:include href="expressions/writing-nix-expressions.xml" />
<xi:include href="advanced-topics/advanced-topics.xml" />

View File

@@ -52,14 +52,6 @@ garbage collector as follows:
<screen>
$ nix-store --gc</screen>
The behaviour of the gargage collector is affected by the <literal>keep-
derivations</literal> (default: true) and <literal>keep-outputs</literal>
(default: false) options in the Nix configuration file. The defaults will ensure
that all derivations that are not build-time dependencies of garbage collector roots
will be collected but that all output paths that are not runtime dependencies
will be collected. (This is usually what you want, but while you are developing
it may make sense to keep outputs to ensure that rebuild times are quick.)
If you are feeling uncertain, you can also first view what files would
be deleted:

View File

@@ -1,183 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<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-s3-substituter">
<title>Serving a Nix store via AWS S3 or S3-compatible Service</title>
<para>Nix has built-in support for storing and fetching store paths
from Amazon S3 and S3 compatible services. This uses the same
<emphasis>binary</emphasis> cache mechanism that Nix usually uses to
fetch prebuilt binaries from <uri>cache.nixos.org</uri>.</para>
<para>The following options can be specified as URL parameters to
the S3 URL:</para>
<variablelist>
<varlistentry><term><literal>profile</literal></term>
<listitem>
<para>
The name of the AWS configuration profile to use. By default
Nix will use the <literal>default</literal> profile.
</para>
</listitem>
</varlistentry>
<varlistentry><term><literal>region</literal></term>
<listitem>
<para>
The region of the S3 bucket. <literal>useast-1</literal> by
default.
</para>
<para>
If your bucket is not in <literal>useast-1</literal>, you
should always explicitly specify the region parameter.
</para>
</listitem>
</varlistentry>
<varlistentry><term><literal>endpoint</literal></term>
<listitem>
<para>
The URL to your S3-compatible service, for when not using
Amazon S3. Do not specify this value if you're using Amazon
S3.
</para>
<note><para>This endpoint must support HTTPS and will use
path-based addressing instead of virtual host based
addressing.</para></note>
</listitem>
</varlistentry>
<varlistentry><term><literal>scheme</literal></term>
<listitem>
<para>
The scheme used for S3 requests, <literal>https</literal>
(default) or <literal>http</literal>. This option allows you to
disable HTTPS for binary caches which don't support it.
</para>
<note><para>HTTPS should be used if the cache might contain
sensitive information.</para></note>
</listitem>
</varlistentry>
</variablelist>
<para>In this example we will use the bucket named
<literal>example-nix-cache</literal>.</para>
<section xml:id="ssec-s3-substituter-anonymous-reads">
<title>Anonymous Reads to your S3-compatible binary cache</title>
<para>If your binary cache is publicly accessible and does not
require authentication, the simplest and easiest way to use Nix with
your S3 compatible binary cache is to use the HTTP URL for that
cache.</para>
<para>For AWS S3 the binary cache URL for example bucket will be
exactly <uri>https://example-nix-cache.s3.amazonaws.com</uri> or
<uri>s3://example-nix-cache</uri>. For S3 compatible binary caches,
consult that cache's documentation.</para>
<para>Your bucket will need the following bucket policy:</para>
<programlisting><![CDATA[
{
"Id": "DirectReads",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowDirectReads",
"Action": [
"s3:GetObject",
"s3:GetBucketLocation"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::example-nix-cache",
"arn:aws:s3:::example-nix-cache/*"
],
"Principal": "*"
}
]
}
]]></programlisting>
</section>
<section xml:id="ssec-s3-substituter-authenticated-reads">
<title>Authenticated Reads to your S3 binary cache</title>
<para>For AWS S3 the binary cache URL for example bucket will be
exactly <uri>s3://example-nix-cache</uri>.</para>
<para>Nix will use the <link
xlink:href="https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html#credentials-default.">default
credential provider chain</link> for authenticating requests to
Amazon S3.</para>
<para>Nix supports authenticated reads from Amazon S3 and S3
compatible binary caches.</para>
<para>Your bucket will need a bucket policy allowing the desired
users to perform the <literal>s3:GetObject</literal> and
<literal>s3:GetBucketLocation</literal> action on all objects in the
bucket. The anonymous policy in <xref
linkend="ssec-s3-substituter-anonymous-reads" /> can be updated to
have a restricted <literal>Principal</literal> to support
this.</para>
</section>
<section xml:id="ssec-s3-substituter-authenticated-writes">
<title>Authenticated Writes to your S3-compatible binary cache</title>
<para>Nix support fully supports writing to Amazon S3 and S3
compatible buckets. The binary cache URL for our example bucket will
be <uri>s3://example-nix-cache</uri>.</para>
<para>Nix will use the <link
xlink:href="https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html#credentials-default.">default
credential provider chain</link> for authenticating requests to
Amazon S3.</para>
<para>Your account will need the following IAM policy to
upload to the cache:</para>
<programlisting><![CDATA[
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "UploadToCache",
"Effect": "Allow",
"Action": [
"s3:AbortMultipartUpload",
"s3:GetBucketLocation",
"s3:GetObject",
"s3:ListBucket",
"s3:ListBucketMultipartUploads",
"s3:ListMultipartUploadParts",
"s3:ListObjects",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::example-nix-cache",
"arn:aws:s3:::example-nix-cache/*"
]
}
]
}
]]></programlisting>
<example><title>Uploading with a specific credential profile for Amazon S3</title>
<para><command>nix copy --to 's3://example-nix-cache?profile=cache-upload&amp;region=eu-west-2' nixpkgs.hello</command></para>
</example>
<example><title>Uploading to an S3-Compatible Binary Cache</title>
<para><command>nix copy --to 's3://example-nix-cache?profile=cache-upload&amp;scheme=https&amp;endpoint=minio.example.com' nixpkgs.hello</command></para>
</example>
</section>
</section>

View File

@@ -15,6 +15,5 @@ packages between machines.</para>
<xi:include href="binary-cache-substituter.xml" />
<xi:include href="copy-closure.xml" />
<xi:include href="ssh-substituter.xml" />
<xi:include href="s3-substituter.xml" />
</chapter>

View File

@@ -12,8 +12,6 @@
</partintro>
-->
<xi:include href="rl-2.2.xml" />
<xi:include href="rl-2.1.xml" />
<xi:include href="rl-2.0.xml" />
<xi:include href="rl-1.11.10.xml" />
<xi:include href="rl-1.11.xml" />

View File

@@ -1,133 +0,0 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="ssec-relnotes-2.1">
<title>Release 2.1 (2018-09-02)</title>
<para>This is primarily a bug fix release. It also reduces memory
consumption in certain situations. In addition, it has the following
new features:</para>
<itemizedlist>
<listitem>
<para>The Nix installer will no longer default to the Multi-User
installation for macOS. You can still <link
linkend="sect-multi-user-installation">instruct the installer to
run in multi-user mode</link>.
</para>
</listitem>
<listitem>
<para>The Nix installer now supports performing a Multi-User
installation for Linux computers which are running systemd. You
can <link
linkend="sect-multi-user-installation">select a Multi-User installation</link> by passing the
<option>--daemon</option> flag to the installer: <command>sh &lt;(curl
https://nixos.org/nix/install) --daemon</command>.
</para>
<para>The multi-user installer cannot handle systems with SELinux.
If your system has SELinux enabled, you can <link
linkend="sect-single-user-installation">force the installer to run
in single-user mode</link>.</para>
</listitem>
<listitem>
<para>New builtin functions:
<literal>builtins.bitAnd</literal>,
<literal>builtins.bitOr</literal>,
<literal>builtins.bitXor</literal>,
<literal>builtins.fromTOML</literal>,
<literal>builtins.concatMap</literal>,
<literal>builtins.mapAttrs</literal>.
</para>
</listitem>
<listitem>
<para>The S3 binary cache store now supports uploading NARs larger
than 5 GiB.</para>
</listitem>
<listitem>
<para>The S3 binary cache store now supports uploading to
S3-compatible services with the <literal>endpoint</literal>
option.</para>
</listitem>
<listitem>
<para>The flag <option>--fallback</option> is no longer required
to recover from disappeared NARs in binary caches.</para>
</listitem>
<listitem>
<para><command>nix-daemon</command> now respects
<option>--store</option>.</para>
</listitem>
<listitem>
<para><command>nix run</command> now respects
<varname>nix-support/propagated-user-env-packages</varname>.</para>
</listitem>
</itemizedlist>
<para>This release has contributions from
Adrien Devresse,
Aleksandr Pashkov,
Alexandre Esteves,
Amine Chikhaoui,
Andrew Dunham,
Asad Saeeduddin,
aszlig,
Ben Challenor,
Ben Gamari,
Benjamin Hipple,
Bogdan Seniuc,
Corey O'Connor,
Daiderd Jordan,
Daniel Peebles,
Daniel Poelzleithner,
Danylo Hlynskyi,
Dmitry Kalinkin,
Domen Kožar,
Doug Beardsley,
Eelco Dolstra,
Erik Arvstedt,
Félix Baylac-Jacqué,
Gleb Peregud,
Graham Christensen,
Guillaume Maudoux,
Ivan Kozik,
John Arnold,
Justin Humm,
Linus Heckemann,
Lorenzo Manacorda,
Matthew Justin Bauer,
Matthew O'Gorman,
Maximilian Bosch,
Michael Bishop,
Michael Fiano,
Michael Mercier,
Michael Raskin,
Michael Weiss,
Nicolas Dudebout,
Peter Simons,
Ryan Trinkle,
Samuel Dionne-Riel,
Sean Seefried,
Shea Levy,
Symphorien Gibol,
Tim Engler,
Tim Sears,
Tuomas Tynkkynen,
volth,
Will Dietz,
Yorick van Pelt and
zimbatm.
</para>
</section>

View File

@@ -1,143 +0,0 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="ssec-relnotes-2.2">
<title>Release 2.2 (2019-01-11)</title>
<para>This is primarily a bug fix release. It also has the following
changes:</para>
<itemizedlist>
<listitem>
<para>In derivations that use structured attributes (i.e. that
specify set the <varname>__structuredAttrs</varname> attribute to
<literal>true</literal> to cause all attributes to be passed to
the builder in JSON format), you can now specify closure checks
per output, e.g.:
<programlisting>
outputChecks."out" = {
# The closure of 'out' must not be larger than 256 MiB.
maxClosureSize = 256 * 1024 * 1024;
# It must not refer to C compiler or to the 'dev' output.
disallowedRequisites = [ stdenv.cc "dev" ];
};
outputChecks."dev" = {
# The 'dev' output must not be larger than 128 KiB.
maxSize = 128 * 1024;
};
</programlisting>
</para>
</listitem>
<listitem>
<para>The derivation attribute
<varname>requiredSystemFeatures</varname> is now enforced for
local builds, and not just to route builds to remote builders.
The supported features of a machine can be specified through the
configuration setting <varname>system-features</varname>.</para>
<para>By default, <varname>system-features</varname> includes
<literal>kvm</literal> if <filename>/dev/kvm</filename>
exists. For compatibility, it also includes the pseudo-features
<literal>nixos-test</literal>, <literal>benchmark</literal> and
<literal>big-parallel</literal> which are used by Nixpkgs to route
builds to particular Hydra build machines.</para>
</listitem>
<listitem>
<para>Sandbox builds are now enabled by default on Linux.</para>
</listitem>
<listitem>
<para>The new command <command>nix doctor</command> shows
potential issues with your Nix installation.</para>
</listitem>
<listitem>
<para>The <literal>fetchGit</literal> builtin function now uses a
caching scheme that puts different remote repositories in distinct
local repositories, rather than a single shared repository. This
may require more disk space but is faster.</para>
</listitem>
<listitem>
<para>The <literal>dirOf</literal> builtin function now works on
relative paths.</para>
</listitem>
<listitem>
<para>Nix now supports <link
xlink:href="https://www.w3.org/TR/SRI/">SRI hashes</link>,
allowing the hash algorithm and hash to be specified in a single
string. For example, you can write:
<programlisting>
import &lt;nix/fetchurl.nix> {
url = https://nixos.org/releases/nix/nix-2.1.3/nix-2.1.3.tar.xz;
hash = "sha256-XSLa0FjVyADWWhFfkZ2iKTjFDda6mMXjoYMXLRSYQKQ=";
};
</programlisting>
instead of
<programlisting>
import &lt;nix/fetchurl.nix> {
url = https://nixos.org/releases/nix/nix-2.1.3/nix-2.1.3.tar.xz;
sha256 = "5d22dad058d5c800d65a115f919da22938c50dd6ba98c5e3a183172d149840a4";
};
</programlisting>
</para>
<para>In fixed-output derivations, the
<varname>outputHashAlgo</varname> attribute is no longer mandatory
if <varname>outputHash</varname> specifies the hash.</para>
<para><command>nix hash-file</command> and <command>nix
hash-path</command> now print hashes in SRI format by
default. They also use SHA-256 by default instead of SHA-512
because that's what we use most of the time in Nixpkgs.</para>
</listitem>
<listitem>
<para>Integers are now 64 bits on all platforms.</para>
</listitem>
<listitem>
<para>The evaluator now prints profiling statistics (enabled via
the <envar>NIX_SHOW_STATS</envar> and
<envar>NIX_COUNT_CALLS</envar> environment variables) in JSON
format.</para>
</listitem>
<listitem>
<para>The option <option>--xml</option> in <command>nix-store
--query</command> has been removed. Instead, there now is an
option <option>--graphml</option> to output the dependency graph
in GraphML format.</para>
</listitem>
<listitem>
<para>All <filename>nix-*</filename> commands are now symlinks to
<filename>nix</filename>. This saves a bit of disk space.</para>
</listitem>
<listitem>
<para><command>nix repl</command> now uses
<literal>libeditline</literal> or
<literal>libreadline</literal>.</para>
</listitem>
</itemizedlist>
</section>

View File

@@ -6,7 +6,9 @@ dist-files += configure config.h.in nix.spec perl/configure
clean-files += Makefile.config
GLOBAL_CXXFLAGS += -I . -I src -I src/libutil -I src/libstore -I src/libmain -I src/libexpr -I src/nix
GLOBAL_CXXFLAGS += -I . -I src -I src/libutil -I src/libstore -I src/libmain -I src/libexpr
$(foreach i, config.h $(call rwildcard, src/lib*, *.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)))

View File

@@ -6,7 +6,6 @@ use Data::Dumper;
use File::Basename;
use File::Path;
use File::Slurp;
use File::Copy;
use JSON::PP;
use LWP::UserAgent;
@@ -55,7 +54,7 @@ sub downloadFile {
my $buildInfo = decode_json(fetch("$evalUrl/job/$jobName", 'application/json'));
my $srcFile = $buildInfo->{buildproducts}->{$productNr}->{path} or die "job '$jobName' lacks product $productNr\n";
my $srcFile = $buildInfo->{buildproducts}->{$productNr}->{path} or die;
$dstName //= basename($srcFile);
my $dstFile = "$releaseDir/" . $dstName;
@@ -76,22 +75,16 @@ sub downloadFile {
write_file("$dstFile.sha256", $sha256_expected);
if (! -e "$dstFile.asc") {
system("gpg2 --detach-sign --armor $dstFile") == 0 or die "unable to sign $dstFile\n";
}
return ($dstFile, $sha256_expected);
}
downloadFile("tarball", "2"); # .tar.bz2
my ($tarball, $tarballHash) = downloadFile("tarball", "3"); # .tar.xz
downloadFile("binaryTarball.i686-linux", "1");
downloadFile("binaryTarball.x86_64-linux", "1");
downloadFile("binaryTarball.aarch64-linux", "1");
downloadFile("binaryTarball.x86_64-darwin", "1");
downloadFile("installerScript", "1");
exit if $version =~ /pre/;
downloadFile("tarball", "2"); # PDF
downloadFile("tarball", "3"); # .tar.bz2
my ($tarball, $tarballHash) = downloadFile("tarball", "4"); # .tar.xz
my ($tarball_i686_linux, $tarball_i686_linux_hash) = downloadFile("binaryTarball.i686-linux", "1");
my ($tarball_x86_64_linux, $tarball_x86_64_linux_hash) = downloadFile("binaryTarball.x86_64-linux", "1");
my ($tarball_aarch64_linux, $tarball_aarch64_linux_hash) = downloadFile("binaryTarball.aarch64-linux", "1");
my ($tarball_x86_64_darwin, $tarball_x86_64_darwin_hash) = downloadFile("binaryTarball.x86_64-darwin", "1");
# Update Nixpkgs in a very hacky way.
system("cd $nixpkgsDir && git pull") == 0 or die;
@@ -151,6 +144,12 @@ system("cd $siteDir && git pull") == 0 or die;
write_file("$siteDir/nix-release.tt",
"[%-\n" .
"latestNixVersion = \"$version\"\n" .
"nix_hash_i686_linux = \"$tarball_i686_linux_hash\"\n" .
"nix_hash_x86_64_linux = \"$tarball_x86_64_linux_hash\"\n" .
"nix_hash_aarch64_linux = \"$tarball_aarch64_linux_hash\"\n" .
"nix_hash_x86_64_darwin = \"$tarball_x86_64_darwin_hash\"\n" .
"-%]\n");
system("cd $siteDir && nix-shell --run 'make nix/install nix/install.sig'") == 0 or die;
system("cd $siteDir && git commit -a -m 'Nix $version released'") == 0 or die;

26
misc/docker/Dockerfile Normal file
View File

@@ -0,0 +1,26 @@
FROM alpine
# Enable HTTPS support in wget.
RUN apk add --update openssl
# Download Nix and install it into the system.
RUN wget -O- https://nixos.org/releases/nix/nix-1.11.14/nix-1.11.14-x86_64-linux.tar.bz2 | bzcat - | tar xf - \
&& addgroup -g 30000 -S nixbld \
&& for i in $(seq 1 30); do adduser -S -D -h /var/empty -g "Nix build user $i" -u $((30000 + i)) -G nixbld nixbld$i ; done \
&& mkdir -m 0755 /nix && USER=root sh nix-*-x86_64-linux/install \
&& ln -s /nix/var/nix/profiles/default/etc/profile.d/nix.sh /etc/profile.d/ \
&& rm -r /nix-*-x86_64-linux \
&& rm -r /var/cache/apk/*
ONBUILD ENV \
ENV=/etc/profile \
PATH=/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt \
NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt
ENV \
ENV=/etc/profile \
PATH=/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt \
NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt \
NIX_PATH=/nix/var/nix/profiles/per-user/root/channels

View File

@@ -2,11 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>OBJC_DISABLE_INITIALIZE_FORK_SAFETY</key>
<string>YES</string>
</dict>
<key>Label</key>
<string>org.nixos.nix-daemon</string>
<key>KeepAlive</key>

View File

@@ -125,7 +125,7 @@ define build-library
$(1)_PATH := $$(_d)/$$($(1)_NAME).a
$$($(1)_PATH): $$($(1)_OBJS) | $$(_d)/
$(trace-ar) $(AR) crs $$@ $$?
$(trace-ar) ar crs $$@ $$?
$(1)_LDFLAGS_USE += $$($(1)_PATH) $$($(1)_LDFLAGS)

View File

@@ -3,47 +3,31 @@
%global nixbld_user "nix-builder-"
%global nixbld_group "nixbld"
# NOTE: BUILD on EL7 requires
# - Centos / RHEL7 software collection repository
# yum install centos-release-scl
#
# - Recent boost backport
# curl https://copr.fedorainfracloud.org/coprs/whosthere/boost/repo/epel-7/whosthere-boost-epel-7.repo -o /etc/yum.repos.d/whosthere-boost-epel-7.repo
#
# Disable documentation generation
# necessary on some platforms
%bcond_without docgen
Summary: The Nix software deployment system
Name: nix
Version: @PACKAGE_VERSION@
Release: 2%{?dist}
License: LGPLv2+
%if 0%{?rhel} && 0%{?rhel} < 7
Group: Applications/System
%endif
URL: http://nixos.org/
Source0: %{name}-%{version}.tar.bz2
%if 0%{?el5}
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
%endif
Requires: curl
Requires: bzip2
Requires: gzip
Requires: xz
BuildRequires: bison
BuildRequires: boost-devel >= 1.60
Requires: libseccomp
BuildRequires: bzip2-devel
# for RHEL <= 7, we need software collections for a C++14 compatible compatible compiler
%if 0%{?rhel}
BuildRequires: devtoolset-7-gcc
BuildRequires: devtoolset-7-gcc-c++
%endif
BuildRequires: flex
BuildRequires: sqlite-devel
BuildRequires: libcurl-devel
BuildRequires: libseccomp-devel
BuildRequires: openssl-devel
BuildRequires: sqlite-devel
BuildRequires: xz-devel
# Hack to make that shitty RPM scanning hack shut up.
Provides: perl(Nix::SSH)
%description
Nix is a purely functional package manager. It allows multiple
@@ -55,6 +39,9 @@ it can be used equally well under other Unix systems.
%package devel
Summary: Development files for %{name}
%if 0%{?rhel} && 0%{?rhel} < 7
Group: Development/Libraries
%endif
Requires: %{name}%{?_isa} = %{version}-%{release}
%description devel
@@ -64,6 +51,9 @@ developing applications that use %{name}.
%package doc
Summary: Documentation files for %{name}
%if 0%{?rhel} && 0%{?rhel} < 7
Group: Documentation
%endif
BuildArch: noarch
Requires: %{name} = %{version}-%{release}
@@ -75,25 +65,20 @@ The %{name}-doc package contains documentation files for %{name}.
%build
%if 0%{?rhel}
source /opt/rh/devtoolset-7/enable
%endif
extraFlags=
# - override docdir so large documentation files are owned by the
# -doc subpackage
# - set localstatedir by hand to the preferred nix value
%configure --localstatedir=/nix/var \
%{!?without_docgen:--disable-doc-gen} \
--docdir=%{_defaultdocdir}/%{name}-doc-%{version} \
$extraFlags
make V=1 %{?_smp_mflags}
make -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES
%install
%if 0%{?rhel}
source /opt/rh/devtoolset-7/enable
%if 0%{?el5}
rm -rf $RPM_BUILD_ROOT
%endif
make DESTDIR=$RPM_BUILD_ROOT install
find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';'
@@ -143,7 +128,6 @@ systemctl start nix-daemon.socket
%endif
%files
%license COPYING
%{_bindir}/nix*
%{_libdir}/*.so
%{_prefix}/libexec/*
@@ -152,11 +136,9 @@ systemctl start nix-daemon.socket
%{_prefix}/lib/systemd/system/nix-daemon.service
%endif
%{_datadir}/nix
#%if ! %{without docgen}
#%{_mandir}/man1/*.1*
#%{_mandir}/man5/*.5*
#%{_mandir}/man8/*.8*
#%endif
%{_mandir}/man1/*.1*
%{_mandir}/man5/*.5*
%{_mandir}/man8/*.8*
%config(noreplace) %{_sysconfdir}/profile.d/nix.sh
%config(noreplace) %{_sysconfdir}/profile.d/nix-daemon.sh
/nix
@@ -165,9 +147,6 @@ systemctl start nix-daemon.socket
%{_includedir}/nix
%{_prefix}/lib/pkgconfig/*.pc
#%if ! %{without docgen}
#%files doc
#%docdir %{_defaultdocdir}/%{name}-doc-%{version}
#%{_defaultdocdir}/%{name}-doc-%{version}
#%endif
%files doc
%docdir %{_defaultdocdir}/%{name}-doc-%{version}
%{_defaultdocdir}/%{name}-doc-%{version}

View File

@@ -1,6 +1,6 @@
makefiles = local.mk
GLOBAL_CXXFLAGS += -g -Wall
GLOBAL_CXXFLAGS += -std=c++14 -g -Wall
-include Makefile.config

View File

@@ -1,4 +1,4 @@
AC_INIT(nix-perl, m4_esyscmd([bash -c "echo -n $(cat ../.version)$VERSION_SUFFIX"]))
AC_INIT(nix-perl, m4_esyscmd([bash -c "echo -n $(cat ../version)$VERSION_SUFFIX"]))
AC_CONFIG_SRCDIR(MANIFEST)
AC_CONFIG_AUX_DIR(../config)

View File

@@ -27,7 +27,7 @@ static ref<Store> store()
static std::shared_ptr<Store> _store;
if (!_store) {
try {
loadConfFile();
settings.loadConfFile();
settings.lockCPU = false;
_store = openStore();
} catch (Error & e) {

View File

@@ -1,11 +1,9 @@
{ pkgs }:
with pkgs;
rec {
# Use "busybox-sandbox-shell" if present,
# if not (legacy) fallback and hope it's sufficient.
sh = pkgs.busybox-sandbox-shell or (busybox.override {
sh = pkgs.busybox-sandbox-shell or (pkgs.busybox.override {
useMusl = true;
enableStatic = true;
enableMinimal = true;
@@ -30,50 +28,9 @@ rec {
});
configureFlags =
[
[ "--disable-init-state"
"--enable-gc"
] ++ lib.optionals stdenv.isLinux [
] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [
"--with-sandbox-shell=${sh}/bin/busybox"
];
tarballDeps =
[ bison
flex
libxml2
libxslt
docbook5
docbook5_xsl
autoconf-archive
autoreconfHook
];
buildDeps =
[ curl
bzip2 xz brotli editline
openssl pkgconfig sqlite boehmgc
boost
# Tests
git
mercurial
]
++ lib.optionals stdenv.isLinux [libseccomp utillinuxMinimal]
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
++ lib.optional (stdenv.isLinux || stdenv.isDarwin)
((aws-sdk-cpp.override {
apis = ["s3" "transfer"];
customMemoryManagement = false;
}).overrideDerivation (args: {
/*
patches = args.patches or [] ++ [ (fetchpatch {
url = https://github.com/edolstra/aws-sdk-cpp/commit/3e07e1f1aae41b4c8b340735ff9e8c735f0c063f.patch;
sha256 = "1pij0v449p166f9l29x7ppzk8j7g9k9mp15ilh5qxp29c7fnvxy2";
}) ];
*/
}));
perlDeps =
[ perl
perlPackages.DBDSQLite
];
}

View File

@@ -1,5 +1,5 @@
{ nix ? builtins.fetchGit ./.
, nixpkgs ? builtins.fetchGit { url = https://github.com/NixOS/nixpkgs-channels.git; ref = "nixos-19.03"; }
, nixpkgs ? builtins.fetchGit https://github.com/NixOS/nixpkgs.git
, officialRelease ? false
, systems ? [ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" ]
}:
@@ -14,22 +14,26 @@ let
tarball =
with pkgs;
with import ./release-common.nix { inherit pkgs; };
releaseTools.sourceTarball {
name = "nix-tarball";
version = builtins.readFile ./.version;
version = builtins.readFile ./version;
versionSuffix = if officialRelease then "" else "pre${toString nix.revCount}_${nix.shortRev}";
src = nix;
inherit officialRelease;
buildInputs = tarballDeps ++ buildDeps;
buildInputs =
[ curl bison flex libxml2 libxslt
bzip2 xz brotli
pkgconfig sqlite libsodium boehmgc
docbook5 docbook5_xsl
autoconf-archive
] ++ lib.optional stdenv.isLinux libseccomp;
configureFlags = "--enable-gc";
postUnpack = ''
(cd $sourceRoot && find . -type f) | cut -c3- > $sourceRoot/.dist-files
cat $sourceRoot/.dist-files
(cd source && find . -type f) | cut -c3- > source/.dist-files
cat source/.dist-files
'';
preConfigure = ''
@@ -55,9 +59,7 @@ let
build = pkgs.lib.genAttrs systems (system:
let pkgs = import nixpkgs { inherit system; }; in
with pkgs;
with import nixpkgs { inherit system; };
with import ./release-common.nix { inherit pkgs; };
@@ -65,15 +67,22 @@ let
name = "nix";
src = tarball;
buildInputs = buildDeps;
buildInputs =
[ curl
bzip2 xz brotli
openssl pkgconfig sqlite boehmgc
preConfigure =
# Copy libboost_context so we don't get all of Boost in our closure.
# https://github.com/NixOS/nixpkgs/issues/45462
''
mkdir -p $out/lib
cp ${boost}/lib/libboost_context* $out/lib
'';
# Tests
git
mercurial
]
++ lib.optional stdenv.isLinux libseccomp
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
++ lib.optional (stdenv.isLinux || stdenv.isDarwin)
(aws-sdk-cpp.override {
apis = ["s3"];
customMemoryManagement = false;
});
configureFlags = configureFlags ++
[ "--sysconfdir=/etc" ];
@@ -82,6 +91,8 @@ let
makeFlags = "profiledir=$(out)/etc/profile.d";
preBuild = "unset NIX_INDENT_MAKE";
installFlags = "sysconfdir=$(out)/etc";
doInstallCheck = true;
@@ -98,7 +109,7 @@ let
src = tarball;
buildInputs =
[ jobs.build.${system} curl bzip2 xz pkgconfig pkgs.perl boost ]
[ (builtins.getAttr system jobs.build) curl bzip2 xz pkgconfig pkgs.perl ]
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium;
configureFlags = ''
@@ -109,6 +120,8 @@ let
enableParallelBuilding = true;
postUnpack = "sourceRoot=$sourceRoot/perl";
preBuild = "unset NIX_INDENT_MAKE";
});
@@ -183,15 +196,21 @@ let
coverage =
with pkgs;
with import ./release-common.nix { inherit pkgs; };
with import nixpkgs { system = "x86_64-linux"; };
releaseTools.coverageAnalysis {
name = "nix-build";
src = tarball;
buildInputs = buildDeps;
buildInputs =
[ curl bzip2 openssl pkgconfig sqlite xz libsodium libseccomp
# These are for "make check" only:
graphviz libxml2 libxslt git mercurial
];
configureFlags = ''
--disable-init-state
'';
dontInstall = false;
@@ -206,14 +225,15 @@ let
};
#rpm_fedora27x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora27x86_64) [ ];
rpm_fedora27i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora27i386) [ "libsodium-devel" ];
rpm_fedora27x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora27x86_64) [ "libsodium-devel" ];
#deb_debian8i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.debian8i386) [ "libsodium-dev" ] [ "libsodium13" ];
#deb_debian8x86_64 = makeDeb_x86_64 (diskImageFunsFun: diskImageFunsFun.debian8x86_64) [ "libsodium-dev" ] [ "libsodium13" ];
#deb_ubuntu1710i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1710i386) [ ] [ "libsodium18" ];
#deb_ubuntu1710x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1710x86_64) [ ] [ "libsodium18" "libboost-context1.62.0" ];
deb_ubuntu1604i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1604i386) [ "libsodium-dev" ] [ "libsodium18" ];
deb_ubuntu1604x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1604x86_64) [ "libsodium-dev" ] [ "libsodium18" ];
# System tests.
@@ -241,7 +261,6 @@ let
{ diskImage = vmTools.diskImages.ubuntu1204x86_64;
}
''
set -x
useradd -m alice
su - alice -c 'tar xf ${binaryTarball.x86_64-linux}/*.tar.*'
mkdir /dest-nix
@@ -250,17 +269,6 @@ let
su - alice -c '_NIX_INSTALLER_TEST=1 ./nix-*/install'
su - alice -c 'nix-store --verify'
su - alice -c 'PAGER= nix-store -qR ${build.x86_64-linux}'
# Check whether 'nix upgrade-nix' works.
cat > /tmp/paths.nix <<EOF
{
x86_64-linux = "${build.x86_64-linux}";
}
EOF
su - alice -c 'nix upgrade-nix -vvv --nix-store-paths-url file:///tmp/paths.nix'
(! [ -L /home/alice/.profile-1-link ])
su - alice -c 'PAGER= nix-store -qR ${build.x86_64-linux}'
mkdir -p $out/nix-support
touch $out/nix-support/hydra-build-products
umount /nix
@@ -278,6 +286,7 @@ let
pkgs.runCommand "eval-nixos" { buildInputs = [ build.x86_64-linux ]; }
''
export NIX_STATE_DIR=$TMPDIR
nix-store --init
nix-instantiate ${nixpkgs}/nixos/release-combined.nix -A tested --dry-run \
--arg nixpkgs '{ outPath = ${nixpkgs}; revCount = 123; shortRev = "abcdefgh"; }'
@@ -286,24 +295,6 @@ let
'';
installerScript =
pkgs.runCommand "installer-script"
{ buildInputs = [ build.x86_64-linux ];
}
''
mkdir -p $out/nix-support
substitute ${./scripts/install.in} $out/install \
${pkgs.lib.concatMapStrings
(system: "--replace '@binaryTarball_${system}@' $(nix hash-file --base16 --type sha256 ${binaryTarball.${system}}/*.tar.bz2) ")
[ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" ]
} \
--replace '@nixVersion@' ${build.x86_64-linux.src.version}
echo "file installer $out/install" >> $out/nix-support/hydra-build-products
'';
# Aggregate job containing the release-critical jobs.
release = pkgs.releaseTools.aggregate {
name = "nix-${tarball.version}";
@@ -313,17 +304,14 @@ let
build.i686-linux
build.x86_64-darwin
build.x86_64-linux
build.aarch64-linux
binaryTarball.i686-linux
binaryTarball.x86_64-darwin
binaryTarball.x86_64-linux
binaryTarball.aarch64-linux
tests.remoteBuilds
tests.nix-copy-closure
tests.binaryTarball
tests.evalNixpkgs
tests.evalNixOS
installerScript
];
};
@@ -343,7 +331,7 @@ let
src = jobs.tarball;
diskImage = (diskImageFun vmTools.diskImageFuns)
{ extraPackages =
[ "sqlite" "sqlite-devel" "bzip2-devel" "libcurl-devel" "openssl-devel" "xz-devel" "libseccomp-devel" "libsodium-devel" "boost-devel" "bison" "flex" ]
[ "sqlite" "sqlite-devel" "bzip2-devel" "libcurl-devel" "openssl-devel" "xz-devel" "libseccomp-devel" ]
++ extraPackages; };
# At most 2047MB can be simulated in qemu-system-i386
memSize = 2047;
@@ -366,9 +354,9 @@ let
src = jobs.tarball;
diskImage = (diskImageFun vmTools.diskImageFuns)
{ extraPackages =
[ "libsqlite3-dev" "libbz2-dev" "libcurl-dev" "libcurl3-nss" "libssl-dev" "liblzma-dev" "libseccomp-dev" "libsodium-dev" "libboost-all-dev" ]
[ "libsqlite3-dev" "libbz2-dev" "libcurl-dev" "libcurl3-nss" "libssl-dev" "liblzma-dev" "libseccomp-dev" ]
++ extraPackages; };
memSize = 2047;
memSize = 1024;
meta.schedulingPriority = 50;
postInstall = "make installcheck";
configureFlags = "--sysconfdir=/etc";

View File

@@ -674,6 +674,9 @@ $NIX_INSTALLED_NIX.
EOF
fi
_sudo "to initialize the Nix Database" \
$NIX_INSTALLED_NIX/bin/nix-store --init
cat ./.reginfo \
| _sudo "to load data for the first time in to the Nix Database" \
"$NIX_INSTALLED_NIX/bin/nix-store" --load-db
@@ -724,17 +727,11 @@ setup_default_profile() {
_sudo "to installing a bootstrapping Nix in to the default Profile" \
HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_NIX"
if [ -z "${NIX_SSL_CERT_FILE:-}" ] || ! [ -f "${NIX_SSL_CERT_FILE:-}" ]; then
_sudo "to installing a bootstrapping SSL certificate just for Nix in to the default Profile" \
HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_CACERT"
export NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt
fi
_sudo "to installing a bootstrapping SSL certificate just for Nix in to the default Profile" \
HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_CACERT"
# Have to explicitly pass NIX_SSL_CERT_FILE as part of the sudo call,
# otherwise it will be lost in environments where sudo doesn't pass
# all the environment variables by default.
_sudo "to update the default channel in the default profile" \
HOME="$ROOT_HOME" NIX_SSL_CERT_FILE="$NIX_SSL_CERT_FILE" "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs
HOME="$ROOT_HOME" NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs
}
@@ -744,6 +741,7 @@ build-users-group = $NIX_BUILD_GROUP_NAME
max-jobs = $NIX_USER_COUNT
cores = 1
sandbox = false
EOF
_sudo "to place the default nix daemon configuration (part 2)" \
install -m 0664 "$SCRATCH/nix.conf" /etc/nix/nix.conf

View File

@@ -30,14 +30,15 @@ if [ "$(uname -s)" = "Darwin" ]; then
fi
fi
# Determine if we could use the multi-user installer or not
# Determine if we should punt to the single-user installer or not
if [ "$(uname -s)" = "Darwin" ]; then
echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2
INSTALL_MODE=daemon
elif [ "$(uname -s)" = "Linux" ] && [ -e /run/systemd/system ]; then
echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2
INSTALL_MODE=no-daemon
else
INSTALL_MODE=no-daemon
fi
INSTALL_MODE=no-daemon
# Trivially handle the --daemon / --no-daemon options
if [ "x${1:-}" = "x--no-daemon" ]; then
INSTALL_MODE=no-daemon
@@ -46,18 +47,14 @@ elif [ "x${1:-}" = "x--daemon" ]; then
elif [ "x${1:-}" != "x" ]; then
(
echo "Nix Installer [--daemon|--no-daemon]"
echo "Choose installation method."
echo ""
echo " --daemon: Installs and configures a background daemon that manages the store,"
echo " providing multi-user support and better isolation for local builds."
echo " Both for security and reproducibility, this method is recommended if"
echo " supported on your platform."
echo " See https://nixos.org/nix/manual/#sect-multi-user-installation"
echo " --daemon: Force the installer to use the Daemon"
echo " based installer, even though it may not"
echo " work."
echo ""
echo " --no-daemon: Simple, single-user installation that does not require root and is"
echo " trivial to uninstall."
echo " (default)"
echo " --no-daemon: Force a no-daemon, single-user"
echo " installation even when the preferred"
echo " method is with the daemon."
echo ""
) >&2
exit
@@ -109,6 +106,12 @@ for i in $(cd "$self/store" >/dev/null && echo ./*); do
done
echo "" >&2
echo "initialising Nix database..." >&2
if ! $nix/bin/nix-store --init; then
echo "$0: failed to initialize the Nix database" >&2
exit 1
fi
if ! "$nix/bin/nix-store" --load-db < "$self/.reginfo"; then
echo "$0: unable to register valid paths" >&2
exit 1

View File

@@ -1,67 +0,0 @@
#!/bin/sh
# This script installs the Nix package manager on your system by
# downloading a binary distribution and running its installer script
# (which in turn creates and populates /nix).
{ # Prevent execution if this script was only partially downloaded
oops() {
echo "$0:" "$@" >&2
exit 1
}
tmpDir="$(mktemp -d -t nix-binary-tarball-unpack.XXXXXXXXXX || \
oops "Can't create temporary directory for downloading the Nix binary tarball")"
cleanup() {
rm -rf "$tmpDir"
}
trap cleanup EXIT INT QUIT TERM
require_util() {
type "$1" > /dev/null 2>&1 || command -v "$1" > /dev/null 2>&1 ||
oops "you do not have '$1' installed, which I need to $2"
}
case "$(uname -s).$(uname -m)" in
Linux.x86_64) system=x86_64-linux; hash=@binaryTarball_x86_64-linux@;;
Linux.i?86) system=i686-linux; hash=@binaryTarball_i686-linux@;;
Linux.aarch64) system=aarch64-linux; hash=@binaryTarball_aarch64-linux@;;
Darwin.x86_64) system=x86_64-darwin; hash=@binaryTarball_x86_64-darwin@;;
*) oops "sorry, there is no binary distribution of Nix for your platform";;
esac
url="https://nixos.org/releases/nix/nix-@nixVersion@/nix-@nixVersion@-$system.tar.bz2"
tarball="$tmpDir/$(basename "$tmpDir/nix-@nixVersion@-$system.tar.bz2")"
require_util curl "download the binary tarball"
require_util bzcat "decompress the binary tarball"
require_util tar "unpack the binary tarball"
echo "downloading Nix @nixVersion@ binary tarball for $system from '$url' to '$tmpDir'..."
curl -L "$url" -o "$tarball" || oops "failed to download '$url'"
if type sha256sum > /dev/null 2>&1; then
hash2="$(sha256sum -b "$tarball" | cut -c1-64)"
elif type shasum > /dev/null 2>&1; then
hash2="$(shasum -a 256 -b "$tarball" | cut -c1-64)"
elif type openssl > /dev/null 2>&1; then
hash2="$(openssl dgst -r -sha256 "$tarball" | cut -c1-64)"
else
oops "cannot verify the SHA-256 hash of '$url'; you need one of 'shasum', 'sha256sum', or 'openssl'"
fi
if [ "$hash" != "$hash2" ]; then
oops "SHA-256 hash mismatch in '$url'; expected $hash, got $hash2"
fi
unpack=$tmpDir/unpack
mkdir -p "$unpack"
< "$tarball" bzcat | tar -xf - -C "$unpack" || oops "failed to unpack '$url'"
script=$(echo "$unpack"/*/install)
[ -e "$script" ] || oops "installation script is missing from the binary tarball!"
"$script" "$@"
} # End of wrapping

View File

@@ -1,5 +1,5 @@
# Only execute this file once per shell.
if [ -n "${__ETC_PROFILE_NIX_SOURCED:-}" ]; then return; fi
if [ -n "$__ETC_PROFILE_NIX_SOURCED" ]; then return; fi
__ETC_PROFILE_NIX_SOURCED=1
# Set up secure multi-user builds: non-root users build through the
@@ -49,26 +49,6 @@ if test -w $HOME; then
fi
fi
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
if [ ! -z "${NIX_SSL_CERT_FILE:-}" ]; then
: # Allow users to override the NIX_SSL_CERT_FILE
elif [ -e /etc/ssl/certs/ca-certificates.crt ]; then # NixOS, Ubuntu, Debian, Gentoo, Arch
export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
elif [ -e /etc/ssl/ca-bundle.pem ]; then # openSUSE Tumbleweed
export NIX_SSL_CERT_FILE=/etc/ssl/ca-bundle.pem
elif [ -e /etc/ssl/certs/ca-bundle.crt ]; then # Old NixOS
export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt
elif [ -e /etc/pki/tls/certs/ca-bundle.crt ]; then # Fedora, CentOS
export NIX_SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt
else
# Fall back to what is in the nix profiles, favouring whatever is defined last.
for i in $NIX_PROFILES; do
if [ -e $i/etc/ssl/certs/ca-bundle.crt ]; then
export NIX_SSL_CERT_FILE=$i/etc/ssl/certs/ca-bundle.crt
fi
done
fi
export NIX_PATH="nixpkgs=@localstatedir@/nix/profiles/per-user/root/channels/nixpkgs:@localstatedir@/nix/profiles/per-user/root/channels"
export PATH="$HOME/.nix-profile/bin:@localstatedir@/nix/profiles/default/bin:$PATH"
export NIX_SSL_CERT_FILE="@localstatedir@/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
export NIX_PATH="@localstatedir@/nix/profiles/per-user/root/channels"
export PATH="$HOME/.nix-profile/bin:$HOME/.nix-profile/lib/kde4/libexec:@localstatedir@/nix/profiles/default/bin:@localstatedir@/nix/profiles/default:@localstatedir@/nix/profiles/default/lib/kde4/libexec:$PATH"

View File

@@ -75,7 +75,7 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then
export NIX_SSL_CERT_FILE="$NIX_LINK/etc/ca-bundle.crt"
fi
if [ -n "${MANPATH-}" ]; then
if [ -n "${MANPATH}" ]; then
export MANPATH="$NIX_LINK/share/man:$MANPATH"
fi

View File

@@ -1,13 +1,33 @@
{ useClang ? false }:
with import (builtins.fetchGit { url = https://github.com/NixOS/nixpkgs-channels.git; ref = "nixos-19.03"; }) {};
with import <nixpkgs> {};
with import ./release-common.nix { inherit pkgs; };
(if useClang then clangStdenv else stdenv).mkDerivation {
name = "nix";
buildInputs = buildDeps ++ tarballDeps ++ perlDeps;
buildInputs =
[ curl bison flex libxml2 libxslt
bzip2 xz brotli
pkgconfig sqlite libsodium boehmgc
docbook5 docbook5_xsl
autoconf-archive
(aws-sdk-cpp.override {
apis = ["s3"];
customMemoryManagement = false;
})
autoreconfHook
# For nix-perl
perl
perlPackages.DBDSQLite
# Tests
git
mercurial
]
++ lib.optional stdenv.isLinux libseccomp;
inherit configureFlags;

38
src/boost/assert.hpp Normal file
View File

@@ -0,0 +1,38 @@
//
// boost/assert.hpp - BOOST_ASSERT(expr)
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// Note: There are no include guards. This is intentional.
//
// See http://www.boost.org/libs/utility/assert.html for documentation.
//
#undef BOOST_ASSERT
#if defined(BOOST_DISABLE_ASSERTS)
# define BOOST_ASSERT(expr) ((void)0)
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
#include <boost/current_function.hpp>
namespace boost
{
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
} // namespace boost
#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#else
# include <assert.h>
# define BOOST_ASSERT(expr) assert(expr)
#endif

64
src/boost/format.hpp Normal file
View File

@@ -0,0 +1,64 @@
// -*- C++ -*-
// Boost general library 'format' ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rüdiger Loos's format class
// and Karl Nelson's ofstream
// ----------------------------------------------------------------------------
// format.hpp : primary header
// ----------------------------------------------------------------------------
#ifndef BOOST_FORMAT_HPP
#define BOOST_FORMAT_HPP
#include <vector>
#include <string>
#include <sstream>
#include <cassert>
#if HAVE_LOCALE
#include <locale>
#else
#define BOOST_NO_STD_LOCALE
#define BOOST_NO_LOCALE_ISIDIGIT
#include <cctype>
#endif
#include <boost/format/macros_default.hpp>
// **** Forward declarations ----------------------------------
#include <boost/format/format_fwd.hpp> // basic_format<Ch,Tr>, and other frontends
#include <boost/format/internals_fwd.hpp> // misc forward declarations for internal use
// **** Auxiliary structs (stream_format_state<Ch,Tr> , and format_item<Ch,Tr> )
#include <boost/format/internals.hpp>
// **** Format class interface --------------------------------
#include <boost/format/format_class.hpp>
// **** Exceptions -----------------------------------------------
#include <boost/format/exceptions.hpp>
// **** Implementation -------------------------------------------
//#include <boost/format/format_implementation.hpp> // member functions
#include <boost/format/group.hpp> // class for grouping arguments
#include <boost/format/feed_args.hpp> // argument-feeding functions
//#include <boost/format/parsing.hpp> // format-string parsing (member-)functions
// **** Implementation of the free functions ----------------------
//#include <boost/format/free_funcs.hpp>
#endif // BOOST_FORMAT_HPP

View File

@@ -0,0 +1,96 @@
// -*- C++ -*-
// Boost general library 'format' ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rüdiger Loos's format class
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
// ------------------------------------------------------------------------------
// exceptions.hpp
// ------------------------------------------------------------------------------
#ifndef BOOST_FORMAT_EXCEPTIONS_HPP
#define BOOST_FORMAT_EXCEPTIONS_HPP
#include <stdexcept>
namespace boost {
namespace io {
// **** exceptions -----------------------------------------------
class format_error : public std::exception
{
public:
format_error() { abort(); }
virtual const char *what() const throw()
{
return "boost::format_error: "
"format generic failure";
}
};
class bad_format_string : public format_error
{
public:
bad_format_string() { abort(); }
virtual const char *what() const throw()
{
return "boost::bad_format_string: "
"format-string is ill-formed";
}
};
class too_few_args : public format_error
{
public:
too_few_args() { abort(); }
virtual const char *what() const throw()
{
return "boost::too_few_args: "
"format-string refered to more arguments than were passed";
}
};
class too_many_args : public format_error
{
public:
too_many_args() { abort(); }
virtual const char *what() const throw()
{
return "boost::too_many_args: "
"format-string refered to less arguments than were passed";
}
};
class out_of_range : public format_error
{
public:
out_of_range() { abort(); }
virtual const char *what() const throw()
{
return "boost::out_of_range: "
"tried to refer to an argument (or item) number which is out of range, "
"according to the format string.";
}
};
} // namespace io
} // namespace boost
#endif // BOOST_FORMAT_EXCEPTIONS_HPP

View File

@@ -0,0 +1,254 @@
// -*- C++ -*-
// Boost general library 'format' ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rüdiger Loos's format class
// and Karl Nelson's ofstream
// ----------------------------------------------------------------------------
// feed_args.hpp : functions for processing each argument
// (feed, feed_manip, and distribute)
// ----------------------------------------------------------------------------
#ifndef BOOST_FORMAT_FEED_ARGS_HPP
#define BOOST_FORMAT_FEED_ARGS_HPP
#include "boost/format/format_class.hpp"
#include "boost/format/group.hpp"
#include "boost/throw_exception.hpp"
namespace boost {
namespace io {
namespace detail {
namespace {
inline
void empty_buf(BOOST_IO_STD ostringstream & os) {
static const std::string emptyStr;
os.str(emptyStr);
}
void do_pad( std::string & s,
std::streamsize w,
const char c,
std::ios::fmtflags f,
bool center)
__attribute__ ((unused));
void do_pad( std::string & s,
std::streamsize w,
const char c,
std::ios::fmtflags f,
bool center)
// applies centered / left / right padding to the string s.
// Effects : string s is padded.
{
std::streamsize n=w-s.size();
if(n<=0) {
return;
}
if(center)
{
s.reserve(w); // allocate once for the 2 inserts
const std::streamsize n1 = n /2, n0 = n - n1;
s.insert(s.begin(), n0, c);
s.append(n1, c);
}
else
{
if(f & std::ios::left) {
s.append(n, c);
}
else {
s.insert(s.begin(), n, c);
}
}
} // -do_pad(..)
template<class T> inline
void put_head(BOOST_IO_STD ostream& , const T& ) {
}
template<class T> inline
void put_head( BOOST_IO_STD ostream& os, const group1<T>& x ) {
os << group_head(x.a1_); // send the first N-1 items, not the last
}
template<class T> inline
void put_last( BOOST_IO_STD ostream& os, const T& x ) {
os << x ;
}
template<class T> inline
void put_last( BOOST_IO_STD ostream& os, const group1<T>& x ) {
os << group_last(x.a1_); // this selects the last element
}
#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST
template<class T> inline
void put_head( BOOST_IO_STD ostream& , T& ) {
}
template<class T> inline
void put_last( BOOST_IO_STD ostream& os, T& x ) {
os << x ;
}
#endif
template<class T>
void put( T x,
const format_item& specs,
std::string & res,
BOOST_IO_STD ostringstream& oss_ )
{
// does the actual conversion of x, with given params, into a string
// using the *supplied* strinstream. (the stream state is important)
typedef std::string string_t;
typedef format_item format_item_t;
stream_format_state prev_state(oss_);
specs.state_.apply_on(oss_);
// in case x is a group, apply the manip part of it,
// in order to find width
put_head( oss_, x );
empty_buf( oss_);
const std::streamsize w=oss_.width();
const std::ios::fmtflags fl=oss_.flags();
const bool internal = (fl & std::ios::internal) != 0;
const bool two_stepped_padding = internal
&& ! ( specs.pad_scheme_ & format_item_t::spacepad )
&& specs.truncate_ < 0 ;
if(! two_stepped_padding)
{
if(w>0) // handle simple padding via do_pad, not natively in stream
oss_.width(0);
put_last( oss_, x);
res = oss_.str();
if (specs.truncate_ >= 0)
res.erase(specs.truncate_);
// complex pads :
if(specs.pad_scheme_ & format_item_t::spacepad)
{
if( res.size()==0 || ( res[0]!='+' && res[0]!='-' ))
{
res.insert(res.begin(), 1, ' '); // insert 1 space at pos 0
}
}
if(w > 0) // need do_pad
{
do_pad(res,w,oss_.fill(), fl, (specs.pad_scheme_ & format_item_t::centered) !=0 );
}
}
else // 2-stepped padding
{
put_last( oss_, x); // oss_.width() may result in padding.
res = oss_.str();
if (specs.truncate_ >= 0)
res.erase(specs.truncate_);
if( res.size() - w > 0)
{ // length w exceeded
// either it was multi-output with first output padding up all width..
// either it was one big arg and we are fine.
empty_buf( oss_);
oss_.width(0);
put_last(oss_, x );
string_t tmp = oss_.str(); // minimal-length output
std::streamsize d;
if( (d=w - tmp.size()) <=0 )
{
// minimal length is already >= w, so no padding (cool!)
res.swap(tmp);
}
else
{ // hum.. we need to pad (it was necessarily multi-output)
typedef typename string_t::size_type size_type;
size_type i = 0;
while( i<tmp.size() && tmp[i] == res[i] ) // find where we should pad.
++i;
tmp.insert(i, static_cast<size_type>( d ), oss_.fill());
res.swap( tmp );
}
}
else
{ // okay, only one thing was printed and padded, so res is fine.
}
}
prev_state.apply_on(oss_);
empty_buf( oss_);
oss_.clear();
} // end- put(..)
} // local namespace
template<class T>
void distribute(basic_format& self, T x)
// call put(x, ..) on every occurence of the current argument :
{
if(self.cur_arg_ >= self.num_args_)
{
if( self.exceptions() & too_many_args_bit )
boost::throw_exception(too_many_args()); // too many variables have been supplied !
else return;
}
for(unsigned long i=0; i < self.items_.size(); ++i)
{
if(self.items_[i].argN_ == self.cur_arg_)
{
put<T> (x, self.items_[i], self.items_[i].res_, self.oss_ );
}
}
}
template<class T>
basic_format& feed(basic_format& self, T x)
{
if(self.dumped_) self.clear();
distribute<T> (self, x);
++self.cur_arg_;
if(self.bound_.size() != 0)
{
while( self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_] )
++self.cur_arg_;
}
// this arg is finished, reset the stream's format state
self.state0_.apply_on(self.oss_);
return self;
}
} // namespace detail
} // namespace io
} // namespace boost
#endif // BOOST_FORMAT_FEED_ARGS_HPP

View File

@@ -0,0 +1,135 @@
// -*- C++ -*-
// Boost general library 'format' ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rüdiger Loos's format class
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
// ------------------------------------------------------------------------------
// format_class.hpp : class interface
// ------------------------------------------------------------------------------
#ifndef BOOST_FORMAT_CLASS_HPP
#define BOOST_FORMAT_CLASS_HPP
#include <vector>
#include <string>
#include <boost/format/format_fwd.hpp>
#include <boost/format/internals_fwd.hpp>
#include <boost/format/internals.hpp>
namespace boost {
class basic_format
{
public:
typedef std::string string_t;
typedef BOOST_IO_STD ostringstream internal_stream_t;
private:
typedef BOOST_IO_STD ostream stream_t;
typedef io::detail::stream_format_state stream_format_state;
typedef io::detail::format_item format_item_t;
public:
basic_format(const char* str);
basic_format(const string_t& s);
#ifndef BOOST_NO_STD_LOCALE
basic_format(const char* str, const std::locale & loc);
basic_format(const string_t& s, const std::locale & loc);
#endif // no locale
basic_format(const basic_format& x);
basic_format& operator= (const basic_format& x);
basic_format& clear(); // empty the string buffers (except bound arguments, see clear_binds() )
// pass arguments through those operators :
template<class T> basic_format& operator%(const T& x)
{
return io::detail::feed<const T&>(*this,x);
}
#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST
template<class T> basic_format& operator%(T& x)
{
return io::detail::feed<T&>(*this,x);
}
#endif
// system for binding arguments :
template<class T>
basic_format& bind_arg(int argN, const T& val)
{
return io::detail::bind_arg_body(*this, argN, val);
}
basic_format& clear_bind(int argN);
basic_format& clear_binds();
// modify the params of a directive, by applying a manipulator :
template<class T>
basic_format& modify_item(int itemN, const T& manipulator)
{
return io::detail::modify_item_body(*this, itemN, manipulator) ;
}
// Choosing which errors will throw exceptions :
unsigned char exceptions() const;
unsigned char exceptions(unsigned char newexcept);
// final output
string_t str() const;
friend BOOST_IO_STD ostream&
operator<< ( BOOST_IO_STD ostream& , const basic_format& );
template<class T> friend basic_format&
io::detail::feed(basic_format&, T);
template<class T> friend
void io::detail::distribute(basic_format&, T);
template<class T> friend
basic_format& io::detail::modify_item_body(basic_format&, int, const T&);
template<class T> friend
basic_format& io::detail::bind_arg_body(basic_format&, int, const T&);
// make the members private only if the friend templates are supported
private:
// flag bits, used for style_
enum style_values { ordered = 1, // set only if all directives are positional directives
special_needs = 4 };
// parse the format string :
void parse(const string_t&);
int style_; // style of format-string : positional or not, etc
int cur_arg_; // keep track of wich argument will come
int num_args_; // number of expected arguments
mutable bool dumped_; // true only after call to str() or <<
std::vector<format_item_t> items_; // vector of directives (aka items)
string_t prefix_; // piece of string to insert before first item
std::vector<bool> bound_; // stores which arguments were bound
// size = num_args OR zero
internal_stream_t oss_; // the internal stream.
stream_format_state state0_; // reference state for oss_
unsigned char exceptions_;
}; // class basic_format
} // namespace boost
#endif // BOOST_FORMAT_CLASS_HPP

View File

@@ -0,0 +1,49 @@
// -*- C++ -*-
// Boost general library 'format' ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rüdiger Loos's format class
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
// ------------------------------------------------------------------------------
// format_fwd.hpp : forward declarations, for primary header format.hpp
// ------------------------------------------------------------------------------
#ifndef BOOST_FORMAT_FWD_HPP
#define BOOST_FORMAT_FWD_HPP
#include <string>
#include <iosfwd>
namespace boost {
class basic_format;
typedef basic_format format;
namespace io {
enum format_error_bits { bad_format_string_bit = 1,
too_few_args_bit = 2, too_many_args_bit = 4,
out_of_range_bit = 8,
all_error_bits = 255, no_error_bits=0 };
// Convertion: format to string
std::string str(const basic_format& ) ;
} // namespace io
BOOST_IO_STD ostream&
operator<<( BOOST_IO_STD ostream&, const basic_format&);
} // namespace boost
#endif // BOOST_FORMAT_FWD_HPP

View File

@@ -0,0 +1,256 @@
// -*- C++ -*-
// Boost general library format ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rüdiger Loos's format class
// and Karl Nelson's ofstream
// ----------------------------------------------------------------------------
// format_implementation.hpp Implementation of the basic_format class
// ----------------------------------------------------------------------------
#ifndef BOOST_FORMAT_IMPLEMENTATION_HPP
#define BOOST_FORMAT_IMPLEMENTATION_HPP
#include <boost/throw_exception.hpp>
#include <boost/assert.hpp>
#include <boost/format.hpp>
namespace boost {
// -------- format:: -------------------------------------------
basic_format::basic_format(const char* str)
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
items_(), oss_(), exceptions_(io::all_error_bits)
{
state0_.set_by_stream(oss_);
string_t emptyStr;
if( !str) str = emptyStr.c_str();
parse( str );
}
#ifndef BOOST_NO_STD_LOCALE
basic_format::basic_format(const char* str, const std::locale & loc)
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
items_(), oss_(), exceptions_(io::all_error_bits)
{
oss_.imbue( loc );
state0_.set_by_stream(oss_);
string_t emptyStr;
if( !str) str = emptyStr.c_str();
parse( str );
}
basic_format::basic_format(const string_t& s, const std::locale & loc)
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
items_(), oss_(), exceptions_(io::all_error_bits)
{
oss_.imbue( loc );
state0_.set_by_stream(oss_);
parse(s);
}
#endif //BOOST_NO_STD_LOCALE
basic_format::basic_format(const string_t& s)
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
items_(), oss_(), exceptions_(io::all_error_bits)
{
state0_.set_by_stream(oss_);
parse(s);
}
basic_format:: basic_format(const basic_format& x)
: style_(x.style_), cur_arg_(x.cur_arg_), num_args_(x.num_args_), dumped_(false),
items_(x.items_), prefix_(x.prefix_), bound_(x.bound_),
oss_(), // <- we obviously can't copy x.oss_
state0_(x.state0_), exceptions_(x.exceptions_)
{
state0_.apply_on(oss_);
}
basic_format& basic_format::operator= (const basic_format& x)
{
if(this == &x)
return *this;
state0_ = x.state0_;
state0_.apply_on(oss_);
// plus all the other (trivial) assignments :
exceptions_ = x.exceptions_;
items_ = x.items_;
prefix_ = x.prefix_;
bound_=x.bound_;
style_=x.style_;
cur_arg_=x.cur_arg_;
num_args_=x.num_args_;
dumped_=x.dumped_;
return *this;
}
unsigned char basic_format::exceptions() const
{
return exceptions_;
}
unsigned char basic_format::exceptions(unsigned char newexcept)
{
unsigned char swp = exceptions_;
exceptions_ = newexcept;
return swp;
}
basic_format& basic_format ::clear()
// empty the string buffers (except bound arguments, see clear_binds() )
// and make the format object ready for formatting a new set of arguments
{
BOOST_ASSERT( bound_.size()==0 || num_args_ == static_cast<int>(bound_.size()) );
for(unsigned long i=0; i<items_.size(); ++i){
items_[i].state_ = items_[i].ref_state_;
// clear converted strings only if the corresponding argument is not bound :
if( bound_.size()==0 || !bound_[ items_[i].argN_ ] ) items_[i].res_.resize(0);
}
cur_arg_=0; dumped_=false;
// maybe first arg is bound:
if(bound_.size() != 0)
{
while(cur_arg_ < num_args_ && bound_[cur_arg_] ) ++cur_arg_;
}
return *this;
}
basic_format& basic_format ::clear_binds()
// cancel all bindings, and clear()
{
bound_.resize(0);
clear();
return *this;
}
basic_format& basic_format::clear_bind(int argN)
// cancel the binding of ONE argument, and clear()
{
if(argN<1 || argN > num_args_ || bound_.size()==0 || !bound_[argN-1] )
{
if( exceptions() & io::out_of_range_bit )
boost::throw_exception(io::out_of_range()); // arg not in range.
else return *this;
}
bound_[argN-1]=false;
clear();
return *this;
}
std::string basic_format::str() const
{
dumped_=true;
if(items_.size()==0)
return prefix_;
if( cur_arg_ < num_args_)
if( exceptions() & io::too_few_args_bit )
boost::throw_exception(io::too_few_args()); // not enough variables have been supplied !
unsigned long sz = prefix_.size();
unsigned long i;
for(i=0; i < items_.size(); ++i)
sz += items_[i].res_.size() + items_[i].appendix_.size();
string_t res;
res.reserve(sz);
res += prefix_;
for(i=0; i < items_.size(); ++i)
{
const format_item_t& item = items_[i];
res += item.res_;
if( item.argN_ == format_item_t::argN_tabulation)
{
BOOST_ASSERT( item.pad_scheme_ & format_item_t::tabulation);
std::streamsize n = item.state_.width_ - res.size();
if( n > 0 )
res.append( n, item.state_.fill_ );
}
res += item.appendix_;
}
return res;
}
namespace io {
namespace detail {
template<class T>
basic_format& bind_arg_body( basic_format& self,
int argN,
const T& val)
// bind one argument to a fixed value
// this is persistent over clear() calls, thus also over str() and <<
{
if(self.dumped_) self.clear(); // needed, because we will modify cur_arg_..
if(argN<1 || argN > self.num_args_)
{
if( self.exceptions() & io::out_of_range_bit )
boost::throw_exception(io::out_of_range()); // arg not in range.
else return self;
}
if(self.bound_.size()==0)
self.bound_.assign(self.num_args_,false);
else
BOOST_ASSERT( self.num_args_ == static_cast<signed int>(self.bound_.size()) );
int o_cur_arg = self.cur_arg_;
self.cur_arg_ = argN-1; // arrays begin at 0
self.bound_[self.cur_arg_]=false; // if already set, we unset and re-sets..
self.operator%(val); // put val at the right place, because cur_arg is set
// Now re-position cur_arg before leaving :
self.cur_arg_ = o_cur_arg;
self.bound_[argN-1]=true;
if(self.cur_arg_ == argN-1 )
// hum, now this arg is bound, so move to next free arg
{
while(self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_]) ++self.cur_arg_;
}
// In any case, we either have all args, or are on a non-binded arg :
BOOST_ASSERT( self.cur_arg_ >= self.num_args_ || ! self.bound_[self.cur_arg_]);
return self;
}
template<class T>
basic_format& modify_item_body( basic_format& self,
int itemN,
const T& manipulator)
// applies a manipulator to the format_item describing a given directive.
// this is a permanent change, clear or clear_binds won't cancel that.
{
if(itemN<1 || itemN >= static_cast<signed int>(self.items_.size() ))
{
if( self.exceptions() & io::out_of_range_bit )
boost::throw_exception(io::out_of_range()); // item not in range.
else return self;
}
self.items_[itemN-1].ref_state_.apply_manip( manipulator );
self.items_[itemN-1].state_ = self.items_[itemN-1].ref_state_;
return self;
}
} // namespace detail
} // namespace io
} // namespace boost
#endif // BOOST_FORMAT_IMPLEMENTATION_HPP

View File

@@ -0,0 +1,71 @@
// -*- C++ -*-
// Boost general library 'format' ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rüdiger Loos's format class
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
// ------------------------------------------------------------------------------
// free_funcs.hpp : implementation of the free functions declared in namespace format
// ------------------------------------------------------------------------------
#ifndef BOOST_FORMAT_FUNCS_HPP
#define BOOST_FORMAT_FUNCS_HPP
#include "boost/format.hpp"
#include "boost/throw_exception.hpp"
namespace boost {
namespace io {
inline
std::string str(const basic_format& f)
// adds up all pieces of strings and converted items, and return the formatted string
{
return f.str();
}
} // - namespace io
BOOST_IO_STD ostream&
operator<<( BOOST_IO_STD ostream& os,
const boost::basic_format& f)
// effect: "return os << str(f);" but we can try to do it faster
{
typedef boost::basic_format format_t;
if(f.items_.size()==0)
os << f.prefix_;
else {
if(f.cur_arg_ < f.num_args_)
if( f.exceptions() & io::too_few_args_bit )
boost::throw_exception(io::too_few_args()); // not enough variables have been supplied !
if(f.style_ & format_t::special_needs)
os << f.str();
else {
// else we dont have to count chars output, so we dump directly to os :
os << f.prefix_;
for(unsigned long i=0; i<f.items_.size(); ++i)
{
const format_t::format_item_t& item = f.items_[i];
os << item.res_;
os << item.appendix_;
}
}
}
f.dumped_=true;
return os;
}
} // namespace boost
#endif // BOOST_FORMAT_FUNCS_HPP

680
src/boost/format/group.hpp Normal file
View File

@@ -0,0 +1,680 @@
// -*- C++ -*-
// Boost general library 'format' ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rüdiger Loos's format class
// and Karl Nelson's ofstream
// ----------------------------------------------------------------------------
// group.hpp : encapsulates a group of manipulators along with an argument
//
// group_head : cut the last element of a group out.
// (is overloaded below on each type of group)
// group_last : returns the last element of a group
// (is overloaded below on each type of group)
// ----------------------------------------------------------------------------
#ifndef BOOST_FORMAT_GROUP_HPP
#define BOOST_FORMAT_GROUP_HPP
namespace boost {
namespace io {
namespace detail {
// empty group, but useful even though.
struct group0
{
group0() {}
};
template <class Ch, class Tr>
inline
BOOST_IO_STD ostream&
operator << ( BOOST_IO_STD ostream& os,
const group0& )
{
return os;
}
template <class T1>
struct group1
{
T1 a1_;
group1(T1 a1)
: a1_(a1)
{}
};
template <class Ch, class Tr, class T1>
inline
BOOST_IO_STD ostream&
operator << (BOOST_IO_STD ostream& os,
const group1<T1>& x)
{
os << x.a1_;
return os;
}
template <class T1,class T2>
struct group2
{
T1 a1_;
T2 a2_;
group2(T1 a1,T2 a2)
: a1_(a1),a2_(a2)
{}
};
template <class Ch, class Tr, class T1,class T2>
inline
BOOST_IO_STD ostream&
operator << (BOOST_IO_STD ostream& os,
const group2<T1,T2>& x)
{
os << x.a1_<< x.a2_;
return os;
}
template <class T1,class T2,class T3>
struct group3
{
T1 a1_;
T2 a2_;
T3 a3_;
group3(T1 a1,T2 a2,T3 a3)
: a1_(a1),a2_(a2),a3_(a3)
{}
};
template <class Ch, class Tr, class T1,class T2,class T3>
inline
BOOST_IO_STD ostream&
operator << (BOOST_IO_STD ostream& os,
const group3<T1,T2,T3>& x)
{
os << x.a1_<< x.a2_<< x.a3_;
return os;
}
template <class T1,class T2,class T3,class T4>
struct group4
{
T1 a1_;
T2 a2_;
T3 a3_;
T4 a4_;
group4(T1 a1,T2 a2,T3 a3,T4 a4)
: a1_(a1),a2_(a2),a3_(a3),a4_(a4)
{}
};
template <class Ch, class Tr, class T1,class T2,class T3,class T4>
inline
BOOST_IO_STD ostream&
operator << (BOOST_IO_STD ostream& os,
const group4<T1,T2,T3,T4>& x)
{
os << x.a1_<< x.a2_<< x.a3_<< x.a4_;
return os;
}
template <class T1,class T2,class T3,class T4,class T5>
struct group5
{
T1 a1_;
T2 a2_;
T3 a3_;
T4 a4_;
T5 a5_;
group5(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5)
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5)
{}
};
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5>
inline
BOOST_IO_STD ostream&
operator << (BOOST_IO_STD ostream& os,
const group5<T1,T2,T3,T4,T5>& x)
{
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_;
return os;
}
template <class T1,class T2,class T3,class T4,class T5,class T6>
struct group6
{
T1 a1_;
T2 a2_;
T3 a3_;
T4 a4_;
T5 a5_;
T6 a6_;
group6(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6)
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6)
{}
};
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5,class T6>
inline
BOOST_IO_STD ostream&
operator << (BOOST_IO_STD ostream& os,
const group6<T1,T2,T3,T4,T5,T6>& x)
{
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_;
return os;
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7>
struct group7
{
T1 a1_;
T2 a2_;
T3 a3_;
T4 a4_;
T5 a5_;
T6 a6_;
T7 a7_;
group7(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7)
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7)
{}
};
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5,class T6,class T7>
inline
BOOST_IO_STD ostream&
operator << (BOOST_IO_STD ostream& os,
const group7<T1,T2,T3,T4,T5,T6,T7>& x)
{
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_;
return os;
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8>
struct group8
{
T1 a1_;
T2 a2_;
T3 a3_;
T4 a4_;
T5 a5_;
T6 a6_;
T7 a7_;
T8 a8_;
group8(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8)
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8)
{}
};
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8>
inline
BOOST_IO_STD ostream&
operator << (BOOST_IO_STD ostream& os,
const group8<T1,T2,T3,T4,T5,T6,T7,T8>& x)
{
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_;
return os;
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9>
struct group9
{
T1 a1_;
T2 a2_;
T3 a3_;
T4 a4_;
T5 a5_;
T6 a6_;
T7 a7_;
T8 a8_;
T9 a9_;
group9(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9)
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8),a9_(a9)
{}
};
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9>
inline
BOOST_IO_STD ostream&
operator << (BOOST_IO_STD ostream& os,
const group9<T1,T2,T3,T4,T5,T6,T7,T8,T9>& x)
{
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_<< x.a9_;
return os;
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9,class T10>
struct group10
{
T1 a1_;
T2 a2_;
T3 a3_;
T4 a4_;
T5 a5_;
T6 a6_;
T7 a7_;
T8 a8_;
T9 a9_;
T10 a10_;
group10(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9,T10 a10)
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8),a9_(a9),a10_(a10)
{}
};
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9,class T10>
inline
BOOST_IO_STD ostream&
operator << (BOOST_IO_STD ostream& os,
const group10<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>& x)
{
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_<< x.a9_<< x.a10_;
return os;
}
template <class T1,class T2>
inline
group1<T1>
group_head( group2<T1,T2> const& x)
{
return group1<T1> (x.a1_);
}
template <class T1,class T2>
inline
group1<T2>
group_last( group2<T1,T2> const& x)
{
return group1<T2> (x.a2_);
}
template <class T1,class T2,class T3>
inline
group2<T1,T2>
group_head( group3<T1,T2,T3> const& x)
{
return group2<T1,T2> (x.a1_,x.a2_);
}
template <class T1,class T2,class T3>
inline
group1<T3>
group_last( group3<T1,T2,T3> const& x)
{
return group1<T3> (x.a3_);
}
template <class T1,class T2,class T3,class T4>
inline
group3<T1,T2,T3>
group_head( group4<T1,T2,T3,T4> const& x)
{
return group3<T1,T2,T3> (x.a1_,x.a2_,x.a3_);
}
template <class T1,class T2,class T3,class T4>
inline
group1<T4>
group_last( group4<T1,T2,T3,T4> const& x)
{
return group1<T4> (x.a4_);
}
template <class T1,class T2,class T3,class T4,class T5>
inline
group4<T1,T2,T3,T4>
group_head( group5<T1,T2,T3,T4,T5> const& x)
{
return group4<T1,T2,T3,T4> (x.a1_,x.a2_,x.a3_,x.a4_);
}
template <class T1,class T2,class T3,class T4,class T5>
inline
group1<T5>
group_last( group5<T1,T2,T3,T4,T5> const& x)
{
return group1<T5> (x.a5_);
}
template <class T1,class T2,class T3,class T4,class T5,class T6>
inline
group5<T1,T2,T3,T4,T5>
group_head( group6<T1,T2,T3,T4,T5,T6> const& x)
{
return group5<T1,T2,T3,T4,T5> (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_);
}
template <class T1,class T2,class T3,class T4,class T5,class T6>
inline
group1<T6>
group_last( group6<T1,T2,T3,T4,T5,T6> const& x)
{
return group1<T6> (x.a6_);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7>
inline
group6<T1,T2,T3,T4,T5,T6>
group_head( group7<T1,T2,T3,T4,T5,T6,T7> const& x)
{
return group6<T1,T2,T3,T4,T5,T6> (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7>
inline
group1<T7>
group_last( group7<T1,T2,T3,T4,T5,T6,T7> const& x)
{
return group1<T7> (x.a7_);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8>
inline
group7<T1,T2,T3,T4,T5,T6,T7>
group_head( group8<T1,T2,T3,T4,T5,T6,T7,T8> const& x)
{
return group7<T1,T2,T3,T4,T5,T6,T7> (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8>
inline
group1<T8>
group_last( group8<T1,T2,T3,T4,T5,T6,T7,T8> const& x)
{
return group1<T8> (x.a8_);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9>
inline
group8<T1,T2,T3,T4,T5,T6,T7,T8>
group_head( group9<T1,T2,T3,T4,T5,T6,T7,T8,T9> const& x)
{
return group8<T1,T2,T3,T4,T5,T6,T7,T8> (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_,x.a8_);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9>
inline
group1<T9>
group_last( group9<T1,T2,T3,T4,T5,T6,T7,T8,T9> const& x)
{
return group1<T9> (x.a9_);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9,class T10>
inline
group9<T1,T2,T3,T4,T5,T6,T7,T8,T9>
group_head( group10<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> const& x)
{
return group9<T1,T2,T3,T4,T5,T6,T7,T8,T9> (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_,x.a8_,x.a9_);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9,class T10>
inline
group1<T10>
group_last( group10<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> const& x)
{
return group1<T10> (x.a10_);
}
} // namespace detail
// helper functions
inline detail::group1< detail::group0 >
group() { return detail::group1< detail::group0 > ( detail::group0() ); }
template <class T1, class Var>
inline
detail::group1< detail::group2<T1, Var const&> >
group(T1 a1, Var const& var)
{
return detail::group1< detail::group2<T1, Var const&> >
( detail::group2<T1, Var const&>
(a1, var)
);
}
template <class T1,class T2, class Var>
inline
detail::group1< detail::group3<T1,T2, Var const&> >
group(T1 a1,T2 a2, Var const& var)
{
return detail::group1< detail::group3<T1,T2, Var const&> >
( detail::group3<T1,T2, Var const&>
(a1,a2, var)
);
}
template <class T1,class T2,class T3, class Var>
inline
detail::group1< detail::group4<T1,T2,T3, Var const&> >
group(T1 a1,T2 a2,T3 a3, Var const& var)
{
return detail::group1< detail::group4<T1,T2,T3, Var const&> >
( detail::group4<T1,T2,T3, Var const&>
(a1,a2,a3, var)
);
}
template <class T1,class T2,class T3,class T4, class Var>
inline
detail::group1< detail::group5<T1,T2,T3,T4, Var const&> >
group(T1 a1,T2 a2,T3 a3,T4 a4, Var const& var)
{
return detail::group1< detail::group5<T1,T2,T3,T4, Var const&> >
( detail::group5<T1,T2,T3,T4, Var const&>
(a1,a2,a3,a4, var)
);
}
template <class T1,class T2,class T3,class T4,class T5, class Var>
inline
detail::group1< detail::group6<T1,T2,T3,T4,T5, Var const&> >
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5, Var const& var)
{
return detail::group1< detail::group6<T1,T2,T3,T4,T5, Var const&> >
( detail::group6<T1,T2,T3,T4,T5, Var const&>
(a1,a2,a3,a4,a5, var)
);
}
template <class T1,class T2,class T3,class T4,class T5,class T6, class Var>
inline
detail::group1< detail::group7<T1,T2,T3,T4,T5,T6, Var const&> >
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6, Var const& var)
{
return detail::group1< detail::group7<T1,T2,T3,T4,T5,T6, Var const&> >
( detail::group7<T1,T2,T3,T4,T5,T6, Var const&>
(a1,a2,a3,a4,a5,a6, var)
);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7, class Var>
inline
detail::group1< detail::group8<T1,T2,T3,T4,T5,T6,T7, Var const&> >
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7, Var const& var)
{
return detail::group1< detail::group8<T1,T2,T3,T4,T5,T6,T7, Var const&> >
( detail::group8<T1,T2,T3,T4,T5,T6,T7, Var const&>
(a1,a2,a3,a4,a5,a6,a7, var)
);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8, class Var>
inline
detail::group1< detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var const&> >
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8, Var const& var)
{
return detail::group1< detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var const&> >
( detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var const&>
(a1,a2,a3,a4,a5,a6,a7,a8, var)
);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9, class Var>
inline
detail::group1< detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var const&> >
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9, Var const& var)
{
return detail::group1< detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var const&> >
( detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var const&>
(a1,a2,a3,a4,a5,a6,a7,a8,a9, var)
);
}
#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST
template <class T1, class Var>
inline
detail::group1< detail::group2<T1, Var&> >
group(T1 a1, Var& var)
{
return detail::group1< detail::group2<T1, Var&> >
( detail::group2<T1, Var&>
(a1, var)
);
}
template <class T1,class T2, class Var>
inline
detail::group1< detail::group3<T1,T2, Var&> >
group(T1 a1,T2 a2, Var& var)
{
return detail::group1< detail::group3<T1,T2, Var&> >
( detail::group3<T1,T2, Var&>
(a1,a2, var)
);
}
template <class T1,class T2,class T3, class Var>
inline
detail::group1< detail::group4<T1,T2,T3, Var&> >
group(T1 a1,T2 a2,T3 a3, Var& var)
{
return detail::group1< detail::group4<T1,T2,T3, Var&> >
( detail::group4<T1,T2,T3, Var&>
(a1,a2,a3, var)
);
}
template <class T1,class T2,class T3,class T4, class Var>
inline
detail::group1< detail::group5<T1,T2,T3,T4, Var&> >
group(T1 a1,T2 a2,T3 a3,T4 a4, Var& var)
{
return detail::group1< detail::group5<T1,T2,T3,T4, Var&> >
( detail::group5<T1,T2,T3,T4, Var&>
(a1,a2,a3,a4, var)
);
}
template <class T1,class T2,class T3,class T4,class T5, class Var>
inline
detail::group1< detail::group6<T1,T2,T3,T4,T5, Var&> >
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5, Var& var)
{
return detail::group1< detail::group6<T1,T2,T3,T4,T5, Var&> >
( detail::group6<T1,T2,T3,T4,T5, Var&>
(a1,a2,a3,a4,a5, var)
);
}
template <class T1,class T2,class T3,class T4,class T5,class T6, class Var>
inline
detail::group1< detail::group7<T1,T2,T3,T4,T5,T6, Var&> >
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6, Var& var)
{
return detail::group1< detail::group7<T1,T2,T3,T4,T5,T6, Var&> >
( detail::group7<T1,T2,T3,T4,T5,T6, Var&>
(a1,a2,a3,a4,a5,a6, var)
);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7, class Var>
inline
detail::group1< detail::group8<T1,T2,T3,T4,T5,T6,T7, Var&> >
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7, Var& var)
{
return detail::group1< detail::group8<T1,T2,T3,T4,T5,T6,T7, Var&> >
( detail::group8<T1,T2,T3,T4,T5,T6,T7, Var&>
(a1,a2,a3,a4,a5,a6,a7, var)
);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8, class Var>
inline
detail::group1< detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var&> >
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8, Var& var)
{
return detail::group1< detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var&> >
( detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var&>
(a1,a2,a3,a4,a5,a6,a7,a8, var)
);
}
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9, class Var>
inline
detail::group1< detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var&> >
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9, Var& var)
{
return detail::group1< detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var&> >
( detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var&>
(a1,a2,a3,a4,a5,a6,a7,a8,a9, var)
);
}
#endif //end- #ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST
} // namespace io
} // namespace boost
#endif // BOOST_FORMAT_GROUP_HPP

View File

@@ -0,0 +1,167 @@
// -*- C++ -*-
// Boost general library 'format' ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rüdiger Loos's format class
// and Karl Nelson's ofstream
// ----------------------------------------------------------------------------
// internals.hpp : internal structs. included by format.hpp
// stream_format_state, and format_item
// ----------------------------------------------------------------------------
#ifndef BOOST_FORMAT_INTERNALS_HPP
#define BOOST_FORMAT_INTERNALS_HPP
#include <string>
#include <sstream>
namespace boost {
namespace io {
namespace detail {
// --------------
// set of params that define the format state of a stream
struct stream_format_state
{
typedef std::ios basic_ios;
std::streamsize width_;
std::streamsize precision_;
char fill_;
std::ios::fmtflags flags_;
stream_format_state() : width_(-1), precision_(-1), fill_(0), flags_(std::ios::dec) {}
stream_format_state(basic_ios& os) {set_by_stream(os); }
void apply_on(basic_ios & os) const; //- applies format_state to the stream
template<class T> void apply_manip(T manipulator) //- modifies state by applying manipulator.
{ apply_manip_body<T>( *this, manipulator) ; }
void reset(); //- sets to default state.
void set_by_stream(const basic_ios& os); //- sets to os's state.
};
// --------------
// format_item : stores all parameters that can be defined by directives in the format-string
struct format_item
{
enum pad_values { zeropad = 1, spacepad =2, centered=4, tabulation = 8 };
enum arg_values { argN_no_posit = -1, // non-positional directive. argN will be set later.
argN_tabulation = -2, // tabulation directive. (no argument read)
argN_ignored = -3 // ignored directive. (no argument read)
};
typedef BOOST_IO_STD ios basic_ios;
typedef detail::stream_format_state stream_format_state;
typedef std::string string_t;
typedef BOOST_IO_STD ostringstream internal_stream_t;
int argN_; //- argument number (starts at 0, eg : %1 => argN=0)
// negative values are used for items that don't process
// an argument
string_t res_; //- result of the formatting of this item
string_t appendix_; //- piece of string between this item and the next
stream_format_state ref_state_;// set by parsing the format_string, is only affected by modify_item
stream_format_state state_; // always same as ref_state, _unless_ modified by manipulators 'group(..)'
// non-stream format-state parameters
signed int truncate_; //- is >=0 for directives like %.5s (take 5 chars from the string)
unsigned int pad_scheme_; //- several possible padding schemes can mix. see pad_values
format_item() : argN_(argN_no_posit), truncate_(-1), pad_scheme_(0) {}
void compute_states(); // sets states according to truncate and pad_scheme.
};
// -----------------------------------------------------------
// Definitions
// -----------------------------------------------------------
// --- stream_format_state:: -------------------------------------------
inline
void stream_format_state::apply_on(basic_ios & os) const
// set the state of this stream according to our params
{
if(width_ != -1)
os.width(width_);
if(precision_ != -1)
os.precision(precision_);
if(fill_ != 0)
os.fill(fill_);
os.flags(flags_);
}
inline
void stream_format_state::set_by_stream(const basic_ios& os)
// set our params according to the state of this stream
{
flags_ = os.flags();
width_ = os.width();
precision_ = os.precision();
fill_ = os.fill();
}
template<class T> inline
void apply_manip_body( stream_format_state& self,
T manipulator)
// modify our params according to the manipulator
{
BOOST_IO_STD stringstream ss;
self.apply_on( ss );
ss << manipulator;
self.set_by_stream( ss );
}
inline
void stream_format_state::reset()
// set our params to standard's default state
{
width_=-1; precision_=-1; fill_=0;
flags_ = std::ios::dec;
}
// --- format_items:: -------------------------------------------
inline
void format_item::compute_states()
// reflect pad_scheme_ on state_ and ref_state_
// because some pad_schemes has complex consequences on several state params.
{
if(pad_scheme_ & zeropad)
{
if(ref_state_.flags_ & std::ios::left)
{
pad_scheme_ = pad_scheme_ & (~zeropad); // ignore zeropad in left alignment
}
else
{
ref_state_.fill_='0';
ref_state_.flags_ |= std::ios::internal;
}
}
state_ = ref_state_;
}
} } } // namespaces boost :: io :: detail
#endif // BOOST_FORMAT_INTERNALS_HPP

View File

@@ -0,0 +1,65 @@
// -*- C++ -*-
// Boost general library 'format' ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rüdiger Loos's format class
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
// ------------------------------------------------------------------------------
// internals_fwd.hpp : forward declarations, for internal headers
// ------------------------------------------------------------------------------
#ifndef BOOST_FORMAT_INTERNAL_FWD_HPP
#define BOOST_FORMAT_INTERNAL_FWD_HPP
#include "boost/format/format_fwd.hpp"
namespace boost {
namespace io {
namespace detail {
struct stream_format_state;
struct format_item;
}
namespace detail {
// these functions were intended as methods,
// but MSVC have problems with template member functions :
// defined in format_implementation.hpp :
template<class T>
basic_format& modify_item_body( basic_format& self,
int itemN, const T& manipulator);
template<class T>
basic_format& bind_arg_body( basic_format& self,
int argN, const T& val);
template<class T>
void apply_manip_body( stream_format_state& self,
T manipulator);
// argument feeding (defined in feed_args.hpp ) :
template<class T>
void distribute(basic_format& self, T x);
template<class T>
basic_format& feed(basic_format& self, T x);
} // namespace detail
} // namespace io
} // namespace boost
#endif // BOOST_FORMAT_INTERNAL_FWD_HPP

View File

@@ -0,0 +1,7 @@
libraries += libformat
libformat_NAME = libnixformat
libformat_DIR := $(d)
libformat_SOURCES := $(wildcard $(d)/*.cc)

View File

@@ -0,0 +1,48 @@
// -*- C++ -*-
// Boost general library 'format' ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rüdiger Loos's format class
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
// ------------------------------------------------------------------------------
// macros_default.hpp : configuration for the format library
// provides default values for the stl workaround macros
// ------------------------------------------------------------------------------
#ifndef BOOST_FORMAT_MACROS_DEFAULT_HPP
#define BOOST_FORMAT_MACROS_DEFAULT_HPP
// *** This should go to "boost/config/suffix.hpp".
#ifndef BOOST_IO_STD
# define BOOST_IO_STD std::
#endif
// **** Workaround for io streams, stlport and msvc.
#ifdef BOOST_IO_NEEDS_USING_DECLARATION
namespace boost {
using std::char_traits;
using std::basic_ostream;
using std::basic_ostringstream;
namespace io {
using std::basic_ostream;
namespace detail {
using std::basic_ios;
using std::basic_ostream;
using std::basic_ostringstream;
}
}
}
#endif
// ------------------------------------------------------------------------------
#endif // BOOST_FORMAT_MACROS_DEFAULT_HPP

454
src/boost/format/parsing.cc Normal file
View File

@@ -0,0 +1,454 @@
// -*- C++ -*-
// Boost general library 'format' ---------------------------
// See http://www.boost.org for updates, documentation, and revision history.
// (C) Samuel Krempp 2001
// krempp@crans.ens-cachan.fr
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// ideas taken from Rudiger Loos's format class
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
// ------------------------------------------------------------------------------
// parsing.hpp : implementation of the parsing member functions
// ( parse, parse_printf_directive)
// ------------------------------------------------------------------------------
#ifndef BOOST_FORMAT_PARSING_HPP
#define BOOST_FORMAT_PARSING_HPP
#include <boost/format.hpp>
#include <boost/throw_exception.hpp>
#include <boost/assert.hpp>
namespace boost {
namespace io {
namespace detail {
template<class Stream> inline
bool wrap_isdigit(char c, Stream &os)
{
#ifndef BOOST_NO_LOCALE_ISIDIGIT
return std::isdigit(c, os.rdbuf()->getloc() );
# else
using namespace std;
return isdigit(c);
#endif
} //end- wrap_isdigit(..)
template<class Res> inline
Res str2int(const std::string& s,
std::string::size_type start,
BOOST_IO_STD ios &os,
const Res = Res(0) )
// Input : char string, with starting index
// a basic_ios& merely to call its widen/narrow member function in the desired locale.
// Effects : reads s[start:] and converts digits into an integral n, of type Res
// Returns : n
{
Res n = 0;
while(start<s.size() && wrap_isdigit(s[start], os) ) {
char cur_ch = s[start];
BOOST_ASSERT(cur_ch != 0 ); // since we called isdigit, this should not happen.
n *= 10;
n += cur_ch - '0'; // 22.2.1.1.2 of the C++ standard
++start;
}
return n;
}
void skip_asterisk(const std::string & buf,
std::string::size_type * pos_p,
BOOST_IO_STD ios &os)
// skip printf's "asterisk-fields" directives in the format-string buf
// Input : char string, with starting index *pos_p
// a basic_ios& merely to call its widen/narrow member function in the desired locale.
// Effects : advance *pos_p by skipping printf's asterisk fields.
// Returns : nothing
{
using namespace std;
BOOST_ASSERT( pos_p != 0);
if(*pos_p >= buf.size() ) return;
if(buf[ *pos_p]=='*') {
++ (*pos_p);
while (*pos_p < buf.size() && wrap_isdigit(buf[*pos_p],os)) ++(*pos_p);
if(buf[*pos_p]=='$') ++(*pos_p);
}
}
inline void maybe_throw_exception( unsigned char exceptions)
// auxiliary func called by parse_printf_directive
// for centralising error handling
// it either throws if user sets the corresponding flag, or does nothing.
{
if(exceptions & io::bad_format_string_bit)
boost::throw_exception(io::bad_format_string());
}
bool parse_printf_directive(const std::string & buf,
std::string::size_type * pos_p,
detail::format_item * fpar,
BOOST_IO_STD ios &os,
unsigned char exceptions)
// Input : a 'printf-directive' in the format-string, starting at buf[ *pos_p ]
// a basic_ios& merely to call its widen/narrow member function in the desired locale.
// a bitset'excpetions' telling whether to throw exceptions on errors.
// Returns : true if parse somehow succeeded (possibly ignoring errors if exceptions disabled)
// false if it failed so bad that the directive should be printed verbatim
// Effects : - *pos_p is incremented so that buf[*pos_p] is the first char after the directive
// - *fpar is set with the parameters read in the directive
{
typedef format_item format_item_t;
BOOST_ASSERT( pos_p != 0);
std::string::size_type &i1 = *pos_p,
i0;
fpar->argN_ = format_item_t::argN_no_posit; // if no positional-directive
bool in_brackets=false;
if(buf[i1]=='|')
{
in_brackets=true;
if( ++i1 >= buf.size() ) {
maybe_throw_exception(exceptions);
return false;
}
}
// the flag '0' would be picked as a digit for argument order, but here it's a flag :
if(buf[i1]=='0')
goto parse_flags;
// handle argument order (%2$d) or possibly width specification: %2d
i0 = i1; // save position before digits
while (i1 < buf.size() && wrap_isdigit(buf[i1], os))
++i1;
if (i1!=i0)
{
if( i1 >= buf.size() ) {
maybe_throw_exception(exceptions);
return false;
}
int n=str2int(buf,i0, os, int(0) );
// %N% case : this is already the end of the directive
if( buf[i1] == '%' )
{
fpar->argN_ = n-1;
++i1;
if( in_brackets)
maybe_throw_exception(exceptions);
// but don't return. maybe "%" was used in lieu of '$', so we go on.
else return true;
}
if ( buf[i1]=='$' )
{
fpar->argN_ = n-1;
++i1;
}
else
{
// non-positionnal directive
fpar->ref_state_.width_ = n;
fpar->argN_ = format_item_t::argN_no_posit;
goto parse_precision;
}
}
parse_flags:
// handle flags
while ( i1 <buf.size()) // as long as char is one of + - = # 0 l h or ' '
{
// misc switches
switch (buf[i1])
{
case '\'' : break; // no effect yet. (painful to implement)
case 'l':
case 'h': // short/long modifier : for printf-comaptibility (no action needed)
break;
case '-':
fpar->ref_state_.flags_ |= std::ios::left;
break;
case '=':
fpar->pad_scheme_ |= format_item_t::centered;
break;
case ' ':
fpar->pad_scheme_ |= format_item_t::spacepad;
break;
case '+':
fpar->ref_state_.flags_ |= std::ios::showpos;
break;
case '0':
fpar->pad_scheme_ |= format_item_t::zeropad;
// need to know alignment before really setting flags,
// so just add 'zeropad' flag for now, it will be processed later.
break;
case '#':
fpar->ref_state_.flags_ |= std::ios::showpoint | std::ios::showbase;
break;
default:
goto parse_width;
}
++i1;
} // loop on flag.
if( i1>=buf.size()) {
maybe_throw_exception(exceptions);
return true;
}
parse_width:
// handle width spec
skip_asterisk(buf, &i1, os); // skips 'asterisk fields' : *, or *N$
i0 = i1; // save position before digits
while (i1<buf.size() && wrap_isdigit(buf[i1], os))
i1++;
if (i1!=i0)
{ fpar->ref_state_.width_ = str2int( buf,i0, os, std::streamsize(0) ); }
parse_precision:
if( i1>=buf.size()) {
maybe_throw_exception(exceptions);
return true;
}
// handle precision spec
if (buf[i1]=='.')
{
++i1;
skip_asterisk(buf, &i1, os);
i0 = i1; // save position before digits
while (i1<buf.size() && wrap_isdigit(buf[i1], os))
++i1;
if(i1==i0)
fpar->ref_state_.precision_ = 0;
else
fpar->ref_state_.precision_ = str2int(buf,i0, os, std::streamsize(0) );
}
// handle formatting-type flags :
while( i1<buf.size() &&
( buf[i1]=='l' || buf[i1]=='L' || buf[i1]=='h') )
++i1;
if( i1>=buf.size()) {
maybe_throw_exception(exceptions);
return true;
}
if( in_brackets && buf[i1]=='|' )
{
++i1;
return true;
}
switch (buf[i1])
{
case 'X':
fpar->ref_state_.flags_ |= std::ios::uppercase;
case 'p': // pointer => set hex.
case 'x':
fpar->ref_state_.flags_ &= ~std::ios::basefield;
fpar->ref_state_.flags_ |= std::ios::hex;
break;
case 'o':
fpar->ref_state_.flags_ &= ~std::ios::basefield;
fpar->ref_state_.flags_ |= std::ios::oct;
break;
case 'E':
fpar->ref_state_.flags_ |= std::ios::uppercase;
case 'e':
fpar->ref_state_.flags_ &= ~std::ios::floatfield;
fpar->ref_state_.flags_ |= std::ios::scientific;
fpar->ref_state_.flags_ &= ~std::ios::basefield;
fpar->ref_state_.flags_ |= std::ios::dec;
break;
case 'f':
fpar->ref_state_.flags_ &= ~std::ios::floatfield;
fpar->ref_state_.flags_ |= std::ios::fixed;
case 'u':
case 'd':
case 'i':
fpar->ref_state_.flags_ &= ~std::ios::basefield;
fpar->ref_state_.flags_ |= std::ios::dec;
break;
case 'T':
++i1;
if( i1 >= buf.size())
maybe_throw_exception(exceptions);
else
fpar->ref_state_.fill_ = buf[i1];
fpar->pad_scheme_ |= format_item_t::tabulation;
fpar->argN_ = format_item_t::argN_tabulation;
break;
case 't':
fpar->ref_state_.fill_ = ' ';
fpar->pad_scheme_ |= format_item_t::tabulation;
fpar->argN_ = format_item_t::argN_tabulation;
break;
case 'G':
fpar->ref_state_.flags_ |= std::ios::uppercase;
break;
case 'g': // 'g' conversion is default for floats.
fpar->ref_state_.flags_ &= ~std::ios::basefield;
fpar->ref_state_.flags_ |= std::ios::dec;
// CLEAR all floatield flags, so stream will CHOOSE
fpar->ref_state_.flags_ &= ~std::ios::floatfield;
break;
case 'C':
case 'c':
fpar->truncate_ = 1;
break;
case 'S':
case 's':
fpar->truncate_ = fpar->ref_state_.precision_;
fpar->ref_state_.precision_ = -1;
break;
case 'n' :
fpar->argN_ = format_item_t::argN_ignored;
break;
default:
maybe_throw_exception(exceptions);
}
++i1;
if( in_brackets )
{
if( i1<buf.size() && buf[i1]=='|' )
{
++i1;
return true;
}
else maybe_throw_exception(exceptions);
}
return true;
}
} // detail namespace
} // io namespace
// -----------------------------------------------
// format :: parse(..)
void basic_format::parse(const string_t & buf)
// parse the format-string
{
using namespace std;
const char arg_mark = '%';
bool ordered_args=true;
int max_argN=-1;
string_t::size_type i1=0;
int num_items=0;
// A: find upper_bound on num_items and allocates arrays
i1=0;
while( (i1=buf.find(arg_mark,i1)) != string::npos )
{
if( i1+1 >= buf.size() ) {
if(exceptions() & io::bad_format_string_bit)
boost::throw_exception(io::bad_format_string()); // must not end in "bla bla %"
else break; // stop there, ignore last '%'
}
if(buf[i1+1] == buf[i1] ) { i1+=2; continue; } // escaped "%%" / "##"
++i1;
// in case of %N% directives, dont count it double (wastes allocations..) :
while(i1 < buf.size() && io::detail::wrap_isdigit(buf[i1],oss_)) ++i1;
if( i1 < buf.size() && buf[i1] == arg_mark ) ++ i1;
++num_items;
}
items_.assign( num_items, format_item_t() );
// B: Now the real parsing of the format string :
num_items=0;
i1 = 0;
string_t::size_type i0 = i1;
bool special_things=false;
int cur_it=0;
while( (i1=buf.find(arg_mark,i1)) != string::npos )
{
string_t & piece = (cur_it==0) ? prefix_ : items_[cur_it-1].appendix_;
if( buf[i1+1] == buf[i1] ) // escaped mark, '%%'
{
piece += buf.substr(i0, i1-i0) + buf[i1];
i1+=2; i0=i1;
continue;
}
BOOST_ASSERT( static_cast<unsigned int>(cur_it) < items_.size() || cur_it==0);
if(i1!=i0) piece += buf.substr(i0, i1-i0);
++i1;
bool parse_ok;
parse_ok = io::detail::parse_printf_directive(buf, &i1, &items_[cur_it], oss_, exceptions());
if( ! parse_ok ) continue; // the directive will be printed verbatim
i0=i1;
items_[cur_it].compute_states(); // process complex options, like zeropad, into stream params.
int argN=items_[cur_it].argN_;
if(argN == format_item_t::argN_ignored)
continue;
if(argN ==format_item_t::argN_no_posit)
ordered_args=false;
else if(argN == format_item_t::argN_tabulation) special_things=true;
else if(argN > max_argN) max_argN = argN;
++num_items;
++cur_it;
} // loop on %'s
BOOST_ASSERT(cur_it == num_items);
// store the final piece of string
string_t & piece = (cur_it==0) ? prefix_ : items_[cur_it-1].appendix_;
piece += buf.substr(i0);
if( !ordered_args)
{
if(max_argN >= 0 ) // dont mix positional with non-positionnal directives
{
if(exceptions() & io::bad_format_string_bit)
boost::throw_exception(io::bad_format_string());
// else do nothing. => positionnal arguments are processed as non-positionnal
}
// set things like it would have been with positional directives :
int non_ordered_items = 0;
for(int i=0; i< num_items; ++i)
if(items_[i].argN_ == format_item_t::argN_no_posit)
{
items_[i].argN_ = non_ordered_items;
++non_ordered_items;
}
max_argN = non_ordered_items-1;
}
// C: set some member data :
items_.resize(num_items);
if(special_things) style_ |= special_needs;
num_args_ = max_argN + 1;
if(ordered_args) style_ |= ordered;
else style_ &= ~ordered;
}
} // namespace boost
#endif // BOOST_FORMAT_PARSING_HPP

View File

@@ -0,0 +1,47 @@
#ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED
#define BOOST_THROW_EXCEPTION_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/throw_exception.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// http://www.boost.org/libs/utility/throw_exception.html
//
//#include <boost/config.hpp>
#ifdef BOOST_NO_EXCEPTIONS
# include <exception>
#endif
namespace boost
{
#ifdef BOOST_NO_EXCEPTIONS
void throw_exception(std::exception const & e); // user defined
#else
template<class E> void throw_exception(E const & e)
{
throw e;
}
#endif
} // namespace boost
#endif // #ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED

View File

@@ -17,7 +17,6 @@
#include "store-api.hh"
#include "derivations.hh"
#include "local-store.hh"
#include "legacy.hh"
using namespace nix;
using std::cin;
@@ -38,15 +37,11 @@ static AutoCloseFD openSlotLock(const Machine & m, unsigned long long slot)
return openLockFile(fmt("%s/%s-%d", currentLoad, escapeUri(m.storeUri), slot), true);
}
static bool allSupportedLocally(const std::set<std::string>& requiredFeatures) {
for (auto & feature : requiredFeatures)
if (!settings.systemFeatures.get().count(feature)) return false;
return true;
}
static int _main(int argc, char * * argv)
int main (int argc, char * * argv)
{
{
return handleExceptions(argv[0], [&]() {
initNix();
logger = makeJSONLogger(*logger);
/* Ensure we don't get any SSH passphrase or host key popups. */
@@ -85,7 +80,7 @@ static int _main(int argc, char * * argv)
if (machines.empty()) {
std::cerr << "# decline-permanently\n";
return 0;
return;
}
string drvPath;
@@ -95,18 +90,15 @@ static int _main(int argc, char * * argv)
try {
auto s = readString(source);
if (s != "try") return 0;
} catch (EndOfFile &) { return 0; }
if (s != "try") return;
} catch (EndOfFile &) { return; }
auto amWilling = readInt(source);
auto neededSystem = readString(source);
source >> drvPath;
auto requiredFeatures = readStrings<std::set<std::string>>(source);
auto canBuildLocally = amWilling
&& ( neededSystem == settings.thisSystem
|| settings.extraPlatforms.get().count(neededSystem) > 0)
&& allSupportedLocally(requiredFeatures);
auto canBuildLocally = amWilling && (neededSystem == settings.thisSystem);
/* Error ignored here, will be caught later */
mkdir(currentLoad.c_str(), 0777);
@@ -199,10 +191,8 @@ static int _main(int argc, char * * argv)
storeUri = bestMachine->storeUri;
} catch (std::exception & e) {
auto msg = chomp(drainFD(5, false));
printError("cannot build on '%s': %s%s",
bestMachine->storeUri, e.what(),
(msg.empty() ? "" : ": " + msg));
printError("unable to open SSH connection to '%s': %s; trying other available machines...",
bestMachine->storeUri, e.what());
bestMachine->enabled = false;
continue;
}
@@ -212,8 +202,6 @@ static int _main(int argc, char * * argv)
}
connected:
close(5);
std::cerr << "# accept\n" << storeUri << "\n";
auto inputs = readStrings<PathSet>(source);
@@ -259,8 +247,6 @@ connected:
copyPaths(ref<Store>(sshStore), store, missing, NoRepair, NoCheckSigs, NoSubstitute);
}
return 0;
}
return;
});
}
static RegisterLegacyCommand s1("build-remote", _main);

View File

@@ -0,0 +1,9 @@
programs += build-remote
build-remote_DIR := $(d)
build-remote_INSTALL_DIR := $(libexecdir)/nix
build-remote_LIBS = libmain libutil libformat libstore
build-remote_SOURCES := $(d)/build-remote.cc

187
src/buildenv/buildenv.cc Normal file
View File

@@ -0,0 +1,187 @@
#include "shared.hh"
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <algorithm>
using namespace nix;
typedef std::map<Path,int> Priorities;
static bool isDirectory (const Path & path)
{
struct stat st;
if (stat(path.c_str(), &st) == -1)
throw SysError(format("getting status of '%1%'") % path);
return S_ISDIR(st.st_mode);
}
static auto priorities = Priorities{};
static auto symlinks = 0;
/* For each activated package, create symlinks */
static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
{
auto srcFiles = readDirectory(srcDir);
for (const auto & ent : srcFiles) {
if (ent.name[0] == '.')
/* not matched by glob */
continue;
const auto & srcFile = srcDir + "/" + ent.name;
auto dstFile = dstDir + "/" + ent.name;
/* The files below are special-cased to that they don't show up
* in user profiles, either because they are useless, or
* because they would cauase pointless collisions (e.g., each
* Python package brings its own
* `$out/lib/pythonX.Y/site-packages/easy-install.pth'.)
*/
if (hasSuffix(srcFile, "/propagated-build-inputs") ||
hasSuffix(srcFile, "/nix-support") ||
hasSuffix(srcFile, "/perllocal.pod") ||
hasSuffix(srcFile, "/info/dir") ||
hasSuffix(srcFile, "/log")) {
continue;
} else if (isDirectory(srcFile)) {
struct stat dstSt;
auto res = lstat(dstFile.c_str(), &dstSt);
if (res == 0) {
if (S_ISDIR(dstSt.st_mode)) {
createLinks(srcFile, dstFile, priority);
continue;
} else if (S_ISLNK(dstSt.st_mode)) {
auto target = readLink(dstFile);
if (!isDirectory(target))
throw Error(format("collision between '%1%' and non-directory '%2%'")
% srcFile % target);
if (unlink(dstFile.c_str()) == -1)
throw SysError(format("unlinking '%1%'") % dstFile);
if (mkdir(dstFile.c_str(), 0755) == -1)
throw SysError(format("creating directory '%1%'"));
createLinks(target, dstFile, priorities[dstFile]);
createLinks(srcFile, dstFile, priority);
continue;
}
} else if (errno != ENOENT)
throw SysError(format("getting status of '%1%'") % dstFile);
} else {
struct stat dstSt;
auto res = lstat(dstFile.c_str(), &dstSt);
if (res == 0) {
if (S_ISLNK(dstSt.st_mode)) {
auto target = readLink(dstFile);
auto prevPriority = priorities[dstFile];
if (prevPriority == priority)
throw Error(format(
"packages '%1%' and '%2%' have the same priority %3%; "
"use 'nix-env --set-flag priority NUMBER INSTALLED_PKGNAME' "
"to change the priority of one of the conflicting packages"
" (0 being the highest priority)"
) % srcFile % target % priority);
if (prevPriority < priority)
continue;
if (unlink(dstFile.c_str()) == -1)
throw SysError(format("unlinking '%1%'") % dstFile);
}
} else if (errno != ENOENT)
throw SysError(format("getting status of '%1%'") % dstFile);
}
createSymlink(srcFile, dstFile);
priorities[dstFile] = priority;
symlinks++;
}
}
typedef std::set<Path> FileProp;
static auto done = FileProp{};
static auto postponed = FileProp{};
static auto out = string{};
static void addPkg(const Path & pkgDir, int priority)
{
if (done.find(pkgDir) != done.end())
return;
done.insert(pkgDir);
createLinks(pkgDir, out, priority);
auto propagatedFN = pkgDir + "/nix-support/propagated-user-env-packages";
auto propagated = string{};
{
AutoCloseFD fd = open(propagatedFN.c_str(), O_RDONLY | O_CLOEXEC);
if (!fd) {
if (errno == ENOENT)
return;
throw SysError(format("opening '%1%'") % propagatedFN);
}
propagated = readFile(fd.get());
}
for (const auto & p : tokenizeString<std::vector<string>>(propagated, " \n"))
if (done.find(p) == done.end())
postponed.insert(p);
}
struct Package {
Path path;
bool active;
int priority;
Package(Path path, bool active, int priority) : path{std::move(path)}, active{active}, priority{priority} {}
};
typedef std::vector<Package> Packages;
int main(int argc, char ** argv)
{
return handleExceptions(argv[0], [&]() {
initNix();
out = getEnv("out");
if (mkdir(out.c_str(), 0755) == -1)
throw SysError(format("creating %1%") % out);
/* Convert the stuff we get from the environment back into a coherent
* data type.
*/
auto pkgs = Packages{};
auto derivations = tokenizeString<Strings>(getEnv("derivations"));
while (!derivations.empty()) {
/* !!! We're trusting the caller to structure derivations env var correctly */
auto active = derivations.front(); derivations.pop_front();
auto priority = stoi(derivations.front()); derivations.pop_front();
auto outputs = stoi(derivations.front()); derivations.pop_front();
for (auto n = 0; n < outputs; n++) {
auto path = derivations.front(); derivations.pop_front();
pkgs.emplace_back(path, active != "false", priority);
}
}
/* Symlink to the packages that have been installed explicitly by the
* user. Process in priority order to reduce unnecessary
* symlink/unlink steps.
*/
std::sort(pkgs.begin(), pkgs.end(), [](const Package & a, const Package & b) {
return a.priority < b.priority || (a.priority == b.priority && a.path < b.path);
});
for (const auto & pkg : pkgs)
if (pkg.active)
addPkg(pkg.path, pkg.priority);
/* Symlink to the packages that have been "propagated" by packages
* 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.
*/
auto priorityCounter = 1000;
while (!postponed.empty()) {
auto pkgDirs = postponed;
postponed = FileProp{};
for (const auto & pkgDir : pkgDirs)
addPkg(pkgDir, priorityCounter++);
}
std::cerr << "created " << symlinks << " symlinks in user environment\n";
createSymlink(getEnv("manifest"), out + "/manifest.nix");
});
}

9
src/buildenv/local.mk Normal file
View File

@@ -0,0 +1,9 @@
programs += buildenv
buildenv_DIR := $(d)
buildenv_INSTALL_DIR := $(libexecdir)/nix
buildenv_LIBS = libmain libstore libutil libformat
buildenv_SOURCES := $(d)/buildenv.cc

View File

@@ -1,18 +0,0 @@
Copyright (c) 2014 Chase Geigle
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
#include "attr-set.hh"
#include "eval-inline.hh"
#include "eval.hh"
#include <algorithm>
@@ -7,18 +7,30 @@
namespace nix {
/* Allocate a new array of attributes for an attribute set with a specific
capacity. The space is implicitly reserved after the Bindings
structure. */
Bindings * EvalState::allocBindings(size_t capacity)
/* Note: Various places expect the allocated memory to be zeroed. */
static void * allocBytes(size_t n)
{
if (capacity > std::numeric_limits<Bindings::size_t>::max())
throw Error("attribute set of size %d is too big", capacity);
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity);
void * p;
#if HAVE_BOEHMGC
p = GC_malloc(n);
#else
p = calloc(n, 1);
#endif
if (!p) throw std::bad_alloc();
return p;
}
void EvalState::mkAttrs(Value & v, size_t capacity)
/* 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;

View File

@@ -78,18 +78,4 @@ inline void EvalState::forceList(Value & v, const Pos & pos)
throwTypeError("value is %1% while a list was expected, at %2%", v, pos);
}
/* Note: Various places expect the allocated memory to be zeroed. */
inline void * allocBytes(size_t n)
{
void * p;
#if HAVE_BOEHMGC
p = GC_MALLOC(n);
#else
p = calloc(n, 1);
#endif
if (!p) throw std::bad_alloc();
return p;
}
}

View File

@@ -6,16 +6,10 @@
#include "globals.hh"
#include "eval-inline.hh"
#include "download.hh"
#include "json.hh"
#include <algorithm>
#include <cstring>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <iostream>
#include <fstream>
#include <sys/time.h>
#include <sys/resource.h>
@@ -24,8 +18,15 @@
#include <gc/gc.h>
#include <gc/gc_cpp.h>
#define NEW new (UseGC)
#else
#define NEW new
#endif
namespace nix {
@@ -33,7 +34,7 @@ static char * dupString(const char * s)
{
char * t;
#if HAVE_BOEHMGC
t = GC_STRDUP(s);
t = GC_strdup(s);
#else
t = strdup(s);
#endif
@@ -42,6 +43,20 @@ static char * dupString(const char * s)
}
/* Note: Various places expect the allocated memory to be zeroed. */
static void * allocBytes(size_t n)
{
void * p;
#if HAVE_BOEHMGC
p = GC_malloc(n);
#else
p = calloc(n, 1);
#endif
if (!p) throw std::bad_alloc();
return p;
}
static void printValue(std::ostream & str, std::set<const Value *> & active, const Value & v)
{
checkInterrupt();
@@ -130,16 +145,6 @@ std::ostream & operator << (std::ostream & str, const Value & v)
}
const Value *getPrimOp(const Value &v) {
const Value * primOp = &v;
while (primOp->type == tPrimOpApp) {
primOp = primOp->primOpApp.left;
}
assert(primOp->type == tPrimOp);
return primOp;
}
string showType(const Value & v)
{
switch (v.type) {
@@ -154,10 +159,8 @@ string showType(const Value & v)
case tApp: return "a function application";
case tLambda: return "a function";
case tBlackhole: return "a black hole";
case tPrimOp:
return fmt("the built-in function '%s'", string(v.primOp->name));
case tPrimOpApp:
return fmt("the partially applied built-in function '%s'", string(getPrimOp(v)->primOp->name));
case tPrimOp: return "a built-in function";
case tPrimOpApp: return "a partially applied built-in function";
case tExternal: return v.external->showType();
case tFloat: return "a float";
}
@@ -196,15 +199,8 @@ void initGC()
#if HAVE_BOEHMGC
/* Initialise the Boehm garbage collector. */
/* Don't look for interior pointers. This reduces the odds of
misdetection a bit. */
GC_set_all_interior_pointers(0);
/* We don't have any roots in data segments, so don't scan from
there. */
GC_set_no_dls(1);
GC_INIT();
GC_set_oom_fn(oomHandler);
@@ -311,32 +307,20 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
assert(gcInitialised);
static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes");
/* Initialise the Nix expression search path. */
if (!evalSettings.pureEval) {
if (!settings.pureEval) {
Strings paths = parseNixPath(getEnv("NIX_PATH", ""));
for (auto & i : _searchPath) addToSearchPath(i);
for (auto & i : paths) addToSearchPath(i);
}
addToSearchPath("nix=" + canonPath(settings.nixDataDir + "/nix/corepkgs", true));
if (evalSettings.restrictEval || evalSettings.pureEval) {
if (settings.restrictEval || settings.pureEval) {
allowedPaths = PathSet();
for (auto & i : searchPath) {
auto r = resolveSearchPathElem(i);
if (!r.first) continue;
auto path = r.second;
if (store->isInStore(r.second)) {
PathSet closure;
store->computeFSClosure(store->toStorePath(r.second), closure);
for (auto & path : closure)
allowedPaths->insert(path);
} else
allowedPaths->insert(r.second);
allowedPaths->insert(r.second);
}
}
@@ -350,6 +334,7 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
EvalState::~EvalState()
{
fileEvalCache.clear();
}
@@ -357,37 +342,25 @@ Path EvalState::checkSourcePath(const Path & path_)
{
if (!allowedPaths) return path_;
auto i = resolvedPaths.find(path_);
if (i != resolvedPaths.end())
return i->second;
bool found = false;
/* First canonicalize the path without symlinks, so we make sure an
* attacker can't append ../../... to a path that would be in allowedPaths
* and thus leak symlink targets.
*/
Path abspath = canonPath(path_);
for (auto & i : *allowedPaths) {
if (isDirOrInDir(abspath, i)) {
if (isDirOrInDir(path_, i)) {
found = true;
break;
}
}
if (!found)
throw RestrictedPathError("access to path '%1%' is forbidden in restricted mode", abspath);
throw RestrictedPathError("access to path '%1%' is forbidden in restricted mode", path_);
/* Resolve symlinks. */
debug(format("checking access to '%s'") % abspath);
Path path = canonPath(abspath, true);
debug(format("checking access to '%s'") % path_);
Path path = canonPath(path_, true);
for (auto & i : *allowedPaths) {
if (isDirOrInDir(path, i)) {
resolvedPaths[path_] = path;
if (isDirOrInDir(path, i))
return path;
}
}
throw RestrictedPathError("access to path '%1%' is forbidden in restricted mode", path);
@@ -396,13 +369,13 @@ Path EvalState::checkSourcePath(const Path & path_)
void EvalState::checkURI(const std::string & uri)
{
if (!evalSettings.restrictEval) return;
if (!settings.restrictEval) return;
/* 'uri' should be equal to a prefix, or in a subdirectory of a
prefix. Thus, the prefix https://github.co does not permit
access to https://github.com. Note: this allows 'http://' and
'https://' as prefixes for any http/https URI. */
for (auto & prefix : evalSettings.allowedUris.get())
for (auto & prefix : settings.allowedUris.get())
if (uri == prefix ||
(uri.size() > prefix.size()
&& prefix.size() > 0
@@ -449,7 +422,7 @@ Value * EvalState::addConstant(const string & name, Value & v)
Value * EvalState::addPrimOp(const string & name,
size_t arity, PrimOpFun primOp)
unsigned int arity, PrimOpFun primOp)
{
if (arity == 0) {
Value v;
@@ -460,7 +433,7 @@ Value * EvalState::addPrimOp(const string & name,
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
Symbol sym = symbols.create(name2);
v->type = tPrimOp;
v->primOp = new PrimOp(primOp, arity, sym);
v->primOp = NEW PrimOp(primOp, arity, sym);
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl;
baseEnv.values[baseEnvDispl++] = v;
baseEnv.values[0]->attrs->push_back(Attr(sym, v));
@@ -555,7 +528,7 @@ Value & mkString(Value & v, const string & s, const PathSet & context)
{
mkString(v, s.c_str());
if (!context.empty()) {
size_t n = 0;
unsigned int n = 0;
v.string.context = (const char * *)
allocBytes((context.size() + 1) * sizeof(char *));
for (auto & i : context)
@@ -574,17 +547,17 @@ void mkPath(Value & v, const char * s)
inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
{
for (size_t l = var.level; l; --l, env = env->up) ;
for (unsigned int l = var.level; l; --l, env = env->up) ;
if (!var.fromWith) return env->values[var.displ];
while (1) {
if (env->type == Env::HasWithExpr) {
if (!env->haveWithAttrs) {
if (noEval) return 0;
Value * v = allocValue();
evalAttrs(*env->up, (Expr *) env->values[0], *v);
env->values[0] = v;
env->type = Env::HasWithAttrs;
env->haveWithAttrs = true;
}
Bindings::iterator j = env->values[0]->attrs->find(var.name);
if (j != env->values[0]->attrs->end()) {
@@ -593,37 +566,26 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
}
if (!env->prevWith)
throwUndefinedVarError("undefined variable '%1%' at %2%", var.name, var.pos);
for (size_t l = env->prevWith; l; --l, env = env->up) ;
for (unsigned int l = env->prevWith; l; --l, env = env->up) ;
}
}
std::atomic<uint64_t> nrValuesFreed{0};
void finalizeValue(void * obj, void * data)
{
nrValuesFreed++;
}
Value * EvalState::allocValue()
{
nrValues++;
auto v = (Value *) allocBytes(sizeof(Value));
//GC_register_finalizer_no_order(v, finalizeValue, nullptr, nullptr, nullptr);
return v;
return (Value *) allocBytes(sizeof(Value));
}
Env & EvalState::allocEnv(size_t size)
Env & EvalState::allocEnv(unsigned int size)
{
if (size > std::numeric_limits<decltype(Env::size)>::max())
throw Error("environment size %d is too big", size);
assert(size <= std::numeric_limits<decltype(Env::size)>::max());
nrEnvs++;
nrValuesInEnvs += size;
Env * env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *));
env->size = (decltype(Env::size)) size;
env->type = Env::Plain;
env->size = size;
/* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */
@@ -631,7 +593,7 @@ Env & EvalState::allocEnv(size_t size)
}
void EvalState::mkList(Value & v, size_t size)
void EvalState::mkList(Value & v, unsigned int size)
{
clearValue(v);
if (size == 1)
@@ -666,7 +628,7 @@ void EvalState::mkThunk_(Value & v, Expr * expr)
void EvalState::mkPos(Value & v, Pos * pos)
{
if (pos && pos->file.set()) {
if (pos) {
mkAttrs(v, 3);
mkString(*allocAttr(v, sFile), pos->file);
mkInt(*allocAttr(v, sLine), pos->line);
@@ -743,17 +705,7 @@ void EvalState::evalFile(const Path & path_, Value & v)
}
printTalkative("evaluating file '%1%'", path2);
Expr * e = nullptr;
auto j = fileParseCache.find(path2);
if (j != fileParseCache.end())
e = j->second;
if (!e)
e = parseExprFromFile(checkSourcePath(path2));
fileParseCache[path2] = e;
Expr * e = parseExprFromFile(checkSourcePath(path2));
try {
eval(e, v);
} catch (Error & e) {
@@ -769,7 +721,6 @@ void EvalState::evalFile(const Path & path_, Value & v)
void EvalState::resetFileCache()
{
fileEvalCache.clear();
fileParseCache.clear();
}
@@ -854,7 +805,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
/* The recursive attributes are evaluated in the new
environment, while the inherited attributes are evaluated
in the original environment. */
size_t displ = 0;
unsigned int displ = 0;
for (auto & i : attrs) {
Value * vAttr;
if (hasOverrides && !i.second.inherited) {
@@ -928,7 +879,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
/* The recursive attributes are evaluated in the new environment,
while the inherited attributes are evaluated in the original
environment. */
size_t displ = 0;
unsigned int displ = 0;
for (auto & i : attrs->attrs)
env2.values[displ++] = i.second.e->maybeThunk(state, i.second.inherited ? env : env2);
@@ -939,7 +890,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
void ExprList::eval(EvalState & state, Env & env, Value & v)
{
state.mkList(v, elems.size());
for (size_t n = 0; n < elems.size(); ++n)
for (unsigned int n = 0; n < elems.size(); ++n)
v.listElems()[n] = elems[n]->maybeThunk(state, env);
}
@@ -1061,22 +1012,22 @@ void ExprApp::eval(EvalState & state, Env & env, Value & v)
void EvalState::callPrimOp(Value & fun, Value & arg, Value & v, const Pos & pos)
{
/* Figure out the number of arguments still needed. */
size_t argsDone = 0;
unsigned int argsDone = 0;
Value * primOp = &fun;
while (primOp->type == tPrimOpApp) {
argsDone++;
primOp = primOp->primOpApp.left;
}
assert(primOp->type == tPrimOp);
auto arity = primOp->primOp->arity;
auto argsLeft = arity - argsDone;
unsigned int arity = primOp->primOp->arity;
unsigned int argsLeft = arity - argsDone;
if (argsLeft == 1) {
/* We have all the arguments, so call the primop. */
/* Put all the arguments in an array. */
Value * vArgs[arity];
auto n = arity - 1;
unsigned int n = arity - 1;
vArgs[n--] = &arg;
for (Value * arg = &fun; arg->type == tPrimOpApp; arg = arg->primOpApp.left)
vArgs[n--] = arg->primOpApp.right;
@@ -1097,8 +1048,6 @@ void EvalState::callPrimOp(Value & fun, Value & arg, Value & v, const Pos & pos)
void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & pos)
{
forceValue(fun, pos);
if (fun.type == tPrimOp || fun.type == tPrimOpApp) {
callPrimOp(fun, arg, v, pos);
return;
@@ -1114,8 +1063,10 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
auto & fun2 = *allocValue();
fun2 = fun;
/* !!! Should we use the attr pos here? */
forceValue(*found->value, pos);
Value v2;
callFunction(*found->value, fun2, v2, pos);
forceValue(v2, pos);
return callFunction(v2, arg, v, pos);
}
}
@@ -1125,13 +1076,13 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
ExprLambda & lambda(*fun.lambda.fun);
auto size =
unsigned int size =
(lambda.arg.empty() ? 0 : 1) +
(lambda.matchAttrs ? lambda.formals->formals.size() : 0);
Env & env2(allocEnv(size));
env2.up = fun.lambda.env;
size_t displ = 0;
unsigned int displ = 0;
if (!lambda.matchAttrs)
env2.values[displ++] = &arg;
@@ -1145,7 +1096,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
/* For each formal argument, get the actual argument. If
there is no matching actual argument but the formal
argument has a default, use the default. */
size_t attrsUsed = 0;
unsigned int attrsUsed = 0;
for (auto & i : lambda.formals->formals) {
Bindings::iterator j = arg.attrs->find(i.name);
if (j == arg.attrs->end()) {
@@ -1202,6 +1153,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
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);
@@ -1236,7 +1188,7 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v)
Env & env2(state.allocEnv(1));
env2.up = &env;
env2.prevWith = prevWith;
env2.type = Env::HasWithExpr;
env2.haveWithAttrs = false;
env2.values[0] = (Value *) attrs;
body->eval(state, env2, v);
@@ -1342,15 +1294,15 @@ void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v)
}
void EvalState::concatLists(Value & v, size_t nrLists, Value * * lists, const Pos & pos)
void EvalState::concatLists(Value & v, unsigned int nrLists, Value * * lists, const Pos & pos)
{
nrListConcats++;
Value * nonEmpty = 0;
size_t len = 0;
for (size_t n = 0; n < nrLists; ++n) {
unsigned int len = 0;
for (unsigned int n = 0; n < nrLists; ++n) {
forceList(*lists[n], pos);
auto l = lists[n]->listSize();
unsigned int l = lists[n]->listSize();
len += l;
if (l) nonEmpty = lists[n];
}
@@ -1362,10 +1314,9 @@ void EvalState::concatLists(Value & v, size_t nrLists, Value * * lists, const Po
mkList(v, len);
auto out = v.listElems();
for (size_t n = 0, pos = 0; n < nrLists; ++n) {
auto l = lists[n]->listSize();
if (l)
memcpy(out + pos, lists[n]->listElems(), l * sizeof(Value *));
for (unsigned int n = 0, pos = 0; n < nrLists; ++n) {
unsigned int l = lists[n]->listSize();
memcpy(out + pos, lists[n]->listElems(), l * sizeof(Value *));
pos += l;
}
}
@@ -1458,7 +1409,7 @@ void EvalState::forceValueDeep(Value & v)
}
else if (v.isList()) {
for (size_t n = 0; n < v.listSize(); ++n)
for (unsigned int n = 0; n < v.listSize(); ++n)
recurse(*v.listElems()[n]);
}
};
@@ -1585,6 +1536,7 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
if (v.type == tAttrs) {
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);
@@ -1609,7 +1561,7 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
if (v.isList()) {
string result;
for (size_t n = 0; n < v.listSize(); ++n) {
for (unsigned int n = 0; n < v.listSize(); ++n) {
result += coerceToString(pos, *v.listElems()[n],
context, coerceMore, copyToStore);
if (n < v.listSize() - 1
@@ -1696,7 +1648,7 @@ bool EvalState::eqValues(Value & v1, Value & v2)
case tList2:
case tListN:
if (v1.listSize() != v2.listSize()) return false;
for (size_t n = 0; n < v1.listSize(); ++n)
for (unsigned int n = 0; n < v1.listSize(); ++n)
if (!eqValues(*v1.listElems()[n], *v2.listElems()[n])) return false;
return true;
@@ -1738,9 +1690,12 @@ bool EvalState::eqValues(Value & v1, Value & v2)
}
}
void EvalState::printStats()
{
bool showStats = getEnv("NIX_SHOW_STATS", "0") != "0";
Verbosity v = showStats ? lvlInfo : lvlDebug;
printMsg(v, "evaluation statistics:");
struct rusage buf;
getrusage(RUSAGE_SELF, &buf);
@@ -1751,107 +1706,62 @@ void EvalState::printStats()
uint64_t bValues = nrValues * sizeof(Value);
uint64_t bAttrsets = nrAttrsets * sizeof(Bindings) + nrAttrsInAttrsets * sizeof(Attr);
printMsg(v, format(" time elapsed: %1%") % cpuTime);
printMsg(v, format(" size of a value: %1%") % sizeof(Value));
printMsg(v, format(" size of an attr: %1%") % sizeof(Attr));
printMsg(v, format(" environments allocated count: %1%") % nrEnvs);
printMsg(v, format(" environments allocated bytes: %1%") % bEnvs);
printMsg(v, format(" list elements count: %1%") % nrListElems);
printMsg(v, format(" list elements bytes: %1%") % bLists);
printMsg(v, format(" list concatenations: %1%") % nrListConcats);
printMsg(v, format(" values allocated count: %1%") % nrValues);
printMsg(v, format(" values allocated bytes: %1%") % bValues);
printMsg(v, format(" sets allocated: %1% (%2% bytes)") % nrAttrsets % bAttrsets);
printMsg(v, format(" right-biased unions: %1%") % nrOpUpdates);
printMsg(v, format(" values copied in right-biased unions: %1%") % nrOpUpdateValuesCopied);
printMsg(v, format(" symbols in symbol table: %1%") % symbols.size());
printMsg(v, format(" size of symbol table: %1%") % symbols.totalSize());
printMsg(v, format(" number of thunks: %1%") % nrThunks);
printMsg(v, format(" number of thunks avoided: %1%") % nrAvoided);
printMsg(v, format(" number of attr lookups: %1%") % nrLookups);
printMsg(v, format(" number of primop calls: %1%") % nrPrimOpCalls);
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);
#endif
if (showStats) {
auto outPath = getEnv("NIX_SHOW_STATS_PATH","-");
std::fstream fs;
if (outPath != "-")
fs.open(outPath, std::fstream::out);
JSONObject topObj(outPath == "-" ? std::cerr : fs, true);
topObj.attr("cpuTime",cpuTime);
{
auto envs = topObj.object("envs");
envs.attr("number", nrEnvs);
envs.attr("elements", nrValuesInEnvs);
envs.attr("bytes", bEnvs);
}
{
auto lists = topObj.object("list");
lists.attr("elements", nrListElems);
lists.attr("bytes", bLists);
lists.attr("concats", nrListConcats);
}
{
auto values = topObj.object("values");
values.attr("number", nrValues);
values.attr("bytes", bValues);
}
{
auto syms = topObj.object("symbols");
syms.attr("number", symbols.size());
syms.attr("bytes", symbols.totalSize());
}
{
auto sets = topObj.object("sets");
sets.attr("number", nrAttrsets);
sets.attr("bytes", bAttrsets);
sets.attr("elements", nrAttrsInAttrsets);
}
{
auto sizes = topObj.object("sizes");
sizes.attr("Env", sizeof(Env));
sizes.attr("Value", sizeof(Value));
sizes.attr("Bindings", sizeof(Bindings));
sizes.attr("Attr", sizeof(Attr));
}
topObj.attr("nrOpUpdates", nrOpUpdates);
topObj.attr("nrOpUpdateValuesCopied", nrOpUpdateValuesCopied);
topObj.attr("nrThunks", nrThunks);
topObj.attr("nrAvoided", nrAvoided);
topObj.attr("nrLookups", nrLookups);
topObj.attr("nrPrimOpCalls", nrPrimOpCalls);
topObj.attr("nrFunctionCalls", nrFunctionCalls);
#if HAVE_BOEHMGC
{
auto gc = topObj.object("gc");
gc.attr("heapSize", heapSize);
gc.attr("totalBytes", totalBytes);
}
printMsg(v, format(" current Boehm heap size: %1% bytes") % heapSize);
printMsg(v, format(" total Boehm heap allocations: %1% bytes") % totalBytes);
#endif
if (countCalls) {
{
auto obj = topObj.object("primops");
for (auto & i : primOpCalls)
obj.attr(i.first, i.second);
}
{
auto list = topObj.list("functions");
for (auto & i : functionCalls) {
auto obj = list.object();
if (i.first->name.set())
obj.attr("name", (const string &) i.first->name);
else
obj.attr("name", nullptr);
if (i.first->pos) {
obj.attr("file", (const string &) i.first->pos.file);
obj.attr("line", i.first->pos.line);
obj.attr("column", i.first->pos.column);
}
obj.attr("count", i.second);
}
}
{
auto list = topObj.list("attributes");
for (auto & i : attrSelects) {
auto obj = list.object();
if (i.first) {
obj.attr("file", (const string &) i.first.file);
obj.attr("line", i.first.line);
obj.attr("column", i.first.column);
}
obj.attr("count", i.second);
}
}
}
if (countCalls) {
v = lvlInfo;
printMsg(v, format("calls to %1% primops:") % primOpCalls.size());
typedef std::multimap<unsigned int, Symbol> PrimOpCalls_;
PrimOpCalls_ 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_;
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_;
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);
if (getEnv("NIX_SHOW_SYMBOLS", "0") != "0") {
auto list = topObj.list("symbols");
symbols.dump([&](const std::string & s) { list.elem(s); });
}
}
}
@@ -1899,7 +1809,7 @@ size_t valueSize(Value & v)
if (seen.find(v.listElems()) == seen.end()) {
seen.insert(v.listElems());
sz += v.listSize() * sizeof(Value *);
for (size_t n = 0; n < v.listSize(); ++n)
for (unsigned int n = 0; n < v.listSize(); ++n)
sz += doValue(*v.listElems()[n]);
}
break;
@@ -1935,10 +1845,9 @@ size_t valueSize(Value & v)
size_t sz = sizeof(Env) + sizeof(Value *) * env.size;
if (env.type != Env::HasWithExpr)
for (size_t i = 0; i < env.size; ++i)
if (env.values[i])
sz += doValue(*env.values[i]);
for (unsigned int i = 0; i < env.size; ++i)
if (env.values[i])
sz += doValue(*env.values[i]);
if (env.up) sz += doEnv(*env.up);
@@ -1967,9 +1876,4 @@ std::ostream & operator << (std::ostream & str, const ExternalValueBase & v) {
}
EvalSettings evalSettings;
static GlobalConfig::Register r1(&evalSettings);
}

View File

@@ -5,10 +5,8 @@
#include "nixexpr.hh"
#include "symbol-table.hh"
#include "hash.hh"
#include "config.hh"
#include <map>
#include <unordered_map>
namespace nix {
@@ -36,8 +34,8 @@ struct Env
{
Env * up;
unsigned short size; // used by valueSize
unsigned short prevWith:14; // nr of levels up to next `with' environment
enum { Plain = 0, HasWithExpr, HasWithAttrs } type:2;
unsigned short prevWith:15; // nr of levels up to next `with' environment
unsigned short haveWithAttrs:1;
Value * values[0];
};
@@ -81,7 +79,7 @@ public:
/* The allowed filesystem paths in restricted or pure evaluation
mode. */
std::optional<PathSet> allowedPaths;
std::experimental::optional<PathSet> allowedPaths;
Value vEmptySet;
@@ -90,14 +88,6 @@ public:
private:
SrcToStore srcToStore;
/* A cache from path names to parse trees. */
#if HAVE_BOEHMGC
typedef std::map<Path, Expr *, std::less<Path>, traceable_allocator<std::pair<const Path, Expr *> > > FileParseCache;
#else
typedef std::map<Path, Expr *> FileParseCache;
#endif
FileParseCache fileParseCache;
/* A cache from path names to values. */
#if HAVE_BOEHMGC
typedef std::map<Path, Value, std::less<Path>, traceable_allocator<std::pair<const Path, Value> > > FileEvalCache;
@@ -110,9 +100,6 @@ private:
std::map<std::string, std::pair<bool, std::string>> searchPathResolved;
/* Cache used by checkSourcePath(). */
std::unordered_map<Path, Path> resolvedPaths;
public:
EvalState(const Strings & _searchPath, ref<Store> store);
@@ -227,7 +214,7 @@ private:
Value * addConstant(const string & name, Value & v);
Value * addPrimOp(const string & name,
size_t arity, PrimOpFun primOp);
unsigned int arity, PrimOpFun primOp);
public:
@@ -261,18 +248,18 @@ public:
/* Allocation primitives. */
Value * allocValue();
Env & allocEnv(size_t size);
Env & allocEnv(unsigned int size);
Value * allocAttr(Value & vAttrs, const Symbol & name);
Bindings * allocBindings(size_t capacity);
Bindings * allocBindings(Bindings::size_t capacity);
void mkList(Value & v, size_t length);
void mkAttrs(Value & v, size_t capacity);
void mkList(Value & v, unsigned int length);
void mkAttrs(Value & v, unsigned int capacity);
void mkThunk_(Value & v, Expr * expr);
void mkPos(Value & v, Pos * pos);
void concatLists(Value & v, size_t nrLists, Value * * lists, const Pos & pos);
void concatLists(Value & v, unsigned int nrLists, Value * * lists, const Pos & pos);
/* Print statistics. */
void printStats();
@@ -295,15 +282,15 @@ private:
bool countCalls;
typedef std::map<Symbol, size_t> PrimOpCalls;
typedef std::map<Symbol, unsigned int> PrimOpCalls;
PrimOpCalls primOpCalls;
typedef std::map<ExprLambda *, size_t> FunctionCalls;
typedef std::map<ExprLambda *, unsigned int> FunctionCalls;
FunctionCalls functionCalls;
void incrFunctionCall(ExprLambda * fun);
typedef std::map<Pos, size_t> AttrSelects;
typedef std::map<Pos, unsigned int> AttrSelects;
AttrSelects attrSelects;
friend struct ExprOpUpdate;
@@ -316,9 +303,6 @@ private:
/* Return a string representing the type of the value `v'. */
string showType(const Value & v);
/* Decode a context string !<name>!<path> into a pair <path,
name>. */
std::pair<string, string> decodeContext(const string & s);
/* If `path' refers to a directory, then append "/default.nix". */
Path resolveExprPath(Path path);
@@ -332,25 +316,4 @@ struct InvalidPathError : EvalError
#endif
};
struct EvalSettings : Config
{
Setting<bool> enableNativeCode{this, false, "allow-unsafe-native-code-during-evaluation",
"Whether builtin functions that allow executing native code should be enabled."};
Setting<bool> restrictEval{this, false, "restrict-eval",
"Whether to restrict file system access to paths in $NIX_PATH, "
"and network access to the URI prefixes listed in 'allowed-uris'."};
Setting<bool> pureEval{this, false, "pure-eval",
"Whether to restrict file system and network access to files specified by cryptographic hash."};
Setting<bool> enableImportFromDerivation{this, true, "allow-import-from-derivation",
"Whether the evaluator allows importing the result of a derivation."};
Setting<Strings> allowedUris{this, {}, "allowed-uris",
"Prefixes of URIs that builtin functions such as fetchurl and fetchGit are allowed to fetch."};
};
extern EvalSettings evalSettings;
}

View File

@@ -295,7 +295,7 @@ static bool getDerivation(EvalState & state, Value & v,
}
std::optional<DrvInfo> getDerivation(EvalState & state, Value & v,
std::experimental::optional<DrvInfo> getDerivation(EvalState & state, Value & v,
bool ignoreAssertionFailures)
{
Done done;

View File

@@ -44,7 +44,7 @@ public:
string queryDrvPath() const;
string queryOutPath() const;
string queryOutputName() const;
/** Return the list of outputs. The "outputs to install" are determined by `meta.outputsToInstall`. */
/** Return the list of outputs. The "outputs to install" are determined by `mesa.outputsToInstall`. */
Outputs queryOutputs(bool onlyOutputsToInstall = false);
StringSet queryMetaNames();
@@ -78,7 +78,7 @@ typedef list<DrvInfo> DrvInfos;
/* If value `v' denotes a derivation, return a DrvInfo object
describing it. Otherwise return nothing. */
std::optional<DrvInfo> getDerivation(EvalState & state,
std::experimental::optional<DrvInfo> getDerivation(EvalState & state,
Value & v, bool ignoreAssertionFailures);
void getDerivations(EvalState & state, Value & v, const string & pathPrefix,

View File

@@ -110,7 +110,7 @@ static void parseJSON(EvalState & state, const char * & s, Value & v)
if (number_type == tFloat)
mkFloat(v, stod(tmp_number));
else
mkInt(v, stol(tmp_number));
mkInt(v, stoi(tmp_number));
} catch (std::invalid_argument e) {
throw JSONParseError("invalid JSON number");
} catch (std::out_of_range e) {

View File

@@ -6,14 +6,12 @@
%option nounput noyy_top_state
%s DEFAULT
%x STRING
%x IND_STRING
%x INSIDE_DOLLAR_CURLY
%{
#include <boost/lexical_cast.hpp>
#include "nixexpr.hh"
#include "parser-tab.hh"
@@ -87,7 +85,6 @@ static Expr * unescapeStr(SymbolTable & symbols, const char * s, size_t length)
%}
ANY .|\n
ID [a-zA-Z\_][a-zA-Z0-9\_\'\-]*
INT [0-9]+
FLOAT (([1-9][0-9]*\.[0-9]*)|(0?\.[0-9]+))([Ee][+-]?[0-9]+)?
@@ -99,6 +96,8 @@ URI [a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~
%%
<INITIAL,INSIDE_DOLLAR_CURLY>{
if { return IF; }
then { return THEN; }
@@ -124,11 +123,9 @@ or { return OR_KW; }
{ID} { yylval->id = strdup(yytext); return ID; }
{INT} { errno = 0;
try {
yylval->n = boost::lexical_cast<int64_t>(yytext);
} catch (const boost::bad_lexical_cast &) {
yylval->n = strtol(yytext, 0, 10);
if (errno != 0)
throw ParseError(format("invalid integer '%1%'") % yytext);
}
return INT;
}
{FLOAT} { errno = 0;
@@ -138,28 +135,26 @@ or { return OR_KW; }
return FLOAT;
}
\$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; }
\$\{ { PUSH_STATE(INSIDE_DOLLAR_CURLY); return DOLLAR_CURLY; }
}
\} { /* State INITIAL only exists at the bottom of the stack and is
used as a marker. DEFAULT replaces it everywhere else.
Popping when in INITIAL state causes an empty stack exception,
so don't */
if (YYSTATE != INITIAL)
POP_STATE();
return '}';
}
\{ { PUSH_STATE(DEFAULT); return '{'; }
\} { return '}'; }
<INSIDE_DOLLAR_CURLY>\} { POP_STATE(); return '}'; }
\{ { return '{'; }
<INSIDE_DOLLAR_CURLY>\{ { PUSH_STATE(INSIDE_DOLLAR_CURLY); return '{'; }
\" { PUSH_STATE(STRING); return '"'; }
<STRING>([^\$\"\\]|\$[^\{\"\\]|\\{ANY}|\$\\{ANY})*\$/\" |
<STRING>([^\$\"\\]|\$[^\{\"\\]|\\{ANY}|\$\\{ANY})+ {
<INITIAL,INSIDE_DOLLAR_CURLY>\" {
PUSH_STATE(STRING); return '"';
}
<STRING>([^\$\"\\]|\$[^\{\"\\]|\\.|\$\\.)*\$/\" |
<STRING>([^\$\"\\]|\$[^\{\"\\]|\\.|\$\\.)+ {
/* It is impossible to match strings ending with '$' with one
regex because trailing contexts are only valid at the end
of a rule. (A sane but undocumented limitation.) */
yylval->e = unescapeStr(data->symbols, yytext, yyleng);
return STR;
}
<STRING>\$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; }
<STRING>\$\{ { PUSH_STATE(INSIDE_DOLLAR_CURLY); return DOLLAR_CURLY; }
<STRING>\" { POP_STATE(); return '"'; }
<STRING>\$|\\|\$\\ {
/* This can only occur when we reach EOF, otherwise the above
@@ -169,7 +164,7 @@ or { return OR_KW; }
return STR;
}
\'\'(\ *\n)? { PUSH_STATE(IND_STRING); return IND_STRING_OPEN; }
<INITIAL,INSIDE_DOLLAR_CURLY>\'\'(\ *\n)? { PUSH_STATE(IND_STRING); return IND_STRING_OPEN; }
<IND_STRING>([^\$\']|\$[^\{\']|\'[^\'\$])+ {
yylval->e = new ExprIndStr(yytext);
return IND_STR;
@@ -183,17 +178,18 @@ or { return OR_KW; }
yylval->e = new ExprIndStr("''");
return IND_STR;
}
<IND_STRING>\'\'\\{ANY} {
<IND_STRING>\'\'\\. {
yylval->e = unescapeStr(data->symbols, yytext + 2, yyleng - 2);
return IND_STR;
}
<IND_STRING>\$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; }
<IND_STRING>\$\{ { PUSH_STATE(INSIDE_DOLLAR_CURLY); return DOLLAR_CURLY; }
<IND_STRING>\'\' { POP_STATE(); return IND_STRING_CLOSE; }
<IND_STRING>\' {
yylval->e = new ExprIndStr("'");
return IND_STR;
}
<INITIAL,INSIDE_DOLLAR_CURLY>{
{PATH} { if (yytext[yyleng-1] == '/')
throw ParseError("path '%s' has a trailing slash", yytext);
@@ -212,11 +208,11 @@ or { return OR_KW; }
\#[^\r\n]* /* single-line comments */
\/\*([^*]|\*+[^*/])*\*+\/ /* long comments */
{ANY} {
/* Don't return a negative number, as this will cause
Bison to stop parsing without an error. */
return (unsigned char) yytext[0];
}
. return yytext[0];
}
<<EOF>> { data->atEnd = true; return 0; }
%%

View File

@@ -6,7 +6,7 @@ libexpr_DIR := $(d)
libexpr_SOURCES := $(wildcard $(d)/*.cc) $(wildcard $(d)/primops/*.cc) $(d)/lexer-tab.cc $(d)/parser-tab.cc
libexpr_LIBS = libutil libstore
libexpr_LIBS = libutil libstore libformat
libexpr_LDFLAGS =
ifneq ($(OS), FreeBSD)

View File

@@ -7,4 +7,4 @@ Description: Nix Package Manager
Version: @PACKAGE_VERSION@
Requires: nix-store bdw-gc
Libs: -L${libdir} -lnixexpr
Cflags: -I${includedir}/nix -std=c++17
Cflags: -I${includedir}/nix -std=c++14

View File

@@ -10,7 +10,7 @@ namespace nix {
/* Displaying abstract syntax trees. */
std::ostream & operator << (std::ostream & str, const Expr & e)
std::ostream & operator << (std::ostream & str, Expr & e)
{
e.show(str);
return str;
@@ -58,48 +58,48 @@ std::ostream & operator << (std::ostream & str, const Symbol & sym)
return str;
}
void Expr::show(std::ostream & str) const
void Expr::show(std::ostream & str)
{
abort();
}
void ExprInt::show(std::ostream & str) const
void ExprInt::show(std::ostream & str)
{
str << n;
}
void ExprFloat::show(std::ostream & str) const
void ExprFloat::show(std::ostream & str)
{
str << nf;
}
void ExprString::show(std::ostream & str) const
void ExprString::show(std::ostream & str)
{
showString(str, s);
}
void ExprPath::show(std::ostream & str) const
void ExprPath::show(std::ostream & str)
{
str << s;
}
void ExprVar::show(std::ostream & str) const
void ExprVar::show(std::ostream & str)
{
str << name;
}
void ExprSelect::show(std::ostream & str) const
void ExprSelect::show(std::ostream & str)
{
str << "(" << *e << ")." << showAttrPath(attrPath);
if (def) str << " or (" << *def << ")";
}
void ExprOpHasAttr::show(std::ostream & str) const
void ExprOpHasAttr::show(std::ostream & str)
{
str << "((" << *e << ") ? " << showAttrPath(attrPath) << ")";
}
void ExprAttrs::show(std::ostream & str) const
void ExprAttrs::show(std::ostream & str)
{
if (recursive) str << "rec ";
str << "{ ";
@@ -113,7 +113,7 @@ void ExprAttrs::show(std::ostream & str) const
str << "}";
}
void ExprList::show(std::ostream & str) const
void ExprList::show(std::ostream & str)
{
str << "[ ";
for (auto & i : elems)
@@ -121,7 +121,7 @@ void ExprList::show(std::ostream & str) const
str << "]";
}
void ExprLambda::show(std::ostream & str) const
void ExprLambda::show(std::ostream & str)
{
str << "(";
if (matchAttrs) {
@@ -143,7 +143,7 @@ void ExprLambda::show(std::ostream & str) const
str << ": " << *body << ")";
}
void ExprLet::show(std::ostream & str) const
void ExprLet::show(std::ostream & str)
{
str << "(let ";
for (auto & i : attrs->attrs)
@@ -155,27 +155,27 @@ void ExprLet::show(std::ostream & str) const
str << "in " << *body << ")";
}
void ExprWith::show(std::ostream & str) const
void ExprWith::show(std::ostream & str)
{
str << "(with " << *attrs << "; " << *body << ")";
}
void ExprIf::show(std::ostream & str) const
void ExprIf::show(std::ostream & str)
{
str << "(if " << *cond << " then " << *then << " else " << *else_ << ")";
}
void ExprAssert::show(std::ostream & str) const
void ExprAssert::show(std::ostream & str)
{
str << "assert " << *cond << "; " << *body;
}
void ExprOpNot::show(std::ostream & str) const
void ExprOpNot::show(std::ostream & str)
{
str << "(! " << *e << ")";
}
void ExprConcatStrings::show(std::ostream & str) const
void ExprConcatStrings::show(std::ostream & str)
{
bool first = true;
str << "(";
@@ -186,7 +186,7 @@ void ExprConcatStrings::show(std::ostream & str) const
str << ")";
}
void ExprPos::show(std::ostream & str) const
void ExprPos::show(std::ostream & str)
{
str << "__curPos";
}

View File

@@ -11,6 +11,7 @@ namespace nix {
MakeError(EvalError, Error)
MakeError(ParseError, Error)
MakeError(IncompleteParseError, ParseError)
MakeError(AssertionError, EvalError)
MakeError(ThrownError, AssertionError)
MakeError(Abort, EvalError)
@@ -75,17 +76,17 @@ string showAttrPath(const AttrPath & attrPath);
struct Expr
{
virtual ~Expr() { };
virtual void show(std::ostream & str) const;
virtual void show(std::ostream & str);
virtual void bindVars(const StaticEnv & env);
virtual void eval(EvalState & state, Env & env, Value & v);
virtual Value * maybeThunk(EvalState & state, Env & env);
virtual void setName(Symbol & name);
};
std::ostream & operator << (std::ostream & str, const Expr & e);
std::ostream & operator << (std::ostream & str, Expr & e);
#define COMMON_METHODS \
void show(std::ostream & str) const; \
void show(std::ostream & str); \
void eval(EvalState & state, Env & env, Value & v); \
void bindVars(const StaticEnv & env);
@@ -254,7 +255,7 @@ struct ExprWith : Expr
{
Pos pos;
Expr * attrs, * body;
size_t prevWith;
unsigned int prevWith;
ExprWith(const Pos & pos, Expr * attrs, Expr * body) : pos(pos), attrs(attrs), body(body) { };
COMMON_METHODS
};
@@ -282,13 +283,13 @@ struct ExprOpNot : Expr
};
#define MakeBinOp(name, s) \
struct name : Expr \
struct Expr##name : Expr \
{ \
Pos pos; \
Expr * e1, * e2; \
name(Expr * e1, Expr * e2) : e1(e1), e2(e2) { }; \
name(const Pos & pos, Expr * e1, Expr * e2) : pos(pos), e1(e1), e2(e2) { }; \
void show(std::ostream & str) const \
Expr##name(Expr * e1, Expr * e2) : e1(e1), e2(e2) { }; \
Expr##name(const Pos & pos, Expr * e1, Expr * e2) : pos(pos), e1(e1), e2(e2) { }; \
void show(std::ostream & str) \
{ \
str << "(" << *e1 << " " s " " << *e2 << ")"; \
} \
@@ -299,14 +300,14 @@ struct ExprOpNot : Expr
void eval(EvalState & state, Env & env, Value & v); \
};
MakeBinOp(ExprApp, "")
MakeBinOp(ExprOpEq, "==")
MakeBinOp(ExprOpNEq, "!=")
MakeBinOp(ExprOpAnd, "&&")
MakeBinOp(ExprOpOr, "||")
MakeBinOp(ExprOpImpl, "->")
MakeBinOp(ExprOpUpdate, "//")
MakeBinOp(ExprOpConcatLists, "++")
MakeBinOp(App, "")
MakeBinOp(OpEq, "==")
MakeBinOp(OpNEq, "!=")
MakeBinOp(OpAnd, "&&")
MakeBinOp(OpOr, "||")
MakeBinOp(OpImpl, "->")
MakeBinOp(OpUpdate, "//")
MakeBinOp(OpConcatLists, "++")
struct ExprConcatStrings : Expr
{

View File

@@ -1,7 +1,7 @@
%glr-parser
%pure-parser
%locations
%define parse.error verbose
%error-verbose
%defines
/* %no-lines */
%parse-param { void * scanner }
@@ -31,10 +31,12 @@ namespace nix {
Path basePath;
Symbol path;
string error;
bool atEnd;
Symbol sLetBody;
ParseData(EvalState & state)
: state(state)
, symbols(state.symbols)
, atEnd(false)
, sLetBody(symbols.create("<let-body>"))
{ };
};
@@ -134,8 +136,8 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex
whitespace-only final lines are not taken into account. (So
the " " in "\n ''" is ignored, but the " " in "\n foo''" is.) */
bool atStartOfLine = true; /* = seen only whitespace in the current line */
size_t minIndent = 1000000;
size_t curIndent = 0;
unsigned int minIndent = 1000000;
unsigned int curIndent = 0;
for (auto & i : es) {
ExprIndStr * e = dynamic_cast<ExprIndStr *>(i);
if (!e) {
@@ -146,7 +148,7 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex
}
continue;
}
for (size_t j = 0; j < e->s.size(); ++j) {
for (unsigned int j = 0; j < e->s.size(); ++j) {
if (atStartOfLine) {
if (e->s[j] == ' ')
curIndent++;
@@ -168,8 +170,8 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex
/* Strip spaces from each line. */
vector<Expr *> * es2 = new vector<Expr *>;
atStartOfLine = true;
size_t curDropped = 0;
size_t n = es.size();
unsigned int curDropped = 0;
unsigned int n = es.size();
for (vector<Expr *>::iterator i = es.begin(); i != es.end(); ++i, --n) {
ExprIndStr * e = dynamic_cast<ExprIndStr *>(*i);
if (!e) {
@@ -180,7 +182,7 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex
}
string s2;
for (size_t j = 0; j < e->s.size(); ++j) {
for (unsigned int j = 0; j < e->s.size(); ++j) {
if (atStartOfLine) {
if (e->s[j] == ' ') {
if (curDropped++ >= minIndent)
@@ -273,11 +275,11 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err
%token IND_STRING_OPEN IND_STRING_CLOSE
%token ELLIPSIS
%right IMPL
%nonassoc IMPL
%left OR
%left AND
%nonassoc EQ NEQ
%nonassoc '<' '>' LEQ GEQ
%left '<' '>' LEQ GEQ
%right UPDATE
%left NOT
%left '+' '-'
@@ -539,7 +541,12 @@ Expr * EvalState::parse(const char * text,
int res = yyparse(scanner, &data);
yylex_destroy(scanner);
if (res) throw ParseError(data.error);
if (res) {
if (data.atEnd)
throw IncompleteParseError(data.error);
else
throw ParseError(data.error);
}
data.result->bindVars(staticEnv);

View File

@@ -73,7 +73,7 @@ void EvalState::realiseContext(const PathSet & context)
if (drvs.empty()) return;
if (!evalSettings.enableImportFromDerivation)
if (!settings.enableImportFromDerivation)
throw EvalError(format("attempted to realize '%1%' during evaluation but 'allow-import-from-derivation' is false") % *(drvs.begin()));
/* For performance, prefetch all substitute info. */
@@ -271,18 +271,7 @@ static void prim_isNull(EvalState & state, const Pos & pos, Value * * args, Valu
static void prim_isFunction(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceValue(*args[0]);
bool res;
switch (args[0]->type) {
case tLambda:
case tPrimOp:
case tPrimOpApp:
res = true;
break;
default:
res = false;
break;
}
mkBool(v, res);
mkBool(v, args[0]->type == tLambda);
}
@@ -315,12 +304,6 @@ static void prim_isBool(EvalState & state, const Pos & pos, Value * * args, Valu
mkBool(v, args[0]->type == tBool);
}
/* Determine whether the argument is a path. */
static void prim_isPath(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceValue(*args[0]);
mkBool(v, args[0]->type == tPath);
}
struct CompareValues
{
@@ -341,8 +324,6 @@ struct CompareValues
return strcmp(v1->string.s, v2->string.s) < 0;
case tPath:
return strcmp(v1->path, v2->path) < 0;
case tAttrs:
return v1 < v2; // FIXME
default:
throw EvalError(format("cannot compare %1% with %2%") % showType(*v1) % showType(*v2));
}
@@ -472,7 +453,7 @@ static void prim_tryEval(EvalState & state, const Pos & pos, Value * * args, Val
static void prim_getEnv(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
string name = state.forceStringNoCtx(*args[0], pos);
mkString(v, evalSettings.restrictEval || evalSettings.pureEval ? "" : getEnv(name));
mkString(v, settings.restrictEval || settings.pureEval ? "" : getEnv(name));
}
@@ -563,7 +544,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
PathSet context;
std::optional<std::string> outputHash;
std::experimental::optional<std::string> outputHash;
std::string outputHashAlgo;
bool outputHashRecursive = false;
@@ -695,12 +676,21 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
}
}
/* See prim_unsafeDiscardOutputDependency. */
else if (path.at(0) == '~')
drv.inputSrcs.insert(string(path, 1));
/* Handle derivation outputs of the form !<name>!<path>. */
else if (path.at(0) == '!') {
std::pair<string, string> ctx = decodeContext(path);
drv.inputDrvs[ctx.first].insert(ctx.second);
}
/* Handle derivation contexts returned by
builtins.storePath. */
else if (isDerivation(path))
drv.inputDrvs[path] = state.store->queryDerivationOutputNames(path);
/* Otherwise it's a source file. */
else
drv.inputSrcs.insert(path);
@@ -723,14 +713,16 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
if (outputs.size() != 1 || *(outputs.begin()) != "out")
throw Error(format("multiple outputs are not supported in fixed-output derivations, at %1%") % posDrvName);
HashType ht = outputHashAlgo.empty() ? htUnknown : parseHashType(outputHashAlgo);
HashType ht = parseHashType(outputHashAlgo);
if (ht == htUnknown)
throw EvalError(format("unknown hash algorithm '%1%', at %2%") % outputHashAlgo % posDrvName);
Hash h(*outputHash, ht);
outputHash = h.to_string(Base16, false);
if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;
Path outPath = state.store->makeFixedOutputPath(outputHashRecursive, h, drvName);
if (!jsonObject) drv.env["out"] = outPath;
drv.outputs["out"] = DerivationOutput(outPath,
(outputHashRecursive ? "r:" : "") + printHashType(h.type),
h.to_string(Base16, false));
drv.outputs["out"] = DerivationOutput(outPath, outputHashAlgo, *outputHash);
}
else {
@@ -863,7 +855,7 @@ static void prim_baseNameOf(EvalState & state, const Pos & pos, Value * * args,
static void prim_dirOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
Path dir = dirOf(state.coerceToString(pos, *args[0], context, false, false));
Path dir = dirOf(state.coerceToPath(pos, *args[0], context));
if (args[0]->type == tPath) mkPath(v, dir.c_str()); else mkString(v, dir, context);
}
@@ -1003,8 +995,13 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
PathSet refs;
for (auto path : context) {
if (path.at(0) != '/')
throw EvalError(format("in 'toFile': the file '%1%' cannot refer to derivation outputs, at %2%") % name % pos);
if (path.at(0) == '=') path = string(path, 1);
if (isDerivation(path)) {
/* See prim_unsafeDiscardOutputDependency. */
if (path.at(0) != '~')
throw EvalError(format("in 'toFile': the file '%1%' cannot refer to derivation outputs, at %2%") % name % pos);
path = string(path, 1);
}
refs.insert(path);
}
@@ -1023,7 +1020,7 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
static void addPath(EvalState & state, const Pos & pos, const string & name, const Path & path_,
Value * filterFun, bool recursive, const Hash & expectedHash, Value & v)
{
const auto path = evalSettings.pureEval && expectedHash ?
const auto path = settings.pureEval && expectedHash ?
path_ :
state.checkSourcePath(path_);
PathFilter filter = filterFun ? ([&](const Path & path) {
@@ -1348,24 +1345,6 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args
}
/* Apply a function to every element of an attribute set. */
static void prim_mapAttrs(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceAttrs(*args[1], pos);
state.mkAttrs(v, args[1]->attrs->size());
for (auto & i : *args[1]->attrs) {
Value * vName = state.allocValue();
Value * vFun2 = state.allocValue();
mkString(*vName, i.name);
mkApp(*vFun2, *args[0], *vName);
mkApp(*state.allocAttr(v, i.name), *vFun2, *i.value);
}
}
/*************************************************************
* Lists
*************************************************************/
@@ -1420,6 +1399,7 @@ static void prim_tail(EvalState & state, const Pos & pos, Value * * args, Value
/* Apply a function to every element of a list. */
static void prim_map(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceFunction(*args[0], pos);
state.forceList(*args[1], pos);
state.mkList(v, args[1]->listSize());
@@ -1498,20 +1478,19 @@ static void prim_foldlStrict(EvalState & state, const Pos & pos, Value * * args,
state.forceFunction(*args[0], pos);
state.forceList(*args[2], pos);
if (args[2]->listSize()) {
Value * vCur = args[1];
Value * vCur = args[1];
if (args[2]->listSize())
for (unsigned int n = 0; n < args[2]->listSize(); ++n) {
Value vTmp;
state.callFunction(*args[0], *vCur, vTmp, pos);
vCur = n == args[2]->listSize() - 1 ? &v : state.allocValue();
state.callFunction(vTmp, *args[2]->listElems()[n], *vCur, pos);
}
state.forceValue(v);
} else {
state.forceValue(*args[1]);
v = *args[1];
}
else
v = *vCur;
state.forceValue(v);
}
@@ -1548,6 +1527,7 @@ static void prim_all(EvalState & state, const Pos & pos, Value * * args, Value &
static void prim_genList(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceFunction(*args[0], pos);
auto len = state.forceInt(*args[1], pos);
if (len < 0)
@@ -1578,6 +1558,7 @@ static void prim_sort(EvalState & state, const Pos & pos, Value * * args, Value
v.listElems()[n] = args[1]->listElems()[n];
}
auto comparator = [&](Value * a, Value * b) {
/* Optimization: if the comparator is lessThan, bypass
callFunction. */
@@ -1597,62 +1578,6 @@ static void prim_sort(EvalState & state, const Pos & pos, Value * * args, Value
}
static void prim_unique(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceFunction(*args[0], pos);
state.forceList(*args[1], pos);
auto len = args[1]->listSize();
Value * vs[len];
for (size_t n = 0; n < len; ++n) {
auto v2 = args[1]->listElems()[n];
state.forceValue(*v2);
vs[n] = v2;
}
auto comparator = [&](Value * a, Value * b) {
/* Optimization: if the comparator is lessThan, bypass
callFunction. */
if (args[0]->type == tPrimOp && args[0]->primOp->fun == prim_lessThan)
return CompareValues()(a, b);
Value vTmp1, vTmp2;
state.callFunction(*args[0], *a, vTmp1, pos);
state.callFunction(vTmp1, *b, vTmp2, pos);
return state.forceBool(vTmp2, pos);
};
std::sort(vs, vs + len, comparator);
auto outLen = std::min((size_t) 1, len);
for (size_t n = 1; n < len; n++) {
if (comparator(vs[outLen - 1], vs[n])) {
vs[outLen++] = vs[n];
}
}
std::sort(vs, vs + outLen);
state.mkList(v, outLen);
size_t outPos = 0;
for (size_t n = 0; n < len; n++) {
auto v2 = args[1]->listElems()[n];
auto i = std::lower_bound(vs, vs + outLen, v2);
if (*i == v2) {
// Remove v2 from the set by setting its least significant
// bit. (This doesn't change the sort order.)
*i = (Value *) (((ptrdiff_t) v2) | 1);
assert(outPos < outLen);
v.listElems()[outPos++] = v2;
}
}
assert(outPos == outLen);
}
static void prim_partition(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceFunction(*args[0], pos);
@@ -1676,50 +1601,17 @@ static void prim_partition(EvalState & state, const Pos & pos, Value * * args, V
state.mkAttrs(v, 2);
Value * vRight = state.allocAttr(v, state.sRight);
auto rsize = right.size();
state.mkList(*vRight, rsize);
if (rsize)
memcpy(vRight->listElems(), right.data(), sizeof(Value *) * rsize);
state.mkList(*vRight, right.size());
memcpy(vRight->listElems(), right.data(), sizeof(Value *) * right.size());
Value * vWrong = state.allocAttr(v, state.sWrong);
auto wsize = wrong.size();
state.mkList(*vWrong, wsize);
if (wsize)
memcpy(vWrong->listElems(), wrong.data(), sizeof(Value *) * wsize);
state.mkList(*vWrong, wrong.size());
memcpy(vWrong->listElems(), wrong.data(), sizeof(Value *) * wrong.size());
v.attrs->sort();
}
/* concatMap = f: list: concatLists (map f list); */
/* C++-version is to avoid allocating `mkApp', call `f' eagerly */
static void prim_concatMap(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceFunction(*args[0], pos);
state.forceList(*args[1], pos);
auto nrLists = args[1]->listSize();
Value lists[nrLists];
size_t len = 0;
for (unsigned int n = 0; n < nrLists; ++n) {
Value * vElem = args[1]->listElems()[n];
state.callFunction(*args[0], *vElem, lists[n], pos);
state.forceList(lists[n], pos);
len += lists[n].listSize();
}
state.mkList(v, len);
auto out = v.listElems();
for (unsigned int n = 0, pos = 0; n < nrLists; ++n) {
auto l = lists[n].listSize();
if (l)
memcpy(out + pos, lists[n].listElems(), l * sizeof(Value *));
pos += l;
}
}
/*************************************************************
* Integer arithmetic
*************************************************************/
@@ -1727,8 +1619,6 @@ static void prim_concatMap(EvalState & state, const Pos & pos, Value * * args, V
static void prim_add(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceValue(*args[0], pos);
state.forceValue(*args[1], pos);
if (args[0]->type == tFloat || args[1]->type == tFloat)
mkFloat(v, state.forceFloat(*args[0], pos) + state.forceFloat(*args[1], pos));
else
@@ -1738,8 +1628,6 @@ static void prim_add(EvalState & state, const Pos & pos, Value * * args, Value &
static void prim_sub(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceValue(*args[0], pos);
state.forceValue(*args[1], pos);
if (args[0]->type == tFloat || args[1]->type == tFloat)
mkFloat(v, state.forceFloat(*args[0], pos) - state.forceFloat(*args[1], pos));
else
@@ -1749,8 +1637,6 @@ static void prim_sub(EvalState & state, const Pos & pos, Value * * args, Value &
static void prim_mul(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceValue(*args[0], pos);
state.forceValue(*args[1], pos);
if (args[0]->type == tFloat || args[1]->type == tFloat)
mkFloat(v, state.forceFloat(*args[0], pos) * state.forceFloat(*args[1], pos));
else
@@ -1760,9 +1646,6 @@ static void prim_mul(EvalState & state, const Pos & pos, Value * * args, Value &
static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceValue(*args[0], pos);
state.forceValue(*args[1], pos);
NixFloat f2 = state.forceFloat(*args[1], pos);
if (f2 == 0) throw EvalError(format("division by zero, at %1%") % pos);
@@ -1778,20 +1661,6 @@ static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value &
}
}
static void prim_bitAnd(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
mkInt(v, state.forceInt(*args[0], pos) & state.forceInt(*args[1], pos));
}
static void prim_bitOr(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
mkInt(v, state.forceInt(*args[0], pos) | state.forceInt(*args[1], pos));
}
static void prim_bitXor(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
mkInt(v, state.forceInt(*args[0], pos) ^ state.forceInt(*args[1], pos));
}
static void prim_lessThan(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
@@ -1843,6 +1712,41 @@ static void prim_stringLength(EvalState & state, const Pos & pos, Value * * args
}
static void prim_unsafeDiscardStringContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
string s = state.coerceToString(pos, *args[0], context);
mkString(v, s, PathSet());
}
static void prim_hasContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
state.forceString(*args[0], context, pos);
mkBool(v, !context.empty());
}
/* Sometimes we want to pass a derivation path (i.e. pkg.drvPath) to a
builder without causing the derivation to be built (for instance,
in the derivation that builds NARs in nix-push, when doing
source-only deployment). This primop marks the string context so
that builtins.derivation adds the path to drv.inputSrcs rather than
drv.inputDrvs. */
static void prim_unsafeDiscardOutputDependency(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
string s = state.coerceToString(pos, *args[0], context);
PathSet context2;
for (auto & p : context)
context2.insert(p.at(0) == '=' ? "~" + string(p, 1) : p);
mkString(v, s, context2);
}
/* Return the cryptographic hash of a string in base-16. */
static void prim_hashString(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
@@ -2123,7 +2027,7 @@ void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
state.checkURI(url);
if (evalSettings.pureEval && !expectedHash)
if (settings.pureEval && !expectedHash)
throw Error("in pure evaluation mode, '%s' requires a 'sha256' argument", who);
Path res = getDownloader()->downloadCached(state.store, url, unpack, name, expectedHash);
@@ -2191,12 +2095,12 @@ void EvalState::createBaseEnv()
addConstant(name, v);
};
if (!evalSettings.pureEval) {
if (!settings.pureEval) {
mkInt(v, time(0));
addConstant("__currentTime", v);
}
if (!evalSettings.pureEval) {
if (!settings.pureEval) {
mkString(v, settings.thisSystem);
addConstant("__currentSystem", v);
}
@@ -2221,7 +2125,7 @@ void EvalState::createBaseEnv()
mkApp(v, *vScopedImport, *v2);
forceValue(v);
addConstant("import", v);
if (evalSettings.enableNativeCode) {
if (settings.enableNativeCode) {
addPrimOp("__importNative", 2, prim_importNative);
addPrimOp("__exec", 1, prim_exec);
}
@@ -2232,7 +2136,6 @@ void EvalState::createBaseEnv()
addPrimOp("__isInt", 1, prim_isInt);
addPrimOp("__isFloat", 1, prim_isFloat);
addPrimOp("__isBool", 1, prim_isBool);
addPrimOp("__isPath", 1, prim_isPath);
addPrimOp("__genericClosure", 1, prim_genericClosure);
addPrimOp("abort", 1, prim_abort);
addPrimOp("__addErrorContext", 2, prim_addErrorContext);
@@ -2249,7 +2152,7 @@ void EvalState::createBaseEnv()
// Paths
addPrimOp("__toPath", 1, prim_toPath);
if (evalSettings.pureEval)
if (settings.pureEval)
addPurityError("__storePath");
else
addPrimOp("__storePath", 1, prim_storePath);
@@ -2280,7 +2183,6 @@ void EvalState::createBaseEnv()
addPrimOp("__intersectAttrs", 2, prim_intersectAttrs);
addPrimOp("__catAttrs", 2, prim_catAttrs);
addPrimOp("__functionArgs", 1, prim_functionArgs);
addPrimOp("__mapAttrs", 2, prim_mapAttrs);
// Lists
addPrimOp("__isList", 1, prim_isList);
@@ -2297,24 +2199,22 @@ void EvalState::createBaseEnv()
addPrimOp("__all", 2, prim_all);
addPrimOp("__genList", 2, prim_genList);
addPrimOp("__sort", 2, prim_sort);
addPrimOp("__unique", 2, prim_unique);
addPrimOp("__partition", 2, prim_partition);
addPrimOp("__concatMap", 2, prim_concatMap);
// Integer arithmetic
addPrimOp("__add", 2, prim_add);
addPrimOp("__sub", 2, prim_sub);
addPrimOp("__mul", 2, prim_mul);
addPrimOp("__div", 2, prim_div);
addPrimOp("__bitAnd", 2, prim_bitAnd);
addPrimOp("__bitOr", 2, prim_bitOr);
addPrimOp("__bitXor", 2, prim_bitXor);
addPrimOp("__lessThan", 2, prim_lessThan);
// String manipulation
addPrimOp("toString", 1, prim_toString);
addPrimOp("__substring", 3, prim_substring);
addPrimOp("__stringLength", 1, prim_stringLength);
addPrimOp("__hasContext", 1, prim_hasContext);
addPrimOp("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext);
addPrimOp("__unsafeDiscardOutputDependency", 1, prim_unsafeDiscardOutputDependency);
addPrimOp("__hashString", 2, prim_hashString);
addPrimOp("__match", 2, prim_match);
addPrimOp("__split", 2, prim_split);

View File

@@ -1,187 +0,0 @@
#include "primops.hh"
#include "eval-inline.hh"
#include "derivations.hh"
namespace nix {
static void prim_unsafeDiscardStringContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
string s = state.coerceToString(pos, *args[0], context);
mkString(v, s, PathSet());
}
static RegisterPrimOp r1("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext);
static void prim_hasContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
state.forceString(*args[0], context, pos);
mkBool(v, !context.empty());
}
static RegisterPrimOp r2("__hasContext", 1, prim_hasContext);
/* Sometimes we want to pass a derivation path (i.e. pkg.drvPath) to a
builder without causing the derivation to be built (for instance,
in the derivation that builds NARs in nix-push, when doing
source-only deployment). This primop marks the string context so
that builtins.derivation adds the path to drv.inputSrcs rather than
drv.inputDrvs. */
static void prim_unsafeDiscardOutputDependency(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
string s = state.coerceToString(pos, *args[0], context);
PathSet context2;
for (auto & p : context)
context2.insert(p.at(0) == '=' ? string(p, 1) : p);
mkString(v, s, context2);
}
static RegisterPrimOp r3("__unsafeDiscardOutputDependency", 1, prim_unsafeDiscardOutputDependency);
/* Extract the context of a string as a structured Nix value.
The context is represented as an attribute set whose keys are the
paths in the context set and whose values are attribute sets with
the following keys:
path: True if the relevant path is in the context as a plain store
path (i.e. the kind of context you get when interpolating
a Nix path (e.g. ./.) into a string). False if missing.
allOutputs: True if the relevant path is a derivation and it is
in the context as a drv file with all of its outputs
(i.e. the kind of context you get when referencing
.drvPath of some derivation). False if missing.
outputs: If a non-empty list, the relevant path is a derivation
and the provided outputs are referenced in the context
(i.e. the kind of context you get when referencing
.outPath of some derivation). Empty list if missing.
Note that for a given path any combination of the above attributes
may be present.
*/
static void prim_getContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
struct ContextInfo {
bool path = false;
bool allOutputs = false;
Strings outputs;
};
PathSet context;
state.forceString(*args[0], context, pos);
auto contextInfos = std::map<Path, ContextInfo>();
for (const auto & p : context) {
Path drv;
string output;
const Path * path = &p;
if (p.at(0) == '=') {
drv = string(p, 1);
path = &drv;
} else if (p.at(0) == '!') {
std::pair<string, string> ctx = decodeContext(p);
drv = ctx.first;
output = ctx.second;
path = &drv;
}
auto isPath = drv.empty();
auto isAllOutputs = (!drv.empty()) && output.empty();
auto iter = contextInfos.find(*path);
if (iter == contextInfos.end()) {
contextInfos.emplace(*path, ContextInfo{isPath, isAllOutputs, output.empty() ? Strings{} : Strings{std::move(output)}});
} else {
if (isPath)
iter->second.path = true;
else if (isAllOutputs)
iter->second.allOutputs = true;
else
iter->second.outputs.emplace_back(std::move(output));
}
}
state.mkAttrs(v, contextInfos.size());
auto sPath = state.symbols.create("path");
auto sAllOutputs = state.symbols.create("allOutputs");
for (const auto & info : contextInfos) {
auto & infoVal = *state.allocAttr(v, state.symbols.create(info.first));
state.mkAttrs(infoVal, 3);
if (info.second.path)
mkBool(*state.allocAttr(infoVal, sPath), true);
if (info.second.allOutputs)
mkBool(*state.allocAttr(infoVal, sAllOutputs), true);
if (!info.second.outputs.empty()) {
auto & outputsVal = *state.allocAttr(infoVal, state.sOutputs);
state.mkList(outputsVal, info.second.outputs.size());
size_t i = 0;
for (const auto & output : info.second.outputs) {
mkString(*(outputsVal.listElems()[i++] = state.allocValue()), output);
}
}
infoVal.attrs->sort();
}
v.attrs->sort();
}
static RegisterPrimOp r4("__getContext", 1, prim_getContext);
/* Append the given context to a given string.
See the commentary above unsafeGetContext for details of the
context representation.
*/
static void prim_appendContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
auto orig = state.forceString(*args[0], context, pos);
state.forceAttrs(*args[1], pos);
auto sPath = state.symbols.create("path");
auto sAllOutputs = state.symbols.create("allOutputs");
for (auto & i : *args[1]->attrs) {
if (!state.store->isStorePath(i.name))
throw EvalError("Context key '%s' is not a store path, at %s", i.name, i.pos);
if (!settings.readOnlyMode)
state.store->ensurePath(i.name);
state.forceAttrs(*i.value, *i.pos);
auto iter = i.value->attrs->find(sPath);
if (iter != i.value->attrs->end()) {
if (state.forceBool(*iter->value, *iter->pos))
context.insert(i.name);
}
iter = i.value->attrs->find(sAllOutputs);
if (iter != i.value->attrs->end()) {
if (state.forceBool(*iter->value, *iter->pos)) {
if (!isDerivation(i.name)) {
throw EvalError("Tried to add all-outputs context of %s, which is not a derivation, to a string, at %s", i.name, i.pos);
}
context.insert("=" + string(i.name));
}
}
iter = i.value->attrs->find(state.sOutputs);
if (iter != i.value->attrs->end()) {
state.forceList(*iter->value, *iter->pos);
if (iter->value->listSize() && !isDerivation(i.name)) {
throw EvalError("Tried to add derivation output context of %s, which is not a derivation, to a string, at %s", i.name, i.pos);
}
for (unsigned int n = 0; n < iter->value->listSize(); ++n) {
auto name = state.forceStringNoCtx(*iter->value->listElems()[n], *iter->pos);
context.insert("!" + name + "!" + string(i.name));
}
}
}
mkString(v, orig, context);
}
static RegisterPrimOp r5("__appendContext", 2, prim_appendContext);
}

View File

@@ -3,7 +3,6 @@
#include "download.hh"
#include "store-api.hh"
#include "pathlocks.hh"
#include "hash.hh"
#include <sys/time.h>
@@ -26,10 +25,10 @@ struct GitInfo
std::regex revRegex("^[0-9a-fA-F]{40}$");
GitInfo exportGit(ref<Store> store, const std::string & uri,
std::optional<std::string> ref, std::string rev,
std::experimental::optional<std::string> ref, std::string rev,
const std::string & name)
{
if (evalSettings.pureEval && rev == "")
if (settings.pureEval && rev == "")
throw Error("in pure evaluation mode, 'fetchGit' requires a Git revision");
if (!ref && rev == "" && hasPrefix(uri, "/") && pathExists(uri + "/.git")) {
@@ -85,16 +84,15 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
if (rev != "" && !std::regex_match(rev, revRegex))
throw Error("invalid Git revision '%s'", rev);
deletePath(getCacheDir() + "/nix/git");
Path cacheDir = getCacheDir() + "/nix/gitv2/" + hashString(htSHA256, uri).to_string(Base32, false);
Path cacheDir = getCacheDir() + "/nix/git";
if (!pathExists(cacheDir)) {
createDirs(dirOf(cacheDir));
runProgram("git", true, { "init", "--bare", cacheDir });
}
Path localRefFile = cacheDir + "/refs/heads/" + *ref;
std::string localRef = hashString(htSHA256, fmt("%s-%s", uri, *ref)).to_string(Base32, false);
Path localRefFile = cacheDir + "/refs/heads/" + localRef;
bool doFetch;
time_t now = time(0);
@@ -116,7 +114,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
git fetch to update the local ref to the remote ref. */
struct stat st;
doFetch = stat(localRefFile.c_str(), &st) != 0 ||
st.st_mtime + settings.tarballTtl <= now;
st.st_mtime <= now - settings.tarballTtl;
}
if (doFetch)
{
@@ -124,7 +122,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
// FIXME: git stderr messes up our progress indicator, so
// we're using --quiet for now. Should process its stderr.
runProgram("git", true, { "-C", cacheDir, "fetch", "--quiet", "--force", "--", uri, fmt("%s:%s", *ref, *ref) });
runProgram("git", true, { "-C", cacheDir, "fetch", "--quiet", "--force", "--", uri, *ref + ":" + localRef });
struct timeval times[2];
times[0].tv_sec = now;
@@ -190,7 +188,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
std::string url;
std::optional<std::string> ref;
std::experimental::optional<std::string> ref;
std::string rev;
std::string name = "source";
PathSet context;
@@ -221,6 +219,8 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va
} else
url = state.coerceToString(pos, *args[0], context, false, false);
if (!isUri(url)) url = absPath(url);
// FIXME: git externals probably can be used to bypass the URI
// whitelist. Ah well.
state.checkURI(url);

View File

@@ -27,7 +27,7 @@ std::regex commitHashRegex("^[0-9a-fA-F]{40}$");
HgInfo exportMercurial(ref<Store> store, const std::string & uri,
std::string rev, const std::string & name)
{
if (evalSettings.pureEval && rev == "")
if (settings.pureEval && rev == "")
throw Error("in pure evaluation mode, 'fetchMercurial' requires a Mercurial revision");
if (rev == "" && hasPrefix(uri, "/") && pathExists(uri + "/.hg")) {
@@ -80,7 +80,7 @@ HgInfo exportMercurial(ref<Store> store, const std::string & uri,
time_t now = time(0);
struct stat st;
if (stat(stampFile.c_str(), &st) != 0 ||
st.st_mtime + settings.tarballTtl <= now)
st.st_mtime <= now - settings.tarballTtl)
{
/* Except that if this is a commit hash that we already have,
we don't have to pull again. */
@@ -93,22 +93,7 @@ HgInfo exportMercurial(ref<Store> store, const std::string & uri,
Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", uri));
if (pathExists(cacheDir)) {
try {
runProgram("hg", true, { "pull", "-R", cacheDir, "--", uri });
}
catch (ExecError & e){
string transJournal = cacheDir + "/.hg/store/journal";
/* hg throws "abandoned transaction" error only if this file exists */
if (pathExists(transJournal))
{
runProgram("hg", true, { "recover", "-R", cacheDir });
runProgram("hg", true, { "pull", "-R", cacheDir, "--", uri });
}
else
{
throw ExecError(e.status, fmt("program hg '%1%' ", statusToString(e.status)));
}
}
runProgram("hg", true, { "pull", "-R", cacheDir, "--", uri });
} else {
createDirs(dirOf(cacheDir));
runProgram("hg", true, { "clone", "--noupdate", "--", uri, cacheDir });
@@ -199,6 +184,8 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
} else
url = state.coerceToString(pos, *args[0], context, false, false);
if (!isUri(url)) url = absPath(url);
// FIXME: git externals probably can be used to bypass the URI
// whitelist. Ah well.
state.checkURI(url);

View File

@@ -1,77 +0,0 @@
#include "primops.hh"
#include "eval-inline.hh"
#include "cpptoml/cpptoml.h"
namespace nix {
static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
using namespace cpptoml;
auto toml = state.forceStringNoCtx(*args[0], pos);
std::istringstream tomlStream(toml);
std::function<void(Value &, std::shared_ptr<base>)> visit;
visit = [&](Value & v, std::shared_ptr<base> t) {
if (auto t2 = t->as_table()) {
size_t size = 0;
for (auto & i : *t2) { (void) i; size++; }
state.mkAttrs(v, size);
for (auto & i : *t2) {
auto & v2 = *state.allocAttr(v, state.symbols.create(i.first));
if (auto i2 = i.second->as_table_array()) {
size_t size2 = i2->get().size();
state.mkList(v2, size2);
for (size_t j = 0; j < size2; ++j)
visit(*(v2.listElems()[j] = state.allocValue()), i2->get()[j]);
}
else
visit(v2, i.second);
}
v.attrs->sort();
}
else if (auto t2 = t->as_array()) {
size_t size = t2->get().size();
state.mkList(v, size);
for (size_t i = 0; i < size; ++i)
visit(*(v.listElems()[i] = state.allocValue()), t2->get()[i]);
}
else if (t->is_value()) {
if (auto val = t->as<int64_t>())
mkInt(v, val->get());
else if (auto val = t->as<NixFloat>())
mkFloat(v, val->get());
else if (auto val = t->as<bool>())
mkBool(v, val->get());
else if (auto val = t->as<std::string>())
mkString(v, val->get());
else
throw EvalError("unsupported value type in TOML");
}
else abort();
};
try {
visit(v, parser(tomlStream).parse());
} catch (std::runtime_error & e) {
throw EvalError("while parsing a TOML string at %s: %s", pos, e.what());
}
}
static RegisterPrimOp r("fromTOML", 1, prim_fromTOML);
}

View File

@@ -69,19 +69,12 @@ public:
return Symbol(&*res.first);
}
size_t size() const
unsigned int size() const
{
return symbols.size();
}
size_t totalSize() const;
template<typename T>
void dump(T callback)
{
for (auto & s : symbols)
callback(s);
}
};
}

View File

@@ -43,8 +43,8 @@ class XMLWriter;
class JSONPlaceholder;
typedef int64_t NixInt;
typedef double NixFloat;
typedef long NixInt;
typedef float NixFloat;
/* External values must descend from ExternalValueBase, so that
* type-agnostic nix functions (e.g. showType) can be implemented
@@ -128,7 +128,7 @@ struct Value
const char * path;
Bindings * attrs;
struct {
size_t size;
unsigned int size;
Value * * elems;
} bigList;
Value * smallList[2];
@@ -166,7 +166,7 @@ struct Value
return type == tList1 || type == tList2 ? smallList : bigList.elems;
}
size_t listSize() const
unsigned int listSize() const
{
return type == tList1 ? 1 : type == tList2 ? 2 : bigList.size;
}

View File

@@ -29,14 +29,14 @@ MixCommonArgs::MixCommonArgs(const string & programName)
.arity(2)
.handler([](std::vector<std::string> ss) {
try {
globalConfig.set(ss[0], ss[1]);
settings.set(ss[0], ss[1]);
} catch (UsageError & e) {
warn(e.what());
}
});
std::string cat = "config";
globalConfig.convertToArgs(*this, cat);
settings.convertToArgs(*this, cat);
// Backward compatibility hack: nix-env already had a --system flag.
if (programName == "nix-env") longFlags.erase("system");

View File

@@ -8,7 +8,7 @@ libmain_SOURCES := $(wildcard $(d)/*.cc)
libmain_LDFLAGS = $(OPENSSL_LIBS)
libmain_LIBS = libstore libutil
libmain_LIBS = libstore libutil libformat
libmain_ALLOW_UNDEFINED = 1

View File

@@ -6,4 +6,4 @@ Name: Nix
Description: Nix Package Manager
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lnixmain
Cflags: -I${includedir}/nix -std=c++17
Cflags: -I${includedir}/nix -std=c++14

View File

@@ -109,7 +109,7 @@ void initNix()
opensslLocks = std::vector<std::mutex>(CRYPTO_num_locks());
CRYPTO_set_locking_callback(opensslLockCallback);
loadConfFile();
settings.loadConfFile();
startSignalHandlerThread();
@@ -263,7 +263,7 @@ void showManPage(const string & name)
{
restoreSignals();
setenv("MANPATH", settings.nixManDir.c_str(), 1);
execlp("man", "man", name.c_str(), nullptr);
execlp("man", "man", name.c_str(), NULL);
throw SysError(format("command 'man %1%' failed") % name.c_str());
}
@@ -325,10 +325,10 @@ RunPager::RunPager()
setenv("LESS", "FRSXMK", 1);
restoreSignals();
if (pager)
execl("/bin/sh", "sh", "-c", pager, nullptr);
execlp("pager", "pager", nullptr);
execlp("less", "less", nullptr);
execlp("more", "more", nullptr);
execl("/bin/sh", "sh", "-c", pager, NULL);
execlp("pager", "pager", NULL);
execlp("less", "less", NULL);
execlp("more", "more", NULL);
throw SysError(format("executing '%1%'") % pager);
});

Some files were not shown because too many files have changed in this diff Show More