Compare commits

..

312 Commits
2.1 ... unique

Author SHA1 Message Date
Eelco Dolstra
a3d874175c Add builtins.unique [WIP]
This cuts ~4.5s from "nix-env -qaP -f `<nixpkgs>` --out-path" and
reduces memory allocations from 7.49 to 7.16 GiB.

Note that builtins.unique requires a less-than comparator function,
which is a change from the 'unique' function in Nixpkgs which uses an
equality function.
2019-04-12 22:47:14 +02:00
Eelco Dolstra
bb6e6923f2 Add environment variable NIX_SHOW_SYMBOLS for dumping the symbol table 2019-04-11 23:04:13 +02:00
Eelco Dolstra
41ba5135e0 primeCache(): Barf if builds are needed but not allowed
Fixes #2753.
2019-04-01 21:09:49 +02:00
Eelco Dolstra
2bc6304793 getMachines(): Cache result 2019-04-01 21:09:35 +02:00
Eelco Dolstra
2f59b30251 Use Nixpkgs 19.03 2019-04-01 21:09:25 +02:00
Eelco Dolstra
f32fbf952d Fix Bison 3.3 warning 2019-03-27 21:09:31 +01:00
Eelco Dolstra
e489f5cabf Update eval-okay-types.exp to match #1828 2019-03-27 21:07:04 +01:00
Graham Christensen
6e9e34ea1f Merge pull request #2744 from veprbl/patch-8
manual: mention the "channel:" shorthand for NIX_PATH
2019-03-25 21:49:48 -04:00
Dmitry Kalinkin
75ec68f93a manual: mention the "channel:" shorthand for NIX_PATH
Bumped to 15.09 because older channels, when downloaded from
nixos.org, require firefox to be accessed via `pkgs.firefox`
2019-03-25 20:55:28 -04:00
Eelco Dolstra
5c05c238e6 Merge pull request #1828 from zimbatm/isPath
Add isPath primop
2019-03-25 19:58:11 +01:00
Will Dietz
63e7fc5096 perl/configure.ac: fix for new version location too 2019-03-25 09:18:30 +01:00
Will Dietz
1f9c8cd68b configure.ac: update for new version file location 2019-03-25 09:18:30 +01:00
Will Dietz
42e2d5e7b7 store-api.hh: add missing include for unordered_map 2019-03-25 09:18:30 +01:00
Will Dietz
0bebca402a version -> .version, avoid conflict with C++20 <version> 2019-03-25 09:18:30 +01:00
Domen Kožar
6f0359012c Merge pull request #2693 from thoughtpolice/scripts/multi-user-sandbox
scripts: remove default 'sandbox = false' from multi-user installer
2019-03-24 19:45:56 +07:00
zimbatm
514b3c7f83 Add isPath primop
this is added for completeness' sake since all the other possible
`builtins.typeOf` results have a corresponding `builtins.is<Type>`
2019-03-24 11:36:49 +01:00
Eelco Dolstra
56f1ed5579 Merge pull request #2741 from mayflower/primop-type-desc
eval: improve type description for primops and applied primops
2019-03-21 15:49:19 +01:00
Linus Heckemann
2aa89daab3 eval: improve type description for primops and applied primops
This can make type errors a little easier to understand.
2019-03-21 15:31:46 +01:00
Eelco Dolstra
6a3dfcb623 Merge pull request #2739 from mayflower/builtins-doc-explicit
manual: include builtins.* for globally available builtins
2019-03-21 12:24:44 +01:00
Linus Heckemann
6f093073b6 manual: include builtins.* for globally available builtins
This improves searchability.
2019-03-21 09:37:22 +01:00
Eelco Dolstra
ffeabf8390 Merge pull request #2731 from nomeata/link-to-conf-builders-use-substitutes
Link to `builders-use-substitutes` in chapter on distributed builds
2019-03-18 13:54:47 +01:00
Joachim Breitner
684c7fff80 Link to builders-use-substitutes in chapter on distributed builds
fixes #2730.
2019-03-16 19:03:40 +01:00
Eelco Dolstra
806291d18c Merge pull request #2727 from Chakerbh/master
Add a 5 seconds of timeout to connecting to S3.
2019-03-15 21:25:10 +08:00
Chaker Benhamed
81a23fa7e2 Add a 5 seconds of timeouts to connect to S3.
The default is 1000ms, but we can hit it a lot of we don't have direct
link to AWS (e.g. using VPN).
2019-03-15 13:23:58 +01:00
Graham Christensen
caf297a9d3 Merge pull request #2725 from andir/docs/s3-typo
docs: fix typo in AllowDirectReads
2019-03-14 18:53:57 -04:00
Andreas Rammhold
34fade478a docs: fix typo in AllowDirectReads
It was just missing an `l` but should be fixed anyway.
2019-03-14 23:51:18 +01:00
Eelco Dolstra
1f64f4c7c8 pkg-config files: Use c++17 2019-03-14 14:11:12 +01:00
Eelco Dolstra
ef52ccf035 experimental/optional -> optional 2019-03-14 14:10:52 +01:00
Eelco Dolstra
86f3b94c8c nix-store --gc --print-roots: Sort output 2019-03-14 13:59:10 +01:00
Eelco Dolstra
578ed7a259 findRoots(): Don't censor for trusted users
They're pretty much root anyway.
2019-03-14 13:53:34 +01:00
Eelco Dolstra
53522cb6ac findRoots(): Add 'censor' parameter
This is less brittle than filtering paths after the fact in
nix-daemon.
2019-03-14 13:53:34 +01:00
Eelco Dolstra
a3f37d87ea findRuntimeRoots: Simplify/fix handling of /proc files
Scanning of /proc/<pid>/{exe,cwd} was broken because '{memory:' was
prepended twice. Also, get rid of the whole '{memory:...}' thing
because it's unnecessary, we can just list the file in /proc directly.
2019-03-14 13:30:25 +01:00
Guillaume Maudoux
115e2c8c67 Update tests to the new --roots format 2019-03-10 01:50:33 +01:00
Guillaume Maudoux
4f4391193c Fix warning about unused variable 2019-03-10 00:56:09 +01:00
Guillaume Maudoux
38ee16ae9c Unify internal findRootsXxx() api 2019-03-10 00:56:09 +01:00
Guillaume Maudoux
9d7221183a unify naming of roots as links & targets 2019-03-10 00:56:09 +01:00
Guillaume Maudoux
9d87e3fbd2 require c++ 17
This fixes warnings about "structured binding declaration" requiring
"-std=c++1z".
2019-03-10 00:56:09 +01:00
Guillaume Maudoux
5c56570726 Also obfuscate the number of memory roots 2019-03-10 00:56:09 +01:00
Guillaume Maudoux
fc02b1b3ee Also print rooted path in nix-store -q --roots 2019-03-10 00:56:09 +01:00
Guillaume Maudoux
8574b70342 fixup! Make roots a map of store paths to pinning links 2019-03-10 00:56:09 +01:00
Guillaume Maudoux
ebc86550f9 Make roots a map of store paths to pinning links
This new structure makes more sense as there may be many sources rooting
the same store path. Many profiles can reference the same path but this
is even more true with /proc/<pid>/maps where distinct pids can and
often do map the same store path.
This implementation is also more efficient as the `Roots` map contains
only one entry per rooted store path.
2019-03-10 00:56:09 +01:00
Guillaume Maudoux
a17f86ce3a Obfuscate memory roots for non-root users 2019-03-10 00:56:09 +01:00
Guillaume Maudoux
43331d6344 detail memory roots 2019-03-10 00:56:09 +01:00
Eelco Dolstra
5886bc5996 Merge pull request #2710 from volth/patch-6
canBuildLocally: check for features
2019-03-06 13:21:44 +08:00
volth
fff8db205c canBuildLocally: check for features
It could happen that the local builder match the system but lacks some features.
Now it results a failure.
The fix gracefully excludes the local builder from the set of available builders for derivation which requires the feature, so the derivation is built on remote builders only (as though it has incompatible system, like ```aarch64-linux``` when local is x86)
2019-03-06 05:03:25 +00:00
Eelco Dolstra
b71e1fb342 Restore --init calls in tests 2019-03-04 18:27:45 +08:00
Vladimír Čunát
4cfc131ec4 manual nitpick: document sha512 support in hashString 2019-03-01 14:30:30 +01:00
Will Dietz
0963479741 archive.cc: ignore more posix_fallocate "not supported" error codes
Fixes w/musl.
2019-03-01 10:31:17 +08:00
Eelco Dolstra
ad6dbecc1d Merge pull request #2674 from LnL7/daemon-disable-fork-safety
nix-daemon: add variable to disable fork safety
2019-03-01 02:07:50 +01:00
Eelco Dolstra
ebd4d50e6e Merge pull request #2703 from pradd/support_s3_region_param
Support parameters in S3 URLs
2019-02-26 22:59:29 +08:00
Dzmitry Zaitsau
06d6335987 fix indentation 2019-02-26 11:07:37 +01:00
Dzmitry Zaitsau
ac200c3678 Apply param values on S3Helper initialization 2019-02-25 18:06:19 +01:00
Dzmitry Zaitsau
56c18c67d9 Extend S3 URL parsing with parameters extraction 2019-02-25 18:00:55 +01:00
Dzmitry Zaitsau
07f992a74b Extract and expose splitUriAndParams function
which splits a URL into localtor and parameter parts
2019-02-25 17:59:26 +01:00
Austin Seipp
d7a7a029ff scripts: remove default 'sandbox = false' from multi-user installer
Sandboxing is now enabled by default on Linux, but is still disabled on
macOS. However, the installer always turned it off to ensure consistent
behavior.

Remove this default configuration, so we fall back to the default
platform-specific value.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
2019-02-23 08:35:26 -06:00
Eelco Dolstra
6bfb082ea2 Merge pull request #2694 from zimbatm/no-store-init
remove noop uses of nix-store --init
2019-02-23 12:12:36 +01:00
zimbatm
b402148d8f remove noop uses of nix-store --init
the nix-store --init command is a noop apparently
2019-02-22 21:07:53 +01:00
Shea Levy
e58a71442a nix.sh: Be set -u compliant. 2019-02-14 13:24:16 -05:00
Eelco Dolstra
d8fe447139 Merge pull request #2579 from catern/dumpdb
nix-store: make --dump-db take a list of paths to dump
2019-02-14 13:08:02 +01:00
Eelco Dolstra
25722bd39a Merge pull request #2677 from matthewbauer/disable-shared
Support --disable-shared flag.
2019-02-13 10:09:31 +01:00
Matthew Bauer
7ce1fae59f Support --disable-shared flag.
This tells Nix to not build the shared libraries.
2019-02-13 00:03:10 -05:00
Eelco Dolstra
7a7ec22298 Merge pull request #2628 from shlevy/context-introspection
Context introspection
2019-02-12 17:57:35 +01:00
Daiderd Jordan
8ac1130cc2 nix-daemon: add variable to disable fork safety
Since macOS 10.14 this has become an error, causing problems if the
nix-daemon loads nix during substitution (this is a forked process).

Workaround for #2523.
2019-02-09 20:35:30 +01:00
Eelco Dolstra
01d07b1e92 Revert "Restore parent mount namespace before executing a child process"
This reverts commit a0ef21262f. This
doesn't work in 'nix run' and nix-shell because setns() fails in
multithreaded programs, and Boehm GC mark threads are uncancellable.

Fixes #2646.
2019-02-05 10:49:19 +01:00
Shea Levy
b30be6b450 Add builtins.appendContext.
A partner of builtins.getContext, useful for the same reasons.
2019-01-31 08:52:23 -05:00
Spencer Baugh
5f1891b795 nix-store: make --dump-db take a list of paths to dump
Inside a derivation, exportReferencesGraph already provides a way to
dump the Nix database for a specific closure. On the command line,
--dump-db gave us the same information, but only for the entire Nix
database at once.

With this change, one can now pass a list of paths to --dump-db to get
the Nix database dumped for just those paths. (The user is responsible
for ensuring this is a closure, like for --export).

Among other things, this is useful for deploying a closure to a new
host without using --import/--export; one can use tar to transfer the
store paths, and --dump-db/--load-db to transfer the validity
information. This is useful if the new host doesn't actually have Nix
yet, and the closure that is being deployed itself contains Nix.
2019-01-23 01:24:34 +00:00
Domen Kožar
92d08c02c8 Merge pull request #2635 from veprbl/patch-7
manual: "sandbox" option default is "true" on Linux
2019-01-20 09:43:26 +07:00
Dmitry Kalinkin
15efd54373 manual: "sandbox" option default is "true" on Linux
Fixes: 812e39313c ('Enable sandboxing by default')
2019-01-19 15:04:43 -05:00
Eelco Dolstra
7cc1a2593e unsupported(): Show the name of the unsupported operation 2019-01-18 13:34:53 +01:00
Eelco Dolstra
df03430586 Merge pull request #2638 from sevanspowell/update-nix-shell-interpreter-haskell-instructions
Update instructions for Haskell script using nix-shell interpreter
2019-01-18 13:17:10 +01:00
Samuel Evans-Powell
2ae5624b2f Update instructions for Haskell script using nix-shell interpreter
- The instructions for using nix-shell as an interpreter has a Haskell script
  example that doesn't work on more recent versions of Nix. Update the
  instructions with a working command
2019-01-18 10:50:54 +10:00
Shea Levy
1d757292d0 Add builtins.getContext.
This can be very helpful when debugging, as well as enabling complex
black magic like surgically removing a single dependency from a
string's context.
2019-01-14 11:27:10 -05:00
Shea Levy
087be7281a Treat plain derivation paths in context as normal paths.
Previously, plain derivation paths in the string context (e.g. those
that arose from builtins.storePath on a drv file, not those that arose
from accessing .drvPath of a derivation) were treated somewhat like
derivaiton paths derived from .drvPath, except their dependencies
weren't recursively added to the input set. With this change, such
plain derivation paths are simply treated as paths and added to the
source inputs set accordingly, simplifying context handling code and
removing the inconsistency. If drvPath-like behavior is desired, the
.drv file can be imported and then .drvPath can be accessed.

This is a backwards-incompatibility, but storePath is never used on
drv files within nixpkgs and almost never used elsewhere.
2019-01-13 11:29:55 -05:00
Eelco Dolstra
4ae6e84901 install: Use base-16 hashes
Issue #2623.
2019-01-11 16:33:59 +01:00
Eelco Dolstra
8ce1986611 Bump version 2019-01-11 16:33:59 +01:00
Eelco Dolstra
bbaf865655 Add 2.2 release notes 2019-01-10 21:02:09 +01:00
Eelco Dolstra
44a8b17556 Revert "Remove some bashisms from configure.ac"
This reverts commit e8b0efdcc9.
2019-01-10 21:02:09 +01:00
Eelco Dolstra
7af5f70139 Revert "Escape square brackets in configure.ac"
This reverts commit 80f464d9d7.
2019-01-10 21:02:09 +01:00
Eelco Dolstra
c7bf1cdb4e Merge pull request #2608 from dtzWill/fix/issue-2546
EvalState::resetFileCache: clear parse cache as well as eval cache
2019-01-10 20:56:31 +01:00
Eelco Dolstra
30906122e2 Merge pull request #2617 from veprbl/pr/V547_nix_repl.cc
remove some dead code in nix/repl.cc
2019-01-10 20:55:27 +01:00
Eelco Dolstra
9a7432672b Merge pull request #2618 from 0mp/fix-configure.ac
Escape square brackets in configure.ac
2019-01-09 16:35:03 +01:00
Mateusz Piotrowski
80f464d9d7 Escape square brackets in configure.ac
This patch attempts to solve the regression introduced in e8b0efdc
(#2607).
2019-01-09 14:51:06 +01:00
Eelco Dolstra
013dd28b15 Merge pull request #2601 from dtzWill/update/json-3.5.0
Update nlohmann-json 3.0.1 -> 3.5.0
2019-01-07 23:13:35 +01:00
Eelco Dolstra
2fadd30ba4 Merge pull request #2607 from 0mp/configure.ac-fix
Remove some bashisms from configure.ac
2019-01-07 23:13:02 +01:00
Eelco Dolstra
85488a93ec Merge pull request #2612 from Ericson2314/remove-dead-dynlib_suffix
[Needs testing and review] Remove dead code
2019-01-07 23:11:34 +01:00
John Ericson
2733287046 Don't look for a "pv" program, or mention it in the manual source
The manual reference was commented out, and the sole reference to this
program other than the configure script. Removed both.
2019-01-07 16:40:19 -05:00
John Ericson
fef9f5653b Remove mentions of libformat, it no longer exists 2019-01-05 14:31:29 -05:00
John Ericson
e10d6ed2a7 brotli is only used as a library now 2019-01-05 14:25:54 -05:00
John Ericson
318153f4c2 Remove dead code computing dynlib_suffix from comfigure.ac 2019-01-05 13:30:42 -05:00
Will Dietz
21ea00d3ec EvalState::resetFileCache: clear parse cache as well as eval cache
Fixes #2546.

(at least the basic reproduction I've been testing)
2018-12-31 10:18:28 -06:00
Mateusz Piotrowski
e8b0efdcc9 Remove some bashisms from configure.ac
"configure.ac" is used to generate "configure", which is supposed to be
run with /bin/sh (as suggested by the shebang line of "configure"). As a
result it is a good idea to remove any /bin/sh-incompatible syntax from
configure.ac. Otherwise, systems that do not use Bash as their /bin/sh
are unable to run "configure" due to syntax errors.
2018-12-30 02:32:29 +01:00
Dmitry Kalinkin
93c9ba3e78 remove some dead code in nix/repl.cc
Fixes a static analyzer warning:

Expression 'isDrv' is always false.

Fixes: 3beb6f6e7 ('Show derivations more concisely')
2018-12-25 22:38:40 +03:00
Will Dietz
3f8b78a84d nlohmann-json: 3.4.0 -> 3.5.0
https://github.com/nlohmann/json/releases/tag/v3.5.0
2018-12-21 22:38:06 -06:00
Will Dietz
e78511743e nlohmann: 3.0.1 -> 3.4.0
```
$ curl -L
"https://github.com/nlohmann/json/releases/download/v3.4.0/json.hpp" -o
src/nlohmann/json.hpp
```
2018-12-21 22:36:53 -06:00
Shea Levy
ff342fc0c2 Merge pull request #2586 from dtzWill/fix/remove-debug-print-nix-store
nix-store: remove debugging print
2018-12-19 14:57:38 -05:00
Shea Levy
e653df3153 Merge pull request #2584 from dtzWill/fix/test-sri-512-256
tests/fetchurl: fix after changing default hash from 512 to 256
2018-12-15 11:04:31 -05:00
Will Dietz
c1112ae9a2 nix-store: remove debugging print 2018-12-15 09:59:47 -06:00
Will Dietz
aa7e52abff tests/fetchurl: fix after changing default hash from 512 to 256 2018-12-14 22:37:20 -06:00
Eelco Dolstra
7b0b349085 Merge pull request #2580 from Synthetica9/nix-instantiate-rwm-docfix
Clarify nix-instantiate --read-write-mode
2018-12-14 10:22:29 +01:00
Patrick Hilhorst
567941fb59 Clarify nix-instantiate --read-write-mode 2018-12-14 09:36:40 +01:00
Eelco Dolstra
6024dc1d97 Support SRI hashes
SRI hashes (https://www.w3.org/TR/SRI/) combine the hash algorithm and
a base-64 hash. This allows more concise and standard hash
specifications. For example, instead of

  import <nix/fetchurl.nl> {
    url = https://nixos.org/releases/nix/nix-2.1.3/nix-2.1.3.tar.xz;
    sha256 = "5d22dad058d5c800d65a115f919da22938c50dd6ba98c5e3a183172d149840a4";
  };

you can write

  import <nix/fetchurl.nl> {
    url = https://nixos.org/releases/nix/nix-2.1.3/nix-2.1.3.tar.xz;
    hash = "sha256-XSLa0FjVyADWWhFfkZ2iKTjFDda6mMXjoYMXLRSYQKQ=";
  };

In fixed-output derivations, the outputHashAlgo is no longer mandatory
if outputHash specifies the hash (either as an SRI or in the old
"<type>:<hash>" format).

'nix hash-{file,path}' now print hashes in SRI format by default. I
also reverted them to use SHA-256 by default because that's what we're
using most of the time in Nixpkgs.

Suggested by @zimbatm.
2018-12-13 14:30:52 +01:00
Eelco Dolstra
c37e6d77ea Merge pull request #2569 from veprbl/pr/update_prerequisites
docs: add missing prerequisites: brotli, boost, libseccomp
2018-12-13 10:42:02 +01:00
Eelco Dolstra
378e89360d Merge pull request #2576 from LnL7/repl-no-link
nix repl: don't create result symlinks
2018-12-13 10:40:39 +01:00
Eelco Dolstra
522cebdef4 Merge pull request #2578 from volth/patch-5
probably typo
2018-12-13 10:17:11 +01:00
Dmitry Kalinkin
0cc4728f71 docs: raise minimal boost version to 1.66 2018-12-13 01:50:39 -05:00
volth
21d494da83 probably typo
...at least MSVC unable to compile this
2018-12-13 02:45:50 +00:00
Daiderd Jordan
0e6c84a771 nix repl: don't create result symlinks 2018-12-12 23:00:07 +01:00
Eelco Dolstra
800cd55ab7 Merge pull request #2574 from zimbatm/multi-line-expected-sha256
libstore: improve hash mismatch error messages
2018-12-12 17:45:11 +01:00
zimbatm
5e6fa9092f libstore: improve hash mismatch error messages
Use the same output ordering and format everywhere.

This is such a common issue that we trade the single-line error message for
more readability.

Old message:
```
fixed-output derivation produced path '/nix/store/d4nw9x2sy9q3r32f3g5l5h1k833c01vq-example.com' with sha256 hash '08y4734bm2zahw75b16bcmcg587vvyvh0n11gwiyir70divwp1rm' instead of the expected hash '1xzwnipjd54wl8g93vpw6hxnpmdabq0wqywriiwmh7x8k0lvpq5m'
```

New message:
```
hash mismatch in fixed-output derivation '/nix/store/d4nw9x2sy9q3r32f3g5l5h1k833c01vq-example.com':
  wanted: sha256:1xzwnipjd54wl8g93vpw6hxnpmdabq0wqywriiwmh7x8k0lvpq5m
  got:    sha256:08y4734bm2zahw75b16bcmcg587vvyvh0n11gwiyir70divwp1rm

```
2018-12-12 17:42:00 +01:00
Eelco Dolstra
f7425d55df Fix assertion failure in NarInfoDiskCache
https://hydra.nixos.org/build/85827920
2018-12-12 17:13:22 +01:00
Eelco Dolstra
03ce0c3a9e Merge pull request #2572 from LnL7/narinfo-ca
nar-info-disk-cache: include ca in the cache entries
2018-12-12 09:51:22 +01:00
Daiderd Jordan
6f89053108 nar-info-disk-cache: include ca in the cache entries
Without this information the content addressable state and hashes are
lost after the first request, this causes signatures to be required for
everything even tho the path could be verified without signing.
2018-12-12 01:08:47 +01:00
Dmitry Kalinkin
419949bf61 docs: add missing prerequisites: brotli, boost, libseccomp 2018-12-10 12:37:15 -05:00
Eelco Dolstra
18ecd087ae Merge pull request #2566 from LnL7/s3-scheme
s3: make scheme configurable
2018-12-09 12:59:13 +01:00
Daiderd Jordan
77cc632186 s3: document scheme query parameter 2018-12-08 00:15:00 +01:00
Daiderd Jordan
898823b67d s3: make scheme configurable
This enables using for http for S3 request for debugging or
implementations that don't have https configured.  This is not a problem
for binary caches since they should not contain sensitive information.
Both package signatures and AWS auth already protect against tampering.
2018-12-07 23:55:38 +01:00
Eelco Dolstra
05f0543a17 Merge pull request #2562 from chawki008/master
Solve hg "abandoned transaction" issue
2018-12-07 22:47:18 +01:00
CHEIKH Chawki
fa5143c722 Solve hg "abandoned transaction" issue 2018-12-06 13:57:59 +01:00
Eelco Dolstra
4aee93d5ce fetchGit: Drop unnecessary localRef 2018-11-20 20:59:44 +01:00
Eelco Dolstra
3f4de91d80 Merge branch 'better-git-cache' of https://github.com/graham-at-target/nix 2018-11-20 20:41:19 +01:00
Eelco Dolstra
ebeea068d5 Merge pull request #2216 from dtzWill/fix/curl-760-timeout
download: if there are active requests, never sleep for 10s
2018-11-20 19:07:56 +01:00
Eelco Dolstra
5e64470b19 Fix typo 2018-11-20 16:54:17 +01:00
Eelco Dolstra
338fcec779 Merge pull request #2551 from KaiHa/kaiha/libreadline_option
repl: give user the choice between libeditline and libreadline
2018-11-20 16:16:31 +01:00
Kai Harries
de5997332d repl: give user the choice between libeditline and libreadline
The goal is to support libeditline AND libreadline and let the user
decide at compile time which one to use.

Add a compile time option to use libreadline instead of
libeditline. If compiled against libreadline completion functionality
is lost because of a incompatibility between libeditlines and
libreadlines completion function. Completion with libreadline is
possible and can be added later.

To use libreadline instead of libeditline the environment
variables 'EDITLINE_LIBS' and 'EDITLINE_CFLAGS' have to been set
during the ./configure step.

Example:

  EDITLINE_LIBS="/usr/lib/x86_64-linux-gnu/libhistory.so /usr/lib/x86_64-linux-gnu/libreadline.so"
  EDITLINE_CFLAGS="-DREADLINE"

The reason for this change is that for example on Debian already three
different editline libraries exist but none of those is compatible the
flavor used by nix. My hope is that with this change it would be
easier to port nix to systems that have already libreadline available.
2018-11-20 15:43:21 +01:00
Kai Harries
b289d86cd1 repl: Remove code that was commented out 2018-11-20 15:42:58 +01:00
Eelco Dolstra
2f8255cba1 Merge pull request #2544 from mayflower/lsnar-allow-fifo
nix ls-nar: allow reading from FIFOs
2018-11-17 22:07:10 +01:00
Linus Heckemann
40e0c9e925 nix ls-nar: allow reading from FIFOs
fixes #2528
2018-11-16 16:24:36 +01:00
Eelco Dolstra
a32ff2573b Fix 'Read-only file system' when building a derivation 2018-11-15 13:20:39 +01:00
Eelco Dolstra
32a0a223d5 Merge pull request #2432 from luke-clifton/fixssl
SSL certificate search failed to find user profile certificates.
2018-11-15 13:07:43 +01:00
Eelco Dolstra
9dc9b64aad Remove editline expression, not needed anymore 2018-11-13 20:55:08 +01:00
Eelco Dolstra
6c6bbeb439 Merge branch 'feature/editline-pr' of https://github.com/dtzWill/nix 2018-11-13 20:42:13 +01:00
Eelco Dolstra
a0ef21262f Restore parent mount namespace before executing a child process
This ensures that they can't write to /nix/store. Fixes #2535.
2018-11-13 16:15:30 +01:00
Eelco Dolstra
56f6e382be Merge pull request #2534 from obfusk/patch-2
manual: quote $servlets
2018-11-13 11:47:27 +01:00
Felix C. Stegerman
fb2c21f71c manual: quote $servlets 2018-11-13 01:18:26 +01:00
Eelco Dolstra
ee88babffa Merge pull request #2533 from obfusk/patch-1
manual: fix typo (s/gift/git/)
2018-11-12 18:42:24 +01:00
Felix C. Stegerman
18215be59d fix typo (s/gift/git/) 2018-11-12 17:50:39 +01:00
Eelco Dolstra
b05d6dac7b Manual: build locally -> build 2018-11-09 16:08:36 +01:00
Eelco Dolstra
7751616645 nix-prefetch-url: Stop progress bar before printing results 2018-11-09 10:34:12 +01:00
Eelco Dolstra
220c79ec22 Merge branch 'feature/prefetch-progress' of https://github.com/dtzWill/nix 2018-11-09 10:29:59 +01:00
Eelco Dolstra
4ea4d0b1a3 Urgh 2018-11-09 10:29:16 +01:00
Eelco Dolstra
fdd19fa2d7 Revert "Bump version"
This reverts commit 5a1a870849. Counting
is hard.
2018-11-09 10:27:23 +01:00
Eelco Dolstra
5eddc24fab Merge pull request #2526 from mayflower/manual-fix
Fix manual build
2018-11-08 14:19:09 +01:00
Linus Heckemann
34d2948f21 Fix manual build
This was broken by some missing closing tags in 0bea4a50e0
2018-11-08 14:07:19 +01:00
Eelco Dolstra
750400e0fa Merge pull request #2524 from domenkozar/deprecate-toPath
Deprecate builtins.toPath
2018-11-08 13:22:21 +01:00
Domen Kožar
0bea4a50e0 Deprecate builtins.toPath 2018-11-08 12:03:50 +00:00
Eelco Dolstra
812e39313c Enable sandboxing by default
Closes #179.
2018-11-07 17:08:28 +01:00
Eelco Dolstra
5a3f140856 Document allowSubstitutes 2018-11-07 11:42:22 +01:00
Eelco Dolstra
1109193ea3 Fix preferLocalBuild description
preferLocalBuild does not in fact prevent substitution.
2018-11-07 11:37:43 +01:00
Eelco Dolstra
5a1a870849 Bump version 2018-11-05 23:28:32 +01:00
Eelco Dolstra
6323b0729a Disable the S3 content-encoding patch
Since we're not using multi-part uploads at the moment, we can drop
this patch.
2018-11-01 15:18:38 +01:00
Eelco Dolstra
fc59fe029b Merge pull request #2502 from janpath/patch-1
Fix typo in comments
2018-11-01 00:49:52 +01:00
Jan Path
d1b049c4ea Fix typo in comments 2018-10-31 20:50:18 +01:00
Eelco Dolstra
fb35aaa422 Merge pull request #2501 from mayflower/xdg_config_dirs
config: use all of XDG_CONFIG_DIRS
2018-10-31 12:37:23 +01:00
Linus Heckemann
f3b8173a93 config: use all of XDG_CONFIG_DIRS
Previously, config would only be read from XDG_CONFIG_HOME. This change
allows reading config from additional directories, which enables e.g.
per-project binary caches or chroot stores with the help of direnv.
2018-10-31 09:24:43 +01:00
Eelco Dolstra
38d76d6d78 Remove redundant message 2018-10-30 19:28:42 +01:00
Eelco Dolstra
9f99d62480 S3BinaryCacheStore: Allow disabling multipart uploads
The use of TransferManager has several issues, including that it
doesn't allow setting a Content-Encoding without a patch, and it
doesn't handle exceptions in worker threads (causing termination on
memory allocation failure).

Fixes #2493.
2018-10-30 14:25:00 +01:00
Eelco Dolstra
0163e8928c Fix broken uploadProgressCallback closure
Since the callback is global we can't refer to 'path' in it. This
could cause a segfault or printing of arbitrary data.
2018-10-30 11:45:31 +01:00
Eelco Dolstra
056c3fbbfc Merge pull request #2494 from FPtje/fix-copy-from-old
copyStorePath: Fix hash errors when copying from older store
2018-10-29 20:45:25 +01:00
Falco Peijnenburg
49e272f647 copyStorePath: Fix hash errors when copying from older store
This commit partially reverts 48662d151b. When
copying from an older store (in my case a store running Nix 1.11.7), nix would
throw errors about there being no hash. This is fixed by recalculating the hash.
2018-10-29 20:24:37 +01:00
Will Dietz
2a8bdfd31a editline: 1.15.3 -> 1.16.0
Bump fallback editline expression to latest in nixpkgs.
2018-10-29 08:47:46 -05:00
Will Dietz
9f998096d2 repl: complete if all matches share prefix 2018-10-29 08:45:04 -05:00
Will Dietz
3d974d31fa editline: wip 2018-10-29 08:44:58 -05:00
Eelco Dolstra
f90a67e24d Merge pull request #2495 from LnL7/doctor-exit-code
nix doctor: return nonzero exitcode if a check fails
2018-10-29 13:19:55 +01:00
Daiderd Jordan
8e6bf49297 nix doctor: return nonzero exitcode if a check fails
This makes it easier to use this when testing the installer or when
running the checks with other automated tooling.
2018-10-29 12:09:22 +00:00
Eelco Dolstra
18b4c53f71 Restore old (dis)allowedRequisites behaviour for self-references
stdenv relies on this. So ignore self-references (but only in legacy non-structured attributes mode).
2018-10-27 15:41:53 +02:00
Eelco Dolstra
1427958b3c Merge branch 'simplify-lexer' of https://github.com/layus/nix 2018-10-27 13:42:06 +02:00
Eelco Dolstra
0c61515be1 Fix signedness warning 2018-10-27 13:07:26 +02:00
Eelco Dolstra
63575ffa38 Merge branch 'nix-doctor' of https://github.com/LnL7/nix 2018-10-27 12:54:22 +02:00
Eelco Dolstra
2cf98218c8 Merge pull request #2488 from dtzWill/fix/struct-class-minor
remote-store.hh: ConnectionHandle is struct, minor fix warning
2018-10-27 12:50:16 +02:00
Eelco Dolstra
cb073f5218 Merge pull request #2487 from dtzWill/fix/symlink-names
src/nix/local.mk: fix typos in names of symlinks
2018-10-27 12:49:05 +02:00
Guillaume Maudoux
6a5bf9b143 simplify handling of extra '}' 2018-10-27 00:14:51 +02:00
Will Dietz
9d24b5d56e nix-prefetch-url: progressbar 2018-10-26 13:19:10 -05:00
Will Dietz
3283c0dc45 remote-store.hh: ConnectionHandle is struct, minor fix warning 2018-10-26 13:15:48 -05:00
Will Dietz
27c2fcd4c0 src/nix/local.mk: fix typos in names of symlinks 2018-10-26 13:15:07 -05:00
Eelco Dolstra
f6a3dfe4e0 Merge all nix-* binaries into nix
These are all symlinks to 'nix' now, reducing the installed size by
about ~1.7 MiB.
2018-10-26 12:54:00 +02:00
Eelco Dolstra
c47e14ee45 Merge pull request #2483 from mayflower/tail-config
Promote verbose-build and log-lines
2018-10-23 16:59:52 +02:00
Linus Heckemann
a25abe823f Promote log-lines to a fully-qualified option
This allows commands like

nix build --log-lines 30 nixpkgs.hello

in order to obtain more information in case of a failure.
2018-10-23 16:54:24 +02:00
Eelco Dolstra
1a08ad75ea Merge pull request #2479 from nlewo/graphml
Add --graphml option to the nix-store --query command
2018-10-23 15:56:05 +02:00
Eelco Dolstra
3cd15c5b1f Per-output reference and closure size checks
In structured-attributes derivations, you can now specify per-output
checks such as:

  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;
  };

Also fixed a bug in allowedRequisites that caused it to ignore
self-references.
2018-10-23 01:29:16 +02:00
Antoine Eiche
d506342aa2 Remove the --xml query command option
The `--graphml` option can be used instead.
2018-10-20 09:48:53 +02:00
Antoine Eiche
73c2ae43f0 Add --graphml option to the nix-store --query command
This prints the references graph of the store paths in the graphML
format [1]. The graphML format is supported by several graph tools
such as the Python Networkx library or the Apache Thinkerpop project.

[1] http://graphml.graphdrawing.org
2018-10-20 09:48:34 +02:00
Eelco Dolstra
7a9ac91a43 Merge pull request #2481 from graham-at-target/patch-1
install script: remove unportable command check, fixup errant escape
2018-10-17 15:16:04 +02:00
Eelco Dolstra
bd78544f66 Fix assertion failure in Store::queryPathInfo()
$ nix-store -qR /nix/store/fnord
  nix-store: src/libstore/store-api.cc:80: std::__cxx11::string nix::storePathToHash(const Path&): Assertion `base.size() >= storePathHashLen' failed.
  Aborted
2018-10-16 23:39:36 +02:00
Eelco Dolstra
79e358ce6d RemoteStore: Close connection if an exception occurs
Fixes #2075.
2018-10-16 23:36:15 +02:00
Eelco Dolstra
ba51100d64 Get rid of UDSRemoteStore::Connection
Since its superclass RemoteStore::Connection contains 'to' and 'from'
fields that refer to the file descriptor maintained in the subclass,
it was possible for the flush() call in Connection::~Connection() to
write to a closed file descriptor (or worse, a file descriptor now
referencing another file). So make sure that the file descriptor
survives 'to' and 'from'.
2018-10-16 22:58:01 +02:00
Graham Christensen (Target)
ea41838ae0 install script: remove unportable command check, fixup errant escape
`which` isn't necessarily portable, but `command -v` is an equivalent form.

Additionally, the `\'` is not necessary, as it is already quoted by `"`.
2018-10-16 10:22:36 -04:00
Eelco Dolstra
9617a04354 Merge pull request #2454 from dtzWill/update/nixpkgs-1809
bump base nixpkgs used by default 18.03 -> 18.09
2018-10-09 13:56:33 +02:00
Eelco Dolstra
01bd66bf83 Merge pull request #2452 from ElvishJerricco/verify-sigs-overflow
Fix overflow when verifying signatures of content addressable paths
2018-10-08 12:03:03 +02:00
Eelco Dolstra
0fda9b22c7 Remove unnecessary typecast 2018-10-04 13:16:30 +02:00
Eelco Dolstra
38b960136d Merge pull request #2468 from bhipple/docs/fixedOutputHashes
Docs: update fixed output hashes
2018-10-04 09:20:26 +02:00
Benjamin Hipple
65453e2d77 Docs: update fixed output hashes
`fetchurl` will now throw if given an `md5`, and the hashes have generally
been upgraded to avoid it and use `sha256` as a default. This updates the
documentation examples in the manual accordingly.
2018-10-04 02:37:15 +00:00
Eelco Dolstra
d93db0ace0 Merge pull request #2464 from Profpatsch/docs-builtins-add-ids
manual: add XML IDs to all builtin list entries
2018-10-02 15:45:59 +02:00
Profpatsch
05cfc71cab manual: add XML IDs to all builtin list entries 2018-10-02 15:38:16 +02:00
Eelco Dolstra
aa5e47b2f4 Merge pull request #2456 from grahamc/s3-substituters
Update docs to describe how s3:// URLS does in fact support endpoint, region, and profile for upload
2018-10-01 22:47:00 +02:00
Graham Christensen
47ed3b282f Merge pull request #2462 from matthewbauer/patch-10
nix-profile-daemon: remove cruft
2018-10-01 14:28:29 -04:00
Matthew Bauer
9cc876fb11 nix-profile-daemon: remove cruft
This removes part of the PATH that were being added automatically in multi-user installs:

- $HOME/.nix-profile/lib/kde4/libexec - shouldn't be needed anymore, we are now using kde5
- @localstatedir@/nix/profiles/default/lib/kde4/libexec - same as above
- @localstatedir@/nix/profiles/default - shouldn't ever contain binaries
2018-10-01 13:26:59 -05:00
Eelco Dolstra
5b7cfa487e Add missing file 2018-10-01 11:58:54 +02:00
Eelco Dolstra
1e7b8deea7 Check requiredSystemFeatures for local builds
For example, this prevents a "kvm" build on machines that don't have
KVM.

Fixes #2012.
2018-09-28 16:10:27 +02:00
Eelco Dolstra
7ae7a38c9a Move structured attrs handling into a separate class
This is primarily because Derivation::{can,will}BuildLocally() depends
on attributes like preferLocalBuild and requiredSystemFeatures, but it
can't handle them properly because it doesn't have access to the
structured attributes.
2018-09-28 14:32:46 +02:00
Eelco Dolstra
99d4bb2d4c Remove obsolete check on system features 2018-09-28 13:28:15 +02:00
Eelco Dolstra
c9ba33870e Support special attributes in structured attributes derivations
E.g. __noChroot and allowedReferences now work correctly. We also now
check that the attribute type is correct. For instance, instead of

  allowedReferences = "out";

you have to write

  allowedReferences = [ "out" ];

Fixes #2453.
2018-09-28 12:43:01 +02:00
Graham Christensen
51cbeec49a Update docs to describe how s3:// URLS does in fact support endpoint, region, and profile for upload 2018-09-27 17:01:39 -04:00
Eelco Dolstra
63786cbd3b S3BinaryCacheStore: Don't create buckets
This meant that making a typo in an s3:// URI would cause a bucket to
be created. Also it didn't handle eventual consistency very well. Now
it's up to the user to create the bucket.
2018-09-27 21:34:41 +02:00
Eelco Dolstra
f74e0b4786 Merge pull request #2455 from grahamc/add-interactive-path
nix-shell: add bashInteractive to the start of the PATH, set SHELL
2018-09-27 21:15:50 +02:00
Graham Christensen
f11acbaf17 nix-shell: add bashInteractive to the start of the PATH, set SHELL
Tools which re-exec `$SHELL` or `$0` or `basename $SHELL` or even just
`bash` will otherwise  get the non-interactive bash, providing a
broken shell for the same reasons described in
https://github.com/NixOS/nixpkgs/issues/27493.

Extends c94f3d5575
2018-09-27 15:12:56 -04:00
Eelco Dolstra
7cba4214a8 Don't talk about a "current folder build output"
Presumably this refers to ./default.nix but the support for that in
'nix' is tenuous. Also folders are a Mac thing.
2018-09-27 21:01:19 +02:00
Daiderd Jordan
ed25753501 nix doctor: reimplement profile warning without gcroot check
Calculating roots seems significantly slower on darwin compared to
linux.  Checking for /profile/ links could show some false positives but
should still catch most issues.
2018-09-26 23:13:17 +02:00
Will Dietz
d4f78a6b64 bump base nixpkgs used by default 18.03 -> 18.09 2018-09-26 15:37:13 -05:00
Eelco Dolstra
9750430003 Ensure download thread liveness
* Don't wait forever for the client to remove data from the
  buffer. This does mean that the buffer can grow without bounds
  (e.g. when downloading is faster than writing to disk), but meh.

* Don't hold the state lock while calling the sink. The sink could
  take any amount of time to process the data (in particular when it's
  actually a coroutine), so we don't want to block the download
  thread.
2018-09-26 21:47:34 +02:00
Eelco Dolstra
98b2cc2e6e Untabify 2018-09-26 21:39:06 +02:00
Eelco Dolstra
ed78582847 sinkToSource(): Start the coroutine lazily
In particular this causes copyStorePath() from HttpBinaryCacheStore to
only start a download if needed. E.g. if the destination LocalStore
goes to sleep waiting for the path lock and another process creates
the path, then LocalStore::addToStore() will never read from the
source so we don't have to do the download.
2018-09-26 21:19:34 +02:00
Eelco Dolstra
44e86304b6 Make NAR header check more robust
Changes

  std::bad_alloc

into

  bad archive: input doesn't look like a Nix archive
2018-09-26 12:03:58 +02:00
Will Fancher
b7091ce41e Add a test for signed content-addressed paths 2018-09-25 22:18:52 -04:00
Will Fancher
0ae8d4033d Fix overflow when verifying signatures of content addressable paths 2018-09-25 21:19:24 -04:00
Eelco Dolstra
7ccdcc7fed Merge pull request #2448 from dtzWill/feature/nix-daemon-accept-empty-builders-untrusted
nix-daemon: allow setting builders to "" by any user (untrusted)
2018-09-25 14:09:00 +02:00
Will Dietz
8df367a92d nix-daemon: allow setting builders to "" by any user (untrusted)
(cherry picked from commit a94a2eb1cb1c81e90a7529be5fecac27899a3442)
2018-09-25 03:22:08 -05:00
Eelco Dolstra
42e4ea2b6d Merge pull request #2312 from dtzWill/fix/matched-names-should-still-print-version
search: include version for matches too!
2018-09-24 13:03:28 +02:00
Luke Clifton
fb72104b80 Search NIX_PROFILE for SSL CA 2018-09-20 07:33:35 +08:00
Eelco Dolstra
a48c2e3411 Merge pull request #2434 from grahamc/graham-improve-upgrade
Upgrade docs: improve the upgrade command
2018-09-19 21:53:50 +02:00
Anders Riutta
1915862767 Upgrade docs: improve the upgrade command
and make it more copy-pastable.
2018-09-19 14:17:06 -04:00
Eelco Dolstra
43b7eebfab Merge pull request #2433 from grahamc/doc-shebang-quotes
Document that nix-shell's shebang requires double quotes for expressions
2018-09-19 20:08:45 +02:00
Graham Christensen
be9e356e61 nix-shell: document double quotes being necessary for a simple Nix expression in the shebang 2018-09-19 13:01:27 -04:00
Graham Christensen
10a7f19937 nix-shell: explain the merging property close to the example 2018-09-19 12:48:08 -04:00
Luke Clifton
1241a58975 Look inside the user profile 2018-09-19 15:22:39 +08:00
Eelco Dolstra
2ca6ef0fec Merge pull request #2428 from grahamc/docs-aliases
Document Aliases
2018-09-18 20:24:24 +02:00
Graham Christensen
0cd863197b docs: document deprecated aliases 2018-09-18 12:23:32 -04:00
Eelco Dolstra
52f6d541b9 nix-env: Fix segfault if -f argument is not a directory or a Nix expression
Fixes #2425.
2018-09-17 16:36:30 +02:00
Eelco Dolstra
901dfc7978 Fix build failure if parallel xz is not available 2018-09-17 16:36:11 +02:00
Eelco Dolstra
8327a7a8fa Merge branch 'dirOf-relative' of https://github.com/lheckemann/nix 2018-09-13 14:33:12 +02:00
Graham Christensen
0aca1ffb6e Prefer 'remote builder' over 'slave' 2018-09-10 18:57:46 +02:00
Eelco Dolstra
5b2fdfdca2 Merge pull request #2412 from dingxiangfei2009/patch-repl-autoargs
nix repl respects --arg and --argstr
2018-09-10 10:50:51 +02:00
Ding Xiang Fei
d6ac762bf7 auto args on repl 2018-09-10 15:43:17 +08:00
Eelco Dolstra
bba3f0a308 If fallback is enabled, temporarily disable substituters after a failure
Otherwise, we just keep asking the substituter for other .narinfo
files, which can take a very long time due to retries/timeouts.
2018-09-07 17:08:43 +02:00
Eelco Dolstra
33c3f91885 Handle queryPathInfo() failure from substituters when fallback is enabled
Fixes #1990.
2018-09-07 16:35:48 +02:00
Eelco Dolstra
91405986f4 Convert NIX_COUNT_CALLS to JSON too 2018-09-05 21:57:54 +02:00
Eelco Dolstra
0a2545f95c Log stats to stderr
We shouldn't pollute stdout.
2018-09-05 21:35:58 +02:00
Eelco Dolstra
c4ba5f4be9 Merge branch 'improve-stats' of https://github.com/cleverca22/nix 2018-09-05 21:28:05 +02:00
Eelco Dolstra
2d91012754 fetchurl: Respect unpack
Fixes #2393.
2018-09-05 21:22:37 +02:00
Eelco Dolstra
e0ddabb0d6 Merge pull request #2400 from matthewbauer/patch-9
Get effective user in Nix commands
2018-09-05 13:28:23 +02:00
Matthew Bauer
74f6d8767d Get effective user in Nix commands
‘geteuid’ gives us the user that the command is being run as,
including in setuid modes. By using geteuid to determind id, we can
avoid the ‘sudo -i’ hack when upgrading Nix. So now, upgrading Nix on
macOS is as simple as:

$ sudo nix-channel --update
$ sudo nix-env -u

$ sudo launchctl stop org.nixos.nix-daemon
$ sudo launchctl start org.nixos.nix-daemon
or
$ sudo systemctl restart nix-daemon
2018-09-04 19:32:39 -05:00
Eelco Dolstra
5e0a7206f5 Merge pull request #2397 from dtzWill/fix/reported-dl-size-with-callback
download: fix size reported to progress bar
2018-09-04 12:16:51 +02:00
Will Dietz
28418af920 download: fix size reported to progress bar 2018-09-03 14:12:54 -05:00
Vladimír Čunát
5f3b72cfc2 docs: change expired bzip2.org to archive.org
Fixes #2396.
2018-09-03 17:57:13 +02:00
Michael Bishop
4b034f390c remove the old text format output 2018-09-02 18:25:23 -03:00
Eelco Dolstra
54996b51fb Bump version 2018-09-02 22:12:00 +02:00
Eelco Dolstra
4dd09210d7 Release notes tweaks 2018-09-02 21:47:10 +02:00
Daiderd Jordan
80a4b44d3d nix doctor: only perform path/profile checks with a daemon/local store
Not all store types LegacySSHStore support these operations and it
doesn't really make sense to check those.
2018-09-02 13:41:55 +02:00
Daiderd Jordan
bfdca55868 nix doctor: add check for profile roots
In most cases profiles that are in PATH should have a gcroot.
2018-09-02 12:56:28 +02:00
Daiderd Jordan
0f18dc5479 nix doctor: add warning for multiple versions
It's pretty easy to unintentionally install a second version of nix
into the user profile when using a daemon install.  In this case it
looks like nix was upgraded while the nix-daemon is probably still
unning an older version.
2018-09-02 12:56:28 +02:00
Daiderd Jordan
246acf93f2 nix doctor: handle serve protocol
The serve protocol used by LegacySSHStore has a different major and
shouldn't be compared to PROTOCOL_VERSION.
2018-09-02 12:54:42 +02:00
Daiderd Jordan
7314dc7f07 nix doctor: add warning if client/daemon protocol mismatches
A protocol mismatch can sometimes cause problems when using specific
features with an older daemon. For example:

Nix 2.0 changed the way files are compied to the store.  The daemon is
backwards compatible and can still handle older clients, however a 1.11
nix-daemon isn't forwards compatible.
2018-09-02 12:54:39 +02:00
Daiderd Jordan
070823baa4 Store: expose the protocol version used by a store 2018-09-02 12:54:29 +02:00
Daiderd Jordan
c9a08540c3 nix doctor: add command
Inspired by the homebrew command, shows a combination of debugging
information and warnings with potential issues with a nix installation.
2018-09-02 12:54:20 +02:00
Michael Bishop
2fd1008c70 add JSON to NIX_SHOW_STATS 2018-09-01 20:05:06 -03:00
Eelco Dolstra
1f49926601 Merge pull request #2388 from grahamc/graham/document-multi-user
Document multi-user installation, and add release notes about it not being the default on 2.1
2018-09-01 22:43:48 +02:00
Michael Bishop
c29e5fbb13 improve the stats when profiling 2018-09-01 17:11:56 -03:00
Graham Christensen
c42eaaf684 Create upgrade notes 2018-09-01 15:35:46 -04:00
Eelco Dolstra
c5ab07ec2b Merge pull request #2168 from grahamc/explain-why-netrc-is-busted
manual: document why ~/.netrc doesn't work
2018-09-01 21:25:04 +02:00
Eelco Dolstra
51003f892d Merge pull request #2309 from symphorien/disallowed-man
add manual entries for disallowedRequisites and disallowedReferences
2018-09-01 21:01:41 +02:00
Eelco Dolstra
291f67aecf Merge pull request #2237 from nh2/patch-1
manual: distributed-builds: Mention - as default
2018-09-01 20:41:49 +02:00
Graham Christensen
4be7652dd3 release notes: note that the multi-user installer is available but not selected for Linux with systemd, and the bug about selinux 2018-09-01 10:45:57 -04:00
Graham Christensen
51f9682a8b Default to single-user install 2018-09-01 10:45:56 -04:00
Graham Christensen
c3e508d924 Document the multi-user installer some
Use sh <(...) syntax for installation to preserve stdin and prompting

also update installation docs to account for changes in multi-user selection
2018-09-01 10:45:50 -04:00
Graham Christensen
f66fa7cd20 We support aarch64 now 2018-09-01 10:44:33 -04:00
Eelco Dolstra
6ed4a6bd0e Merge pull request #2384 from graham-at-target/fetch-git-examples
docs: Add some examples to fetchGit
2018-09-01 14:08:32 +02:00
Eelco Dolstra
254ed7f9f3 Merge pull request #2391 from grahamc/more-stats
Print stats in more programs
2018-09-01 14:05:57 +02:00
Graham Christensen
87702532d2 nix-build: Print stats even in failing builds 2018-08-31 21:03:32 -04:00
Graham Christensen
b7bb627f67 nix-build: print stats on sucessful builds 2018-08-31 20:57:07 -04:00
Graham Christensen
0b7568fb73 Drop ssh://... as a required formatting for builtins.fetchGit 2018-08-31 19:49:56 -04:00
Eelco Dolstra
475a0a54a9 fetchGit/fetchMercurial: Don't absolutize paths
This is already done by coerceToString(), provided that the argument
is a path (e.g. 'fetchGit ./bla'). It fixes the handling of URLs like
git@github.com:owner/repo.git. It breaks 'fetchGit "./bla"', but that
was never intended to work anyway and is inconsistent with other
builtin functions (e.g. 'readFile "./bla"' fails).
2018-09-01 00:19:49 +02:00
Eelco Dolstra
b7409c5754 nix path-info: Remove trailing spaces
Fixes #2390.
2018-09-01 00:04:57 +02:00
Eelco Dolstra
4095cd6438 Add contributors 2018-09-01 00:01:05 +02:00
Eelco Dolstra
d1f36e8787 Really fix the build 2018-08-31 19:20:08 +02:00
Eelco Dolstra
ef09da58f2 nix path-info: Hopefully fix macOS build failure
https://hydra.nixos.org/build/80480356
2018-08-31 17:30:45 +02:00
Eelco Dolstra
e3731a1a1f Merge pull request #2387 from graham-at-target/add-ids-to-important-sections
docs: Add IDs to important sections
2018-08-31 17:24:38 +02:00
Graham Christensen
149d10c308 docs: Add IDs to important sections 2018-08-31 10:06:33 -04:00
Graham Christensen
2df21b78b9 docs: Add some examples to fetchGit 2018-08-31 10:00:32 -04:00
Eelco Dolstra
c0c31b58a4 Add localhost alias for ::1 to the sandbox 2018-08-31 11:12:51 +02:00
Eelco Dolstra
adab8b916a Merge pull request #2383 from cleverca22/fix-error-9
fix `error: unknown serve command 9`
2018-08-31 11:07:16 +02:00
Michael Bishop
0767e402f1 fix error: unknown serve command 9 2018-08-30 20:10:08 -03:00
Eelco Dolstra
39f1722f36 nix upgrade-nix: Handle .nix-profile being a link to .../profiles/per-user/...
Also some cosmetic improvements.
2018-08-30 21:18:56 +02:00
Eelco Dolstra
f08b14c9d0 nix upgrade-nix: Improve error message if 'nix' is not in a profile
E.g.

  $ nix upgrade-nix
  error: directory '/home/eelco/Dev/nix/inst/bin' does not appear to be part of a Nix profile

instead of

  $ nix upgrade-nix
  error: '/home/eelco/Dev/nix/inst' is not a symlink
2018-08-30 17:14:17 +02:00
Eelco Dolstra
ddeda0b62e Merge branch 'nix-upgrade-profile' of https://github.com/LnL7/nix 2018-08-30 17:10:59 +02:00
Eelco Dolstra
264e66f696 Add simple test for nix upgrade-nix 2018-08-30 17:10:28 +02:00
Eelco Dolstra
308689f94b Merge pull request #2365 from erikarvstedt/fix-docs
Docs: Fix install prefix
2018-08-30 16:24:52 +02:00
Eelco Dolstra
99828245f8 printSize() fixes
Fix a 32-bit overflow that resulted in negative numbers being printed;
use fmt() instead of boost::format(); change -H to -h for consistency
with 'ls' and 'du'; make the columns narrower (since they can't be
bigger than 1024.0).
2018-08-30 16:22:04 +02:00
Benjamin Hipple
c908df881f Avoid overflow and use boost::format
If the user has an object greater than 1024 yottabytes, it'll just display it as
N yottabytes instead of overflowing.

Swaps to use boost::format strings instead of std::setw and std::setprecision.
2018-08-30 16:22:04 +02:00
Benjamin Hipple
3407a5d936 Add human readable closure sizes to nix path-info
Unfortunately, -h is already taken as a short option by --help, so we have to
use a different letter or the capitalized version.

Resolves #2363
2018-08-30 16:22:04 +02:00
Eelco Dolstra
5e83b0227f nix: Remove the -h flag 2018-08-30 16:14:19 +02:00
Eelco Dolstra
145db703e5 Remove boost from the closure
This reduces the size of the closure by 45 MiB.
2018-08-30 16:03:06 +02:00
Eelco Dolstra
64d7d1a884 Update release notes 2018-08-30 15:28:18 +02:00
Eelco Dolstra
245d01701d upload-release.pl: Handle prerelease versions 2018-08-30 15:21:58 +02:00
Eelco Dolstra
1286d86b95 Merge pull request #2336 from ivan/repl-trailing-spaces
repl: don't add trailing spaces to history lines
2018-08-29 18:13:29 +02:00
Domen Kožar
d16ff76c69 nix.conf: clarify -j0 doesn't affect preferLocalBuild 2018-08-29 14:33:14 +01:00
Eelco Dolstra
20d74a3257 Merge pull request #2378 from aszlig/int64
libexpr: Use int64_t for NixInt
2018-08-29 13:30:50 +02:00
Domen Kožar
54df4bb0b5 nix.conf: mention -j0 is useful 2018-08-29 11:51:51 +01:00
aszlig
0ad643ed5c libexpr: Use int64_t for NixInt
Using a 64bit integer on 32bit systems will come with a bit of a
performance overhead, but given that Nix doesn't use a lot of integers
compared to other types, I think the overhead is negligible also
considering that 32bit systems are in decline.

The biggest advantage however is that when we use a consistent integer
size across all platforms it's less likely that we miss things that we
break due to that. One example would be:

https://github.com/NixOS/nixpkgs/pull/44233

On Hydra it will evaluate, because the evaluator runs on a 64bit
machine, but when evaluating the same on a 32bit machine it will fail,
so using 64bit integers should make that consistent.

While the change of the type in value.hh is rather easy to do, we have a
few more options available for doing the conversion in the lexer:

  * Via an #ifdef on the architecture and using strtol() or strtoll()
    accordingly depending on which architecture we are. For the #ifdef
    we would need another AX_COMPILE_CHECK_SIZEOF in configure.ac.
  * Using istringstream, which would involve copying the value.
  * As we're already using boost, lexical_cast might be a good idea.

Spoiler: I went for the latter, first of all because lexical_cast does
have an overload for const char* and second of all, because it doesn't
involve copying around the input string. Also, because istringstream
seems to come with a bigger overhead than boost::lexical_cast:

https://www.boost.org/doc/libs/release/doc/html/boost_lexical_cast/performance.html

The first method (still using strtol/strtoll) also wasn't something I
pursued further, because it is also locale-aware which I doubt is what
we want, given that the regex for int is [0-9]+.

Signed-off-by: aszlig <aszlig@nix.build>
Fixes: #2339
2018-08-29 01:05:52 +02:00
Daiderd Jordan
d85bb4814f upgrade-nix: resolve profile symlinks
The profile present in PATH is not necessarily the actual profile
location. User profiles are generally added as $HOME/.nix-profile
in which case the indirect profile link needs to be resolved first.

/home/user/.nix-profile -> /nix/var/nix/profiles/per-user/user/profile
/nix/var/nix/profiles/per-user/user/profile -> profile-15-link
/nix/var/nix/profiles/per-user/user/profile-14-link -> /nix/store/hyi4kkjh3bwi2z3wfljrkfymz9904h62-user-environment
/nix/var/nix/profiles/per-user/user/profile-15-link -> /nix/store/6njpl3qvihz46vj911pwx7hfcvwhifl9-user-environment

To upgrade nix here we want /nix/var/nix/profiles/per-user/user/profile-16-link
instead of /home/user/.nix-profile-1-link. The latter is not a gcroot
and would be garbage collected, resulting in a broken profile.

Fixes #2175
2018-08-25 20:50:44 +02:00
Daiderd Jordan
414397759a upgrade-nix: add --dry-run 2018-08-25 20:25:43 +02:00
Eelco Dolstra
c651b7bdc9 Revert "Fix parser/lexer generation with parallel make"
This reverts commit d277442df5.

Make sucks.
2018-08-23 00:23:35 +02:00
Eelco Dolstra
1b01954a3d Merge pull request #2368 from dezgeg/drop-dead-code
Drop dead code
2018-08-22 21:32:49 +02:00
Erik Arvstedt
8ad2defdf0 Docs: Fix install prefix
shell.nix defines the install prefix as $(pwd)/inst
2018-08-21 21:46:43 +02:00
Tuomas Tynkkynen
2894197de7 Drop all references to NIX_INDENT_MAKE
Dead code since 6669a3b477
2018-08-20 02:01:59 +03:00
Tuomas Tynkkynen
458282be59 Drop all references to --disable-init-state
It's all dead code since 2014 (commit 0c6d62cf27).
2018-08-20 01:51:23 +03:00
Graham Christensen
02098d2073 fetchGit: use a better caching scheme
The current usage technically works by putting multiple different
repos in to the same git directory. However, it is very slow as
Git tries very hard to find common commits between the two
repositories. If the two repositories are large (like Nixpkgs and
another long-running project,) it is maddeningly slow.

This change busts the cache for existing deployments, but users
will be promptly repaid in per-repository performance.
2018-08-17 11:27:34 -04:00
Linus Heckemann
d7402c9cd5 dirOf: allow use on non-absolute paths 2018-08-13 11:27:35 +02:00
Ivan Kozik
ec49ea28dc repl: don't add trailing spaces to history lines 2018-08-07 03:59:34 +00:00
Will Dietz
0d72f4e0ca search: include version 2018-07-27 10:45:35 -05:00
Symphorien Gibol
81d1385437 add manual entries for disallowedRequisites and disallowedReferences 2018-07-26 18:14:50 +02:00
Niklas Hambüchen
10ebcf8670 manual: distributed-builds: Mention - as default 2018-06-17 19:01:07 +02:00
Will Dietz
6bf7dc1baf download: if there are active requests, never sleep for 10s
In some versions/configurations libcurl doesn't handle timeouts
(especially DNS timeouts) in a way that wakes curl_multi_wait.

This doesn't appear to be a problem if using c-ares, FWIW.
2018-06-08 21:12:43 -05:00
Graham Christensen
33712fed38 manual: document why ~/.netrc doesn't work
Maybe there is a better place to document this, which is more generic?
2018-05-18 14:21:47 -04:00
145 changed files with 11298 additions and 8890 deletions

3
.gitignore vendored
View File

@@ -81,6 +81,9 @@ perl/Makefile.config
/tests/common.sh
/tests/dummy
/tests/result*
/tests/restricted-innocent
/tests/shell
/tests/shell.drv
# /tests/lang/
/tests/lang/*.out

1
.version Normal file
View File

@@ -0,0 +1 @@
2.3

View File

@@ -5,17 +5,7 @@ makefiles = \
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/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 \

View File

@@ -1,4 +1,6 @@
AR = @AR@
BDW_GC_LIBS = @BDW_GC_LIBS@
BUILD_SHARED_LIBS = @BUILD_SHARED_LIBS@
CC = @CC@
CFLAGS = @CFLAGS@
CXX = @CXX@
@@ -15,9 +17,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@

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,8 +62,9 @@ CXXFLAGS=
AC_PROG_CC
AC_PROG_CXX
AC_PROG_CPP
AX_CXX_COMPILE_STDCXX_14
AX_CXX_COMPILE_STDCXX_17
AC_CHECK_TOOL([AR], [ar])
# Use 64-bit file system calls so that we can support files > 2 GiB.
AC_SYS_LARGEFILE
@@ -127,8 +128,6 @@ 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)
@@ -152,9 +151,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 http://www.bzip.org/.])])
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See https://web.archive.org/web/20180624184756/http://www.bzip.org/.])])
AC_CHECK_HEADERS([bzlib.h], [true],
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See http://www.bzip.org/.])])
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See https://web.archive.org/web/20180624184756/http://www.bzip.org/.])])
# Look for SQLite, a required dependency.
@@ -164,6 +163,8 @@ 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],
@@ -251,11 +252,6 @@ 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
@@ -272,6 +268,15 @@ 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,10 +1,14 @@
{ system ? "" # obsolete
, url
, hash ? "" # an SRI ash
# Legacy hash specification
, md5 ? "", sha1 ? "", sha256 ? "", sha512 ? ""
, outputHash ?
if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256
if hash != "" then hash else if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256
, outputHashAlgo ?
if sha512 != "" then "sha512" else if sha1 != "" then "sha1" else if md5 != "" then "md5" else "sha256"
if hash != "" then "" else 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

@@ -180,4 +180,8 @@ 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

@@ -135,7 +135,6 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-builders">
<term><literal>builders</literal></term>
<listitem>
@@ -159,7 +158,6 @@ 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
@@ -210,7 +208,6 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-connect-timeout"><term><literal>connect-timeout</literal></term>
<listitem>
@@ -243,7 +240,6 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-extra-sandbox-paths">
<term><literal>extra-sandbox-paths</literal></term>
@@ -283,7 +279,6 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-fallback"><term><literal>fallback</literal></term>
<listitem><para>If set to <literal>true</literal>, Nix will fall
@@ -293,7 +288,6 @@ false</literal>.</para>
</varlistentry>
<varlistentry xml:id="conf-fsync-metadata"><term><literal>fsync-metadata</literal></term>
<listitem><para>If set to <literal>true</literal>, changes to the
@@ -304,7 +298,6 @@ 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
@@ -367,10 +360,8 @@ 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>
<listitem><para>If <literal>false</literal> (default), derivations
@@ -394,7 +385,6 @@ builtins.fetchurl {
</varlistentry>
<varlistentry xml:id="conf-keep-outputs"><term><literal>keep-outputs</literal></term>
<listitem><para>If <literal>true</literal>, the garbage collector
@@ -408,10 +398,8 @@ 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>
@@ -437,14 +425,15 @@ builtins.fetchurl {
<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. It can be
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
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>
@@ -600,7 +589,6 @@ 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
@@ -612,7 +600,6 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-require-sigs"><term><literal>require-sigs</literal></term>
<listitem><para>If set to <literal>true</literal> (the default),
@@ -670,13 +657,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>false</literal>.</para>
<para>The default is <literal>true</literal> on Linux and
<literal>false</literal> on all other platforms.</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
@@ -742,7 +729,6 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-substituters"><term><literal>substituters</literal></term>
<listitem><para>A list of URLs of substituters, separated by
@@ -751,7 +737,6 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-system"><term><literal>system</literal></term>
<listitem><para>This option specifies the canonical Nix system
@@ -773,6 +758,33 @@ 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>
@@ -792,7 +804,6 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-trusted-public-keys"><term><literal>trusted-public-keys</literal></term>
<listitem><para>A whitespace-separated list of public keys. When
@@ -803,7 +814,6 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-trusted-substituters"><term><literal>trusted-substituters</literal></term>
<listitem><para>A list of URLs of substituters, separated by
@@ -816,7 +826,6 @@ password <replaceable>my-password</replaceable>
</varlistentry>
<varlistentry xml:id="conf-trusted-users"><term><literal>trusted-users</literal></term>
<listitem>
@@ -842,9 +851,178 @@ password <replaceable>my-password</replaceable>
</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,10 +52,15 @@ nixpkgs=/home/eelco/Dev/nixpkgs-branch:/etc/nixos</screen>
<envar>NIX_PATH</envar> to
<screen>
nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz</screen>
nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-15.09.tar.gz</screen>
tells Nix to download the latest revision in the Nixpkgs/NixOS
14.12 channel.</para>
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>
<para>The search path can be extended using the <option
linkend="opt-I">-I</option> option, which takes precedence over

View File

@@ -95,15 +95,6 @@ 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

@@ -154,7 +154,9 @@ 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).</para>
instantiation of every evaluated derivation). If this option is
not enabled, there may be uninstantiated store paths in the final
output.</para>
</listitem>

View File

@@ -317,13 +317,28 @@ while (my $token = $p->get_tag("a")) {
</para>
<para>Finally, the following Haskell script uses a specific branch of
Nixpkgs/NixOS (the 14.12 stable branch):
<para>Sometimes you need to pass a simple Nix expression to customize
a package like Terraform:
<programlisting><![CDATA[
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p haskellPackages.ghc haskellPackages.HTTP haskellPackages.tagsoup
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz
#! 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
import Network.HTTP
import Text.HTML.TagSoup

View File

@@ -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 build slave.</para></listitem>
as a remote builder.</para></listitem>
</varlistentry>
@@ -679,6 +679,18 @@ 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>
@@ -1270,6 +1282,7 @@ 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>
@@ -1280,6 +1293,13 @@ 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

@@ -216,7 +216,7 @@ fetchurl {
<programlisting>
{ stdenv, curl }: # The <command>curl</command> program is used for downloading.
{ url, md5 }:
{ url, sha256 }:
stdenv.mkDerivation {
name = baseNameOf (toString url);
@@ -224,10 +224,10 @@ stdenv.mkDerivation {
buildInputs = [ curl ];
# This is a fixed-output derivation; the output must be a regular
# file with MD5 hash <varname>md5</varname>.
# file with SHA256 hash <varname>sha256</varname>.
outputHashMode = "flat";
outputHashAlgo = "md5";
outputHash = md5;
outputHashAlgo = "sha256";
outputHash = sha256;
inherit url;
}
@@ -237,8 +237,8 @@ stdenv.mkDerivation {
<para>The <varname>outputHashAlgo</varname> attribute specifies
the hash algorithm used to compute the hash. It can currently be
<literal>"md5"</literal>, <literal>"sha1"</literal> or
<literal>"sha256"</literal>.</para>
<literal>"sha1"</literal>, <literal>"sha256"</literal> or
<literal>"sha512"</literal>.</para>
<para>The <varname>outputHashMode</varname> attribute determines
how the hash is computed. It must be one of the following two
@@ -251,7 +251,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>md5sum</command> or
Unix commands like <command>sha256sum</command> or
<command>sha1sum</command> produce).</para>
<para>This is the default.</para></listitem>
@@ -312,9 +312,7 @@ big = "a very long string";
<varlistentry><term><varname>preferLocalBuild</varname></term>
<listitem><para>If this attribute is set to
<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
<literal>true</literal> and <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
@@ -324,6 +322,19 @@ 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>

View File

@@ -21,7 +21,9 @@ available as <function>builtins.derivation</function>.</para>
<variablelist>
<varlistentry><term><function>abort</function> <replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-abort'>
<term><function>abort</function> <replaceable>s</replaceable></term>
<term><function>builtins.abort</function> <replaceable>s</replaceable></term>
<listitem><para>Abort Nix expression evaluation, print error
message <replaceable>s</replaceable>.</para></listitem>
@@ -29,8 +31,10 @@ available as <function>builtins.derivation</function>.</para>
</varlistentry>
<varlistentry><term><function>builtins.add</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-add'>
<term><function>builtins.add</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable>
</term>
<listitem><para>Return the sum of the numbers
<replaceable>e1</replaceable> and
@@ -39,8 +43,9 @@ available as <function>builtins.derivation</function>.</para>
</varlistentry>
<varlistentry><term><function>builtins.all</function>
<replaceable>pred</replaceable> <replaceable>list</replaceable></term>
<varlistentry xml:id='builtin-all'>
<term><function>builtins.all</function>
<replaceable>pred</replaceable> <replaceable>list</replaceable></term>
<listitem><para>Return <literal>true</literal> if the function
<replaceable>pred</replaceable> returns <literal>true</literal>
@@ -50,8 +55,9 @@ available as <function>builtins.derivation</function>.</para>
</varlistentry>
<varlistentry><term><function>builtins.any</function>
<replaceable>pred</replaceable> <replaceable>list</replaceable></term>
<varlistentry xml:id='builtin-any'>
<term><function>builtins.any</function>
<replaceable>pred</replaceable> <replaceable>list</replaceable></term>
<listitem><para>Return <literal>true</literal> if the function
<replaceable>pred</replaceable> returns <literal>true</literal>
@@ -61,8 +67,9 @@ available as <function>builtins.derivation</function>.</para>
</varlistentry>
<varlistentry><term><function>builtins.attrNames</function>
<replaceable>set</replaceable></term>
<varlistentry xml:id='builtin-attrNames'>
<term><function>builtins.attrNames</function>
<replaceable>set</replaceable></term>
<listitem><para>Return the names of the attributes in the set
<replaceable>set</replaceable> in an alphabetically sorted list. For instance,
@@ -72,8 +79,9 @@ available as <function>builtins.derivation</function>.</para>
</varlistentry>
<varlistentry><term><function>builtins.attrValues</function>
<replaceable>set</replaceable></term>
<varlistentry xml:id='builtin-attrValues'>
<term><function>builtins.attrValues</function>
<replaceable>set</replaceable></term>
<listitem><para>Return the values of the attributes in the set
<replaceable>set</replaceable> in the order corresponding to the
@@ -82,7 +90,8 @@ available as <function>builtins.derivation</function>.</para>
</varlistentry>
<varlistentry><term><function>baseNameOf</function> <replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-baseNameOf'>
<term><function>baseNameOf</function> <replaceable>s</replaceable></term>
<listitem><para>Return the <emphasis>base name</emphasis> of the
string <replaceable>s</replaceable>, that is, everything following
@@ -92,8 +101,9 @@ available as <function>builtins.derivation</function>.</para>
</varlistentry>
<varlistentry><term><function>builtins.bitAnd</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-bitAnd'>
<term><function>builtins.bitAnd</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return the bitwise AND of the integers
<replaceable>e1</replaceable> and
@@ -102,8 +112,9 @@ available as <function>builtins.derivation</function>.</para>
</varlistentry>
<varlistentry><term><function>builtins.bitOr</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-bitOr'>
<term><function>builtins.bitOr</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return the bitwise OR of the integers
<replaceable>e1</replaceable> and
@@ -112,8 +123,9 @@ available as <function>builtins.derivation</function>.</para>
</varlistentry>
<varlistentry><term><function>builtins.bitXor</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-bitXor'>
<term><function>builtins.bitXor</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return the bitwise XOR of the integers
<replaceable>e1</replaceable> and
@@ -122,7 +134,8 @@ available as <function>builtins.derivation</function>.</para>
</varlistentry>
<varlistentry><term><varname>builtins</varname></term>
<varlistentry xml:id='builtin-builtins'>
<term><varname>builtins</varname></term>
<listitem><para>The set <varname>builtins</varname> contains all
the built-in functions and values. You can use
@@ -139,8 +152,9 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.compareVersions</function>
<replaceable>s1</replaceable> <replaceable>s2</replaceable></term>
<varlistentry xml:id='builtin-compareVersions'>
<term><function>builtins.compareVersions</function>
<replaceable>s1</replaceable> <replaceable>s2</replaceable></term>
<listitem><para>Compare two strings representing versions and
return <literal>-1</literal> if version
@@ -156,8 +170,9 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.splitVersion</function>
<replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-splitVersion'>
<term><function>builtins.splitVersion</function>
<replaceable>s</replaceable></term>
<listitem><para>Split a string representing a version into its
components, by the same version splitting logic underlying the
@@ -167,16 +182,18 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.concatLists</function>
<replaceable>lists</replaceable></term>
<varlistentry xml:id='builtin-concatLists'>
<term><function>builtins.concatLists</function>
<replaceable>lists</replaceable></term>
<listitem><para>Concatenate a list of lists into a single
list.</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.concatStringsSep</function>
<replaceable>separator</replaceable> <replaceable>list</replaceable></term>
<varlistentry xml:id='builtin-concatStringsSep'>
<term><function>builtins.concatStringsSep</function>
<replaceable>separator</replaceable> <replaceable>list</replaceable></term>
<listitem><para>Concatenate a list of strings with a separator
between each element, e.g. <literal>concatStringsSep "/"
@@ -184,8 +201,8 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry
xml:id='builtin-currentSystem'><term><varname>builtins.currentSystem</varname></term>
<varlistentry xml:id='builtin-currentSystem'>
<term><varname>builtins.currentSystem</varname></term>
<listitem><para>The built-in value <varname>currentSystem</varname>
evaluates to the Nix platform identifier for the Nix installation
@@ -218,8 +235,9 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
-->
<varlistentry><term><function>builtins.deepSeq</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-deepSeq'>
<term><function>builtins.deepSeq</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>This is like <literal>seq
<replaceable>e1</replaceable>
@@ -231,8 +249,11 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry><term><function>derivation</function>
<replaceable>attrs</replaceable></term>
<varlistentry xml:id='builtin-derivation'>
<term><function>derivation</function>
<replaceable>attrs</replaceable></term>
<term><function>builtins.derivation</function>
<replaceable>attrs</replaceable></term>
<listitem><para><function>derivation</function> is described in
<xref linkend='ssec-derivation' />.</para></listitem>
@@ -240,7 +261,9 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry><term><function>dirOf</function> <replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-dirOf'>
<term><function>dirOf</function> <replaceable>s</replaceable></term>
<term><function>builtins.dirOf</function> <replaceable>s</replaceable></term>
<listitem><para>Return the directory part of the string
<replaceable>s</replaceable>, that is, everything before the final
@@ -250,8 +273,9 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.div</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-div'>
<term><function>builtins.div</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return the quotient of the numbers
<replaceable>e1</replaceable> and
@@ -259,8 +283,9 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.elem</function>
<replaceable>x</replaceable> <replaceable>xs</replaceable></term>
<varlistentry xml:id='builtin-elem'>
<term><function>builtins.elem</function>
<replaceable>x</replaceable> <replaceable>xs</replaceable></term>
<listitem><para>Return <literal>true</literal> if a value equal to
<replaceable>x</replaceable> occurs in the list
@@ -270,8 +295,9 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.elemAt</function>
<replaceable>xs</replaceable> <replaceable>n</replaceable></term>
<varlistentry xml:id='builtin-elemAt'>
<term><function>builtins.elemAt</function>
<replaceable>xs</replaceable> <replaceable>n</replaceable></term>
<listitem><para>Return element <replaceable>n</replaceable> from
the list <replaceable>xs</replaceable>. Elements are counted
@@ -281,8 +307,9 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.fetchurl</function>
<replaceable>url</replaceable></term>
<varlistentry xml:id='builtin-fetchurl'>
<term><function>builtins.fetchurl</function>
<replaceable>url</replaceable></term>
<listitem><para>Download the specified URL and return the path of
the downloaded file. This function is not available if <link
@@ -292,8 +319,11 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry><term><function>fetchTarball</function>
<replaceable>url</replaceable></term>
<varlistentry xml:id='builtin-fetchTarball'>
<term><function>fetchTarball</function>
<replaceable>url</replaceable></term>
<term><function>builtins.fetchTarball</function>
<replaceable>url</replaceable></term>
<listitem><para>Download the specified URL, unpack it and return
the path of the unpacked tree. The file must be a tape archive
@@ -346,7 +376,7 @@ stdenv.mkDerivation { … }
</varlistentry>
<varlistentry>
<varlistentry xml:id='builtin-fetchGit'>
<term>
<function>builtins.fetchGit</function>
<replaceable>args</replaceable>
@@ -412,7 +442,7 @@ stdenv.mkDerivation { … }
<title>Fetching a repository's specific commit on an arbitrary branch</title>
<para>
If the revision you're looking for is in the default branch
of the gift repository you don't strictly need to specify
of the git repository you don't strictly need to specify
the branch name in the <varname>ref</varname> attribute.
</para>
<para>
@@ -441,7 +471,7 @@ stdenv.mkDerivation { … }
<title>Fetching a repository's specific commit on the default branch</title>
<para>
If the revision you're looking for is in the default branch
of the gift repository you may omit the
of the git repository you may omit the
<varname>ref</varname> attribute.
</para>
<programlisting>builtins.fetchGit {
@@ -546,7 +576,8 @@ stdenv.mkDerivation {
</varlistentry>
<varlistentry><term><function>builtins.foldl</function>
<varlistentry xml:id='builtin-foldl-prime'>
<term><function>builtins.foldl</function>
<replaceable>op</replaceable> <replaceable>nul</replaceable> <replaceable>list</replaceable></term>
<listitem><para>Reduce a list by applying a binary operator, from
@@ -559,7 +590,8 @@ stdenv.mkDerivation {
</varlistentry>
<varlistentry><term><function>builtins.functionArgs</function>
<varlistentry xml:id='builtin-functionArgs'>
<term><function>builtins.functionArgs</function>
<replaceable>f</replaceable></term>
<listitem><para>
@@ -577,7 +609,8 @@ stdenv.mkDerivation {
</varlistentry>
<varlistentry><term><function>builtins.fromJSON</function> <replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-fromJSON'>
<term><function>builtins.fromJSON</function> <replaceable>e</replaceable></term>
<listitem><para>Convert a JSON string to a Nix
value. For example,
@@ -592,8 +625,9 @@ builtins.fromJSON ''{"x": [1, 2, 3], "y": null}''
</varlistentry>
<varlistentry><term><function>builtins.genList</function>
<replaceable>generator</replaceable> <replaceable>length</replaceable></term>
<varlistentry xml:id='builtin-genList'>
<term><function>builtins.genList</function>
<replaceable>generator</replaceable> <replaceable>length</replaceable></term>
<listitem><para>Generate list of size
<replaceable>length</replaceable>, with each element
@@ -610,8 +644,9 @@ builtins.genList (x: x * x) 5
</varlistentry>
<varlistentry><term><function>builtins.getAttr</function>
<replaceable>s</replaceable> <replaceable>set</replaceable></term>
<varlistentry xml:id='builtin-getAttr'>
<term><function>builtins.getAttr</function>
<replaceable>s</replaceable> <replaceable>set</replaceable></term>
<listitem><para><function>getAttr</function> returns the attribute
named <replaceable>s</replaceable> from
@@ -623,8 +658,9 @@ builtins.genList (x: x * x) 5
</varlistentry>
<varlistentry><term><function>builtins.getEnv</function>
<replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-getEnv'>
<term><function>builtins.getEnv</function>
<replaceable>s</replaceable></term>
<listitem><para><function>getEnv</function> returns the value of
the environment variable <replaceable>s</replaceable>, or an empty
@@ -641,8 +677,9 @@ builtins.genList (x: x * x) 5
</varlistentry>
<varlistentry><term><function>builtins.hasAttr</function>
<replaceable>s</replaceable> <replaceable>set</replaceable></term>
<varlistentry xml:id='builtin-hasAttr'>
<term><function>builtins.hasAttr</function>
<replaceable>s</replaceable> <replaceable>set</replaceable></term>
<listitem><para><function>hasAttr</function> returns
<literal>true</literal> if <replaceable>set</replaceable> has an
@@ -655,20 +692,22 @@ builtins.genList (x: x * x) 5
</varlistentry>
<varlistentry><term><function>builtins.hashString</function>
<replaceable>type</replaceable> <replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-hashString'>
<term><function>builtins.hashString</function>
<replaceable>type</replaceable> <replaceable>s</replaceable></term>
<listitem><para>Return a base-16 representation of the
cryptographic hash of string <replaceable>s</replaceable>. The
hash algorithm specified by <replaceable>type</replaceable> must
be one of <literal>"md5"</literal>, <literal>"sha1"</literal> or
<literal>"sha256"</literal>.</para></listitem>
be one of <literal>"md5"</literal>, <literal>"sha1"</literal>,
<literal>"sha256"</literal> or <literal>"sha512"</literal>.</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.head</function>
<replaceable>list</replaceable></term>
<varlistentry xml:id='builtin-head'>
<term><function>builtins.head</function>
<replaceable>list</replaceable></term>
<listitem><para>Return the first element of a list; abort
evaluation if the argument isnt a list or is an empty list. You
@@ -678,8 +717,11 @@ builtins.genList (x: x * x) 5
</varlistentry>
<varlistentry><term><function>import</function>
<replaceable>path</replaceable></term>
<varlistentry xml:id='builtin-import'>
<term><function>import</function>
<replaceable>path</replaceable></term>
<term><function>builtins.import</function>
<replaceable>path</replaceable></term>
<listitem><para>Load, parse and return the Nix expression in the
file <replaceable>path</replaceable>. If <replaceable>path
@@ -733,8 +775,9 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.intersectAttrs</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-intersectAttrs'>
<term><function>builtins.intersectAttrs</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return a set consisting of the attributes in the
set <replaceable>e2</replaceable> that also exist in the set
@@ -743,8 +786,9 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.isAttrs</function>
<replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-isAttrs'>
<term><function>builtins.isAttrs</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to a set, and
@@ -753,8 +797,9 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.isList</function>
<replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-isList'>
<term><function>builtins.isList</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to a list, and
@@ -763,7 +808,7 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.isFunction</function>
<varlistentry xml:id='builtin-isFunction'><term><function>builtins.isFunction</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
@@ -773,8 +818,9 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.isString</function>
<replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-isString'>
<term><function>builtins.isString</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to a string, and
@@ -783,8 +829,9 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.isInt</function>
<replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-isInt'>
<term><function>builtins.isInt</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to an int, and
@@ -793,8 +840,9 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.isFloat</function>
<replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-isFloat'>
<term><function>builtins.isFloat</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to a float, and
@@ -803,8 +851,9 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.isBool</function>
<replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-isBool'>
<term><function>builtins.isBool</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to a bool, and
@@ -812,10 +861,21 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>isNull</function>
<varlistentry><term><function>builtins.isPath</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to a path, and
<literal>false</literal> otherwise.</para></listitem>
</varlistentry>
<varlistentry xml:id='builtin-isNull'>
<term><function>isNull</function>
<replaceable>e</replaceable></term>
<term><function>builtins.isNull</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to <literal>null</literal>,
and <literal>false</literal> otherwise.</para>
@@ -828,8 +888,9 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.length</function>
<replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-length'>
<term><function>builtins.length</function>
<replaceable>e</replaceable></term>
<listitem><para>Return the length of the list
<replaceable>e</replaceable>.</para></listitem>
@@ -837,8 +898,9 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.lessThan</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-lessThan'>
<term><function>builtins.lessThan</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return <literal>true</literal> if the number
<replaceable>e1</replaceable> is less than the number
@@ -850,8 +912,9 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.listToAttrs</function>
<replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-listToAttrs'>
<term><function>builtins.listToAttrs</function>
<replaceable>e</replaceable></term>
<listitem><para>Construct a set from a list specifying the names
and values of each attribute. Each element of the list should be
@@ -877,8 +940,11 @@ builtins.listToAttrs
</varlistentry>
<varlistentry><term><function>map</function>
<replaceable>f</replaceable> <replaceable>list</replaceable></term>
<varlistentry xml:id='builtin-map'>
<term><function>map</function>
<replaceable>f</replaceable> <replaceable>list</replaceable></term>
<term><function>builtins.map</function>
<replaceable>f</replaceable> <replaceable>list</replaceable></term>
<listitem><para>Apply the function <replaceable>f</replaceable> to
each element in the list <replaceable>list</replaceable>. For
@@ -893,14 +959,15 @@ map (x: "foo" + x) [ "bar" "bla" "abc" ]</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.match</function>
<replaceable>regex</replaceable> <replaceable>str</replaceable></term>
<varlistentry xml:id='builtin-match'>
<term><function>builtins.match</function>
<replaceable>regex</replaceable> <replaceable>str</replaceable></term>
<listitem><para>Returns a list if the <link
xlink:href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04">extended
POSIX regular expression</link> <replaceable>regex</replaceable>
matches <replaceable>str</replaceable> precisely, otherwise returns
<literal>null</literal>. Each item in the list is a regex group.
<listitem><para>Returns a list if the <link
xlink:href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04">extended
POSIX regular expression</link> <replaceable>regex</replaceable>
matches <replaceable>str</replaceable> precisely, otherwise returns
<literal>null</literal>. Each item in the list is a regex group.
<programlisting>
builtins.match "ab" "abc"
@@ -926,11 +993,12 @@ builtins.match "[[:space:]]+([[:upper:]]+)[[:space:]]+" " FOO "
Evaluates to <literal>[ "foo" ]</literal>.
</para></listitem>
</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.mul</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-mul'>
<term><function>builtins.mul</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return the product of the numbers
<replaceable>e1</replaceable> and
@@ -939,8 +1007,9 @@ Evaluates to <literal>[ "foo" ]</literal>.
</varlistentry>
<varlistentry><term><function>builtins.parseDrvName</function>
<replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-parseDrvName'>
<term><function>builtins.parseDrvName</function>
<replaceable>s</replaceable></term>
<listitem><para>Split the string <replaceable>s</replaceable> into
a package name and version. The package name is everything up to
@@ -953,7 +1022,7 @@ Evaluates to <literal>[ "foo" ]</literal>.
</varlistentry>
<varlistentry>
<varlistentry xml:id='builtin-path'>
<term>
<function>builtins.path</function>
<replaceable>args</replaceable>
@@ -1023,32 +1092,20 @@ Evaluates to <literal>[ "foo" ]</literal>.
</listitem>
</varlistentry>
<varlistentry><term><function>builtins.pathExists</function>
<replaceable>path</replaceable></term>
<varlistentry xml:id='builtin-pathExists'>
<term><function>builtins.pathExists</function>
<replaceable>path</replaceable></term>
<listitem><para>Return <literal>true</literal> if the path
<replaceable>path</replaceable> exists, and
<literal>false</literal> otherwise. One application of this
function is to conditionally include a Nix expression containing
user configuration:
<programlisting>
let
fileName = builtins.getEnv "CONFIG_FILE";
config =
if fileName != "" &amp;&amp; builtins.pathExists (builtins.toPath fileName)
then import (builtins.toPath fileName)
else { someSetting = false; }; <lineannotation># default configuration</lineannotation>
in config.someSetting</programlisting>
(Note that <envar>CONFIG_FILE</envar> must be an absolute path for
this to work.)</para></listitem>
<replaceable>path</replaceable> exists at evaluation time, and
<literal>false</literal> otherwise.</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.readDir</function>
<replaceable>path</replaceable></term>
<varlistentry xml:id='builtin-readDir'>
<term><function>builtins.readDir</function>
<replaceable>path</replaceable></term>
<listitem><para>Return the contents of the directory
<replaceable>path</replaceable> as a set mapping directory entries
@@ -1069,8 +1126,9 @@ in config.someSetting</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.readFile</function>
<replaceable>path</replaceable></term>
<varlistentry xml:id='builtin-readFile'>
<term><function>builtins.readFile</function>
<replaceable>path</replaceable></term>
<listitem><para>Return the contents of the file
<replaceable>path</replaceable> as a string.</para></listitem>
@@ -1078,8 +1136,11 @@ in config.someSetting</programlisting>
</varlistentry>
<varlistentry><term><function>removeAttrs</function>
<replaceable>set</replaceable> <replaceable>list</replaceable></term>
<varlistentry xml:id='builtin-removeAttrs'>
<term><function>removeAttrs</function>
<replaceable>set</replaceable> <replaceable>list</replaceable></term>
<term><function>builtins.removeAttrs</function>
<replaceable>set</replaceable> <replaceable>list</replaceable></term>
<listitem><para>Remove the attributes listed in
<replaceable>list</replaceable> from
@@ -1094,8 +1155,9 @@ removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ]</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.replaceStrings</function>
<replaceable>from</replaceable> <replaceable>to</replaceable> <replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-replaceStrings'>
<term><function>builtins.replaceStrings</function>
<replaceable>from</replaceable> <replaceable>to</replaceable> <replaceable>s</replaceable></term>
<listitem><para>Given string <replaceable>s</replaceable>, replace
every occurrence of the strings in <replaceable>from</replaceable>
@@ -1111,8 +1173,9 @@ builtins.replaceStrings ["oo" "a"] ["a" "i"] "foobar"
</varlistentry>
<varlistentry><term><function>builtins.seq</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-seq'>
<term><function>builtins.seq</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Evaluate <replaceable>e1</replaceable>, then
evaluate and return <replaceable>e2</replaceable>. This ensures
@@ -1122,8 +1185,9 @@ builtins.replaceStrings ["oo" "a"] ["a" "i"] "foobar"
</varlistentry>
<varlistentry><term><function>builtins.sort</function>
<replaceable>comparator</replaceable> <replaceable>list</replaceable></term>
<varlistentry xml:id='builtin-sort'>
<term><function>builtins.sort</function>
<replaceable>comparator</replaceable> <replaceable>list</replaceable></term>
<listitem><para>Return <replaceable>list</replaceable> in sorted
order. It repeatedly calls the function
@@ -1145,15 +1209,16 @@ builtins.sort builtins.lessThan [ 483 249 526 147 42 77 ]
</varlistentry>
<varlistentry><term><function>builtins.split</function>
<replaceable>regex</replaceable> <replaceable>str</replaceable></term>
<varlistentry xml:id='builtin-split'>
<term><function>builtins.split</function>
<replaceable>regex</replaceable> <replaceable>str</replaceable></term>
<listitem><para>Returns a list composed of non matched strings interleaved
with the lists of the <link
xlink:href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04">extended
POSIX regular expression</link> <replaceable>regex</replaceable> matches
of <replaceable>str</replaceable>. Each item in the lists of matched
sequences is a regex group.
<listitem><para>Returns a list composed of non matched strings interleaved
with the lists of the <link
xlink:href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04">extended
POSIX regular expression</link> <replaceable>regex</replaceable> matches
of <replaceable>str</replaceable>. Each item in the lists of matched
sequences is a regex group.
<programlisting>
builtins.split "(a)b" "abc"
@@ -1179,11 +1244,12 @@ builtins.split "([[:upper:]]+)" " FOO "
Evaluates to <literal>[ " " [ "FOO" ] " " ]</literal>.
</para></listitem>
</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.stringLength</function>
<replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-stringLength'>
<term><function>builtins.stringLength</function>
<replaceable>e</replaceable></term>
<listitem><para>Return the length of the string
<replaceable>e</replaceable>. If <replaceable>e</replaceable> is
@@ -1192,8 +1258,9 @@ Evaluates to <literal>[ " " [ "FOO" ] " " ]</literal>.
</varlistentry>
<varlistentry><term><function>builtins.sub</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-sub'>
<term><function>builtins.sub</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return the difference between the numbers
<replaceable>e1</replaceable> and
@@ -1202,9 +1269,10 @@ Evaluates to <literal>[ " " [ "FOO" ] " " ]</literal>.
</varlistentry>
<varlistentry><term><function>builtins.substring</function>
<replaceable>start</replaceable> <replaceable>len</replaceable>
<replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-substring'>
<term><function>builtins.substring</function>
<replaceable>start</replaceable> <replaceable>len</replaceable>
<replaceable>s</replaceable></term>
<listitem><para>Return the substring of
<replaceable>s</replaceable> from character position
@@ -1227,8 +1295,9 @@ builtins.substring 0 3 "nixos"
</varlistentry>
<varlistentry><term><function>builtins.tail</function>
<replaceable>list</replaceable></term>
<varlistentry xml:id='builtin-tail'>
<term><function>builtins.tail</function>
<replaceable>list</replaceable></term>
<listitem><para>Return the second to last elements of a list;
abort evaluation if the argument isnt a list or is an empty
@@ -1237,8 +1306,11 @@ builtins.substring 0 3 "nixos"
</varlistentry>
<varlistentry><term><function>throw</function>
<replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-throw'>
<term><function>throw</function>
<replaceable>s</replaceable></term>
<term><function>builtins.throw</function>
<replaceable>s</replaceable></term>
<listitem><para>Throw an error message
<replaceable>s</replaceable>. This usually aborts Nix expression
@@ -1251,9 +1323,10 @@ builtins.substring 0 3 "nixos"
</varlistentry>
<varlistentry
xml:id='builtin-toFile'><term><function>builtins.toFile</function>
<replaceable>name</replaceable> <replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-toFile'>
<term><function>builtins.toFile</function>
<replaceable>name</replaceable>
<replaceable>s</replaceable></term>
<listitem><para>Store the string <replaceable>s</replaceable> in a
file in the Nix store and return its path. The file has suffix
@@ -1329,7 +1402,8 @@ in foo</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.toJSON</function> <replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-toJSON'>
<term><function>builtins.toJSON</function> <replaceable>e</replaceable></term>
<listitem><para>Return a string containing a JSON representation
of <replaceable>e</replaceable>. Strings, integers, floats, booleans,
@@ -1342,20 +1416,20 @@ in foo</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.toPath</function> <replaceable>s</replaceable></term>
<varlistentry xml:id='builtin-toPath'>
<term><function>builtins.toPath</function> <replaceable>s</replaceable></term>
<listitem><para>Convert the string value
<replaceable>s</replaceable> into a path value. The string
<replaceable>s</replaceable> must represent an absolute path
(i.e., must start with <literal>/</literal>). The path need not
exist. The resulting path is canonicalised, e.g.,
<literal>builtins.toPath "//foo/xyzzy/../bar/"</literal> returns
<literal>/foo/bar</literal>.</para></listitem>
<listitem><para> DEPRECATED. Use <literal>/. + "/path"</literal>
to convert a string into an absolute path. For relative paths,
use <literal>./. + "/path"</literal>.
</para></listitem>
</varlistentry>
<varlistentry><term><function>toString</function> <replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-toString'>
<term><function>toString</function> <replaceable>e</replaceable></term>
<term><function>builtins.toString</function> <replaceable>e</replaceable></term>
<listitem><para>Convert the expression
<replaceable>e</replaceable> to a string.
@@ -1374,7 +1448,8 @@ in foo</programlisting>
</varlistentry>
<varlistentry xml:id='builtin-toXML'><term><function>builtins.toXML</function> <replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-toXML'>
<term><function>builtins.toXML</function> <replaceable>e</replaceable></term>
<listitem><para>Return a string containing an XML representation
of <replaceable>e</replaceable>. The main application for
@@ -1430,7 +1505,7 @@ stdenv.mkDerivation (rec {
builder = builtins.toFile "builder.sh" "
source $stdenv/setup
mkdir $out
echo $servlets | xsltproc ${stylesheet} - > $out/server-conf.xml]]> <co xml:id='ex-toxml-co-apply' /> <![CDATA[
echo "$servlets" | xsltproc ${stylesheet} - > $out/server-conf.xml]]> <co xml:id='ex-toxml-co-apply' /> <![CDATA[
";
stylesheet = builtins.toFile "stylesheet.xsl"]]> <co xml:id='ex-toxml-co-stylesheet' /> <![CDATA[
@@ -1489,8 +1564,9 @@ stdenv.mkDerivation (rec {
</varlistentry>
<varlistentry><term><function>builtins.trace</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<varlistentry xml:id='builtin-trace'>
<term><function>builtins.trace</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Evaluate <replaceable>e1</replaceable> and print its
abstract syntax representation on standard error. Then return
@@ -1499,8 +1575,9 @@ stdenv.mkDerivation (rec {
</varlistentry>
<varlistentry><term><function>builtins.tryEval</function>
<replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-tryEval'>
<term><function>builtins.tryEval</function>
<replaceable>e</replaceable></term>
<listitem><para>Try to evaluate <replaceable>e</replaceable>.
Return a set containing the attributes <literal>success</literal>
@@ -1513,8 +1590,9 @@ stdenv.mkDerivation (rec {
</varlistentry>
<varlistentry><term><function>builtins.typeOf</function>
<replaceable>e</replaceable></term>
<varlistentry xml:id='builtin-typeOf'>
<term><function>builtins.typeOf</function>
<replaceable>e</replaceable></term>
<listitem><para>Return a string representing the type of the value
<replaceable>e</replaceable>, namely <literal>"int"</literal>,

View File

@@ -25,11 +25,18 @@
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="http://www.bzip.org/"/>.</para></listitem>
xlink:href="https://web.archive.org/web/20180624184756/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
@@ -51,6 +58,10 @@
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
@@ -76,6 +87,15 @@
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

@@ -7,15 +7,16 @@
<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'; sudo launchctl stop org.nixos.nix-daemon; sudo
launchctl start org.nixos.nix-daemon</command>.
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 <command>nix-channel
--update; nix-env -iA nixpkgs.nix</command>.
Single-user installations of Nix should run this:
<command>nix-channel --update; nix-env -iA nixpkgs.nix</command>
</para>
</chapter>

View File

@@ -262,12 +262,6 @@ xlink:href="http://nixos.org/">NixOS homepage</link>.</para>
xlink:href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">GNU
LGPLv2.1 or (at your option) any later version</link>.</para>
<para>Nix uses the <link
xlink:href="https://github.com/arangodb/linenoise-ng">linenoise-ng
library</link>, which has the following license:</para>
<programlisting><xi:include href="../../../src/linenoise/LICENSE" parse="text" /></programlisting>
</simplesect>

View File

@@ -12,8 +12,61 @@ 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-bucket</literal>.</para>
<literal>example-nix-cache</literal>.</para>
<section xml:id="ssec-s3-substituter-anonymous-reads">
<title>Anonymous Reads to your S3-compatible binary cache</title>
@@ -24,65 +77,56 @@ fetch prebuilt binaries from <uri>cache.nixos.org</uri>.</para>
cache.</para>
<para>For AWS S3 the binary cache URL for example bucket will be
exactly <uri>https://example-bucket.s3.amazonaws.com</uri>. For S3
compatible binary caches ago have to consult your software's
documentation.</para>
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[
<programlisting><![CDATA[
{
"Id": "DirectReads",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AlowDirectReads",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::example-bucket/*",
"Principal": "*"
}
]
"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>
]]></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-bucket</uri>.</para>
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 writes to S3 compatible binary
caches but only supports Authenticated reads from Amazon S3.
Additionally, the following limitations are in place for
authenticated reads:</para>
<itemizedlist>
<listitem><para>The bucket must actually be hosted by Amazon S3 and
<emphasis>not</emphasis> an S3 compatible
service.</para></listitem>
<listitem><para>The bucket must be within the
<literal>us-east-1</literal> region.</para></listitem>
<listitem><para>The Amazon credentials, if stored in a credential
profile, must be stored in the <literal>default</literal>
profile.</para></listitem>
</itemizedlist>
<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> action on all
objects in the bucket.</para>
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>
@@ -91,69 +135,49 @@ fetch prebuilt binaries from <uri>cache.nixos.org</uri>.</para>
<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-bucket</uri>.</para>
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>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>
<para>Your account will need the following IAM policy to
upload to the cache:</para>
<varlistentry><term><literal>region</literal></term>
<listitem>
<para>
The region of the S3 bucket. <literal>useast-1</literal> by
default.
</para>
</listitem>
</varlistentry>
<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>
<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>
</variablelist>
<example><title>Uploading with non-default credential profile for Amazon S3</title>
<para><command>nix copy --to ssh://machine nixpkgs.hello s3://example-bucket?profile=cache-upload</command></para>
<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 ssh://machine nixpkgs.hello s3://example-bucket?profile=cache-upload&amp;endpoint=minio.example.com</command></para>
<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>
<para>The user writing to the bucket will need to perform the
following actions against the bucket:</para>
<itemizedlist>
<listitem><para><literal>s3:ListBucket</literal></para></listitem>
<listitem><para><literal>s3:GetBucketLocation</literal></para></listitem>
<listitem><para><literal>s3:ListObjects</literal></para></listitem>
<listitem><para><literal>s3:GetObject</literal></para></listitem>
<listitem><para><literal>s3:PutObject</literal></para></listitem>
<listitem><para><literal>s3:ListBucketMultipartUploads</literal></para></listitem>
<listitem><para><literal>s3:CreateMultipartUpload</literal></para></listitem>
<listitem><para><literal>s3:ListMultipartUploadParts</literal></para></listitem>
<listitem><para><literal>s3:AbortMultipartUpload</literal></para></listitem>
</itemizedlist>
</section>
</section>

View File

@@ -12,6 +12,7 @@
</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" />

View File

@@ -0,0 +1,143 @@
<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,7 @@ 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
GLOBAL_CXXFLAGS += -I . -I src -I src/libutil -I src/libstore -I src/libmain -I src/libexpr -I src/nix
$(foreach i, config.h $(call rwildcard, src/lib*, *.hh), \
$(eval $(call install-file-in, $(i), $(includedir)/nix, 0644)))

View File

@@ -91,6 +91,8 @@ downloadFile("binaryTarball.aarch64-linux", "1");
downloadFile("binaryTarball.x86_64-darwin", "1");
downloadFile("installerScript", "1");
exit if $version =~ /pre/;
# Update Nixpkgs in a very hacky way.
system("cd $nixpkgsDir && git pull") == 0 or die;
my $oldName = `nix-instantiate --eval $nixpkgsDir -A nix.name`; chomp $oldName;

View File

@@ -2,6 +2,11 @@
<!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

@@ -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

@@ -49,7 +49,7 @@ rec {
buildDeps =
[ curl
bzip2 xz brotli
bzip2 xz brotli editline
openssl pkgconfig sqlite boehmgc
boost
@@ -64,10 +64,12 @@ rec {
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 =

View File

@@ -1,5 +1,5 @@
{ nix ? builtins.fetchGit ./.
, nixpkgs ? builtins.fetchGit { url = https://github.com/NixOS/nixpkgs-channels.git; ref = "nixos-18.03"; }
, nixpkgs ? builtins.fetchGit { url = https://github.com/NixOS/nixpkgs-channels.git; ref = "nixos-19.03"; }
, officialRelease ? false
, systems ? [ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" ]
}:
@@ -18,7 +18,7 @@ let
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;
@@ -278,7 +278,6 @@ 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"; }'
@@ -296,7 +295,7 @@ let
substitute ${./scripts/install.in} $out/install \
${pkgs.lib.concatMapStrings
(system: "--replace '@binaryTarball_${system}@' $(nix hash-file --type sha256 ${binaryTarball.${system}}/*.tar.bz2) ")
(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}

View File

@@ -674,9 +674,6 @@ $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
@@ -747,7 +744,6 @@ 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

@@ -109,12 +109,6 @@ 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

@@ -11,14 +11,14 @@ oops() {
}
tmpDir="$(mktemp -d -t nix-binary-tarball-unpack.XXXXXXXXXX || \
oops "Can\'t create temporary directory for downloading the Nix binary tarball")"
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 || which "$1" > /dev/null 2>&1 ||
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"
}

View File

@@ -61,11 +61,14 @@ 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
elif [ -e "$NIX_USER_PROFILE_DIR/etc/ssl/certs/ca-bundle.crt" ]; then # fall back to cacert in the user's Nix profile
export NIX_SSL_CERT_FILE=$NIX_USER_PROFILE_DIR/etc/ssl/certs/ca-bundle.crt
elif [ -e "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" ]; then # fall back to cacert in the default Nix profile
export NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/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:$HOME/.nix-profile/lib/kde4/libexec:@localstatedir@/nix/profiles/default/bin:@localstatedir@/nix/profiles/default:@localstatedir@/nix/profiles/default/lib/kde4/libexec:$PATH"
export PATH="$HOME/.nix-profile/bin:@localstatedir@/nix/profiles/default/bin:$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,6 +1,6 @@
{ useClang ? false }:
with import (builtins.fetchGit { url = https://github.com/NixOS/nixpkgs-channels.git; ref = "nixos-18.03"; }) {};
with import (builtins.fetchGit { url = https://github.com/NixOS/nixpkgs-channels.git; ref = "nixos-19.03"; }) {};
with import ./release-common.nix { inherit pkgs; };

View File

@@ -17,6 +17,7 @@
#include "store-api.hh"
#include "derivations.hh"
#include "local-store.hh"
#include "legacy.hh"
using namespace nix;
using std::cin;
@@ -37,11 +38,15 @@ static AutoCloseFD openSlotLock(const Machine & m, unsigned long long slot)
return openLockFile(fmt("%s/%s-%d", currentLoad, escapeUri(m.storeUri), slot), true);
}
int main (int argc, char * * argv)
{
return handleExceptions(argv[0], [&]() {
initNix();
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)
{
{
logger = makeJSONLogger(*logger);
/* Ensure we don't get any SSH passphrase or host key popups. */
@@ -80,7 +85,7 @@ int main (int argc, char * * argv)
if (machines.empty()) {
std::cerr << "# decline-permanently\n";
return;
return 0;
}
string drvPath;
@@ -90,17 +95,18 @@ int main (int argc, char * * argv)
try {
auto s = readString(source);
if (s != "try") return;
} catch (EndOfFile &) { return; }
if (s != "try") return 0;
} catch (EndOfFile &) { return 0; }
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);
auto canBuildLocally = amWilling
&& ( neededSystem == settings.thisSystem
|| settings.extraPlatforms.get().count(neededSystem) > 0)
&& allSupportedLocally(requiredFeatures);
/* Error ignored here, will be caught later */
mkdir(currentLoad.c_str(), 0777);
@@ -253,6 +259,8 @@ connected:
copyPaths(ref<Store>(sshStore), store, missing, NoRepair, NoCheckSigs, NoSubstitute);
}
return;
});
return 0;
}
}
static RegisterLegacyCommand s1("build-remote", _main);

View File

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

View File

@@ -6,12 +6,15 @@
#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>
@@ -23,7 +26,6 @@
#endif
namespace nix {
@@ -128,6 +130,16 @@ 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) {
@@ -142,8 +154,10 @@ 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 "a built-in function";
case tPrimOpApp: return "a partially applied built-in function";
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 tExternal: return v.external->showType();
case tFloat: return "a float";
}
@@ -755,6 +769,7 @@ void EvalState::evalFile(const Path & path_, Value & v)
void EvalState::resetFileCache()
{
fileEvalCache.clear();
fileParseCache.clear();
}
@@ -1723,12 +1738,9 @@ 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);
@@ -1739,62 +1751,107 @@ 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);
printMsg(v, format(" current Boehm heap size: %1% bytes") % heapSize);
printMsg(v, format(" total Boehm heap allocations: %1% bytes") % 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);
}
#endif
if (countCalls) {
v = lvlInfo;
printMsg(v, format("calls to %1% primops:") % primOpCalls.size());
typedef std::multimap<size_t, Symbol> PrimOpCalls_;
PrimOpCalls_ primOpCalls_;
for (auto & i : primOpCalls)
primOpCalls_.insert(std::pair<size_t, 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<size_t, ExprLambda *> FunctionCalls_;
FunctionCalls_ functionCalls_;
for (auto & i : functionCalls)
functionCalls_.insert(std::pair<size_t, 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<size_t, Pos> AttrSelects_;
AttrSelects_ attrSelects_;
for (auto & i : attrSelects)
attrSelects_.insert(std::pair<size_t, 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 (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 (getEnv("NIX_SHOW_SYMBOLS", "0") != "0") {
auto list = topObj.list("symbols");
symbols.dump([&](const std::string & s) { list.elem(s); });
}
}
}

View File

@@ -81,7 +81,7 @@ public:
/* The allowed filesystem paths in restricted or pure evaluation
mode. */
std::experimental::optional<PathSet> allowedPaths;
std::optional<PathSet> allowedPaths;
Value vEmptySet;
@@ -316,6 +316,9 @@ 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);

View File

@@ -295,7 +295,7 @@ static bool getDerivation(EvalState & state, Value & v,
}
std::experimental::optional<DrvInfo> getDerivation(EvalState & state, Value & v,
std::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 `mesa.outputsToInstall`. */
/** Return the list of outputs. The "outputs to install" are determined by `meta.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::experimental::optional<DrvInfo> getDerivation(EvalState & state,
std::optional<DrvInfo> getDerivation(EvalState & state,
Value & v, bool ignoreAssertionFailures);
void getDerivations(EvalState & state, Value & v, const string & pathPrefix,

View File

@@ -6,12 +6,14 @@
%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"
@@ -97,8 +99,6 @@ URI [a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~
%%
<INITIAL,INSIDE_DOLLAR_CURLY>{
if { return IF; }
then { return THEN; }
@@ -124,9 +124,11 @@ or { return OR_KW; }
{ID} { yylval->id = strdup(yytext); return ID; }
{INT} { errno = 0;
yylval->n = strtol(yytext, 0, 10);
if (errno != 0)
try {
yylval->n = boost::lexical_cast<int64_t>(yytext);
} catch (const boost::bad_lexical_cast &) {
throw ParseError(format("invalid integer '%1%'") % yytext);
}
return INT;
}
{FLOAT} { errno = 0;
@@ -136,17 +138,19 @@ or { return OR_KW; }
return FLOAT;
}
\$\{ { PUSH_STATE(INSIDE_DOLLAR_CURLY); return DOLLAR_CURLY; }
}
\$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; }
\} { return '}'; }
<INSIDE_DOLLAR_CURLY>\} { POP_STATE(); return '}'; }
\{ { return '{'; }
<INSIDE_DOLLAR_CURLY>\{ { PUSH_STATE(INSIDE_DOLLAR_CURLY); return '{'; }
\} { /* 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 '{'; }
<INITIAL,INSIDE_DOLLAR_CURLY>\" {
PUSH_STATE(STRING); return '"';
}
\" { PUSH_STATE(STRING); return '"'; }
<STRING>([^\$\"\\]|\$[^\{\"\\]|\\{ANY}|\$\\{ANY})*\$/\" |
<STRING>([^\$\"\\]|\$[^\{\"\\]|\\{ANY}|\$\\{ANY})+ {
/* It is impossible to match strings ending with '$' with one
@@ -155,7 +159,7 @@ or { return OR_KW; }
yylval->e = unescapeStr(data->symbols, yytext, yyleng);
return STR;
}
<STRING>\$\{ { PUSH_STATE(INSIDE_DOLLAR_CURLY); return DOLLAR_CURLY; }
<STRING>\$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; }
<STRING>\" { POP_STATE(); return '"'; }
<STRING>\$|\\|\$\\ {
/* This can only occur when we reach EOF, otherwise the above
@@ -165,7 +169,7 @@ or { return OR_KW; }
return STR;
}
<INITIAL,INSIDE_DOLLAR_CURLY>\'\'(\ *\n)? { PUSH_STATE(IND_STRING); return IND_STRING_OPEN; }
\'\'(\ *\n)? { PUSH_STATE(IND_STRING); return IND_STRING_OPEN; }
<IND_STRING>([^\$\']|\$[^\{\']|\'[^\'\$])+ {
yylval->e = new ExprIndStr(yytext);
return IND_STR;
@@ -183,14 +187,13 @@ or { return OR_KW; }
yylval->e = unescapeStr(data->symbols, yytext + 2, yyleng - 2);
return IND_STR;
}
<IND_STRING>\$\{ { PUSH_STATE(INSIDE_DOLLAR_CURLY); return DOLLAR_CURLY; }
<IND_STRING>\$\{ { PUSH_STATE(DEFAULT); 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);
@@ -215,7 +218,5 @@ or { return OR_KW; }
return (unsigned char) yytext[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 libformat
libexpr_LIBS = libutil libstore
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++14
Cflags: -I${includedir}/nix -std=c++17

View File

@@ -1,7 +1,7 @@
%glr-parser
%pure-parser
%locations
%error-verbose
%define parse.error verbose
%defines
/* %no-lines */
%parse-param { void * scanner }

View File

@@ -315,6 +315,12 @@ 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
{
@@ -335,6 +341,8 @@ 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));
}
@@ -555,7 +563,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
PathSet context;
std::experimental::optional<std::string> outputHash;
std::optional<std::string> outputHash;
std::string outputHashAlgo;
bool outputHashRecursive = false;
@@ -687,21 +695,12 @@ 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);
@@ -724,16 +723,14 @@ 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 = parseHashType(outputHashAlgo);
if (ht == htUnknown)
throw EvalError(format("unknown hash algorithm '%1%', at %2%") % outputHashAlgo % posDrvName);
HashType ht = outputHashAlgo.empty() ? htUnknown : parseHashType(outputHashAlgo);
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, outputHashAlgo, *outputHash);
drv.outputs["out"] = DerivationOutput(outPath,
(outputHashRecursive ? "r:" : "") + printHashType(h.type),
h.to_string(Base16, false));
}
else {
@@ -866,7 +863,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.coerceToPath(pos, *args[0], context));
Path dir = dirOf(state.coerceToString(pos, *args[0], context, false, false));
if (args[0]->type == tPath) mkPath(v, dir.c_str()); else mkString(v, dir, context);
}
@@ -1006,13 +1003,8 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
PathSet refs;
for (auto path : context) {
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);
}
if (path.at(0) != '/')
throw EvalError(format("in 'toFile': the file '%1%' cannot refer to derivation outputs, at %2%") % name % pos);
refs.insert(path);
}
@@ -1586,7 +1578,6 @@ 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. */
@@ -1606,6 +1597,62 @@ 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);
@@ -1796,41 +1843,6 @@ 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)
{
@@ -2220,6 +2232,7 @@ 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);
@@ -2284,6 +2297,7 @@ 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);
@@ -2301,9 +2315,6 @@ void EvalState::createBaseEnv()
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

@@ -0,0 +1,187 @@
#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,6 +3,7 @@
#include "download.hh"
#include "store-api.hh"
#include "pathlocks.hh"
#include "hash.hh"
#include <sys/time.h>
@@ -25,7 +26,7 @@ struct GitInfo
std::regex revRegex("^[0-9a-fA-F]{40}$");
GitInfo exportGit(ref<Store> store, const std::string & uri,
std::experimental::optional<std::string> ref, std::string rev,
std::optional<std::string> ref, std::string rev,
const std::string & name)
{
if (evalSettings.pureEval && rev == "")
@@ -84,15 +85,16 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
if (rev != "" && !std::regex_match(rev, revRegex))
throw Error("invalid Git revision '%s'", rev);
Path cacheDir = getCacheDir() + "/nix/git";
deletePath(getCacheDir() + "/nix/git");
Path cacheDir = getCacheDir() + "/nix/gitv2/" + hashString(htSHA256, uri).to_string(Base32, false);
if (!pathExists(cacheDir)) {
createDirs(dirOf(cacheDir));
runProgram("git", true, { "init", "--bare", cacheDir });
}
std::string localRef = hashString(htSHA256, fmt("%s-%s", uri, *ref)).to_string(Base32, false);
Path localRefFile = cacheDir + "/refs/heads/" + localRef;
Path localRefFile = cacheDir + "/refs/heads/" + *ref;
bool doFetch;
time_t now = time(0);
@@ -122,7 +124,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, *ref + ":" + localRef });
runProgram("git", true, { "-C", cacheDir, "fetch", "--quiet", "--force", "--", uri, fmt("%s:%s", *ref, *ref) });
struct timeval times[2];
times[0].tv_sec = now;
@@ -188,7 +190,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::experimental::optional<std::string> ref;
std::optional<std::string> ref;
std::string rev;
std::string name = "source";
PathSet context;

View File

@@ -93,7 +93,22 @@ HgInfo exportMercurial(ref<Store> store, const std::string & uri,
Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", uri));
if (pathExists(cacheDir)) {
runProgram("hg", true, { "pull", "-R", cacheDir, "--", uri });
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)));
}
}
} else {
createDirs(dirOf(cacheDir));
runProgram("hg", true, { "clone", "--noupdate", "--", uri, cacheDir });

View File

@@ -75,6 +75,13 @@ public:
}
size_t totalSize() const;
template<typename T>
void dump(T callback)
{
for (auto & s : symbols)
callback(s);
}
};
}

View File

@@ -43,7 +43,7 @@ class XMLWriter;
class JSONPlaceholder;
typedef long NixInt;
typedef int64_t NixInt;
typedef double NixFloat;
/* External values must descend from ExternalValueBase, so that

View File

@@ -8,7 +8,7 @@ libmain_SOURCES := $(wildcard $(d)/*.cc)
libmain_LDFLAGS = $(OPENSSL_LIBS)
libmain_LIBS = libstore libutil libformat
libmain_LIBS = libstore libutil
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++14
Cflags: -I${includedir}/nix -std=c++17

View File

@@ -63,7 +63,7 @@ void detectStackOverflow()
act.sa_sigaction = sigsegvHandler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
if (sigaction(SIGSEGV, &act, 0))
throw SysError("resetting SIGCHLD");
throw SysError("resetting SIGSEGV");
#endif
}

View File

@@ -72,24 +72,11 @@ public:
bool isValidPathUncached(const Path & path) override;
PathSet queryAllValidPaths() override
{ unsupported(); }
void queryPathInfoUncached(const Path & path,
Callback<std::shared_ptr<ValidPathInfo>> callback) override;
void queryReferrers(const Path & path,
PathSet & referrers) override
{ unsupported(); }
PathSet queryDerivationOutputs(const Path & path) override
{ unsupported(); }
StringSet queryDerivationOutputNames(const Path & path) override
{ unsupported(); }
Path queryPathFromHashPart(const string & hashPart) override
{ unsupported(); }
{ unsupported("queryPathFromHashPart"); }
bool wantMassQuery() override { return wantMassQuery_; }
@@ -108,22 +95,10 @@ public:
BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv,
BuildMode buildMode) override
{ unsupported(); }
{ unsupported("buildDerivation"); }
void ensurePath(const Path & path) override
{ unsupported(); }
void addTempRoot(const Path & path) override
{ unsupported(); }
void addIndirectRoot(const Path & path) override
{ unsupported(); }
Roots findRoots() override
{ unsupported(); }
void collectGarbage(const GCOptions & options, GCResults & results) override
{ unsupported(); }
{ unsupported("ensurePath"); }
ref<FSAccessor> getFSAccessor() override;

View File

@@ -11,6 +11,8 @@
#include "compression.hh"
#include "json.hh"
#include "nar-info.hh"
#include "parsed-derivations.hh"
#include "machines.hh"
#include <algorithm>
#include <iostream>
@@ -20,6 +22,7 @@
#include <future>
#include <chrono>
#include <regex>
#include <queue>
#include <limits.h>
#include <sys/time.h>
@@ -740,6 +743,8 @@ private:
/* The derivation stored at drvPath. */
std::unique_ptr<BasicDerivation> drv;
std::unique_ptr<ParsedDerivation> parsedDrv;
/* The remainder is state held during the build. */
/* Locks on the output paths. */
@@ -854,7 +859,7 @@ private:
building multiple times. Since this contains the hash, it
allows us to compare whether two rounds produced the same
result. */
ValidPathInfos prevInfos;
std::map<Path, ValidPathInfo> prevInfos;
const uid_t sandboxUid = 1000;
const gid_t sandboxGid = 100;
@@ -935,6 +940,11 @@ private:
as valid. */
void registerOutputs();
/* Check that an output meets the requirements specified by the
'outputChecks' attribute (or the legacy
'{allowed,disallowed}{References,Requisites}' attributes). */
void checkOutputs(const std::map<std::string, ValidPathInfo> & outputs);
/* Open a log file and a pipe to it. */
Path openLogFile();
@@ -1139,6 +1149,8 @@ void DerivationGoal::haveDerivation()
return;
}
parsedDrv = std::make_unique<ParsedDerivation>(drvPath, *drv);
/* We are first going to try to create the invalid output paths
through substitutes. If that doesn't work, we'll build
them. */
@@ -1395,7 +1407,7 @@ void DerivationGoal::tryToBuild()
/* Don't do a remote build if the derivation has the attribute
`preferLocalBuild' set. Also, check and repair modes are only
supported for local builds. */
bool buildLocally = buildMode != bmNormal || drv->willBuildLocally();
bool buildLocally = buildMode != bmNormal || parsedDrv->willBuildLocally();
auto started = [&]() {
auto msg = fmt(
@@ -1641,19 +1653,13 @@ HookReply DerivationGoal::tryBuildHook()
try {
/* Tell the hook about system features (beyond the system type)
required from the build machine. (The hook could parse the
drv file itself, but this is easier.) */
Strings features = tokenizeString<Strings>(get(drv->env, "requiredSystemFeatures"));
for (auto & i : features) checkStoreName(i); /* !!! abuse */
/* Send the request to the hook. */
worker.hook->sink
<< "try"
<< (worker.getNrLocalBuilds() < settings.maxBuildJobs ? 1 : 0)
<< drv->platform
<< drvPath
<< features;
<< parsedDrv->getRequiredSystemFeatures();
worker.hook->sink.flush();
/* Read the first line of input, which should be a word indicating
@@ -1793,23 +1799,26 @@ static void preloadNSS() {
void DerivationGoal::startBuilder()
{
/* Right platform? */
if (!drv->canBuildLocally()) {
throw Error(
format("a '%1%' is required to build '%3%', but I am a '%2%'")
% drv->platform % settings.thisSystem % drvPath);
}
if (!parsedDrv->canBuildLocally())
throw Error("a '%s' with features {%s} is required to build '%s', but I am a '%s' with features {%s}",
drv->platform,
concatStringsSep(", ", parsedDrv->getRequiredSystemFeatures()),
drvPath,
settings.thisSystem,
concatStringsSep(", ", settings.systemFeatures));
if (drv->isBuiltin())
preloadNSS();
#if __APPLE__
additionalSandboxProfile = get(drv->env, "__sandboxProfile");
additionalSandboxProfile = parsedDrv->getStringAttr("__sandboxProfile").value_or("");
#endif
/* Are we doing a chroot build? */
{
auto noChroot = parsedDrv->getBoolAttr("__noChroot");
if (settings.sandboxMode == smEnabled) {
if (get(drv->env, "__noChroot") == "1")
if (noChroot)
throw Error(format("derivation '%1%' has '__noChroot' set, "
"but that's not allowed when 'sandbox' is 'true'") % drvPath);
#if __APPLE__
@@ -1822,7 +1831,7 @@ void DerivationGoal::startBuilder()
else if (settings.sandboxMode == smDisabled)
useChroot = false;
else if (settings.sandboxMode == smRelaxed)
useChroot = !fixedOutput && get(drv->env, "__noChroot") != "1";
useChroot = !fixedOutput && !noChroot;
}
if (worker.store.storeDir != worker.store.realStoreDir) {
@@ -1873,7 +1882,7 @@ void DerivationGoal::startBuilder()
writeStructuredAttrs();
/* Handle exportReferencesGraph(), if set. */
if (!drv->env.count("__json")) {
if (!parsedDrv->getStructuredAttrs()) {
/* The `exportReferencesGraph' feature allows the references graph
to be passed to a builder. This attribute should be a list of
pairs [name1 path1 name2 path2 ...]. The references graph of
@@ -1938,7 +1947,7 @@ void DerivationGoal::startBuilder()
PathSet allowedPaths = settings.allowedImpureHostPrefixes;
/* This works like the above, except on a per-derivation level */
Strings impurePaths = tokenizeString<Strings>(get(drv->env, "__impureHostDeps"));
auto impurePaths = parsedDrv->getStringsAttr("__impureHostDeps").value_or(Strings());
for (auto & i : impurePaths) {
bool found = false;
@@ -2007,7 +2016,7 @@ void DerivationGoal::startBuilder()
/* Create /etc/hosts with localhost entry. */
if (!fixedOutput)
writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n");
writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n::1 localhost\n");
/* Make the closure of the inputs available in the chroot,
rather than the whole Nix store. This prevents any access
@@ -2306,7 +2315,7 @@ void DerivationGoal::initEnv()
passAsFile is ignored in structure mode because it's not
needed (attributes are not passed through the environment, so
there is no size constraint). */
if (!drv->env.count("__json")) {
if (!parsedDrv->getStructuredAttrs()) {
StringSet passAsFile = tokenizeString<StringSet>(get(drv->env, "passAsFile"));
int fileNr = 0;
@@ -2353,8 +2362,8 @@ void DerivationGoal::initEnv()
fixed-output derivations is by definition pure (since we
already know the cryptographic hash of the output). */
if (fixedOutput) {
Strings varNames = tokenizeString<Strings>(get(drv->env, "impureEnvVars"));
for (auto & i : varNames) env[i] = getEnv(i);
for (auto & i : parsedDrv->getStringsAttr("impureEnvVars").value_or(Strings()))
env[i] = getEnv(i);
}
/* Currently structured log messages piggyback on stderr, but we
@@ -2369,111 +2378,103 @@ static std::regex shVarName("[A-Za-z_][A-Za-z0-9_]*");
void DerivationGoal::writeStructuredAttrs()
{
auto jsonAttr = drv->env.find("__json");
if (jsonAttr == drv->env.end()) return;
auto & structuredAttrs = parsedDrv->getStructuredAttrs();
if (!structuredAttrs) return;
try {
auto json = *structuredAttrs;
auto jsonStr = rewriteStrings(jsonAttr->second, inputRewrites);
/* Add an "outputs" object containing the output paths. */
nlohmann::json outputs;
for (auto & i : drv->outputs)
outputs[i.first] = rewriteStrings(i.second.path, inputRewrites);
json["outputs"] = outputs;
auto json = nlohmann::json::parse(jsonStr);
/* Add an "outputs" object containing the output paths. */
nlohmann::json outputs;
for (auto & i : drv->outputs)
outputs[i.first] = rewriteStrings(i.second.path, inputRewrites);
json["outputs"] = outputs;
/* Handle exportReferencesGraph. */
auto e = json.find("exportReferencesGraph");
if (e != json.end() && e->is_object()) {
for (auto i = e->begin(); i != e->end(); ++i) {
std::ostringstream str;
{
JSONPlaceholder jsonRoot(str, true);
PathSet storePaths;
for (auto & p : *i)
storePaths.insert(p.get<std::string>());
worker.store.pathInfoToJSON(jsonRoot,
exportReferences(storePaths), false, true);
}
json[i.key()] = nlohmann::json::parse(str.str()); // urgh
/* Handle exportReferencesGraph. */
auto e = json.find("exportReferencesGraph");
if (e != json.end() && e->is_object()) {
for (auto i = e->begin(); i != e->end(); ++i) {
std::ostringstream str;
{
JSONPlaceholder jsonRoot(str, true);
PathSet storePaths;
for (auto & p : *i)
storePaths.insert(p.get<std::string>());
worker.store.pathInfoToJSON(jsonRoot,
exportReferences(storePaths), false, true);
}
json[i.key()] = nlohmann::json::parse(str.str()); // urgh
}
writeFile(tmpDir + "/.attrs.json", json.dump());
/* As a convenience to bash scripts, write a shell file that
maps all attributes that are representable in bash -
namely, strings, integers, nulls, Booleans, and arrays and
objects consisting entirely of those values. (So nested
arrays or objects are not supported.) */
auto handleSimpleType = [](const nlohmann::json & value) -> std::experimental::optional<std::string> {
if (value.is_string())
return shellEscape(value);
if (value.is_number()) {
auto f = value.get<float>();
if (std::ceil(f) == f)
return std::to_string(value.get<int>());
}
if (value.is_null())
return std::string("''");
if (value.is_boolean())
return value.get<bool>() ? std::string("1") : std::string("");
return {};
};
std::string jsonSh;
for (auto i = json.begin(); i != json.end(); ++i) {
if (!std::regex_match(i.key(), shVarName)) continue;
auto & value = i.value();
auto s = handleSimpleType(value);
if (s)
jsonSh += fmt("declare %s=%s\n", i.key(), *s);
else if (value.is_array()) {
std::string s2;
bool good = true;
for (auto i = value.begin(); i != value.end(); ++i) {
auto s3 = handleSimpleType(i.value());
if (!s3) { good = false; break; }
s2 += *s3; s2 += ' ';
}
if (good)
jsonSh += fmt("declare -a %s=(%s)\n", i.key(), s2);
}
else if (value.is_object()) {
std::string s2;
bool good = true;
for (auto i = value.begin(); i != value.end(); ++i) {
auto s3 = handleSimpleType(i.value());
if (!s3) { good = false; break; }
s2 += fmt("[%s]=%s ", shellEscape(i.key()), *s3);
}
if (good)
jsonSh += fmt("declare -A %s=(%s)\n", i.key(), s2);
}
}
writeFile(tmpDir + "/.attrs.sh", jsonSh);
} catch (std::exception & e) {
throw Error("cannot process __json attribute of '%s': %s", drvPath, e.what());
}
writeFile(tmpDir + "/.attrs.json", rewriteStrings(json.dump(), inputRewrites));
/* As a convenience to bash scripts, write a shell file that
maps all attributes that are representable in bash -
namely, strings, integers, nulls, Booleans, and arrays and
objects consisting entirely of those values. (So nested
arrays or objects are not supported.) */
auto handleSimpleType = [](const nlohmann::json & value) -> std::optional<std::string> {
if (value.is_string())
return shellEscape(value);
if (value.is_number()) {
auto f = value.get<float>();
if (std::ceil(f) == f)
return std::to_string(value.get<int>());
}
if (value.is_null())
return std::string("''");
if (value.is_boolean())
return value.get<bool>() ? std::string("1") : std::string("");
return {};
};
std::string jsonSh;
for (auto i = json.begin(); i != json.end(); ++i) {
if (!std::regex_match(i.key(), shVarName)) continue;
auto & value = i.value();
auto s = handleSimpleType(value);
if (s)
jsonSh += fmt("declare %s=%s\n", i.key(), *s);
else if (value.is_array()) {
std::string s2;
bool good = true;
for (auto i = value.begin(); i != value.end(); ++i) {
auto s3 = handleSimpleType(i.value());
if (!s3) { good = false; break; }
s2 += *s3; s2 += ' ';
}
if (good)
jsonSh += fmt("declare -a %s=(%s)\n", i.key(), s2);
}
else if (value.is_object()) {
std::string s2;
bool good = true;
for (auto i = value.begin(); i != value.end(); ++i) {
auto s3 = handleSimpleType(i.value());
if (!s3) { good = false; break; }
s2 += fmt("[%s]=%s ", shellEscape(i.key()), *s3);
}
if (good)
jsonSh += fmt("declare -A %s=(%s)\n", i.key(), s2);
}
}
writeFile(tmpDir + "/.attrs.sh", rewriteStrings(jsonSh, inputRewrites));
}
@@ -2628,7 +2629,7 @@ void DerivationGoal::runChild()
createDirs(chrootRootDir + "/dev/shm");
createDirs(chrootRootDir + "/dev/pts");
ss.push_back("/dev/full");
if (pathExists("/dev/kvm"))
if (settings.systemFeatures.get().count("kvm") && pathExists("/dev/kvm"))
ss.push_back("/dev/kvm");
ss.push_back("/dev/null");
ss.push_back("/dev/random");
@@ -2917,7 +2918,7 @@ void DerivationGoal::runChild()
writeFile(sandboxFile, sandboxProfile);
bool allowLocalNetworking = get(drv->env, "__darwinAllowLocalNetworking") == "1";
bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking");
/* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms
to find temporary directories, so we want to open up a broader place for them to dump their files, if needed. */
@@ -2989,10 +2990,9 @@ void DerivationGoal::runChild()
/* Parse a list of reference specifiers. Each element must either be
a store path, or the symbolic name of the output of the derivation
(such as `out'). */
PathSet parseReferenceSpecifiers(Store & store, const BasicDerivation & drv, string attr)
PathSet parseReferenceSpecifiers(Store & store, const BasicDerivation & drv, const Strings & paths)
{
PathSet result;
Paths paths = tokenizeString<Paths>(attr);
for (auto & i : paths) {
if (store.isStorePath(i))
result.insert(i);
@@ -3017,7 +3017,7 @@ void DerivationGoal::registerOutputs()
if (allValid) return;
}
ValidPathInfos infos;
std::map<std::string, ValidPathInfo> infos;
/* Set of inodes seen during calls to canonicalisePathMetaData()
for this build's outputs. This needs to be shared between
@@ -3121,15 +3121,15 @@ void DerivationGoal::registerOutputs()
the derivation to its content-addressed location. */
Hash h2 = recursive ? hashPath(h.type, actualPath).first : hashFile(h.type, actualPath);
Path dest = worker.store.makeFixedOutputPath(recursive, h2, drv->env["name"]);
Path dest = worker.store.makeFixedOutputPath(recursive, h2, storePathToName(path));
if (h != h2) {
/* Throw an error after registering the path as
valid. */
delayedException = std::make_exception_ptr(
BuildError("fixed-output derivation produced path '%s' with %s hash '%s' instead of the expected hash '%s'",
dest, printHashType(h.type), printHash16or32(h2), printHash16or32(h)));
BuildError("hash mismatch in fixed-output derivation '%s':\n wanted: %s\n got: %s",
dest, h.to_string(), h2.to_string()));
Path actualDest = worker.store.toRealPath(dest);
@@ -3202,48 +3202,6 @@ void DerivationGoal::registerOutputs()
debug(format("referenced input: '%1%'") % i);
}
/* Enforce `allowedReferences' and friends. */
auto checkRefs = [&](const string & attrName, bool allowed, bool recursive) {
if (drv->env.find(attrName) == drv->env.end()) return;
PathSet spec = parseReferenceSpecifiers(worker.store, *drv, get(drv->env, attrName));
PathSet used;
if (recursive) {
/* Our requisites are the union of the closures of our references. */
for (auto & i : references)
/* Don't call computeFSClosure on ourselves. */
if (path != i)
worker.store.computeFSClosure(i, used);
} else
used = references;
PathSet badPaths;
for (auto & i : used)
if (allowed) {
if (spec.find(i) == spec.end())
badPaths.insert(i);
} else {
if (spec.find(i) != spec.end())
badPaths.insert(i);
}
if (!badPaths.empty()) {
string badPathsStr;
for (auto & i : badPaths) {
badPathsStr += "\n\t";
badPathsStr += i;
}
throw BuildError(format("output '%1%' is not allowed to refer to the following paths:%2%") % actualPath % badPathsStr);
}
};
checkRefs("allowedReferences", true, false);
checkRefs("allowedRequisites", true, true);
checkRefs("disallowedReferences", false, false);
checkRefs("disallowedRequisites", false, true);
if (curRound == nrRounds) {
worker.store.optimisePath(actualPath); // FIXME: combine with scanForReferences()
worker.markContentsGood(path);
@@ -3259,11 +3217,14 @@ void DerivationGoal::registerOutputs()
if (!info.references.empty()) info.ca.clear();
infos.push_back(info);
infos[i.first] = info;
}
if (buildMode == bmCheck) return;
/* Apply output checks. */
checkOutputs(infos);
/* Compare the result with the previous round, and report which
path is different, if any.*/
if (curRound > 1 && prevInfos != infos) {
@@ -3271,16 +3232,16 @@ void DerivationGoal::registerOutputs()
for (auto i = prevInfos.begin(), j = infos.begin(); i != prevInfos.end(); ++i, ++j)
if (!(*i == *j)) {
result.isNonDeterministic = true;
Path prev = i->path + checkSuffix;
Path prev = i->second.path + checkSuffix;
bool prevExists = keepPreviousRound && pathExists(prev);
auto msg = prevExists
? fmt("output '%1%' of '%2%' differs from '%3%' from previous round", i->path, drvPath, prev)
: fmt("output '%1%' of '%2%' differs from previous round", i->path, drvPath);
? fmt("output '%1%' of '%2%' differs from '%3%' from previous round", i->second.path, drvPath, prev)
: fmt("output '%1%' of '%2%' differs from previous round", i->second.path, drvPath);
auto diffHook = settings.diffHook;
if (prevExists && diffHook != "" && runDiffHook) {
try {
auto diff = runProgram(diffHook, true, {prev, i->path});
auto diff = runProgram(diffHook, true, {prev, i->second.path});
if (diff != "")
printError(chomp(diff));
} catch (Error & error) {
@@ -3325,7 +3286,11 @@ void DerivationGoal::registerOutputs()
/* Register each output path as valid, and register the sets of
paths referenced by each of them. If there are cycles in the
outputs, this will fail. */
worker.store.registerValidPaths(infos);
{
ValidPathInfos infos2;
for (auto & i : infos) infos2.push_back(i.second);
worker.store.registerValidPaths(infos2);
}
/* In case of a fixed-output derivation hash mismatch, throw an
exception now that we have registered the output as valid. */
@@ -3334,6 +3299,158 @@ void DerivationGoal::registerOutputs()
}
void DerivationGoal::checkOutputs(const std::map<Path, ValidPathInfo> & outputs)
{
std::map<Path, const ValidPathInfo &> outputsByPath;
for (auto & output : outputs)
outputsByPath.emplace(output.second.path, output.second);
for (auto & output : outputs) {
auto & outputName = output.first;
auto & info = output.second;
struct Checks
{
bool ignoreSelfRefs = false;
std::optional<uint64_t> maxSize, maxClosureSize;
std::optional<Strings> allowedReferences, allowedRequisites, disallowedReferences, disallowedRequisites;
};
/* Compute the closure and closure size of some output. This
is slightly tricky because some of its references (namely
other outputs) may not be valid yet. */
auto getClosure = [&](const Path & path)
{
uint64_t closureSize = 0;
PathSet pathsDone;
std::queue<Path> pathsLeft;
pathsLeft.push(path);
while (!pathsLeft.empty()) {
auto path = pathsLeft.front();
pathsLeft.pop();
if (!pathsDone.insert(path).second) continue;
auto i = outputsByPath.find(path);
if (i != outputsByPath.end()) {
closureSize += i->second.narSize;
for (auto & ref : i->second.references)
pathsLeft.push(ref);
} else {
auto info = worker.store.queryPathInfo(path);
closureSize += info->narSize;
for (auto & ref : info->references)
pathsLeft.push(ref);
}
}
return std::make_pair(pathsDone, closureSize);
};
auto applyChecks = [&](const Checks & checks)
{
if (checks.maxSize && info.narSize > *checks.maxSize)
throw BuildError("path '%s' is too large at %d bytes; limit is %d bytes",
info.path, info.narSize, *checks.maxSize);
if (checks.maxClosureSize) {
uint64_t closureSize = getClosure(info.path).second;
if (closureSize > *checks.maxClosureSize)
throw BuildError("closure of path '%s' is too large at %d bytes; limit is %d bytes",
info.path, closureSize, *checks.maxClosureSize);
}
auto checkRefs = [&](const std::optional<Strings> & value, bool allowed, bool recursive)
{
if (!value) return;
PathSet spec = parseReferenceSpecifiers(worker.store, *drv, *value);
PathSet used = recursive ? getClosure(info.path).first : info.references;
if (recursive && checks.ignoreSelfRefs)
used.erase(info.path);
PathSet badPaths;
for (auto & i : used)
if (allowed) {
if (!spec.count(i))
badPaths.insert(i);
} else {
if (spec.count(i))
badPaths.insert(i);
}
if (!badPaths.empty()) {
string badPathsStr;
for (auto & i : badPaths) {
badPathsStr += "\n ";
badPathsStr += i;
}
throw BuildError("output '%s' is not allowed to refer to the following paths:%s", info.path, badPathsStr);
}
};
checkRefs(checks.allowedReferences, true, false);
checkRefs(checks.allowedRequisites, true, true);
checkRefs(checks.disallowedReferences, false, false);
checkRefs(checks.disallowedRequisites, false, true);
};
if (auto structuredAttrs = parsedDrv->getStructuredAttrs()) {
auto outputChecks = structuredAttrs->find("outputChecks");
if (outputChecks != structuredAttrs->end()) {
auto output = outputChecks->find(outputName);
if (output != outputChecks->end()) {
Checks checks;
auto maxSize = output->find("maxSize");
if (maxSize != output->end())
checks.maxSize = maxSize->get<uint64_t>();
auto maxClosureSize = output->find("maxClosureSize");
if (maxClosureSize != output->end())
checks.maxClosureSize = maxClosureSize->get<uint64_t>();
auto get = [&](const std::string & name) -> std::optional<Strings> {
auto i = output->find(name);
if (i != output->end()) {
Strings res;
for (auto j = i->begin(); j != i->end(); ++j) {
if (!j->is_string())
throw Error("attribute '%s' of derivation '%s' must be a list of strings", name, drvPath);
res.push_back(j->get<std::string>());
}
checks.disallowedRequisites = res;
return res;
}
return {};
};
checks.allowedReferences = get("allowedReferences");
checks.allowedRequisites = get("allowedRequisites");
checks.disallowedReferences = get("disallowedReferences");
checks.disallowedRequisites = get("disallowedRequisites");
applyChecks(checks);
}
}
} else {
// legacy non-structured-attributes case
Checks checks;
checks.ignoreSelfRefs = true;
checks.allowedReferences = parsedDrv->getStringsAttr("allowedReferences");
checks.allowedRequisites = parsedDrv->getStringsAttr("allowedRequisites");
checks.disallowedReferences = parsedDrv->getStringsAttr("disallowedReferences");
checks.disallowedRequisites = parsedDrv->getStringsAttr("disallowedRequisites");
applyChecks(checks);
}
}
}
Path DerivationGoal::openLogFile()
{
logSize = 0;
@@ -3682,6 +3799,19 @@ void SubstitutionGoal::tryNext()
} catch (InvalidPath &) {
tryNext();
return;
} catch (SubstituterDisabled &) {
if (settings.tryFallback) {
tryNext();
return;
}
throw;
} catch (Error & e) {
if (settings.tryFallback) {
printError(e.what());
tryNext();
return;
}
throw;
}
/* Update the total expected download size. */
@@ -4282,6 +4412,11 @@ static void primeCache(Store & store, const PathSet & paths)
PathSet willBuild, willSubstitute, unknown;
unsigned long long downloadSize, narSize;
store.queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize, narSize);
if (!willBuild.empty() && 0 == settings.maxBuildJobs && getMachines().empty())
throw Error(
"%d derivations need to be built, but neither local builds ('--max-jobs') "
"nor remote builds ('--builders') are enabled", willBuild.size());
}

View File

@@ -24,6 +24,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
Path storePath = getAttr("out");
auto mainUrl = getAttr("url");
bool unpack = get(drv.env, "unpack", "") == "1";
/* Note: have to use a fresh downloader here because we're in
a forked process. */
@@ -40,12 +41,12 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
request.decompress = false;
auto decompressor = makeDecompressionSink(
hasSuffix(mainUrl, ".xz") ? "xz" : "none", sink);
unpack && hasSuffix(mainUrl, ".xz") ? "xz" : "none", sink);
downloader->download(std::move(request), *decompressor);
decompressor->finish();
});
if (get(drv.env, "unpack", "") == "1")
if (unpack)
restorePath(storePath, *source);
else
writeFile(storePath, *source);

View File

@@ -36,12 +36,6 @@ Path BasicDerivation::findOutput(const string & id) const
}
bool BasicDerivation::willBuildLocally() const
{
return get(env, "preferLocalBuild") == "1" && canBuildLocally();
}
bool BasicDerivation::substitutesAllowed() const
{
return get(env, "allowSubstitutes", "1") == "1";
@@ -54,14 +48,6 @@ bool BasicDerivation::isBuiltin() const
}
bool BasicDerivation::canBuildLocally() const
{
return platform == settings.thisSystem
|| settings.extraPlatforms.get().count(platform) > 0
|| isBuiltin();
}
Path writeDerivation(ref<Store> store,
const Derivation & drv, const string & name, RepairFlag repair)
{

View File

@@ -56,14 +56,10 @@ struct BasicDerivation
the given derivation. */
Path findOutput(const string & id) const;
bool willBuildLocally() const;
bool substitutesAllowed() const;
bool isBuiltin() const;
bool canBuildLocally() const;
/* Return true iff this is a fixed-output derivation. */
bool isFixedOutput() const;

View File

@@ -345,7 +345,7 @@ struct CurlDownloader : public Downloader
done = true;
try {
act.progress(result.data->size(), result.data->size());
act.progress(result.bodySize, result.bodySize);
callback(std::move(result));
} catch (...) {
done = true;
@@ -528,10 +528,11 @@ struct CurlDownloader : public Downloader
extraFDs[0].fd = wakeupPipe.readSide.get();
extraFDs[0].events = CURL_WAIT_POLLIN;
extraFDs[0].revents = 0;
long maxSleepTimeMs = items.empty() ? 10000 : 100;
auto sleepTimeMs =
nextWakeup != std::chrono::steady_clock::time_point()
? std::max(0, (int) std::chrono::duration_cast<std::chrono::milliseconds>(nextWakeup - std::chrono::steady_clock::now()).count())
: 10000;
: maxSleepTimeMs;
vomit("download thread waiting for %d ms", sleepTimeMs);
mc = curl_multi_wait(curlm, extraFDs, 1, sleepTimeMs, &numfds);
if (mc != CURLM_OK)
@@ -613,6 +614,22 @@ struct CurlDownloader : public Downloader
writeFull(wakeupPipe.writeSide.get(), " ");
}
#ifdef ENABLE_S3
std::tuple<std::string, std::string, Store::Params> parseS3Uri(std::string uri)
{
auto [path, params] = splitUriAndParams(uri);
auto slash = path.find('/', 5); // 5 is the length of "s3://" prefix
if (slash == std::string::npos)
throw nix::Error("bad S3 URI '%s'", path);
std::string bucketName(path, 5, slash - 5);
std::string key(path, slash + 1);
return {bucketName, key, params};
}
#endif
void enqueueDownload(const DownloadRequest & request,
Callback<DownloadResult> callback) override
{
@@ -621,12 +638,15 @@ struct CurlDownloader : public Downloader
// FIXME: do this on a worker thread
try {
#ifdef ENABLE_S3
S3Helper s3Helper("", Aws::Region::US_EAST_1, ""); // FIXME: make configurable
auto slash = request.uri.find('/', 5);
if (slash == std::string::npos)
throw nix::Error("bad S3 URI '%s'", request.uri);
std::string bucketName(request.uri, 5, slash - 5);
std::string key(request.uri, slash + 1);
auto [bucketName, key, params] = parseS3Uri(request.uri);
std::string profile = get(params, "profile", "");
std::string region = get(params, "region", Aws::Region::US_EAST_1);
std::string scheme = get(params, "scheme", "");
std::string endpoint = get(params, "endpoint", "");
S3Helper s3Helper(profile, region, scheme, endpoint);
// FIXME: implement ETag
auto s3Res = s3Helper.getObject(bucketName, key);
DownloadResult res;
@@ -710,11 +730,12 @@ void Downloader::download(DownloadRequest && request, Sink & sink)
/* If the buffer is full, then go to sleep until the calling
thread wakes us up (i.e. when it has removed data from the
buffer). Note: this does stall the download thread. */
while (state->data.size() > 1024 * 1024) {
if (state->quit) return;
buffer). We don't wait forever to prevent stalling the
download thread. (Hopefully sleeping will throttle the
sender.) */
if (state->data.size() > 1024 * 1024) {
debug("download buffer is full; going to sleep");
state.wait(state->request);
state.wait_for(state->request, std::chrono::seconds(10));
}
/* Append data to the buffer and wake up the calling
@@ -736,30 +757,36 @@ void Downloader::download(DownloadRequest && request, Sink & sink)
state->request.notify_one();
}});
auto state(_state->lock());
while (true) {
checkInterrupt();
/* If no data is available, then wait for the download thread
to wake us up. */
if (state->data.empty()) {
std::string chunk;
if (state->quit) {
if (state->exc) std::rethrow_exception(state->exc);
break;
/* Grab data if available, otherwise wait for the download
thread to wake us up. */
{
auto state(_state->lock());
while (state->data.empty()) {
if (state->quit) {
if (state->exc) std::rethrow_exception(state->exc);
return;
}
state.wait(state->avail);
}
state.wait(state->avail);
}
chunk = std::move(state->data);
/* If data is available, then flush it to the sink and wake up
the download thread if it's blocked on a full buffer. */
if (!state->data.empty()) {
sink((unsigned char *) state->data.data(), state->data.size());
state->data.clear();
state->request.notify_one();
}
/* Flush the data to the sink and wake up the download thread
if it's blocked on a full buffer. We don't hold the state
lock while doing this to prevent blocking the download
thread if sink() takes a long time. */
sink((unsigned char *) chunk.data(), chunk.size());
}
}
@@ -873,8 +900,8 @@ Path Downloader::downloadCached(ref<Store> store, const string & url_, bool unpa
Hash gotHash = unpack
? hashPath(expectedHash.type, store->toRealPath(storePath)).first
: hashFile(expectedHash.type, store->toRealPath(storePath));
throw nix::Error("hash mismatch in file downloaded from '%s': got hash '%s' instead of the expected hash '%s'",
url, gotHash.to_string(), expectedHash.to_string());
throw nix::Error("hash mismatch in file downloaded from '%s':\n wanted: %s\n got: %s",
url, expectedHash.to_string(), gotHash.to_string());
}
return store->toRealPath(storePath);

View File

@@ -129,8 +129,8 @@ Path LocalFSStore::addPermRoot(const Path & _storePath,
check if the root is in a directory in or linked from the
gcroots directory. */
if (settings.checkRootReachability) {
Roots roots = findRoots();
if (roots.find(gcRoot) == roots.end())
Roots roots = findRoots(false);
if (roots[storePath].count(gcRoot) == 0)
printError(
format(
"warning: '%1%' is not in a directory where the garbage collector looks for roots; "
@@ -197,10 +197,11 @@ void LocalStore::addTempRoot(const Path & path)
}
std::set<std::pair<pid_t, Path>> LocalStore::readTempRoots(FDs & fds)
{
std::set<std::pair<pid_t, Path>> tempRoots;
static std::string censored = "{censored}";
void LocalStore::findTempRoots(FDs & fds, Roots & tempRoots, bool censor)
{
/* Read the `temproots' directory for per-process temporary root
files. */
for (auto & i : readDirectory(tempRootsDir)) {
@@ -250,14 +251,12 @@ std::set<std::pair<pid_t, Path>> LocalStore::readTempRoots(FDs & fds)
Path root(contents, pos, end - pos);
debug("got temporary root '%s'", root);
assertStorePath(root);
tempRoots.emplace(pid, root);
tempRoots[root].emplace(censor ? censored : fmt("{temp:%d}", pid));
pos = end + 1;
}
fds.push_back(fd); /* keep open */
}
return tempRoots;
}
@@ -266,7 +265,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
auto foundRoot = [&](const Path & path, const Path & target) {
Path storePath = toStorePath(target);
if (isStorePath(storePath) && isValidPath(storePath))
roots[path] = storePath;
roots[storePath].emplace(path);
else
printInfo(format("skipping invalid root from '%1%' to '%2%'") % path % storePath);
};
@@ -306,7 +305,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
else if (type == DT_REG) {
Path storePath = storeDir + "/" + baseNameOf(path);
if (isStorePath(storePath) && isValidPath(storePath))
roots[path] = storePath;
roots[storePath].emplace(path);
}
}
@@ -321,10 +320,8 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
}
Roots LocalStore::findRootsNoTemp()
void LocalStore::findRootsNoTemp(Roots & roots, bool censor)
{
Roots roots;
/* Process direct roots in {gcroots,profiles}. */
findRoots(stateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
findRoots(stateDir + "/profiles", DT_UNKNOWN, roots);
@@ -333,32 +330,22 @@ Roots LocalStore::findRootsNoTemp()
NIX_ROOT_FINDER environment variable. This is typically used
to add running programs to the set of roots (to prevent them
from being garbage collected). */
size_t n = 0;
for (auto & root : findRuntimeRoots())
roots[fmt("{memory:%d}", n++)] = root;
return roots;
findRuntimeRoots(roots, censor);
}
Roots LocalStore::findRoots()
Roots LocalStore::findRoots(bool censor)
{
Roots roots = findRootsNoTemp();
Roots roots;
findRootsNoTemp(roots, censor);
FDs fds;
pid_t prev = -1;
size_t n = 0;
for (auto & root : readTempRoots(fds)) {
if (prev != root.first) n = 0;
prev = root.first;
roots[fmt("{temp:%d:%d}", root.first, n++)] = root.second;
}
findTempRoots(fds, roots, censor);
return roots;
}
static void readProcLink(const string & file, StringSet & paths)
static void readProcLink(const string & file, Roots & roots)
{
/* 64 is the starting buffer size gnu readlink uses... */
auto bufsiz = ssize_t{64};
@@ -377,8 +364,8 @@ try_again:
goto try_again;
}
if (res > 0 && buf[0] == '/')
paths.emplace(static_cast<char *>(buf), res);
return;
roots[std::string(static_cast<char *>(buf), res)]
.emplace(file);
}
static string quoteRegexChars(const string & raw)
@@ -387,20 +374,20 @@ static string quoteRegexChars(const string & raw)
return std::regex_replace(raw, specialRegex, R"(\$&)");
}
static void readFileRoots(const char * path, StringSet & paths)
static void readFileRoots(const char * path, Roots & roots)
{
try {
paths.emplace(readFile(path));
roots[readFile(path)].emplace(path);
} catch (SysError & e) {
if (e.errNo != ENOENT && e.errNo != EACCES)
throw;
}
}
PathSet LocalStore::findRuntimeRoots()
void LocalStore::findRuntimeRoots(Roots & roots, bool censor)
{
PathSet roots;
StringSet paths;
Roots unchecked;
auto procDir = AutoCloseDir{opendir("/proc")};
if (procDir) {
struct dirent * ent;
@@ -410,10 +397,10 @@ PathSet LocalStore::findRuntimeRoots()
while (errno = 0, ent = readdir(procDir.get())) {
checkInterrupt();
if (std::regex_match(ent->d_name, digitsRegex)) {
readProcLink((format("/proc/%1%/exe") % ent->d_name).str(), paths);
readProcLink((format("/proc/%1%/cwd") % ent->d_name).str(), paths);
readProcLink(fmt("/proc/%s/exe" ,ent->d_name), unchecked);
readProcLink(fmt("/proc/%s/cwd", ent->d_name), unchecked);
auto fdStr = (format("/proc/%1%/fd") % ent->d_name).str();
auto fdStr = fmt("/proc/%s/fd", ent->d_name);
auto fdDir = AutoCloseDir(opendir(fdStr.c_str()));
if (!fdDir) {
if (errno == ENOENT || errno == EACCES)
@@ -422,9 +409,8 @@ PathSet LocalStore::findRuntimeRoots()
}
struct dirent * fd_ent;
while (errno = 0, fd_ent = readdir(fdDir.get())) {
if (fd_ent->d_name[0] != '.') {
readProcLink((format("%1%/%2%") % fdStr % fd_ent->d_name).str(), paths);
}
if (fd_ent->d_name[0] != '.')
readProcLink(fmt("%s/%s", fdStr, fd_ent->d_name), unchecked);
}
if (errno) {
if (errno == ESRCH)
@@ -434,18 +420,19 @@ PathSet LocalStore::findRuntimeRoots()
fdDir.reset();
try {
auto mapLines =
tokenizeString<std::vector<string>>(readFile((format("/proc/%1%/maps") % ent->d_name).str(), true), "\n");
for (const auto& line : mapLines) {
auto mapFile = fmt("/proc/%s/maps", ent->d_name);
auto mapLines = tokenizeString<std::vector<string>>(readFile(mapFile, true), "\n");
for (const auto & line : mapLines) {
auto match = std::smatch{};
if (std::regex_match(line, match, mapRegex))
paths.emplace(match[1]);
unchecked[match[1]].emplace(mapFile);
}
auto envString = readFile((format("/proc/%1%/environ") % ent->d_name).str(), true);
auto envFile = fmt("/proc/%s/environ", ent->d_name);
auto envString = readFile(envFile, true);
auto env_end = std::sregex_iterator{};
for (auto i = std::sregex_iterator{envString.begin(), envString.end(), storePathRegex}; i != env_end; ++i)
paths.emplace(i->str());
unchecked[i->str()].emplace(envFile);
} catch (SysError & e) {
if (errno == ENOENT || errno == EACCES || errno == ESRCH)
continue;
@@ -465,7 +452,7 @@ PathSet LocalStore::findRuntimeRoots()
for (const auto & line : lsofLines) {
std::smatch match;
if (std::regex_match(line, match, lsofRegex))
paths.emplace(match[1]);
unchecked[match[1]].emplace("{lsof}");
}
} catch (ExecError & e) {
/* lsof not installed, lsof failed */
@@ -473,21 +460,23 @@ PathSet LocalStore::findRuntimeRoots()
#endif
#if defined(__linux__)
readFileRoots("/proc/sys/kernel/modprobe", paths);
readFileRoots("/proc/sys/kernel/fbsplash", paths);
readFileRoots("/proc/sys/kernel/poweroff_cmd", paths);
readFileRoots("/proc/sys/kernel/modprobe", unchecked);
readFileRoots("/proc/sys/kernel/fbsplash", unchecked);
readFileRoots("/proc/sys/kernel/poweroff_cmd", unchecked);
#endif
for (auto & i : paths)
if (isInStore(i)) {
Path path = toStorePath(i);
if (roots.find(path) == roots.end() && isStorePath(path) && isValidPath(path)) {
for (auto & [target, links] : unchecked) {
if (isInStore(target)) {
Path path = toStorePath(target);
if (isStorePath(path) && isValidPath(path)) {
debug(format("got additional root '%1%'") % path);
roots.insert(path);
if (censor)
roots[path].insert(censored);
else
roots[path].insert(links.begin(), links.end());
}
}
return roots;
}
}
@@ -754,16 +743,20 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
/* Find the roots. Since we've grabbed the GC lock, the set of
permanent roots cannot increase now. */
printError(format("finding garbage collector roots..."));
Roots rootMap = options.ignoreLiveness ? Roots() : findRootsNoTemp();
Roots rootMap;
if (!options.ignoreLiveness)
findRootsNoTemp(rootMap, true);
for (auto & i : rootMap) state.roots.insert(i.second);
for (auto & i : rootMap) state.roots.insert(i.first);
/* Read the temporary roots. This acquires read locks on all
per-process temporary root files. So after this point no paths
can be added to the set of temporary roots. */
FDs fds;
for (auto & root : readTempRoots(fds))
state.tempRoots.insert(root.second);
Roots tempRoots;
findTempRoots(fds, tempRoots, true);
for (auto & root : tempRoots)
state.tempRoots.insert(root.first);
state.roots.insert(state.tempRoots.begin(), state.tempRoots.end());
/* After this point the set of roots or temporary roots cannot

View File

@@ -78,7 +78,11 @@ void loadConfFile()
~/.nix/nix.conf or the command line. */
globalConfig.resetOverriden();
globalConfig.applyConfigFile(getConfigDir() + "/nix/nix.conf");
auto dirs = getConfigDirs();
// Iterate over them in reverse so that the ones appearing first in the path take priority
for (auto dir = dirs.rbegin(); dir != dirs.rend(); dir++) {
globalConfig.applyConfigFile(*dir + "/nix/nix.conf");
}
}
unsigned int Settings::getDefaultCores()
@@ -86,6 +90,21 @@ unsigned int Settings::getDefaultCores()
return std::max(1U, std::thread::hardware_concurrency());
}
StringSet Settings::getDefaultSystemFeatures()
{
/* For backwards compatibility, accept some "features" that are
used in Nixpkgs to route builds to certain machines but don't
actually require anything special on the machines. */
StringSet features{"nixos-test", "benchmark", "big-parallel"};
#if __linux__
if (access("/dev/kvm", R_OK | W_OK) == 0)
features.insert("kvm");
#endif
return features;
}
const string nixVersion = PACKAGE_VERSION;
template<> void BaseSetting<SandboxMode>::set(const std::string & str)

View File

@@ -32,6 +32,8 @@ class Settings : public Config {
unsigned int getDefaultCores();
StringSet getDefaultSystemFeatures();
public:
Settings();
@@ -80,9 +82,9 @@ public:
/* Whether to show build log output in real time. */
bool verboseBuild = true;
/* If verboseBuild is false, the number of lines of the tail of
the log to show if a build fails. */
size_t logLines = 10;
Setting<size_t> logLines{this, 10, "log-lines",
"If verbose-build is false, the number of lines of the tail of "
"the log to show if a build fails."};
MaxBuildJobsSetting maxBuildJobs{this, 1, "max-jobs",
"Maximum number of parallel build jobs. \"auto\" means use number of cores.",
@@ -193,7 +195,13 @@ public:
Setting<bool> showTrace{this, false, "show-trace",
"Whether to show a stack trace on evaluation errors."};
Setting<SandboxMode> sandboxMode{this, smDisabled, "sandbox",
Setting<SandboxMode> sandboxMode{this,
#if __linux__
smEnabled
#else
smDisabled
#endif
, "sandbox",
"Whether to enable sandboxed builds. Can be \"true\", \"false\" or \"relaxed\".",
{"build-use-chroot", "build-use-sandbox"}};
@@ -261,6 +269,10 @@ public:
"These may be supported natively (e.g. armv7 on some aarch64 CPUs "
"or using hacks like qemu-user."};
Setting<StringSet> systemFeatures{this, getDefaultSystemFeatures(),
"system-features",
"Optional features that this system implements (like \"kvm\")."};
Setting<Strings> substituters{this,
nixStore == "/nix/store" ? Strings{"https://cache.nixos.org/"} : Strings(),
"substituters",

View File

@@ -13,6 +13,14 @@ private:
Path cacheUri;
struct State
{
bool enabled = true;
std::chrono::steady_clock::time_point disabledUntil;
};
Sync<State> _state;
public:
HttpBinaryCacheStore(
@@ -46,8 +54,33 @@ public:
protected:
void maybeDisable()
{
auto state(_state.lock());
if (state->enabled && settings.tryFallback) {
int t = 60;
printError("disabling binary cache '%s' for %s seconds", getUri(), t);
state->enabled = false;
state->disabledUntil = std::chrono::steady_clock::now() + std::chrono::seconds(t);
}
}
void checkEnabled()
{
auto state(_state.lock());
if (state->enabled) return;
if (std::chrono::steady_clock::now() > state->disabledUntil) {
state->enabled = true;
debug("re-enabling binary cache '%s'", getUri());
return;
}
throw SubstituterDisabled("substituter '%s' is disabled", getUri());
}
bool fileExists(const std::string & path) override
{
checkEnabled();
try {
DownloadRequest request(cacheUri + "/" + path);
request.head = true;
@@ -59,6 +92,7 @@ protected:
bucket is unlistable, so treat 403 as 404. */
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden)
return false;
maybeDisable();
throw;
}
}
@@ -86,12 +120,14 @@ protected:
void getFile(const std::string & path, Sink & sink) override
{
checkEnabled();
auto request(makeRequest(path));
try {
getDownloader()->download(std::move(request), sink);
} catch (DownloadError & e) {
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden)
throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache '%s'", path, getUri());
maybeDisable();
throw;
}
}
@@ -99,15 +135,18 @@ protected:
void getFile(const std::string & path,
Callback<std::shared_ptr<std::string>> callback) override
{
checkEnabled();
auto request(makeRequest(path));
getDownloader()->enqueueDownload(request,
{[callback](std::future<DownloadResult> result) {
{[callback, this](std::future<DownloadResult> result) {
try {
callback(result.get().data);
} catch (DownloadError & e) {
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden)
return callback(std::shared_ptr<std::string>());
maybeDisable();
callback.rethrow();
} catch (...) {
callback.rethrow();

View File

@@ -187,28 +187,17 @@ struct LegacySSHStore : public Store
copyNAR(conn->from, sink);
}
PathSet queryAllValidPaths() override { unsupported(); }
void queryReferrers(const Path & path, PathSet & referrers) override
{ unsupported(); }
PathSet queryDerivationOutputs(const Path & path) override
{ unsupported(); }
StringSet queryDerivationOutputNames(const Path & path) override
{ unsupported(); }
Path queryPathFromHashPart(const string & hashPart) override
{ unsupported(); }
{ unsupported("queryPathFromHashPart"); }
Path addToStore(const string & name, const Path & srcPath,
bool recursive, HashType hashAlgo,
PathFilter & filter, RepairFlag repair) override
{ unsupported(); }
{ unsupported("addToStore"); }
Path addTextToStore(const string & name, const string & s,
const PathSet & references, RepairFlag repair) override
{ unsupported(); }
{ unsupported("addTextToStore"); }
BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv,
BuildMode buildMode) override
@@ -242,25 +231,7 @@ struct LegacySSHStore : public Store
}
void ensurePath(const Path & path) override
{ unsupported(); }
void addTempRoot(const Path & path) override
{ unsupported(); }
void addIndirectRoot(const Path & path) override
{ unsupported(); }
Roots findRoots() override
{ unsupported(); }
void collectGarbage(const GCOptions & options, GCResults & results) override
{ unsupported(); }
ref<FSAccessor> getFSAccessor() override
{ unsupported(); }
void addSignatures(const Path & storePath, const StringSet & sigs) override
{ unsupported(); }
{ unsupported("ensurePath"); }
void computeFSClosure(const PathSet & paths,
PathSet & out, bool flipDirection = false,
@@ -303,6 +274,12 @@ struct LegacySSHStore : public Store
{
auto conn(connections->get());
}
unsigned int getProtocol() override
{
auto conn(connections->get());
return conn->remoteVersion;
}
};
static RegisterStoreImplementation regStore([](

View File

@@ -880,6 +880,12 @@ void LocalStore::querySubstitutablePathInfos(const PathSet & paths,
narInfo ? narInfo->fileSize : 0,
info->narSize};
} catch (InvalidPath) {
} catch (SubstituterDisabled) {
} catch (Error & e) {
if (settings.tryFallback)
printError(e.what());
else
throw;
}
}
}
@@ -1014,11 +1020,11 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
auto hashResult = hashSink.finish();
if (hashResult.first != info.narHash)
throw Error("hash mismatch importing path '%s'; expected hash '%s', got '%s'",
throw Error("hash mismatch importing path '%s';\n wanted: %s\n got: %s",
info.path, info.narHash.to_string(), hashResult.first.to_string());
if (hashResult.second != info.narSize)
throw Error("size mismatch importing path '%s'; expected %s, got %s",
throw Error("size mismatch importing path '%s';\n wanted: %s\n got: %s",
info.path, info.narSize, hashResult.second);
autoGC();
@@ -1332,6 +1338,12 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store,
}
unsigned int LocalStore::getProtocol()
{
return PROTOCOL_VERSION;
}
#if defined(FS_IOC_SETFLAGS) && defined(FS_IOC_GETFLAGS) && defined(FS_IMMUTABLE_FL)
static void makeMutable(const Path & path)

View File

@@ -180,11 +180,11 @@ private:
typedef std::shared_ptr<AutoCloseFD> FDPtr;
typedef list<FDPtr> FDs;
std::set<std::pair<pid_t, Path>> readTempRoots(FDs & fds);
void findTempRoots(FDs & fds, Roots & roots, bool censor);
public:
Roots findRoots() override;
Roots findRoots(bool censor) override;
void collectGarbage(const GCOptions & options, GCResults & results) override;
@@ -209,6 +209,8 @@ public:
void registerValidPaths(const ValidPathInfos & infos);
unsigned int getProtocol() override;
void vacuumDB();
/* Repair the contents of the given path by redownloading it using
@@ -265,9 +267,9 @@ private:
void findRoots(const Path & path, unsigned char type, Roots & roots);
Roots findRootsNoTemp();
void findRootsNoTemp(Roots & roots, bool censor);
PathSet findRuntimeRoots();
void findRuntimeRoots(Roots & roots, bool censor);
void removeUnusedLinks(const GCState & state);

View File

@@ -6,7 +6,7 @@ libstore_DIR := $(d)
libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc)
libstore_LIBS = libutil libformat
libstore_LIBS = libutil
libstore_LDFLAGS = $(SQLITE3_LIBS) -lbz2 $(LIBCURL_LIBS) $(SODIUM_LIBS) -pthread
ifneq ($(OS), FreeBSD)

View File

@@ -89,10 +89,11 @@ void parseMachines(const std::string & s, Machines & machines)
Machines getMachines()
{
Machines machines;
parseMachines(settings.builders, machines);
static auto machines = [&]() {
Machines machines;
parseMachines(settings.builders, machines);
return machines;
}();
return machines;
}

View File

@@ -31,6 +31,7 @@ create table if not exists NARs (
refs text,
deriver text,
sigs text,
ca text,
timestamp integer not null,
present integer not null,
primary key (cache, hashPart),
@@ -72,7 +73,7 @@ public:
{
auto state(_state.lock());
Path dbPath = getCacheDir() + "/nix/binary-cache-v5.sqlite";
Path dbPath = getCacheDir() + "/nix/binary-cache-v6.sqlite";
createDirs(dirOf(dbPath));
state->db = SQLite(dbPath);
@@ -94,13 +95,13 @@ public:
state->insertNAR.create(state->db,
"insert or replace into NARs(cache, hashPart, namePart, url, compression, fileHash, fileSize, narHash, "
"narSize, refs, deriver, sigs, timestamp, present) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)");
"narSize, refs, deriver, sigs, ca, timestamp, present) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)");
state->insertMissingNAR.create(state->db,
"insert or replace into NARs(cache, hashPart, timestamp, present) values (?, ?, ?, 0)");
state->queryNAR.create(state->db,
"select * from NARs where cache = ? and hashPart = ? and ((present = 0 and timestamp > ?) or (present = 1 and timestamp > ?))");
"select present, namePart, url, compression, fileHash, fileSize, narHash, narSize, refs, deriver, sigs, ca from NARs where cache = ? and hashPart = ? and ((present = 0 and timestamp > ?) or (present = 1 and timestamp > ?))");
/* Periodically purge expired entries from the database. */
retrySQLite<void>([&]() {
@@ -189,27 +190,28 @@ public:
if (!queryNAR.next())
return {oUnknown, 0};
if (!queryNAR.getInt(13))
if (!queryNAR.getInt(0))
return {oInvalid, 0};
auto narInfo = make_ref<NarInfo>();
auto namePart = queryNAR.getStr(2);
auto namePart = queryNAR.getStr(1);
narInfo->path = cache.storeDir + "/" +
hashPart + (namePart.empty() ? "" : "-" + namePart);
narInfo->url = queryNAR.getStr(3);
narInfo->compression = queryNAR.getStr(4);
if (!queryNAR.isNull(5))
narInfo->fileHash = Hash(queryNAR.getStr(5));
narInfo->fileSize = queryNAR.getInt(6);
narInfo->narHash = Hash(queryNAR.getStr(7));
narInfo->narSize = queryNAR.getInt(8);
for (auto & r : tokenizeString<Strings>(queryNAR.getStr(9), " "))
narInfo->url = queryNAR.getStr(2);
narInfo->compression = queryNAR.getStr(3);
if (!queryNAR.isNull(4))
narInfo->fileHash = Hash(queryNAR.getStr(4));
narInfo->fileSize = queryNAR.getInt(5);
narInfo->narHash = Hash(queryNAR.getStr(6));
narInfo->narSize = queryNAR.getInt(7);
for (auto & r : tokenizeString<Strings>(queryNAR.getStr(8), " "))
narInfo->references.insert(cache.storeDir + "/" + r);
if (!queryNAR.isNull(10))
narInfo->deriver = cache.storeDir + "/" + queryNAR.getStr(10);
for (auto & sig : tokenizeString<Strings>(queryNAR.getStr(11), " "))
if (!queryNAR.isNull(9))
narInfo->deriver = cache.storeDir + "/" + queryNAR.getStr(9);
for (auto & sig : tokenizeString<Strings>(queryNAR.getStr(10), " "))
narInfo->sigs.insert(sig);
narInfo->ca = queryNAR.getStr(11);
return {oValid, narInfo};
});
@@ -243,6 +245,7 @@ public:
(concatStringsSep(" ", info->shortRefs()))
(info->deriver != "" ? baseNameOf(info->deriver) : "", info->deriver != "")
(concatStringsSep(" ", info->sigs))
(info->ca)
(time(0)).exec();
} else {

View File

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

View File

@@ -0,0 +1,111 @@
#include "parsed-derivations.hh"
namespace nix {
ParsedDerivation::ParsedDerivation(const Path & drvPath, BasicDerivation & drv)
: drvPath(drvPath), drv(drv)
{
/* Parse the __json attribute, if any. */
auto jsonAttr = drv.env.find("__json");
if (jsonAttr != drv.env.end()) {
try {
structuredAttrs = nlohmann::json::parse(jsonAttr->second);
} catch (std::exception & e) {
throw Error("cannot process __json attribute of '%s': %s", drvPath, e.what());
}
}
}
std::optional<std::string> ParsedDerivation::getStringAttr(const std::string & name) const
{
if (structuredAttrs) {
auto i = structuredAttrs->find(name);
if (i == structuredAttrs->end())
return {};
else {
if (!i->is_string())
throw Error("attribute '%s' of derivation '%s' must be a string", name, drvPath);
return i->get<std::string>();
}
} else {
auto i = drv.env.find(name);
if (i == drv.env.end())
return {};
else
return i->second;
}
}
bool ParsedDerivation::getBoolAttr(const std::string & name, bool def) const
{
if (structuredAttrs) {
auto i = structuredAttrs->find(name);
if (i == structuredAttrs->end())
return def;
else {
if (!i->is_boolean())
throw Error("attribute '%s' of derivation '%s' must be a Boolean", name, drvPath);
return i->get<bool>();
}
} else {
auto i = drv.env.find(name);
if (i == drv.env.end())
return def;
else
return i->second == "1";
}
}
std::optional<Strings> ParsedDerivation::getStringsAttr(const std::string & name) const
{
if (structuredAttrs) {
auto i = structuredAttrs->find(name);
if (i == structuredAttrs->end())
return {};
else {
if (!i->is_array())
throw Error("attribute '%s' of derivation '%s' must be a list of strings", name, drvPath);
Strings res;
for (auto j = i->begin(); j != i->end(); ++j) {
if (!j->is_string())
throw Error("attribute '%s' of derivation '%s' must be a list of strings", name, drvPath);
res.push_back(j->get<std::string>());
}
return res;
}
} else {
auto i = drv.env.find(name);
if (i == drv.env.end())
return {};
else
return tokenizeString<Strings>(i->second);
}
}
StringSet ParsedDerivation::getRequiredSystemFeatures() const
{
StringSet res;
for (auto & i : getStringsAttr("requiredSystemFeatures").value_or(Strings()))
res.insert(i);
return res;
}
bool ParsedDerivation::canBuildLocally() const
{
if (drv.platform != settings.thisSystem.get()
&& !settings.extraPlatforms.get().count(drv.platform)
&& !drv.isBuiltin())
return false;
for (auto & feature : getRequiredSystemFeatures())
if (!settings.systemFeatures.get().count(feature)) return false;
return true;
}
bool ParsedDerivation::willBuildLocally() const
{
return getBoolAttr("preferLocalBuild") && canBuildLocally();
}
}

View File

@@ -0,0 +1,35 @@
#include "derivations.hh"
#include <nlohmann/json.hpp>
namespace nix {
class ParsedDerivation
{
Path drvPath;
BasicDerivation & drv;
std::optional<nlohmann::json> structuredAttrs;
public:
ParsedDerivation(const Path & drvPath, BasicDerivation & drv);
const std::optional<nlohmann::json> & getStructuredAttrs() const
{
return structuredAttrs;
}
std::optional<std::string> getStringAttr(const std::string & name) const;
bool getBoolAttr(const std::string & name, bool def = false) const;
std::optional<Strings> getStringsAttr(const std::string & name) const;
StringSet getRequiredSystemFeatures() const;
bool canBuildLocally() const;
bool willBuildLocally() const;
};
}

View File

@@ -161,7 +161,8 @@ void RemoteStore::initConnection(Connection & conn)
if (GET_PROTOCOL_MINOR(conn.daemonVersion) >= 11)
conn.to << false;
conn.processStderr();
auto ex = conn.processStderr();
if (ex) std::rethrow_exception(ex);
}
catch (Error & e) {
throw Error("cannot open connection to remote store '%s': %s", getUri(), e.what());
@@ -195,22 +196,68 @@ void RemoteStore::setOptions(Connection & conn)
conn.to << i.first << i.second.value;
}
conn.processStderr();
auto ex = conn.processStderr();
if (ex) std::rethrow_exception(ex);
}
/* A wrapper around Pool<RemoteStore::Connection>::Handle that marks
the connection as bad (causing it to be closed) if a non-daemon
exception is thrown before the handle is closed. Such an exception
causes a deviation from the expected protocol and therefore a
desynchronization between the client and daemon. */
struct ConnectionHandle
{
Pool<RemoteStore::Connection>::Handle handle;
bool daemonException = false;
ConnectionHandle(Pool<RemoteStore::Connection>::Handle && handle)
: handle(std::move(handle))
{ }
ConnectionHandle(ConnectionHandle && h)
: handle(std::move(h.handle))
{ }
~ConnectionHandle()
{
if (!daemonException && std::uncaught_exception()) {
handle.markBad();
debug("closing daemon connection because of an exception");
}
}
RemoteStore::Connection * operator -> () { return &*handle; }
void processStderr(Sink * sink = 0, Source * source = 0)
{
auto ex = handle->processStderr(sink, source);
if (ex) {
daemonException = true;
std::rethrow_exception(ex);
}
}
};
ConnectionHandle RemoteStore::getConnection()
{
return ConnectionHandle(connections->get());
}
bool RemoteStore::isValidPathUncached(const Path & path)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopIsValidPath << path;
conn->processStderr();
conn.processStderr();
return readInt(conn->from);
}
PathSet RemoteStore::queryValidPaths(const PathSet & paths, SubstituteFlag maybeSubstitute)
{
auto conn(connections->get());
auto conn(getConnection());
if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 12) {
PathSet res;
for (auto & i : paths)
@@ -218,7 +265,7 @@ PathSet RemoteStore::queryValidPaths(const PathSet & paths, SubstituteFlag maybe
return res;
} else {
conn->to << wopQueryValidPaths << paths;
conn->processStderr();
conn.processStderr();
return readStorePaths<PathSet>(*this, conn->from);
}
}
@@ -226,27 +273,27 @@ PathSet RemoteStore::queryValidPaths(const PathSet & paths, SubstituteFlag maybe
PathSet RemoteStore::queryAllValidPaths()
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopQueryAllValidPaths;
conn->processStderr();
conn.processStderr();
return readStorePaths<PathSet>(*this, conn->from);
}
PathSet RemoteStore::querySubstitutablePaths(const PathSet & paths)
{
auto conn(connections->get());
auto conn(getConnection());
if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 12) {
PathSet res;
for (auto & i : paths) {
conn->to << wopHasSubstitutes << i;
conn->processStderr();
conn.processStderr();
if (readInt(conn->from)) res.insert(i);
}
return res;
} else {
conn->to << wopQuerySubstitutablePaths << paths;
conn->processStderr();
conn.processStderr();
return readStorePaths<PathSet>(*this, conn->from);
}
}
@@ -257,14 +304,14 @@ void RemoteStore::querySubstitutablePathInfos(const PathSet & paths,
{
if (paths.empty()) return;
auto conn(connections->get());
auto conn(getConnection());
if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 12) {
for (auto & i : paths) {
SubstitutablePathInfo info;
conn->to << wopQuerySubstitutablePathInfo << i;
conn->processStderr();
conn.processStderr();
unsigned int reply = readInt(conn->from);
if (reply == 0) continue;
info.deriver = readString(conn->from);
@@ -278,7 +325,7 @@ void RemoteStore::querySubstitutablePathInfos(const PathSet & paths,
} else {
conn->to << wopQuerySubstitutablePathInfos << paths;
conn->processStderr();
conn.processStderr();
size_t count = readNum<size_t>(conn->from);
for (size_t n = 0; n < count; n++) {
Path path = readStorePath(*this, conn->from);
@@ -300,10 +347,10 @@ void RemoteStore::queryPathInfoUncached(const Path & path,
try {
std::shared_ptr<ValidPathInfo> info;
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopQueryPathInfo << path;
try {
conn->processStderr();
conn.processStderr();
} catch (Error & e) {
// Ugly backwards compatibility hack.
if (e.msg().find("is not valid") != std::string::npos)
@@ -335,9 +382,9 @@ void RemoteStore::queryPathInfoUncached(const Path & path,
void RemoteStore::queryReferrers(const Path & path,
PathSet & referrers)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopQueryReferrers << path;
conn->processStderr();
conn.processStderr();
PathSet referrers2 = readStorePaths<PathSet>(*this, conn->from);
referrers.insert(referrers2.begin(), referrers2.end());
}
@@ -345,36 +392,36 @@ void RemoteStore::queryReferrers(const Path & path,
PathSet RemoteStore::queryValidDerivers(const Path & path)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopQueryValidDerivers << path;
conn->processStderr();
conn.processStderr();
return readStorePaths<PathSet>(*this, conn->from);
}
PathSet RemoteStore::queryDerivationOutputs(const Path & path)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopQueryDerivationOutputs << path;
conn->processStderr();
conn.processStderr();
return readStorePaths<PathSet>(*this, conn->from);
}
PathSet RemoteStore::queryDerivationOutputNames(const Path & path)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopQueryDerivationOutputNames << path;
conn->processStderr();
conn.processStderr();
return readStrings<PathSet>(conn->from);
}
Path RemoteStore::queryPathFromHashPart(const string & hashPart)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopQueryPathFromHashPart << hashPart;
conn->processStderr();
conn.processStderr();
Path path = readString(conn->from);
if (!path.empty()) assertStorePath(path);
return path;
@@ -384,7 +431,7 @@ Path RemoteStore::queryPathFromHashPart(const string & hashPart)
void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
RepairFlag repair, CheckSigsFlag checkSigs, std::shared_ptr<FSAccessor> accessor)
{
auto conn(connections->get());
auto conn(getConnection());
if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 18) {
conn->to << wopImportPaths;
@@ -403,7 +450,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
;
});
conn->processStderr(0, source2.get());
conn.processStderr(0, source2.get());
auto importedPaths = readStorePaths<PathSet>(*this, conn->from);
assert(importedPaths.size() <= 1);
@@ -417,7 +464,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
<< repair << !checkSigs;
bool tunnel = GET_PROTOCOL_MINOR(conn->daemonVersion) >= 21;
if (!tunnel) copyNAR(source, conn->to);
conn->processStderr(0, tunnel ? &source : nullptr);
conn.processStderr(0, tunnel ? &source : nullptr);
}
}
@@ -427,7 +474,7 @@ Path RemoteStore::addToStore(const string & name, const Path & _srcPath,
{
if (repair) throw Error("repairing is not supported when building through the Nix daemon");
auto conn(connections->get());
auto conn(getConnection());
Path srcPath(absPath(_srcPath));
@@ -445,13 +492,13 @@ Path RemoteStore::addToStore(const string & name, const Path & _srcPath,
dumpPath(srcPath, conn->to, filter);
}
conn->to.warn = false;
conn->processStderr();
conn.processStderr();
} catch (SysError & e) {
/* Daemon closed while we were sending the path. Probably OOM
or I/O error. */
if (e.errNo == EPIPE)
try {
conn->processStderr();
conn.processStderr();
} catch (EndOfFile & e) { }
throw;
}
@@ -465,17 +512,17 @@ Path RemoteStore::addTextToStore(const string & name, const string & s,
{
if (repair) throw Error("repairing is not supported when building through the Nix daemon");
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopAddTextToStore << name << s << references;
conn->processStderr();
conn.processStderr();
return readStorePath(*this, conn->from);
}
void RemoteStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopBuildPaths;
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 13) {
conn->to << drvPaths;
@@ -494,7 +541,7 @@ void RemoteStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode)
drvPaths2.insert(string(i, 0, i.find('!')));
conn->to << drvPaths2;
}
conn->processStderr();
conn.processStderr();
readInt(conn->from);
}
@@ -502,9 +549,9 @@ void RemoteStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode)
BuildResult RemoteStore::buildDerivation(const Path & drvPath, const BasicDerivation & drv,
BuildMode buildMode)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopBuildDerivation << drvPath << drv << buildMode;
conn->processStderr();
conn.processStderr();
BuildResult res;
unsigned int status;
conn->from >> status >> res.errorMsg;
@@ -515,51 +562,51 @@ BuildResult RemoteStore::buildDerivation(const Path & drvPath, const BasicDeriva
void RemoteStore::ensurePath(const Path & path)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopEnsurePath << path;
conn->processStderr();
conn.processStderr();
readInt(conn->from);
}
void RemoteStore::addTempRoot(const Path & path)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopAddTempRoot << path;
conn->processStderr();
conn.processStderr();
readInt(conn->from);
}
void RemoteStore::addIndirectRoot(const Path & path)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopAddIndirectRoot << path;
conn->processStderr();
conn.processStderr();
readInt(conn->from);
}
void RemoteStore::syncWithGC()
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopSyncWithGC;
conn->processStderr();
conn.processStderr();
readInt(conn->from);
}
Roots RemoteStore::findRoots()
Roots RemoteStore::findRoots(bool censor)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopFindRoots;
conn->processStderr();
conn.processStderr();
size_t count = readNum<size_t>(conn->from);
Roots result;
while (count--) {
Path link = readString(conn->from);
Path target = readStorePath(*this, conn->from);
result[link] = target;
result[target].emplace(link);
}
return result;
}
@@ -567,7 +614,7 @@ Roots RemoteStore::findRoots()
void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to
<< wopCollectGarbage << options.action << options.pathsToDelete << options.ignoreLiveness
@@ -575,7 +622,7 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
/* removed options */
<< 0 << 0 << 0;
conn->processStderr();
conn.processStderr();
results.paths = readStrings<PathSet>(conn->from);
results.bytesFreed = readLongLong(conn->from);
@@ -590,27 +637,27 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
void RemoteStore::optimiseStore()
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopOptimiseStore;
conn->processStderr();
conn.processStderr();
readInt(conn->from);
}
bool RemoteStore::verifyStore(bool checkContents, RepairFlag repair)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopVerifyStore << checkContents << repair;
conn->processStderr();
conn.processStderr();
return readInt(conn->from);
}
void RemoteStore::addSignatures(const Path & storePath, const StringSet & sigs)
{
auto conn(connections->get());
auto conn(getConnection());
conn->to << wopAddSignatures << storePath << sigs;
conn->processStderr();
conn.processStderr();
readInt(conn->from);
}
@@ -620,13 +667,13 @@ void RemoteStore::queryMissing(const PathSet & targets,
unsigned long long & downloadSize, unsigned long long & narSize)
{
{
auto conn(connections->get());
auto conn(getConnection());
if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 19)
// Don't hold the connection handle in the fallback case
// to prevent a deadlock.
goto fallback;
conn->to << wopQueryMissing << targets;
conn->processStderr();
conn.processStderr();
willBuild = readStorePaths<PathSet>(*this, conn->from);
willSubstitute = readStorePaths<PathSet>(*this, conn->from);
unknown = readStorePaths<PathSet>(*this, conn->from);
@@ -641,8 +688,15 @@ void RemoteStore::queryMissing(const PathSet & targets,
void RemoteStore::connect()
{
auto conn(getConnection());
}
unsigned int RemoteStore::getProtocol()
{
auto conn(connections->get());
return conn->daemonVersion;
}
@@ -679,7 +733,7 @@ static Logger::Fields readFields(Source & from)
}
void RemoteStore::Connection::processStderr(Sink * sink, Source * source)
std::exception_ptr RemoteStore::Connection::processStderr(Sink * sink, Source * source)
{
to.flush();
@@ -704,7 +758,7 @@ void RemoteStore::Connection::processStderr(Sink * sink, Source * source)
else if (msg == STDERR_ERROR) {
string error = readString(from);
unsigned int status = readInt(from);
throw Error(status, error);
return std::make_exception_ptr(Error(status, error));
}
else if (msg == STDERR_NEXT)
@@ -738,6 +792,8 @@ void RemoteStore::Connection::processStderr(Sink * sink, Source * source)
else
throw Error("got unknown message type %x from Nix daemon", msg);
}
return nullptr;
}
static std::string uriScheme = "unix://";

View File

@@ -14,6 +14,7 @@ class Pid;
struct FdSink;
struct FdSource;
template<typename T> class Pool;
struct ConnectionHandle;
/* FIXME: RemoteStore is a misnomer - should be something like
@@ -81,7 +82,7 @@ public:
void syncWithGC() override;
Roots findRoots() override;
Roots findRoots(bool censor) override;
void collectGarbage(const GCOptions & options, GCResults & results) override;
@@ -97,12 +98,15 @@ public:
void connect() override;
unsigned int getProtocol() override;
void flushBadConnections();
protected:
struct Connection
{
AutoCloseFD fd;
FdSink to;
FdSource from;
unsigned int daemonVersion;
@@ -110,7 +114,7 @@ protected:
virtual ~Connection();
void processStderr(Sink * sink = 0, Source * source = 0);
std::exception_ptr processStderr(Sink * sink = 0, Source * source = 0);
};
ref<Connection> openConnectionWrapper();
@@ -123,6 +127,10 @@ protected:
virtual void setOptions(Connection & conn);
ConnectionHandle getConnection();
friend struct ConnectionHandle;
private:
std::atomic_bool failed{false};
@@ -140,13 +148,8 @@ public:
private:
struct Connection : RemoteStore::Connection
{
AutoCloseFD fd;
};
ref<RemoteStore::Connection> openConnection() override;
std::experimental::optional<std::string> path;
std::optional<std::string> path;
};

View File

@@ -19,8 +19,6 @@
#include <aws/core/utils/logging/LogMacros.h>
#include <aws/core/utils/threading/Executor.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/CreateBucketRequest.h>
#include <aws/s3/model/GetBucketLocationRequest.h>
#include <aws/s3/model/GetObjectRequest.h>
#include <aws/s3/model/HeadObjectRequest.h>
#include <aws/s3/model/ListObjectsRequest.h>
@@ -84,8 +82,8 @@ static void initAWS()
});
}
S3Helper::S3Helper(const std::string & profile, const std::string & region, const std::string & endpoint)
: config(makeConfig(region, endpoint))
S3Helper::S3Helper(const string & profile, const string & region, const string & scheme, const string & endpoint)
: config(makeConfig(region, scheme, endpoint))
, client(make_ref<Aws::S3::S3Client>(
profile == ""
? std::dynamic_pointer_cast<Aws::Auth::AWSCredentialsProvider>(
@@ -116,15 +114,19 @@ class RetryStrategy : public Aws::Client::DefaultRetryStrategy
}
};
ref<Aws::Client::ClientConfiguration> S3Helper::makeConfig(const string & region, const string & endpoint)
ref<Aws::Client::ClientConfiguration> S3Helper::makeConfig(const string & region, const string & scheme, const string & endpoint)
{
initAWS();
auto res = make_ref<Aws::Client::ClientConfiguration>();
res->region = region;
if (!scheme.empty()) {
res->scheme = Aws::Http::SchemeMapper::FromString(scheme.c_str());
}
if (!endpoint.empty()) {
res->endpointOverride = endpoint;
}
res->requestTimeoutMs = 600 * 1000;
res->connectTimeoutMs = 5 * 1000;
res->retryStrategy = std::make_shared<RetryStrategy>();
res->caFile = settings.caFile;
return res;
@@ -171,10 +173,13 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
{
const Setting<std::string> profile{this, "", "profile", "The name of the AWS configuration profile to use."};
const Setting<std::string> region{this, Aws::Region::US_EAST_1, "region", {"aws-region"}};
const Setting<std::string> scheme{this, "", "scheme", "The scheme to use for S3 requests, https by default."};
const Setting<std::string> endpoint{this, "", "endpoint", "An optional override of the endpoint to use when talking to S3."};
const Setting<std::string> narinfoCompression{this, "", "narinfo-compression", "compression method for .narinfo files"};
const Setting<std::string> lsCompression{this, "", "ls-compression", "compression method for .ls files"};
const Setting<std::string> logCompression{this, "", "log-compression", "compression method for log/* files"};
const Setting<bool> multipartUpload{
this, false, "multipart-upload", "whether to use multi-part uploads"};
const Setting<uint64_t> bufferSize{
this, 5 * 1024 * 1024, "buffer-size", "size (in bytes) of each part in multi-part uploads"};
@@ -188,7 +193,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
const Params & params, const std::string & bucketName)
: S3BinaryCacheStore(params)
, bucketName(bucketName)
, s3Helper(profile, region, endpoint)
, s3Helper(profile, region, scheme, endpoint)
{
diskCache = getNarInfoDiskCache();
}
@@ -202,32 +207,6 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
{
if (!diskCache->cacheExists(getUri(), wantMassQuery_, priority)) {
/* Create the bucket if it doesn't already exists. */
// FIXME: HeadBucket would be more appropriate, but doesn't return
// an easily parsed 404 message.
auto res = s3Helper.client->GetBucketLocation(
Aws::S3::Model::GetBucketLocationRequest().WithBucket(bucketName));
if (!res.IsSuccess()) {
if (res.GetError().GetErrorType() != Aws::S3::S3Errors::NO_SUCH_BUCKET)
throw Error(format("AWS error checking bucket '%s': %s") % bucketName % res.GetError().GetMessage());
printInfo("creating S3 bucket '%s'...", bucketName);
// Stupid S3 bucket locations.
auto bucketConfig = Aws::S3::Model::CreateBucketConfiguration();
if (s3Helper.config->region != "us-east-1")
bucketConfig.SetLocationConstraint(
Aws::S3::Model::BucketLocationConstraintMapper::GetBucketLocationConstraintForName(
s3Helper.config->region));
checkAws(format("AWS error creating bucket '%s'") % bucketName,
s3Helper.client->CreateBucket(
Aws::S3::Model::CreateBucketRequest()
.WithBucket(bucketName)
.WithCreateBucketConfiguration(bucketConfig)));
}
BinaryCacheStore::init();
diskCache->createCache(getUri(), storeDir, wantMassQuery_, priority);
@@ -289,48 +268,73 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
static std::shared_ptr<Aws::Utils::Threading::PooledThreadExecutor>
executor = std::make_shared<Aws::Utils::Threading::PooledThreadExecutor>(maxThreads);
std::call_once(transferManagerCreated, [&]() {
std::call_once(transferManagerCreated, [&]()
{
if (multipartUpload) {
TransferManagerConfiguration transferConfig(executor.get());
TransferManagerConfiguration transferConfig(executor.get());
transferConfig.s3Client = s3Helper.client;
transferConfig.bufferSize = bufferSize;
transferConfig.s3Client = s3Helper.client;
transferConfig.bufferSize = bufferSize;
transferConfig.uploadProgressCallback =
[](const TransferManager *transferManager,
const std::shared_ptr<const TransferHandle>
&transferHandle)
{
//FIXME: find a way to properly abort the multipart upload.
//checkInterrupt();
debug("upload progress ('%s'): '%d' of '%d' bytes",
transferHandle->GetKey(),
transferHandle->GetBytesTransferred(),
transferHandle->GetBytesTotalSize());
};
transferConfig.uploadProgressCallback =
[&](const TransferManager *transferManager,
const std::shared_ptr<const TransferHandle>
&transferHandle)
{
//FIXME: find a way to properly abort the multipart upload.
//checkInterrupt();
debug("upload progress ('%s'): '%d' of '%d' bytes",
path,
transferHandle->GetBytesTransferred(),
transferHandle->GetBytesTotalSize());
};
transferManager = TransferManager::Create(transferConfig);
transferManager = TransferManager::Create(transferConfig);
}
});
auto now1 = std::chrono::steady_clock::now();
std::shared_ptr<TransferHandle> transferHandle =
transferManager->UploadFile(
stream, bucketName, path, mimeType,
Aws::Map<Aws::String, Aws::String>(),
nullptr, contentEncoding);
if (transferManager) {
transferHandle->WaitUntilFinished();
if (contentEncoding != "")
throw Error("setting a content encoding is not supported with S3 multi-part uploads");
if (transferHandle->GetStatus() == TransferStatus::FAILED)
throw Error("AWS error: failed to upload 's3://%s/%s': %s",
bucketName, path, transferHandle->GetLastError().GetMessage());
std::shared_ptr<TransferHandle> transferHandle =
transferManager->UploadFile(
stream, bucketName, path, mimeType,
Aws::Map<Aws::String, Aws::String>(),
nullptr /*, contentEncoding */);
if (transferHandle->GetStatus() != TransferStatus::COMPLETED)
throw Error("AWS error: transfer status of 's3://%s/%s' in unexpected state",
bucketName, path);
transferHandle->WaitUntilFinished();
printTalkative("upload of '%s' completed", path);
if (transferHandle->GetStatus() == TransferStatus::FAILED)
throw Error("AWS error: failed to upload 's3://%s/%s': %s",
bucketName, path, transferHandle->GetLastError().GetMessage());
if (transferHandle->GetStatus() != TransferStatus::COMPLETED)
throw Error("AWS error: transfer status of 's3://%s/%s' in unexpected state",
bucketName, path);
} else {
auto request =
Aws::S3::Model::PutObjectRequest()
.WithBucket(bucketName)
.WithKey(path);
request.SetContentType(mimeType);
if (contentEncoding != "")
request.SetContentEncoding(contentEncoding);
auto stream = std::make_shared<istringstream_nocopy>(data);
request.SetBody(stream);
auto result = checkAws(fmt("AWS error uploading '%s'", path),
s3Helper.client->PutObject(request));
}
auto now2 = std::chrono::steady_clock::now();

View File

@@ -14,9 +14,9 @@ struct S3Helper
ref<Aws::Client::ClientConfiguration> config;
ref<Aws::S3::S3Client> client;
S3Helper(const std::string & profile, const std::string & region, const std::string & endpoint);
S3Helper(const std::string & profile, const std::string & region, const std::string & scheme, const std::string & endpoint);
ref<Aws::Client::ClientConfiguration> makeConfig(const std::string & region, const std::string & endpoint);
ref<Aws::Client::ClientConfiguration> makeConfig(const std::string & region, const std::string & scheme, const std::string & endpoint);
struct DownloadResult
{

View File

@@ -320,6 +320,8 @@ ref<const ValidPathInfo> Store::queryPathInfo(const Path & storePath)
void Store::queryPathInfo(const Path & storePath,
Callback<ref<ValidPathInfo>> callback)
{
assertStorePath(storePath);
auto hashPart = storePathToHash(storePath);
try {
@@ -560,10 +562,10 @@ void Store::buildPaths(const PathSet & paths, BuildMode buildMode)
{
for (auto & path : paths)
if (isDerivation(path))
unsupported();
unsupported("buildPaths");
if (queryValidPaths(paths).size() != paths.size())
unsupported();
unsupported("buildPaths");
}
@@ -586,15 +588,19 @@ void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
uint64_t total = 0;
// FIXME
#if 0
if (!info->narHash) {
StringSink sink;
srcStore->narFromPath({storePath}, sink);
auto info2 = make_ref<ValidPathInfo>(*info);
info2->narHash = hashString(htSHA256, *sink.s);
if (!info->narSize) info2->narSize = sink.s->size();
if (info->ultimate) info2->ultimate = false;
info = info2;
StringSource source(*sink.s);
dstStore->addToStore(*info, source, repair, checkSigs);
return;
}
#endif
if (info->ultimate) {
auto info2 = make_ref<ValidPathInfo>(*info);
@@ -610,7 +616,7 @@ void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
});
srcStore->narFromPath({storePath}, wrapperSink);
}, [&]() {
throw EndOfFile("NAR for '%s' fetched from '%s' is incomplete", storePath, srcStore->getUri());
throw EndOfFile("NAR for '%s' fetched from '%s' is incomplete", storePath, srcStore->getUri());
});
dstStore->addToStore(*info, *source, repair, checkSigs);
@@ -836,12 +842,11 @@ namespace nix {
RegisterStoreImplementation::Implementations * RegisterStoreImplementation::implementations = 0;
ref<Store> openStore(const std::string & uri_,
const Store::Params & extraParams)
/* Split URI into protocol+hierarchy part and its parameter set. */
std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri_)
{
auto uri(uri_);
Store::Params params(extraParams);
Store::Params params;
auto q = uri.find('?');
if (q != std::string::npos) {
for (auto s : tokenizeString<Strings>(uri.substr(q + 1), "&")) {
@@ -867,6 +872,15 @@ ref<Store> openStore(const std::string & uri_,
}
uri = uri_.substr(0, q);
}
return {uri, params};
}
ref<Store> openStore(const std::string & uri_,
const Store::Params & extraParams)
{
auto [uri, uriParams] = splitUriAndParams(uri_);
auto params = extraParams;
params.insert(uriParams.begin(), uriParams.end());
for (auto fun : *RegisterStoreImplementation::implementations) {
auto store = fun(uri, params);

View File

@@ -11,6 +11,8 @@
#include <atomic>
#include <limits>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <memory>
#include <string>
@@ -23,6 +25,7 @@ MakeError(BuildError, Error) /* denotes a permanent build failure */
MakeError(InvalidPath, Error)
MakeError(Unsupported, Error)
MakeError(SubstituteGone, Error)
MakeError(SubstituterDisabled, Error)
struct BasicDerivation;
@@ -46,7 +49,7 @@ const size_t storePathHashLen = 32; // i.e. 160 bits
const uint32_t exportMagic = 0x4558494e;
typedef std::map<Path, Path> Roots;
typedef std::unordered_map<Path, std::unordered_set<std::string>> Roots;
struct GCOptions
@@ -348,7 +351,8 @@ public:
(i.e. you'll get /nix/store/<hash> rather than
/nix/store/<hash>-<name>). Use queryPathInfo() to obtain the
full store path. */
virtual PathSet queryAllValidPaths() = 0;
virtual PathSet queryAllValidPaths()
{ unsupported("queryAllValidPaths"); }
/* Query information about a valid path. It is permitted to omit
the name part of the store path. */
@@ -367,8 +371,8 @@ public:
/* Queries the set of incoming FS references for a store path.
The result is not cleared. */
virtual void queryReferrers(const Path & path,
PathSet & referrers) = 0;
virtual void queryReferrers(const Path & path, PathSet & referrers)
{ unsupported("queryReferrers"); }
/* Return all currently valid derivations that have `path' as an
output. (Note that the result of `queryDeriver()' is the
@@ -377,10 +381,12 @@ public:
virtual PathSet queryValidDerivers(const Path & path) { return {}; };
/* Query the outputs of the derivation denoted by `path'. */
virtual PathSet queryDerivationOutputs(const Path & path) = 0;
virtual PathSet queryDerivationOutputs(const Path & path)
{ unsupported("queryDerivationOutputs"); }
/* Query the output names of the derivation denoted by `path'. */
virtual StringSet queryDerivationOutputNames(const Path & path) = 0;
virtual StringSet queryDerivationOutputNames(const Path & path)
{ unsupported("queryDerivationOutputNames"); }
/* Query the full store path given the hash part of a valid store
path, or "" if the path doesn't exist. */
@@ -446,14 +452,16 @@ public:
/* Add a store path as a temporary root of the garbage collector.
The root disappears as soon as we exit. */
virtual void addTempRoot(const Path & path) = 0;
virtual void addTempRoot(const Path & path)
{ unsupported("addTempRoot"); }
/* Add an indirect root, which is merely a symlink to `path' from
/nix/var/nix/gcroots/auto/<hash of `path'>. `path' is supposed
to be a symlink to a store path. The garbage collector will
automatically remove the indirect root when it finds that
`path' has disappeared. */
virtual void addIndirectRoot(const Path & path) = 0;
virtual void addIndirectRoot(const Path & path)
{ unsupported("addIndirectRoot"); }
/* Acquire the global GC lock, then immediately release it. This
function must be called after registering a new permanent root,
@@ -477,11 +485,15 @@ public:
/* Find the roots of the garbage collector. Each root is a pair
(link, storepath) where `link' is the path of the symlink
outside of the Nix store that point to `storePath'. */
virtual Roots findRoots() = 0;
outside of the Nix store that point to `storePath'. If
'censor' is true, privacy-sensitive information about roots
found in /proc is censored. */
virtual Roots findRoots(bool censor)
{ unsupported("findRoots"); }
/* Perform a garbage collection. */
virtual void collectGarbage(const GCOptions & options, GCResults & results) = 0;
virtual void collectGarbage(const GCOptions & options, GCResults & results)
{ unsupported("collectGarbage"); }
/* Return a string representing information about the path that
can be loaded into the database using `nix-store --load-db' or
@@ -512,11 +524,13 @@ public:
virtual bool verifyStore(bool checkContents, RepairFlag repair = NoRepair) { return false; };
/* Return an object to access files in the Nix store. */
virtual ref<FSAccessor> getFSAccessor() = 0;
virtual ref<FSAccessor> getFSAccessor()
{ unsupported("getFSAccessor"); }
/* Add signatures to the specified store path. The signatures are
not verified. */
virtual void addSignatures(const Path & storePath, const StringSet & sigs) = 0;
virtual void addSignatures(const Path & storePath, const StringSet & sigs)
{ unsupported("addSignatures"); }
/* Utility functions. */
@@ -598,6 +612,12 @@ public:
a notion of connection. Otherwise this is a no-op. */
virtual void connect() { };
/* Get the protocol version of this store or it's connection. */
virtual unsigned int getProtocol()
{
return 0;
};
/* Get the priority of the store, used to order substituters. In
particular, binary caches can specify a priority field in their
"nix-cache-info" file. Lower value means higher priority. */
@@ -613,9 +633,9 @@ protected:
Stats stats;
/* Unsupported methods. */
[[noreturn]] void unsupported()
[[noreturn]] void unsupported(const std::string & op)
{
throw Unsupported("requested operation is not supported by store '%s'", getUri());
throw Unsupported("operation '%s' is not supported by store '%s'", op, getUri());
}
};
@@ -782,4 +802,8 @@ ValidPathInfo decodeValidPathInfo(std::istream & str,
for paths created by makeFixedOutputPath() / addToStore(). */
std::string makeFixedOutputCA(bool recursive, const Hash & hash);
/* Split URI into protocol+hierarchy part and its parameter set. */
std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri);
}

View File

@@ -283,7 +283,7 @@ void parseDump(ParseSink & sink, Source & source)
{
string version;
try {
version = readString(source);
version = readString(source, narVersionMagic1.size());
} catch (SerialisationError & e) {
/* This generally means the integer at the start couldn't be
decoded. Ignore and throw the exception below. */
@@ -331,7 +331,7 @@ struct RestoreSink : ParseSink
filesystem doesn't support preallocation (e.g. on
OpenSolaris). Since preallocation is just an
optimisation, ignore it. */
if (errno && errno != EINVAL)
if (errno && errno != EINVAL && errno != EOPNOTSUPP && errno != ENOSYS)
throw SysError(format("preallocating file of %1% bytes") % len);
}
#endif

View File

@@ -250,7 +250,7 @@ struct XzCompressionSink : CompressionSink
ret = lzma_stream_encoder_mt(&strm, &mt_options);
done = true;
#else
printMsg(lvlError, "warning: parallel compression requested but not supported for metho d '%1%', falling back to single-threaded compression", method);
printMsg(lvlError, "warning: parallel XZ compression requested but not supported, falling back to single-threaded compression");
#endif
}

View File

@@ -105,9 +105,9 @@ string printHash16or32(const Hash & hash)
std::string Hash::to_string(Base base, bool includeType) const
{
std::string s;
if (includeType) {
if (base == SRI || includeType) {
s += printHashType(type);
s += ':';
s += base == SRI ? '-' : ':';
}
switch (base) {
case Base16:
@@ -117,6 +117,7 @@ std::string Hash::to_string(Base base, bool includeType) const
s += printHash32(*this);
break;
case Base64:
case SRI:
s += base64Encode(std::string((const char *) hash, hashSize));
break;
}
@@ -127,28 +128,33 @@ std::string Hash::to_string(Base base, bool includeType) const
Hash::Hash(const std::string & s, HashType type)
: type(type)
{
auto colon = s.find(':');
size_t pos = 0;
bool isSRI = false;
if (colon == string::npos) {
if (type == htUnknown)
auto sep = s.find(':');
if (sep == string::npos) {
sep = s.find('-');
if (sep != string::npos) {
isSRI = true;
} else if (type == htUnknown)
throw BadHash("hash '%s' does not include a type", s);
} else {
string hts = string(s, 0, colon);
}
if (sep != string::npos) {
string hts = string(s, 0, sep);
this->type = parseHashType(hts);
if (this->type == htUnknown)
throw BadHash("unknown hash type '%s'", hts);
if (type != htUnknown && type != this->type)
throw BadHash("hash '%s' should have type '%s'", s, printHashType(type));
pos = colon + 1;
pos = sep + 1;
}
init();
size_t size = s.size() - pos;
if (size == base16Len()) {
if (!isSRI && size == base16Len()) {
auto parseHexDigit = [&](char c) {
if (c >= '0' && c <= '9') return c - '0';
@@ -164,7 +170,7 @@ Hash::Hash(const std::string & s, HashType type)
}
}
else if (size == base32Len()) {
else if (!isSRI && size == base32Len()) {
for (unsigned int n = 0; n < size; ++n) {
char c = s[pos + size - n - 1];
@@ -187,10 +193,10 @@ Hash::Hash(const std::string & s, HashType type)
}
}
else if (size == base64Len()) {
else if (isSRI || size == base64Len()) {
auto d = base64Decode(std::string(s, pos));
if (d.size() != hashSize)
throw BadHash("invalid base-64 hash '%s'", s);
throw BadHash("invalid %s hash '%s'", isSRI ? "SRI" : "base-64", s);
assert(hashSize);
memcpy(hash, d.data(), hashSize);
}

View File

@@ -20,7 +20,7 @@ const int sha512HashSize = 64;
extern const string base32Chars;
enum Base : int { Base64, Base32, Base16 };
enum Base : int { Base64, Base32, Base16, SRI };
struct Hash
@@ -38,8 +38,9 @@ struct Hash
Hash(HashType type) : type(type) { init(); };
/* Initialize the hash from a string representation, in the format
"[<type>:]<base16|base32|base64>". If the 'type' argument is
htUnknown, then the hash type must be specified in the
"[<type>:]<base16|base32|base64>" or "<type>-<base64>" (a
Subresource Integrity hash expression). If the 'type' argument
is htUnknown, then the hash type must be specified in the
string. */
Hash(const std::string & s, HashType type = htUnknown);

View File

@@ -7,7 +7,3 @@ libutil_DIR := $(d)
libutil_SOURCES := $(wildcard $(d)/*.cc)
libutil_LDFLAGS = $(LIBLZMA_LIBS) -lbz2 -pthread $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) -lboost_context
libutil_LIBS = libformat
libutil_CXXFLAGS = -DBROTLI=\"$(brotli)\"

View File

@@ -2,7 +2,7 @@
#include <map>
#include <list>
#include <experimental/optional>
#include <optional>
namespace nix {
@@ -64,7 +64,7 @@ public:
/* Look up an item in the cache. If it exists, it becomes the most
recently used item. */
std::experimental::optional<Value> get(const Key & key)
std::optional<Value> get(const Key & key)
{
auto i = data.find(key);
if (i == data.end()) return {};

View File

@@ -97,6 +97,7 @@ public:
private:
Pool & pool;
std::shared_ptr<R> r;
bool bad = false;
friend Pool;
@@ -112,7 +113,8 @@ public:
if (!r) return;
{
auto state_(pool.state.lock());
state_->idle.push_back(ref<R>(r));
if (!bad)
state_->idle.push_back(ref<R>(r));
assert(state_->inUse);
state_->inUse--;
}
@@ -121,6 +123,8 @@ public:
R * operator -> () { return &*r; }
R & operator * () { return *r; }
void markBad() { bad = true; }
};
Handle get()

View File

@@ -169,17 +169,13 @@ std::unique_ptr<Source> sinkToSource(
{
typedef boost::coroutines2::coroutine<std::string> coro_t;
std::function<void(Sink &)> fun;
std::function<void()> eof;
coro_t::pull_type coro;
std::optional<coro_t::pull_type> coro;
bool started = false;
SinkToSource(std::function<void(Sink &)> fun, std::function<void()> eof)
: eof(eof)
, coro([&](coro_t::push_type & yield) {
LambdaSink sink([&](const unsigned char * data, size_t len) {
if (len) yield(std::string((const char *) data, len));
});
fun(sink);
})
: fun(fun), eof(eof)
{
}
@@ -188,11 +184,19 @@ std::unique_ptr<Source> sinkToSource(
size_t read(unsigned char * data, size_t len) override
{
if (!coro) { eof(); abort(); }
if (!coro)
coro = coro_t::pull_type([&](coro_t::push_type & yield) {
LambdaSink sink([&](const unsigned char * data, size_t len) {
if (len) yield(std::string((const char *) data, len));
});
fun(sink);
});
if (!*coro) { eof(); abort(); }
if (pos == cur.size()) {
if (!cur.empty()) coro();
cur = coro.get();
if (!cur.empty()) (*coro)();
cur = coro->get();
pos = 0;
}
@@ -268,16 +272,17 @@ void readPadding(size_t len, Source & source)
size_t readString(unsigned char * buf, size_t max, Source & source)
{
auto len = readNum<size_t>(source);
if (len > max) throw Error("string is too long");
if (len > max) throw SerialisationError("string is too long");
source(buf, len);
readPadding(len, source);
return len;
}
string readString(Source & source)
string readString(Source & source, size_t max)
{
auto len = readNum<size_t>(source);
if (len > max) throw SerialisationError("string is too long");
std::string res(len, 0);
source((unsigned char*) res.data(), len);
readPadding(len, source);

View File

@@ -284,7 +284,7 @@ inline uint64_t readLongLong(Source & source)
void readPadding(size_t len, Source & source);
size_t readString(unsigned char * buf, size_t max, Source & source);
string readString(Source & source);
string readString(Source & source, size_t max = std::numeric_limits<size_t>::max());
template<class T> T readStrings(Source & source);
Source & operator >> (Source & in, string & s);

View File

@@ -167,7 +167,7 @@ Path dirOf(const Path & path)
{
Path::size_type pos = path.rfind('/');
if (pos == string::npos)
throw Error(format("invalid file name '%1%'") % path);
return ".";
return pos == 0 ? "/" : Path(path, 0, pos);
}
@@ -202,7 +202,7 @@ bool isInDir(const Path & path, const Path & dir)
bool isDirOrInDir(const Path & path, const Path & dir)
{
return path == dir or isInDir(path, dir);
return path == dir || isInDir(path, dir);
}
@@ -468,7 +468,7 @@ static Lazy<Path> getHome2([]() {
std::vector<char> buf(16384);
struct passwd pwbuf;
struct passwd * pw;
if (getpwuid_r(getuid(), &pwbuf, buf.data(), buf.size(), &pw) != 0
if (getpwuid_r(geteuid(), &pwbuf, buf.data(), buf.size(), &pw) != 0
|| !pw || !pw->pw_dir || !pw->pw_dir[0])
throw Error("cannot determine user's home directory");
homeDir = pw->pw_dir;
@@ -496,6 +496,15 @@ Path getConfigDir()
return configDir;
}
std::vector<Path> getConfigDirs()
{
Path configHome = getConfigDir();
string configDirs = getEnv("XDG_CONFIG_DIRS");
std::vector<Path> result = tokenizeString<std::vector<string>>(configDirs, ":");
result.insert(result.begin(), configHome);
return result;
}
Path getDataDir()
{
@@ -956,7 +965,7 @@ std::vector<char *> stringsToCharPtrs(const Strings & ss)
string runProgram(Path program, bool searchPath, const Strings & args,
const std::experimental::optional<std::string> & input)
const std::optional<std::string> & input)
{
RunOptions opts(program, args);
opts.searchPath = searchPath;

View File

@@ -14,7 +14,7 @@
#include <cstdio>
#include <map>
#include <sstream>
#include <experimental/optional>
#include <optional>
#include <future>
#ifndef HAVE_STRUCT_DIRENT_D_TYPE
@@ -131,6 +131,9 @@ Path getCacheDir();
/* Return $XDG_CONFIG_HOME or $HOME/.config. */
Path getConfigDir();
/* Return the directories to search for user configuration files */
std::vector<Path> getConfigDirs();
/* Return $XDG_DATA_HOME or $HOME/.local/share. */
Path getDataDir();
@@ -256,14 +259,14 @@ pid_t startProcess(std::function<void()> fun, const ProcessOptions & options = P
shell backtick operator). */
string runProgram(Path program, bool searchPath = false,
const Strings & args = Strings(),
const std::experimental::optional<std::string> & input = {});
const std::optional<std::string> & input = {});
struct RunOptions
{
Path program;
bool searchPath = true;
Strings args;
std::experimental::optional<std::string> input;
std::optional<std::string> input;
Source * standardIn = nullptr;
Sink * standardOut = nullptr;
bool _killStderr = false;

View File

@@ -1,542 +0,0 @@
/*
* Copyright 2001-2004 Unicode, Inc.
*
* Disclaimer
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
*/
/* ---------------------------------------------------------------------
Conversions between UTF32, UTF-16, and UTF-8. Source code file.
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
Sept 2001: fixed const & error conditions per
mods suggested by S. Parent & A. Lillich.
June 2002: Tim Dodd added detection and handling of incomplete
source sequences, enhanced error detection, added casts
to eliminate compiler warnings.
July 2003: slight mods to back out aggressive FFFE detection.
Jan 2004: updated switches in from-UTF8 conversions.
Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
See the header file "ConvertUTF.h" for complete documentation.
------------------------------------------------------------------------ */
#include "ConvertUTF.h"
#ifdef CVTUTF_DEBUG
#include <stdio.h>
#endif
namespace linenoise_ng {
static const int halfShift = 10; /* used for shifting by 10 bits */
static const UTF32 halfBase = 0x0010000UL;
static const UTF32 halfMask = 0x3FFUL;
#define UNI_SUR_HIGH_START (UTF32)0xD800
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
#define UNI_SUR_LOW_START (UTF32)0xDC00
#define UNI_SUR_LOW_END (UTF32)0xDFFF
#define false 0
#define true 1
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd,
char16_t** targetStart, char16_t* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
char16_t* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
if (target >= targetEnd) {
result = targetExhausted; break;
}
ch = *source++;
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
/* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
*target++ = (UTF16)ch; /* normal case */
}
} else if (ch > UNI_MAX_LEGAL_UTF32) {
if (flags == strictConversion) {
result = sourceIllegal;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
/* target is a character in range 0xFFFF - 0x10FFFF. */
if (target + 1 >= targetEnd) {
--source; /* Back up source pointer! */
result = targetExhausted; break;
}
ch -= halfBase;
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF32* target = *targetStart;
UTF32 ch, ch2;
while (source < sourceEnd) {
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
ch = *source++;
/* If we have a surrogate pair, convert to UTF32 first. */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
/* If the 16 bits following the high surrogate are in the source buffer... */
if (source < sourceEnd) {
ch2 = *source;
/* If it's a low surrogate, convert to UTF32. */
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
++source;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
} else { /* We don't have the 16 bits following the high surrogate. */
--source; /* return to the high surrogate */
result = sourceExhausted;
break;
}
} else if (flags == strictConversion) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
if (target >= targetEnd) {
source = oldSource; /* Back up source pointer! */
result = targetExhausted; break;
}
*target++ = ch;
}
*sourceStart = source;
*targetStart = target;
#ifdef CVTUTF_DEBUG
if (result == sourceIllegal) {
fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
fflush(stderr);
}
#endif
return result;
}
/* --------------------------------------------------------------------- */
/*
* Index into the table below with the first byte of a UTF-8 sequence to
* get the number of trailing bytes that are supposed to follow it.
* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
* left as-is for anyone who may want to do such conversion, which was
* allowed in earlier algorithms.
*/
static const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
};
/*
* Magic values subtracted from a buffer value during UTF8 conversion.
* This table contains as many values as there might be trailing bytes
* in a UTF-8 sequence.
*/
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
/*
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
* into the first byte, depending on how many bytes follow. There are
* as many entries in this table as there are UTF-8 sequence types.
* (I.e., one byte sequence, two byte... etc.). Remember that sequencs
* for *legal* UTF-8 will be 4 or fewer bytes total.
*/
static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
/* --------------------------------------------------------------------- */
/* The interface converts a whole buffer to avoid function-call overhead.
* Constants have been gathered. Loops & conditionals have been removed as
* much as possible for efficiency, in favor of drop-through switches.
* (See "Note A" at the bottom of the file for equivalent code.)
* If your compiler supports it, the "isLegalUTF8" call can be turned
* into an inline function.
*/
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
unsigned short bytesToWrite = 0;
const UTF32 byteMask = 0xBF;
const UTF32 byteMark = 0x80;
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
ch = *source++;
/* If we have a surrogate pair, convert to UTF32 first. */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
/* If the 16 bits following the high surrogate are in the source buffer... */
if (source < sourceEnd) {
UTF32 ch2 = *source;
/* If it's a low surrogate, convert to UTF32. */
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
++source;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
} else { /* We don't have the 16 bits following the high surrogate. */
--source; /* return to the high surrogate */
result = sourceExhausted;
break;
}
} else if (flags == strictConversion) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
/* Figure out how many bytes the result will require */
if (ch < (UTF32)0x80) { bytesToWrite = 1;
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
} else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
} else { bytesToWrite = 3;
ch = UNI_REPLACEMENT_CHAR;
}
target += bytesToWrite;
if (target > targetEnd) {
source = oldSource; /* Back up source pointer! */
target -= bytesToWrite; result = targetExhausted; break;
}
switch (bytesToWrite) { /* note: everything falls through. */
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
}
target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
/*
* Utility routine to tell whether a sequence of bytes is legal UTF-8.
* This must be called with the length pre-determined by the first byte.
* If not calling this from ConvertUTF8to*, then the length can be set by:
* length = trailingBytesForUTF8[*source]+1;
* and the sequence is illegal right away if there aren't that many bytes
* available.
* If presented with a length > 4, this returns false. The Unicode
* definition of UTF-8 goes up to 4-byte sequences.
*/
static Boolean isLegalUTF8(const UTF8 *source, int length) {
UTF8 a;
const UTF8 *srcptr = source+length;
switch (length) {
default: return false;
/* Everything else falls through when "true"... */
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 2: if ((a = (*--srcptr)) > 0xBF) return false;
switch (*source) {
/* no fall-through in this inner switch */
case 0xE0: if (a < 0xA0) return false; break;
case 0xED: if (a > 0x9F) return false; break;
case 0xF0: if (a < 0x90) return false; break;
case 0xF4: if (a > 0x8F) return false; break;
default: if (a < 0x80) return false;
}
case 1: if (*source >= 0x80 && *source < 0xC2) return false;
}
if (*source > 0xF4) return false;
return true;
}
/* --------------------------------------------------------------------- */
/*
* Exported function to return whether a UTF-8 sequence is legal or not.
* This is not used here; it's just exported.
*/
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
int length = trailingBytesForUTF8[*source]+1;
if (source+length > sourceEnd) {
return false;
}
return isLegalUTF8(source, length);
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch = 0;
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
if (source + extraBytesToRead >= sourceEnd) {
result = sourceExhausted; break;
}
/* Do this check whether lenient or strict */
if (! isLegalUTF8(source, extraBytesToRead+1)) {
result = sourceIllegal;
break;
}
/*
* The cases all fall through. See "Note A" below.
*/
switch (extraBytesToRead) {
case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
case 3: ch += *source++; ch <<= 6;
case 2: ch += *source++; ch <<= 6;
case 1: ch += *source++; ch <<= 6;
case 0: ch += *source++;
}
ch -= offsetsFromUTF8[extraBytesToRead];
if (target >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up source pointer! */
result = targetExhausted; break;
}
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
source -= (extraBytesToRead+1); /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
*target++ = (UTF16)ch; /* normal case */
}
} else if (ch > UNI_MAX_UTF16) {
if (flags == strictConversion) {
result = sourceIllegal;
source -= (extraBytesToRead+1); /* return to the start */
break; /* Bail out; shouldn't continue */
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
/* target is a character in range 0xFFFF - 0x10FFFF. */
if (target + 1 >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up source pointer! */
result = targetExhausted; break;
}
ch -= halfBase;
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
unsigned short bytesToWrite = 0;
const UTF32 byteMask = 0xBF;
const UTF32 byteMark = 0x80;
ch = *source++;
if (flags == strictConversion ) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
/*
* Figure out how many bytes the result will require. Turn any
* illegally large UTF32 things (> Plane 17) into replacement chars.
*/
if (ch < (UTF32)0x80) { bytesToWrite = 1;
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
} else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
} else { bytesToWrite = 3;
ch = UNI_REPLACEMENT_CHAR;
result = sourceIllegal;
}
target += bytesToWrite;
if (target > targetEnd) {
--source; /* Back up source pointer! */
target -= bytesToWrite; result = targetExhausted; break;
}
switch (bytesToWrite) { /* note: everything falls through. */
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
}
target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF32 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF32* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch = 0;
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
if (source + extraBytesToRead >= sourceEnd) {
result = sourceExhausted; break;
}
/* Do this check whether lenient or strict */
if (! isLegalUTF8(source, extraBytesToRead+1)) {
result = sourceIllegal;
break;
}
/*
* The cases all fall through. See "Note A" below.
*/
switch (extraBytesToRead) {
case 5: ch += *source++; ch <<= 6;
case 4: ch += *source++; ch <<= 6;
case 3: ch += *source++; ch <<= 6;
case 2: ch += *source++; ch <<= 6;
case 1: ch += *source++; ch <<= 6;
case 0: ch += *source++;
}
ch -= offsetsFromUTF8[extraBytesToRead];
if (target >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up the source pointer! */
result = targetExhausted; break;
}
if (ch <= UNI_MAX_LEGAL_UTF32) {
/*
* UTF-16 surrogate values are illegal in UTF-32, and anything
* over Plane 17 (> 0x10FFFF) is illegal.
*/
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
source -= (extraBytesToRead+1); /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
*target++ = ch;
}
} else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
result = sourceIllegal;
*target++ = UNI_REPLACEMENT_CHAR;
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
}
/* ---------------------------------------------------------------------
Note A.
The fall-through switches in UTF-8 reading code save a
temp variable, some decrements & conditionals. The switches
are equivalent to the following loop:
{
int tmpBytesToRead = extraBytesToRead+1;
do {
ch += *source++;
--tmpBytesToRead;
if (tmpBytesToRead) ch <<= 6;
} while (tmpBytesToRead > 0);
}
In UTF-8 writing code, the switches on "bytesToWrite" are
similarly unrolled loops.
--------------------------------------------------------------------- */

View File

@@ -1,162 +0,0 @@
/*
* Copyright 2001-2004 Unicode, Inc.
*
* Disclaimer
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
*/
/* ---------------------------------------------------------------------
Conversions between UTF32, UTF-16, and UTF-8. Header file.
Several funtions are included here, forming a complete set of
conversions between the three formats. UTF-7 is not included
here, but is handled in a separate source file.
Each of these routines takes pointers to input buffers and output
buffers. The input buffers are const.
Each routine converts the text between *sourceStart and sourceEnd,
putting the result into the buffer between *targetStart and
targetEnd. Note: the end pointers are *after* the last item: e.g.
*(sourceEnd - 1) is the last item.
The return result indicates whether the conversion was successful,
and if not, whether the problem was in the source or target buffers.
(Only the first encountered problem is indicated.)
After the conversion, *sourceStart and *targetStart are both
updated to point to the end of last text successfully converted in
the respective buffers.
Input parameters:
sourceStart - pointer to a pointer to the source buffer.
The contents of this are modified on return so that
it points at the next thing to be converted.
targetStart - similarly, pointer to pointer to the target buffer.
sourceEnd, targetEnd - respectively pointers to the ends of the
two buffers, for overflow checking only.
These conversion functions take a ConversionFlags argument. When this
flag is set to strict, both irregular sequences and isolated surrogates
will cause an error. When the flag is set to lenient, both irregular
sequences and isolated surrogates are converted.
Whether the flag is strict or lenient, all illegal sequences will cause
an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
must check for illegal sequences.
When the flag is set to lenient, characters over 0x10FFFF are converted
to the replacement character; otherwise (when the flag is set to strict)
they constitute an error.
Output parameters:
The value "sourceIllegal" is returned from some routines if the input
sequence is malformed. When "sourceIllegal" is returned, the source
value will point to the illegal value that caused the problem. E.g.,
in UTF-8 when a sequence is malformed, it points to the start of the
malformed sequence.
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
Fixes & updates, Sept 2001.
------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------
The following 4 definitions are compiler-specific.
The C standard does not guarantee that wchar_t has at least
16 bits, so wchar_t is no less portable than unsigned short!
All should be unsigned values to avoid sign extension during
bit mask & shift operations.
------------------------------------------------------------------------ */
#if 0
typedef unsigned long UTF32; /* at least 32 bits */
typedef unsigned short UTF16; /* at least 16 bits */
typedef unsigned char UTF8; /* typically 8 bits */
#endif
#include <stdint.h>
#include <string>
namespace linenoise_ng {
typedef uint32_t UTF32;
typedef uint16_t UTF16;
typedef uint8_t UTF8;
typedef unsigned char Boolean; /* 0 or 1 */
/* Some fundamental constants */
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
#define UNI_MAX_BMP (UTF32)0x0000FFFF
#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
typedef enum {
conversionOK, /* conversion successful */
sourceExhausted, /* partial character in source, but hit end */
targetExhausted, /* insuff. room in target for conversion */
sourceIllegal /* source sequence is illegal/malformed */
} ConversionResult;
typedef enum {
strictConversion = 0,
lenientConversion
} ConversionFlags;
// /* This is for C++ and does no harm in C */
// #ifdef __cplusplus
// extern "C" {
// #endif
ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF8toUTF32 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd,
char16_t** targetStart, char16_t* targetEnd, ConversionFlags flags);
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
// #ifdef __cplusplus
// }
// #endif
}
/* --------------------------------------------------------------------- */

View File

@@ -1,66 +0,0 @@
linenoise.cpp
=============
Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Redis nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
wcwidth.cpp
===========
Markus Kuhn -- 2007-05-26 (Unicode 5.0)
Permission to use, copy, modify, and distribute this software
for any purpose and without fee is hereby granted. The author
disclaims all warranties with regard to this software.
ConvertUTF.cpp
==============
Copyright 2001-2004 Unicode, Inc.
Disclaimer
This source code is provided as is by Unicode, Inc. No claims are
made as to fitness for any particular purpose. No warranties of any
kind are expressed or implied. The recipient agrees to determine
applicability of information provided. If this file has been
purchased on magnetic or optical media from Unicode, Inc., the
sole remedy for any claim will be exchange of defective media
within 90 days of receipt.
Limitations on Rights to Redistribute This Code
Unicode, Inc. hereby grants the right to freely use the information
supplied in this file in the creation of products supporting the
Unicode Standard, and to make copies of this file in any form
for internal or external distribution as long as this notice
remains attached.

File diff suppressed because it is too large Load Diff

View File

@@ -1,73 +0,0 @@
/* linenoise.h -- guerrilla line editing library against the idea that a
* line editing lib needs to be 20,000 lines of C code.
*
* See linenoise.c for more information.
*
* Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LINENOISE_H
#define __LINENOISE_H
#define LINENOISE_VERSION "1.0.0"
#define LINENOISE_VERSION_MAJOR 1
#define LINENOISE_VERSION_MINOR 1
#ifdef __cplusplus
extern "C" {
#endif
typedef struct linenoiseCompletions linenoiseCompletions;
typedef void(linenoiseCompletionCallback)(const char*, linenoiseCompletions*);
void linenoiseSetCompletionCallback(linenoiseCompletionCallback* fn);
void linenoiseAddCompletion(linenoiseCompletions* lc, const char* str);
char* linenoise(const char* prompt);
void linenoisePreloadBuffer(const char* preloadText);
int linenoiseHistoryAdd(const char* line);
int linenoiseHistorySetMaxLen(int len);
char* linenoiseHistoryLine(int index);
int linenoiseHistorySave(const char* filename);
int linenoiseHistoryLoad(const char* filename);
void linenoiseHistoryFree(void);
void linenoiseClearScreen(void);
void linenoiseSetMultiLine(int ml);
void linenoisePrintKeyCodes(void);
/* the following are extensions to the original linenoise API */
int linenoiseInstallWindowChangeHandler(void);
/* returns type of key pressed: 1 = CTRL-C, 2 = CTRL-D, 0 = other */
int linenoiseKeyType(void);
#ifdef __cplusplus
}
#endif
#endif /* __LINENOISE_H */

View File

@@ -1,315 +0,0 @@
/*
* This is an implementation of wcwidth() and wcswidth() (defined in
* IEEE Std 1002.1-2001) for Unicode.
*
* http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
* http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
*
* In fixed-width output devices, Latin characters all occupy a single
* "cell" position of equal width, whereas ideographic CJK characters
* occupy two such cells. Interoperability between terminal-line
* applications and (teletype-style) character terminals using the
* UTF-8 encoding requires agreement on which character should advance
* the cursor by how many cell positions. No established formal
* standards exist at present on which Unicode character shall occupy
* how many cell positions on character terminals. These routines are
* a first attempt of defining such behavior based on simple rules
* applied to data provided by the Unicode Consortium.
*
* For some graphical characters, the Unicode standard explicitly
* defines a character-cell width via the definition of the East Asian
* FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
* In all these cases, there is no ambiguity about which width a
* terminal shall use. For characters in the East Asian Ambiguous (A)
* class, the width choice depends purely on a preference of backward
* compatibility with either historic CJK or Western practice.
* Choosing single-width for these characters is easy to justify as
* the appropriate long-term solution, as the CJK practice of
* displaying these characters as double-width comes from historic
* implementation simplicity (8-bit encoded characters were displayed
* single-width and 16-bit ones double-width, even for Greek,
* Cyrillic, etc.) and not any typographic considerations.
*
* Much less clear is the choice of width for the Not East Asian
* (Neutral) class. Existing practice does not dictate a width for any
* of these characters. It would nevertheless make sense
* typographically to allocate two character cells to characters such
* as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
* represented adequately with a single-width glyph. The following
* routines at present merely assign a single-cell width to all
* neutral characters, in the interest of simplicity. This is not
* entirely satisfactory and should be reconsidered before
* establishing a formal standard in this area. At the moment, the
* decision which Not East Asian (Neutral) characters should be
* represented by double-width glyphs cannot yet be answered by
* applying a simple rule from the Unicode database content. Setting
* up a proper standard for the behavior of UTF-8 character terminals
* will require a careful analysis not only of each Unicode character,
* but also of each presentation form, something the author of these
* routines has avoided to do so far.
*
* http://www.unicode.org/unicode/reports/tr11/
*
* Markus Kuhn -- 2007-05-26 (Unicode 5.0)
*
* Permission to use, copy, modify, and distribute this software
* for any purpose and without fee is hereby granted. The author
* disclaims all warranties with regard to this software.
*
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
*/
#include <wchar.h>
#include <string>
#include <memory>
namespace linenoise_ng {
struct interval {
char32_t first;
char32_t last;
};
/* auxiliary function for binary search in interval table */
static int bisearch(char32_t ucs, const struct interval *table, int max) {
int min = 0;
int mid;
if (ucs < table[0].first || ucs > table[max].last)
return 0;
while (max >= min) {
mid = (min + max) / 2;
if (ucs > table[mid].last)
min = mid + 1;
else if (ucs < table[mid].first)
max = mid - 1;
else
return 1;
}
return 0;
}
/* The following two functions define the column width of an ISO 10646
* character as follows:
*
* - The null character (U+0000) has a column width of 0.
*
* - Other C0/C1 control characters and DEL will lead to a return
* value of -1.
*
* - Non-spacing and enclosing combining characters (general
* category code Mn or Me in the Unicode database) have a
* column width of 0.
*
* - SOFT HYPHEN (U+00AD) has a column width of 1.
*
* - Other format characters (general category code Cf in the Unicode
* database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
*
* - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
* have a column width of 0.
*
* - Spacing characters in the East Asian Wide (W) or East Asian
* Full-width (F) category as defined in Unicode Technical
* Report #11 have a column width of 2.
*
* - All remaining characters (including all printable
* ISO 8859-1 and WGL4 characters, Unicode control characters,
* etc.) have a column width of 1.
*
* This implementation assumes that wchar_t characters are encoded
* in ISO 10646.
*/
int mk_wcwidth(char32_t ucs)
{
/* sorted list of non-overlapping intervals of non-spacing characters */
/* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
static const struct interval combining[] = {
{ 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
{ 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
{ 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
{ 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
{ 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
{ 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
{ 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
{ 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
{ 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
{ 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
{ 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
{ 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
{ 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
{ 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
{ 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
{ 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
{ 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
{ 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
{ 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
{ 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
{ 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
{ 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
{ 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
{ 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
{ 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
{ 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
{ 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
{ 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
{ 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
{ 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
{ 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
{ 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
{ 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
{ 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
{ 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
{ 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
{ 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
{ 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
{ 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
{ 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
{ 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
{ 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
{ 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
{ 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
{ 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
{ 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
{ 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
{ 0xE0100, 0xE01EF }
};
/* test for 8-bit control characters */
if (ucs == 0)
return 0;
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
return -1;
/* binary search in table of non-spacing characters */
if (bisearch(ucs, combining,
sizeof(combining) / sizeof(struct interval) - 1))
return 0;
/* if we arrive here, ucs is not a combining or C0/C1 control character */
return 1 +
(ucs >= 0x1100 &&
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
ucs == 0x2329 || ucs == 0x232a ||
(ucs >= 0x2e80 && ucs <= 0xa4cf &&
ucs != 0x303f) || /* CJK ... Yi */
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
(ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
(ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
(ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
(ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
(ucs >= 0xffe0 && ucs <= 0xffe6) ||
(ucs >= 0x20000 && ucs <= 0x2fffd) ||
(ucs >= 0x30000 && ucs <= 0x3fffd)));
}
int mk_wcswidth(const char32_t* pwcs, size_t n)
{
int w, width = 0;
for (;*pwcs && n-- > 0; pwcs++)
if ((w = mk_wcwidth(*pwcs)) < 0)
return -1;
else
width += w;
return width;
}
/*
* The following functions are the same as mk_wcwidth() and
* mk_wcswidth(), except that spacing characters in the East Asian
* Ambiguous (A) category as defined in Unicode Technical Report #11
* have a column width of 2. This variant might be useful for users of
* CJK legacy encodings who want to migrate to UCS without changing
* the traditional terminal character-width behaviour. It is not
* otherwise recommended for general use.
*/
int mk_wcwidth_cjk(wchar_t ucs)
{
/* sorted list of non-overlapping intervals of East Asian Ambiguous
* characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
static const struct interval ambiguous[] = {
{ 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
{ 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
{ 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
{ 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
{ 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
{ 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
{ 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
{ 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
{ 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
{ 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
{ 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
{ 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
{ 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
{ 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
{ 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
{ 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
{ 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
{ 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
{ 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
{ 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
{ 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
{ 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
{ 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
{ 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
{ 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
{ 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
{ 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
{ 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
{ 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
{ 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
{ 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
{ 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
{ 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
{ 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
{ 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
{ 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
{ 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
{ 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
{ 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
{ 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
{ 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
{ 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
{ 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
{ 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
{ 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
{ 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
{ 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
{ 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
{ 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
{ 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
{ 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
{ 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
};
/* binary search in table of non-spacing characters */
if (bisearch(ucs, ambiguous,
sizeof(ambiguous) / sizeof(struct interval) - 1))
return 2;
return mk_wcwidth(ucs);
}
int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n)
{
int w, width = 0;
for (;*pwcs && n-- > 0; pwcs++)
if ((w = mk_wcwidth_cjk(*pwcs)) < 0)
return -1;
else
width += w;
return width;
}
}

View File

@@ -1,9 +0,0 @@
programs += nix-build
nix-build_DIR := $(d)
nix-build_SOURCES := $(d)/nix-build.cc
nix-build_LIBS = libmain libexpr libstore libutil libformat
$(eval $(call install-symlink, nix-build, $(bindir)/nix-shell))

View File

@@ -16,6 +16,7 @@
#include "get-drvs.hh"
#include "common-eval-args.hh"
#include "attr-path.hh"
#include "legacy.hh"
using namespace nix;
using namespace std::string_literals;
@@ -66,11 +67,8 @@ std::vector<string> shellwords(const string & s)
return res;
}
void mainWrapped(int argc, char * * argv)
static void _main(int argc, char * * argv)
{
initNix();
initGC();
auto dryRun = false;
auto runEnv = std::regex_search(argv[0], std::regex("nix-shell$"));
auto pure = false;
@@ -417,16 +415,20 @@ void mainWrapped(int argc, char * * argv)
"dontAddDisableDepTrack=1; "
"[ -e $stdenv/setup ] && source $stdenv/setup; "
"%3%"
"PATH=\"%4%:$PATH\"; "
"SHELL=%5%; "
"set +e; "
R"s([ -n "$PS1" ] && PS1='\n\[\033[1;32m\][nix-shell:\w]\$\[\033[0m\] '; )s"
"if [ \"$(type -t runHook)\" = function ]; then runHook shellHook; fi; "
"unset NIX_ENFORCE_PURITY; "
"shopt -u nullglob; "
"unset TZ; %4%"
"%5%",
"unset TZ; %6%"
"%7%",
(Path) tmpDir,
(pure ? "" : "p=$PATH; "),
(pure ? "" : "PATH=$PATH:$p; unset p; "),
dirOf(shell),
shell,
(getenv("TZ") ? (string("export TZ='") + getenv("TZ") + "'; ") : ""),
envCommand));
@@ -500,9 +502,5 @@ void mainWrapped(int argc, char * * argv)
}
}
int main(int argc, char * * argv)
{
return handleExceptions(argv[0], [&]() {
return mainWrapped(argc, argv);
});
}
static RegisterLegacyCommand s1("nix-build", _main);
static RegisterLegacyCommand s2("nix-shell", _main);

View File

@@ -1,7 +0,0 @@
programs += nix-channel
nix-channel_DIR := $(d)
nix-channel_LIBS = libmain libformat libstore libutil
nix-channel_SOURCES := $(d)/nix-channel.cc

View File

@@ -1,9 +1,11 @@
#include "shared.hh"
#include "globals.hh"
#include "download.hh"
#include "store-api.hh"
#include "legacy.hh"
#include <fcntl.h>
#include <regex>
#include "store-api.hh"
#include <pwd.h>
using namespace nix;
@@ -157,11 +159,9 @@ static void update(const StringSet & channelNames)
replaceSymlink(profile, channelLink);
}
int main(int argc, char ** argv)
static int _main(int argc, char ** argv)
{
return handleExceptions(argv[0], [&]() {
initNix();
{
// Figure out the name of the `.nix-channels' file to use
auto home = getHome();
channelsList = home + "/.nix-channels";
@@ -169,7 +169,7 @@ int main(int argc, char ** argv)
// Figure out the name of the channels profile.
;
auto pw = getpwuid(getuid());
auto pw = getpwuid(geteuid());
std::string name = pw ? pw->pw_name : getEnv("USER", "");
if (name.empty())
throw Error("cannot figure out user name");
@@ -255,5 +255,9 @@ int main(int argc, char ** argv)
runProgram(settings.nixBinDir + "/nix-env", false, envArgs);
break;
}
});
return 0;
}
}
static RegisterLegacyCommand s1("nix-channel", _main);

View File

@@ -1,7 +0,0 @@
programs += nix-collect-garbage
nix-collect-garbage_DIR := $(d)
nix-collect-garbage_SOURCES := $(d)/nix-collect-garbage.cc
nix-collect-garbage_LIBS = libmain libstore libutil libformat

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