aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE.md4
-rw-r--r--configure.ac3
-rw-r--r--doc/manual/command-ref/env-common.xml2
-rw-r--r--doc/manual/command-ref/nix-build.xml21
-rw-r--r--doc/manual/expressions/debug-build.xml34
-rw-r--r--doc/manual/expressions/language-constructs.xml32
-rw-r--r--doc/manual/expressions/simple-building-testing.xml2
-rw-r--r--doc/manual/installation/installing-binary.xml10
-rw-r--r--doc/manual/installation/supported-platforms.xml3
-rw-r--r--doc/manual/introduction/quick-start.xml2
-rw-r--r--doc/manual/manual.xml6
-rw-r--r--doc/manual/release-notes/release-notes.xml2
-rw-r--r--doc/manual/release-notes/rl-2.0.xml (renamed from doc/manual/release-notes/rl-1.12.xml)19
-rw-r--r--doc/manual/troubleshooting/collisions-nixenv.xml38
-rw-r--r--doc/manual/troubleshooting/links-nix-store.xml43
-rw-r--r--doc/manual/troubleshooting/troubleshooting.xml16
-rw-r--r--release-common.nix6
-rw-r--r--scripts/install-darwin-multi-user.sh2
-rw-r--r--src/libexpr/eval.cc12
-rw-r--r--src/libexpr/primops.cc34
-rw-r--r--src/libstore/build.cc56
-rw-r--r--src/libstore/download.cc41
-rw-r--r--src/libstore/download.hh2
-rw-r--r--src/libstore/gc.cc4
-rw-r--r--src/libstore/globals.hh5
-rw-r--r--src/libstore/http-binary-cache-store.cc11
-rw-r--r--src/libstore/local-store.hh2
-rw-r--r--src/libstore/remote-store.cc26
-rw-r--r--src/libstore/remote-store.hh2
-rw-r--r--src/libstore/store-api.hh7
-rwxr-xr-xsrc/nix-build/nix-build.cc5
-rw-r--r--src/nix-store/nix-store.cc1
-rw-r--r--src/nix/command.hh2
-rw-r--r--src/nix/local.mk2
-rw-r--r--src/nix/main.cc5
-rw-r--r--src/nix/progress-bar.cc50
-rw-r--r--src/nix/upgrade-nix.cc131
-rw-r--r--tests/common.sh.in1
-rw-r--r--tests/fixed.sh13
-rw-r--r--tests/nix-copy-closure.nix2
-rw-r--r--tests/restricted.sh2
-rw-r--r--version2
42 files changed, 394 insertions, 269 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index cdf642e6a..3372b1f03 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -14,7 +14,7 @@ Examples of _Nix_ issues:
- Nix segfaults when I run `nix-build -A blahblah`
- The Nix language needs a new builtin: `builtins.foobar`
-- Regression in the behavior of `nix-env` in Nix 1.12
+- Regression in the behavior of `nix-env` in Nix 2.0
Examples of _nixpkgs_ issues:
@@ -24,4 +24,4 @@ Examples of _nixpkgs_ issues:
Chances are if you're a newcomer to the Nix world, you'll probably want the [nixpkgs tracker](https://github.com/NixOS/nixpkgs/issues). It also gets a lot more eyeball traffic so you'll probably get a response a lot more quickly.
---> \ No newline at end of file
+-->
diff --git a/configure.ac b/configure.ac
index 9db92ce91..83b2346d0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -61,6 +61,7 @@ CFLAGS=
CXXFLAGS=
AC_PROG_CC
AC_PROG_CXX
+AC_PROG_CPP
AX_CXX_COMPILE_STDCXX_11
@@ -199,7 +200,7 @@ AC_SUBST(ENABLE_S3, [$enable_s3])
AC_LANG_POP(C++)
if test -n "$enable_s3"; then
- declare -a aws_version_tokens=($(printf '#include <aws/core/VersionConfig.h>\nAWS_SDK_VERSION_STRING' | cpp -E | grep -v '^#.*' | sed 's/"//g' | tr '.' ' '))
+ declare -a aws_version_tokens=($(printf '#include <aws/core/VersionConfig.h>\nAWS_SDK_VERSION_STRING' | $CPP - | grep -v '^#.*' | sed 's/"//g' | tr '.' ' '))
AC_DEFINE_UNQUOTED([AWS_VERSION_MAJOR], ${aws_version_tokens@<:@0@:>@}, [Major version of aws-sdk-cpp.])
AC_DEFINE_UNQUOTED([AWS_VERSION_MINOR], ${aws_version_tokens@<:@1@:>@}, [Minor version of aws-sdk-cpp.])
fi
diff --git a/doc/manual/command-ref/env-common.xml b/doc/manual/command-ref/env-common.xml
index a83aeaf2e..361d3e2b0 100644
--- a/doc/manual/command-ref/env-common.xml
+++ b/doc/manual/command-ref/env-common.xml
@@ -154,6 +154,8 @@ $ mount -o bind /mnt/otherdisk/nix /nix</screen>
<literal>daemon</literal> if you want to use the Nix daemon to
execute Nix operations. This is necessary in <link
linkend="ssec-multi-user">multi-user Nix installations</link>.
+ If the Nix daemon's Unix socket is at some non-standard path,
+ this variable should be set to <literal>unix://path/to/socket</literal>.
Otherwise, it should be left unset.</para></listitem>
</varlistentry>
diff --git a/doc/manual/command-ref/nix-build.xml b/doc/manual/command-ref/nix-build.xml
index d6b2e5e5a..40fe7a43f 100644
--- a/doc/manual/command-ref/nix-build.xml
+++ b/doc/manual/command-ref/nix-build.xml
@@ -29,8 +29,6 @@
</group>
<replaceable>attrPath</replaceable>
</arg>
- <arg><option>--drv-link</option> <replaceable>drvlink</replaceable></arg>
- <arg><option>--add-drv-link</option></arg>
<arg><option>--no-out-link</option></arg>
<arg>
<group choice='req'>
@@ -91,25 +89,6 @@ also <xref linkend="sec-common-options" />.</phrase></para>
<variablelist>
- <varlistentry><term><option>--drv-link</option> <replaceable>drvlink</replaceable></term>
-
- <listitem><para>Add a symlink named
- <replaceable>drvlink</replaceable> to the store derivation
- produced by <command>nix-instantiate</command>. The derivation is
- a root of the garbage collector until the symlink is deleted or
- renamed. If there are multiple derivations, numbers are suffixed
- to <replaceable>drvlink</replaceable> to distinguish between
- them.</para></listitem>
-
- </varlistentry>
-
- <varlistentry><term><option>--add-drv-link</option></term>
-
- <listitem><para>Shorthand for <option>--drv-link</option>
- <filename>./derivation</filename>.</para></listitem>
-
- </varlistentry>
-
<varlistentry><term><option>--no-out-link</option></term>
<listitem><para>Do not create a symlink to the output path. Note
diff --git a/doc/manual/expressions/debug-build.xml b/doc/manual/expressions/debug-build.xml
deleted file mode 100644
index 0c1f4e671..000000000
--- a/doc/manual/expressions/debug-build.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<section xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- version="5.0"
- xml:id="sec-debug-build">
-
-<title>Debugging Build Failures</title>
-
-<para>At the beginning of each phase of the build (such as unpacking,
-building or installing), the set of all shell variables is written to
-the file <filename>env-vars</filename> at the top-level build
-directory. This is useful for debugging: it allows you to recreate
-the environment in which a build was performed. For instance, if a
-build fails, then assuming you used the <option>-K</option> flag, you
-can go to the output directory and <quote>switch</quote> to the
-environment of the builder:
-
-<screen>
-$ nix-build -K ./foo.nix
-... fails, keeping build directory `/tmp/nix-1234-0'
-
-$ cd /tmp/nix-1234-0
-
-$ source env-vars
-
-<lineannotation>(edit some files...)</lineannotation>
-
-$ make
-
-<lineannotation>(execution continues with the same GCC, make, etc.)</lineannotation></screen>
-
-</para>
-
-</section>
diff --git a/doc/manual/expressions/language-constructs.xml b/doc/manual/expressions/language-constructs.xml
index 2f0027d47..47d95f8a1 100644
--- a/doc/manual/expressions/language-constructs.xml
+++ b/doc/manual/expressions/language-constructs.xml
@@ -61,7 +61,7 @@ evaluates to <literal>"foobar"</literal>.
<simplesect><title>Inheriting attributes</title>
-<para>When defining a set it is often convenient to copy variables
+<para>When defining a set or in a let-expression it is often convenient to copy variables
from the surrounding lexical scope (e.g., when you want to propagate
attributes). This can be shortened using the
<literal>inherit</literal> keyword. For instance,
@@ -72,7 +72,15 @@ let x = 123; in
y = 456;
}</programlisting>
-evaluates to <literal>{ x = 123; y = 456; }</literal>. (Note that
+is equivalent to
+
+<programlisting>
+let x = 123; in
+{ x = x;
+ y = 456;
+}</programlisting>
+
+and both evaluate to <literal>{ x = 123; y = 456; }</literal>. (Note that
this works because <varname>x</varname> is added to the lexical scope
by the <literal>let</literal> construct.) It is also possible to
inherit attributes from another set. For instance, in this fragment
@@ -101,6 +109,26 @@ variables from the surrounding scope (<varname>fetchurl</varname>
<varname>libXaw</varname> (the X Athena Widgets) from the
<varname>xlibs</varname> (X11 client-side libraries) set.</para>
+<para>
+Summarizing the fragment
+
+<programlisting>
+...
+inherit x y z;
+inherit (src-set) a b c;
+...</programlisting>
+
+is equivalent to
+
+<programlisting>
+...
+x = x; y = y; z = z;
+a = src-set.a; b = src-set.b; c = src-set.c;
+...</programlisting>
+
+when used while defining local variables in a let-expression or
+while defining a set.</para>
+
</simplesect>
diff --git a/doc/manual/expressions/simple-building-testing.xml b/doc/manual/expressions/simple-building-testing.xml
index bd3901a13..0348c082b 100644
--- a/doc/manual/expressions/simple-building-testing.xml
+++ b/doc/manual/expressions/simple-building-testing.xml
@@ -81,6 +81,4 @@ Just pass the option <link linkend='opt-max-jobs'><option>-j
in parallel, or set. Typically this should be the number of
CPUs.</para>
-<xi:include href="debug-build.xml" />
-
</section>
diff --git a/doc/manual/installation/installing-binary.xml b/doc/manual/installation/installing-binary.xml
index 24e76eafe..7e8dfb0db 100644
--- a/doc/manual/installation/installing-binary.xml
+++ b/doc/manual/installation/installing-binary.xml
@@ -79,16 +79,6 @@ alice$ ./install
</para>
-<para>Nix can be uninstalled using <command>rpm -e nix</command> or
-<command>dpkg -r nix</command> on RPM- and Dpkg-based systems,
-respectively. After this you should manually remove the Nix store and
-other auxiliary data, if desired:
-
-<screen>
-$ rm -rf /nix</screen>
-
-</para>
-
<para>You can uninstall Nix simply by running:
<screen>
diff --git a/doc/manual/installation/supported-platforms.xml b/doc/manual/installation/supported-platforms.xml
index a468a5640..6858573ff 100644
--- a/doc/manual/installation/supported-platforms.xml
+++ b/doc/manual/installation/supported-platforms.xml
@@ -33,7 +33,4 @@
</para>
-<para>Nix is fairly portable, so it should work on most platforms that
-support POSIX threads and have a C++11 compiler.</para>
-
</chapter>
diff --git a/doc/manual/introduction/quick-start.xml b/doc/manual/introduction/quick-start.xml
index aa239b753..1ce6c8d50 100644
--- a/doc/manual/introduction/quick-start.xml
+++ b/doc/manual/introduction/quick-start.xml
@@ -15,7 +15,7 @@ to subsequent chapters.</para>
<step><para>Install single-user Nix by running the following:
<screen>
-$ curl https://nixos.org/nix/install | sh
+$ bash &lt;(curl https://nixos.org/nix/install)
</screen>
This will install Nix in <filename>/nix</filename>. The install script
diff --git a/doc/manual/manual.xml b/doc/manual/manual.xml
index 61205d916..b5a6af7d0 100644
--- a/doc/manual/manual.xml
+++ b/doc/manual/manual.xml
@@ -12,14 +12,11 @@
<firstname>Eelco</firstname>
<surname>Dolstra</surname>
</personname>
- <affiliation>
- <orgname>LogicBlox</orgname>
- </affiliation>
<contrib>Author</contrib>
</author>
<copyright>
- <year>2004-2014</year>
+ <year>2004-2017</year>
<holder>Eelco Dolstra</holder>
</copyright>
@@ -41,7 +38,6 @@
<xi:include href="expressions/writing-nix-expressions.xml" />
<xi:include href="advanced-topics/advanced-topics.xml" />
<xi:include href="command-ref/command-ref.xml" />
- <xi:include href="troubleshooting/troubleshooting.xml" />
<xi:include href="glossary/glossary.xml" />
<xi:include href="hacking.xml" />
<xi:include href="release-notes/release-notes.xml" />
diff --git a/doc/manual/release-notes/release-notes.xml b/doc/manual/release-notes/release-notes.xml
index c4b14bc54..b8392a647 100644
--- a/doc/manual/release-notes/release-notes.xml
+++ b/doc/manual/release-notes/release-notes.xml
@@ -12,7 +12,7 @@
</partintro>
-->
-<xi:include href="rl-1.12.xml" />
+<xi:include href="rl-2.0.xml" />
<xi:include href="rl-1.11.10.xml" />
<xi:include href="rl-1.11.xml" />
<xi:include href="rl-1.10.xml" />
diff --git a/doc/manual/release-notes/rl-1.12.xml b/doc/manual/release-notes/rl-2.0.xml
index 29943e3e6..32cdb1d0c 100644
--- a/doc/manual/release-notes/rl-1.12.xml
+++ b/doc/manual/release-notes/rl-2.0.xml
@@ -2,9 +2,9 @@
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
- xml:id="ssec-relnotes-1.12">
+ xml:id="ssec-relnotes-2.0">
-<title>Release 1.12 (TBA)</title>
+<title>Release 2.0 (2018-02-??)</title>
<para>This release has the following new features:</para>
@@ -79,6 +79,11 @@
<listitem><para><command>nix add-to-store</command> (970366266b8df712f5f9cedb45af183ef5a8357f).</para></listitem>
+ <listitem><para><command>nix upgrade-nix</command> upgrades Nix
+ to the latest stable version. This requires that Nix is
+ installed in a profile. (Thus it won’t work on NixOS, or if it’s
+ installed outside of the Nix store.)</para></listitem>
+
<listitem><para>Progress indicator.</para></listitem>
<listitem><para>All options are available as flags now
@@ -94,11 +99,11 @@
</listitem>
<listitem>
- <para>New build mode <command>nix-build --hash</command> that
- builds a derivation, computes the hash of the output, and moves
- the output to the store path corresponding to what a fixed-output
- derivation with that hash would produce.
- (Add docs and examples; see d367b8e7875161e655deaa96bf8a5dd0bcf8229e)</para>
+ <para>If a fixed-output derivation produces a result with an
+ incorrect hash, the output path will be moved to the location
+ corresponding to the actual hash and registered as valid. Thus, a
+ subsequent build of the fixed-output derivation with the correct
+ hash is unnecessary.</para>
</listitem>
<listitem>
diff --git a/doc/manual/troubleshooting/collisions-nixenv.xml b/doc/manual/troubleshooting/collisions-nixenv.xml
deleted file mode 100644
index 23cc43faf..000000000
--- a/doc/manual/troubleshooting/collisions-nixenv.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<section xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- version="5.0"
- xml:id="sec-collisions-nixenv">
-
-<title>Collisions in <command>nix-env</command></title>
-
-<para>Symptom: when installing or upgrading, you get an error message such as
-
-<screen>
-$ nix-env -i docbook-xml
-...
-adding /nix/store/s5hyxgm62gk2...-docbook-xml-4.2
-collision between `/nix/store/s5hyxgm62gk2...-docbook-xml-4.2/xml/dtd/docbook/calstblx.dtd'
- and `/nix/store/06h377hr4b33...-docbook-xml-4.3/xml/dtd/docbook/calstblx.dtd'
- at /nix/store/...-builder.pl line 62.</screen>
-
-</para>
-
-<para>The cause is that two installed packages in the user environment
-have overlapping filenames (e.g.,
-<filename>xml/dtd/docbook/calstblx.dtd</filename>. This usually
-happens when you accidentally try to install two versions of the same
-package. For instance, in the example above, the Nix Packages
-collection contains two versions of <literal>docbook-xml</literal>, so
-<command>nix-env -i</command> will try to install both. The default
-user environment builder has no way to way to resolve such conflicts,
-so it just gives up.</para>
-
-<para>Solution: remove one of the offending packages from the user
-environment (if already installed) using <command>nix-env
--e</command>, or specify exactly which version should be installed
-(e.g., <literal>nix-env -i docbook-xml-4.2</literal>).</para>
-
-<!-- FIXME: describe priorities -->
-
-</section>
diff --git a/doc/manual/troubleshooting/links-nix-store.xml b/doc/manual/troubleshooting/links-nix-store.xml
deleted file mode 100644
index c76888956..000000000
--- a/doc/manual/troubleshooting/links-nix-store.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<section xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- version="5.0"
- xml:id="sec-links-nix-store">
-
-<title><quote>Too many links</quote> Error in the Nix store</title>
-
-
-<para>Symptom: when building something, you get an error message such as
-
-<screen>
-...
-<literal>mkdir: cannot create directory `/nix/store/<replaceable>name</replaceable>': Too many links</literal></screen>
-
-</para>
-
-<para>This is usually because you have more than 32,000 subdirectories
-in <filename>/nix/store</filename>, as can be seen using <command>ls
--l</command>:
-
-<screen>
-$ ls -ld /nix/store
-drwxrwxrwt 32000 nix nix 4620288 Sep 8 15:08 store</screen>
-
-The <literal>ext2</literal> file system is limited to an inode link
-count of 32,000 (each subdirectory increasing the count by one).
-Furthermore, the <literal>st_nlink</literal> field of the
-<function>stat</function> system call is a 16-bit value.</para>
-
-<para>This only happens on very large Nix installations (such as build
-machines).</para>
-
-<para>Quick solution: run the garbage collector. You may want to use
-the <option>--max-links</option> option.</para>
-
-<para>Real solution: put the Nix store on a file system that supports
-more than 32,000 subdirectories per directory, such as ext4. (This
-doesn’t solve the <literal>st_nlink</literal> limit, but ext4 lies to
-the kernel by reporting a link count of 1 if it exceeds the
-limit.)</para>
-
-</section>
diff --git a/doc/manual/troubleshooting/troubleshooting.xml b/doc/manual/troubleshooting/troubleshooting.xml
deleted file mode 100644
index 1e973a192..000000000
--- a/doc/manual/troubleshooting/troubleshooting.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<appendix xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- version="5.0"
- xml:id="ch-troubleshooting">
-
-<title>Troubleshooting</title>
-
-<para>This section provides solutions for some common problems. See
-the <link xlink:href="https://github.com/NixOS/nix/issues">Nix bug
-tracker</link> for a list of currently known issues.</para>
-
-<xi:include href="collisions-nixenv.xml" />
-<xi:include href="links-nix-store.xml" />
-
-</appendix>
diff --git a/release-common.nix b/release-common.nix
index 4553118e1..a4ae24ba4 100644
--- a/release-common.nix
+++ b/release-common.nix
@@ -1,7 +1,9 @@
{ pkgs }:
rec {
- sh = pkgs.busybox.override {
+ # Use "busybox-sandbox-shell" if present,
+ # if not (legacy) fallback and hope it's sufficient.
+ sh = pkgs.busybox-sandbox-shell or (pkgs.busybox.override {
useMusl = true;
enableStatic = true;
enableMinimal = true;
@@ -11,7 +13,7 @@ rec {
CONFIG_ASH_TEST y
CONFIG_ASH_OPTIMIZE_FOR_SIZE y
'';
- };
+ });
configureFlags =
[ "--disable-init-state"
diff --git a/scripts/install-darwin-multi-user.sh b/scripts/install-darwin-multi-user.sh
index 2e9d368c0..8d59c1c2b 100644
--- a/scripts/install-darwin-multi-user.sh
+++ b/scripts/install-darwin-multi-user.sh
@@ -695,7 +695,7 @@ install_from_extracted_nix() {
cd "$EXTRACTED_NIX_PATH"
_sudo "to copy the basic Nix files to the new store at $NIX_ROOT/store" \
- rsync -rlpt "$(pwd)/store/" "$NIX_ROOT/store/"
+ rsync -rlpt ./store/* "$NIX_ROOT/store/"
if [ -d "$NIX_INSTALLED_NIX" ]; then
echo " Alright! We have our first nix at $NIX_INSTALLED_NIX"
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 9499ebe70..0b0a0f7b1 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -378,6 +378,18 @@ void EvalState::checkURI(const std::string & uri)
&& (prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/')))
return;
+ /* If the URI is a path, then check it against allowedPaths as
+ well. */
+ if (hasPrefix(uri, "/")) {
+ checkSourcePath(uri);
+ return;
+ }
+
+ if (hasPrefix(uri, "file://")) {
+ checkSourcePath(std::string(uri, 7));
+ return;
+ }
+
throw RestrictedPathError("access to URI '%s' is forbidden in restricted mode", uri);
}
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 5c8dfd9df..466fd13e8 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -49,24 +49,38 @@ InvalidPathError::InvalidPathError(const Path & path) :
void EvalState::realiseContext(const PathSet & context)
{
PathSet drvs;
+
for (auto & i : context) {
std::pair<string, string> decoded = decodeContext(i);
Path ctx = decoded.first;
assert(store->isStorePath(ctx));
if (!store->isValidPath(ctx))
throw InvalidPathError(ctx);
- if (!decoded.second.empty() && nix::isDerivation(ctx))
+ if (!decoded.second.empty() && nix::isDerivation(ctx)) {
drvs.insert(decoded.first + "!" + decoded.second);
+
+ /* Add the output of this derivation to the allowed
+ paths. */
+ if (allowedPaths) {
+ auto drv = store->derivationFromPath(decoded.first);
+ DerivationOutputs::iterator i = drv.outputs.find(decoded.second);
+ if (i == drv.outputs.end())
+ throw Error("derivation '%s' does not have an output named '%s'", decoded.first, decoded.second);
+ allowedPaths->insert(i->second.path);
+ }
+ }
}
- if (!drvs.empty()) {
- if (!settings.enableImportFromDerivation)
- throw EvalError(format("attempted to realize '%1%' during evaluation but 'allow-import-from-derivation' is false") % *(drvs.begin()));
- /* For performance, prefetch all substitute info. */
- PathSet willBuild, willSubstitute, unknown;
- unsigned long long downloadSize, narSize;
- store->queryMissing(drvs, willBuild, willSubstitute, unknown, downloadSize, narSize);
- store->buildPaths(drvs);
- }
+
+ if (drvs.empty()) return;
+
+ if (!settings.enableImportFromDerivation)
+ throw EvalError(format("attempted to realize '%1%' during evaluation but 'allow-import-from-derivation' is false") % *(drvs.begin()));
+
+ /* For performance, prefetch all substitute info. */
+ PathSet willBuild, willSubstitute, unknown;
+ unsigned long long downloadSize, narSize;
+ store->queryMissing(drvs, willBuild, willSubstitute, unknown, downloadSize, narSize);
+ store->buildPaths(drvs);
}
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index cca51f17e..5be7ce60d 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -1124,11 +1124,6 @@ void DerivationGoal::haveDerivation()
return;
}
- /* Reject doing a hash build of anything other than a fixed-output
- derivation. */
- if (buildMode == bmHash && !drv->isFixedOutput())
- throw Error("cannot do a hash build of non-fixed-output derivation '%1%'", drvPath);
-
/* We are first going to try to create the invalid output paths
through substitutes. If that doesn't work, we'll build
them. */
@@ -1320,9 +1315,7 @@ void DerivationGoal::inputsRealised()
allPaths.insert(inputPaths.begin(), inputPaths.end());
/* Is this a fixed-output derivation? */
- fixedOutput = true;
- for (auto & i : drv->outputs)
- if (i.second.hash == "") fixedOutput = false;
+ fixedOutput = drv->isFixedOutput();
/* Don't repeat fixed-output derivations since they're already
verified by their output hash.*/
@@ -3019,6 +3012,8 @@ void DerivationGoal::registerOutputs()
bool runDiffHook = settings.runDiffHook;
bool keepPreviousRound = settings.keepFailed || runDiffHook;
+ std::exception_ptr delayedException;
+
/* Check whether the output paths were created, and grep each
output path to determine what other paths it references. Also make all
output paths read-only. */
@@ -3093,7 +3088,7 @@ void DerivationGoal::registerOutputs()
/* Check that fixed-output derivations produced the right
outputs (i.e., the content hash should match the specified
hash). */
- if (i.second.hash != "") {
+ if (fixedOutput) {
bool recursive; Hash h;
i.second.parseHashInfo(recursive, h);
@@ -3109,27 +3104,34 @@ void DerivationGoal::registerOutputs()
/* Check the hash. In hash mode, move the path produced by
the derivation to its content-addressed location. */
Hash h2 = recursive ? hashPath(h.type, actualPath).first : hashFile(h.type, actualPath);
- if (buildMode == bmHash) {
- Path dest = worker.store.makeFixedOutputPath(recursive, h2, drv->env["name"]);
- printError(format("build produced path '%1%' with %2% hash '%3%'")
- % dest % printHashType(h.type) % printHash16or32(h2));
- if (worker.store.isValidPath(dest))
- return;
+
+ Path dest = worker.store.makeFixedOutputPath(recursive, h2, drv->env["name"]);
+
+ 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)));
+
Path actualDest = worker.store.toRealPath(dest);
+
+ if (worker.store.isValidPath(dest))
+ std::rethrow_exception(delayedException);
+
if (actualPath != actualDest) {
PathLocks outputLocks({actualDest});
deletePath(actualDest);
if (rename(actualPath.c_str(), actualDest.c_str()) == -1)
throw SysError(format("moving '%1%' to '%2%'") % actualPath % dest);
}
+
path = dest;
actualPath = actualDest;
- } else {
- if (h != h2)
- throw BuildError(
- format("output path '%1%' has %2% hash '%3%' when '%4%' was expected")
- % path % i.second.hashAlgo % printHash16or32(h2) % printHash16or32(h));
}
+ else
+ assert(path == dest);
info.ca = makeFixedOutputCA(recursive, h2);
}
@@ -3306,6 +3308,11 @@ void DerivationGoal::registerOutputs()
paths referenced by each of them. If there are cycles in the
outputs, this will fail. */
worker.store.registerValidPaths(infos);
+
+ /* In case of a fixed-output derivation hash mismatch, throw an
+ exception now that we have registered the output as valid. */
+ if (delayedException)
+ std::rethrow_exception(delayedException);
}
@@ -3663,7 +3670,7 @@ void SubstitutionGoal::tryNext()
/* Update the total expected download size. */
auto narInfo = std::dynamic_pointer_cast<const NarInfo>(info);
- maintainExpectedNar = std::make_unique<MaintainCount<uint64_t>>(worker.expectedNarSize, narInfo->narSize);
+ maintainExpectedNar = std::make_unique<MaintainCount<uint64_t>>(worker.expectedNarSize, info->narSize);
maintainExpectedDownload =
narInfo && narInfo->fileSize
@@ -3677,7 +3684,10 @@ void SubstitutionGoal::tryNext()
/* Bail out early if this substituter lacks a valid
signature. LocalStore::addToStore() also checks for this, but
only after we've downloaded the path. */
- if (worker.store.requireSigs && !info->checkSignatures(worker.store, worker.store.publicKeys)) {
+ if (worker.store.requireSigs
+ && !sub->isTrusted
+ && !info->checkSignatures(worker.store, worker.store.publicKeys))
+ {
printInfo(format("warning: substituter '%s' does not have a valid signature for path '%s'")
% sub->getUri() % storePath);
tryNext();
@@ -3745,7 +3755,7 @@ void SubstitutionGoal::tryToRun()
PushActivity pact(act.id);
copyStorePath(ref<Store>(sub), ref<Store>(worker.store.shared_from_this()),
- storePath, repair);
+ storePath, repair, sub->isTrusted ? NoCheckSigs : CheckSigs);
promise.set_value();
} catch (...) {
diff --git a/src/libstore/download.cc b/src/libstore/download.cc
index ef417685f..258d7937c 100644
--- a/src/libstore/download.cc
+++ b/src/libstore/download.cc
@@ -17,11 +17,13 @@
#include <curl/curl.h>
-#include <queue>
-#include <iostream>
-#include <thread>
+#include <algorithm>
#include <cmath>
+#include <cstring>
+#include <iostream>
+#include <queue>
#include <random>
+#include <thread>
using namespace std::string_literals;
@@ -91,6 +93,8 @@ struct CurlDownloader : public Downloader
{
if (!request.expectedETag.empty())
requestHeaders = curl_slist_append(requestHeaders, ("If-None-Match: " + request.expectedETag).c_str());
+ if (!request.mimeType.empty())
+ requestHeaders = curl_slist_append(requestHeaders, ("Content-Type: " + request.mimeType).c_str());
}
~DownloadItem()
@@ -185,6 +189,22 @@ struct CurlDownloader : public Downloader
return 0;
}
+ size_t readOffset = 0;
+ int readCallback(char *buffer, size_t size, size_t nitems)
+ {
+ if (readOffset == request.data->length())
+ return 0;
+ auto count = std::min(size * nitems, request.data->length() - readOffset);
+ memcpy(buffer, request.data->data() + readOffset, count);
+ readOffset += count;
+ return count;
+ }
+
+ static int readCallbackWrapper(char *buffer, size_t size, size_t nitems, void * userp)
+ {
+ return ((DownloadItem *) userp)->readCallback(buffer, size, nitems);
+ }
+
long lowSpeedTimeout = 300;
void init()
@@ -225,6 +245,13 @@ struct CurlDownloader : public Downloader
if (request.head)
curl_easy_setopt(req, CURLOPT_NOBODY, 1);
+ if (request.data) {
+ curl_easy_setopt(req, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt(req, CURLOPT_READFUNCTION, readCallbackWrapper);
+ curl_easy_setopt(req, CURLOPT_READDATA, this);
+ curl_easy_setopt(req, CURLOPT_INFILESIZE_LARGE, (curl_off_t) request.data->length());
+ }
+
if (request.verifyTLS) {
if (settings.caFile != "")
curl_easy_setopt(req, CURLOPT_CAINFO, settings.caFile.c_str());
@@ -265,7 +292,7 @@ struct CurlDownloader : public Downloader
}
if (code == CURLE_OK &&
- (httpStatus == 200 || httpStatus == 304 || httpStatus == 226 /* FTP */ || httpStatus == 0 /* other protocol */))
+ (httpStatus == 200 || httpStatus == 201 || httpStatus == 204 || httpStatus == 304 || httpStatus == 226 /* FTP */ || httpStatus == 0 /* other protocol */))
{
result.cached = httpStatus == 304;
done = true;
@@ -312,10 +339,10 @@ struct CurlDownloader : public Downloader
case CURLE_BAD_FUNCTION_ARGUMENT:
case CURLE_INTERFACE_FAILED:
case CURLE_UNKNOWN_OPTION:
- err = Misc;
- break;
+ err = Misc;
+ break;
default: // Shut up warnings
- break;
+ break;
}
}
diff --git a/src/libstore/download.hh b/src/libstore/download.hh
index f2d65ad8d..d9d525d4e 100644
--- a/src/libstore/download.hh
+++ b/src/libstore/download.hh
@@ -18,6 +18,8 @@ struct DownloadRequest
unsigned int baseRetryTimeMs = 250;
ActivityId parentAct;
bool decompress = true;
+ std::shared_ptr<std::string> data;
+ std::string mimeType;
DownloadRequest(const std::string & uri)
: uri(uri), parentAct(curActivity) { }
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index ab2c5ca02..943b16c28 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -324,10 +324,8 @@ Roots LocalStore::findRootsNoTemp()
{
Roots roots;
- /* Process direct roots in {gcroots,manifests,profiles}. */
+ /* Process direct roots in {gcroots,profiles}. */
findRoots(stateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
- if (pathExists(stateDir + "/manifests"))
- findRoots(stateDir + "/manifests", DT_UNKNOWN, roots);
findRoots(stateDir + "/profiles", DT_UNKNOWN, roots);
/* Add additional roots returned by the program specified by the
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index 1e50e2d13..20ac8fe4e 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -287,10 +287,7 @@ public:
Setting<unsigned int> tarballTtl{this, 60 * 60, "tarball-ttl",
"How soon to expire files fetched by builtins.fetchTarball and builtins.fetchurl."};
- Setting<std::string> signedBinaryCaches{this, "*", "signed-binary-caches",
- "Obsolete."};
-
- Setting<bool> requireSigs{this, signedBinaryCaches == "*", "require-sigs",
+ Setting<bool> requireSigs{this, true, "require-sigs",
"Whether to check that any non-content-addressed path added to the "
"Nix store has a valid signature (that is, one signed using a key "
"listed in 'trusted-public-keys'."};
diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc
index 057337685..b9e9cd5da 100644
--- a/src/libstore/http-binary-cache-store.cc
+++ b/src/libstore/http-binary-cache-store.cc
@@ -38,7 +38,7 @@ public:
try {
BinaryCacheStore::init();
} catch (UploadToHTTP &) {
- throw Error(format("'%s' does not appear to be a binary cache") % cacheUri);
+ throw Error("'%s' does not appear to be a binary cache", cacheUri);
}
diskCache->createCache(cacheUri, storeDir, wantMassQuery_, priority);
}
@@ -67,7 +67,14 @@ protected:
const std::string & data,
const std::string & mimeType) override
{
- throw UploadToHTTP("uploading to an HTTP binary cache is not supported");
+ auto req = DownloadRequest(cacheUri + "/" + path);
+ req.data = std::make_shared<string>(data); // FIXME: inefficient
+ req.mimeType = mimeType;
+ try {
+ getDownloader()->download(req);
+ } catch (DownloadError & e) {
+ throw UploadToHTTP(format("uploading to HTTP binary cache at %1% not supported: %2%") % cacheUri % e.msg());
+ }
}
void getFile(const std::string & path,
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index d35cd1a94..30bef3a79 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -19,7 +19,7 @@ namespace nix {
/* Nix store and database schema version. Version 1 (or 0) was Nix <=
0.7. Version 2 was Nix 0.8 and 0.9. Version 3 is Nix 0.10.
Version 4 is Nix 0.11. Version 5 is Nix 0.12-0.16. Version 6 is
- Nix 1.0. Version 7 is Nix 1.3. Version 10 is 1.12. */
+ Nix 1.0. Version 7 is Nix 1.3. Version 10 is 2.0. */
const int nixSchemaVersion = 10;
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index 77b41b6bf..8f0b65557 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -78,9 +78,22 @@ UDSRemoteStore::UDSRemoteStore(const Params & params)
}
+UDSRemoteStore::UDSRemoteStore(std::string socket_path, const Params & params)
+ : Store(params)
+ , LocalFSStore(params)
+ , RemoteStore(params)
+ , path(socket_path)
+{
+}
+
+
std::string UDSRemoteStore::getUri()
{
- return "daemon";
+ if (path) {
+ return std::string("unix://") + *path;
+ } else {
+ return "daemon";
+ }
}
@@ -98,7 +111,7 @@ ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
throw SysError("cannot create Unix domain socket");
closeOnExec(conn->fd.get());
- string socketPath = settings.nixDaemonSocketFile;
+ string socketPath = path ? *path : settings.nixDaemonSocketFile;
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
@@ -721,5 +734,14 @@ void RemoteStore::Connection::processStderr(Sink * sink, Source * source)
}
}
+static std::string uriScheme = "unix://";
+
+static RegisterStoreImplementation regStore([](
+ const std::string & uri, const Store::Params & params)
+ -> std::shared_ptr<Store>
+{
+ if (std::string(uri, 0, uriScheme.size()) != uriScheme) return 0;
+ return std::make_shared<UDSRemoteStore>(std::string(uri, uriScheme.size()), params);
+});
}
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 30c6beae6..7f36e2064 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -134,6 +134,7 @@ class UDSRemoteStore : public LocalFSStore, public RemoteStore
public:
UDSRemoteStore(const Params & params);
+ UDSRemoteStore(std::string path, const Params & params);
std::string getUri() override;
@@ -145,6 +146,7 @@ private:
};
ref<RemoteStore::Connection> openConnection() override;
+ std::experimental::optional<std::string> path;
};
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index bf0862ef1..563aa566b 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -192,7 +192,7 @@ struct ValidPathInfo
typedef list<ValidPathInfo> ValidPathInfos;
-enum BuildMode { bmNormal, bmRepair, bmCheck, bmHash };
+enum BuildMode { bmNormal, bmRepair, bmCheck };
struct BuildResult
@@ -248,6 +248,8 @@ public:
const Setting<int> pathInfoCacheSize{this, 65536, "path-info-cache-size", "size of the in-memory store path information cache"};
+ const Setting<bool> isTrusted{this, false, "trusted", "whether paths from this store can be used as substitutes even when they lack trusted signatures"};
+
protected:
struct State
@@ -705,6 +707,9 @@ void removeTempRoots();
* ‘daemon’: The Nix store accessed via a Unix domain socket
connection to nix-daemon.
+ * ‘unix://<path>’: The Nix store accessed via a Unix domain socket
+ connection to nix-daemon, with the socket located at <path>.
+
* ‘auto’ or ‘’: Equivalent to ‘local’ or ‘daemon’ depending on
whether the user has write access to the local Nix
store/database.
diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc
index 1b2494275..1581c282c 100755
--- a/src/nix-build/nix-build.cc
+++ b/src/nix-build/nix-build.cc
@@ -141,7 +141,7 @@ void mainWrapped(int argc, char * * argv)
else if (*arg == "--version")
printVersion(myName);
- else if (*arg == "--add-drv-link")
+ else if (*arg == "--add-drv-link" || *arg == "--indirect")
; // obsolete
else if (*arg == "--no-out-link" || *arg == "--no-link")
@@ -167,9 +167,6 @@ void mainWrapped(int argc, char * * argv)
buildMode = bmRepair;
}
- else if (*arg == "--hash")
- buildMode = bmHash;
-
else if (*arg == "--run-env") // obsolete
runEnv = true;
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index f6f276dd1..4fc3421c0 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -122,7 +122,6 @@ static void opRealise(Strings opFlags, Strings opArgs)
if (i == "--dry-run") dryRun = true;
else if (i == "--repair") buildMode = bmRepair;
else if (i == "--check") buildMode = bmCheck;
- else if (i == "--hash") buildMode = bmHash;
else if (i == "--ignore-unknown") ignoreUnknown = true;
else throw UsageError(format("unknown flag '%1%'") % i);
diff --git a/src/nix/command.hh b/src/nix/command.hh
index 6b34e3881..a7863c49f 100644
--- a/src/nix/command.hh
+++ b/src/nix/command.hh
@@ -5,6 +5,8 @@
namespace nix {
+extern std::string programPath;
+
struct Value;
class Bindings;
class EvalState;
diff --git a/src/nix/local.mk b/src/nix/local.mk
index bddd53b16..f76da1944 100644
--- a/src/nix/local.mk
+++ b/src/nix/local.mk
@@ -6,4 +6,6 @@ nix_SOURCES := $(wildcard $(d)/*.cc) $(wildcard src/linenoise/*.cpp)
nix_LIBS = libexpr libmain libstore libutil libformat
+nix_LDFLAGS = -pthread
+
$(eval $(call install-symlink, nix, $(bindir)/nix-hash))
diff --git a/src/nix/main.cc b/src/nix/main.cc
index 06bb8a1c3..8f6bbe8f5 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -16,6 +16,8 @@ void chrootHelper(int argc, char * * argv);
namespace nix {
+std::string programPath;
+
struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
{
NixArgs() : MultiCommand(*RegisterCommand::commands), MixCommonArgs("nix")
@@ -78,7 +80,8 @@ void mainWrapped(int argc, char * * argv)
initNix();
initGC();
- string programName = baseNameOf(argv[0]);
+ programPath = argv[0];
+ string programName = baseNameOf(programPath);
{
auto legacy = (*RegisterLegacyCommand::commands)[programName];
diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc
index fb9955190..252d12c5d 100644
--- a/src/nix/progress-bar.cc
+++ b/src/nix/progress-bar.cc
@@ -3,8 +3,9 @@
#include "sync.hh"
#include "store-api.hh"
-#include <map>
#include <atomic>
+#include <map>
+#include <thread>
namespace nix {
@@ -101,15 +102,28 @@ private:
Sync<State> state_;
+ std::thread updateThread;
+
+ std::condition_variable quitCV, updateCV;
+
public:
ProgressBar()
{
+ updateThread = std::thread([&]() {
+ auto state(state_.lock());
+ while (state->active) {
+ state.wait(updateCV);
+ draw(*state);
+ state.wait_for(quitCV, std::chrono::milliseconds(50));
+ }
+ });
}
~ProgressBar()
{
stop();
+ updateThread.join();
}
void stop()
@@ -121,6 +135,8 @@ public:
writeToStderr("\r\e[K");
if (status != "")
writeToStderr("[" + status + "]\n");
+ updateCV.notify_one();
+ quitCV.notify_one();
}
void log(Verbosity lvl, const FormatOrString & fs) override
@@ -132,7 +148,7 @@ public:
void log(State & state, Verbosity lvl, const std::string & s)
{
writeToStderr("\r\e[K" + s + ANSI_NORMAL "\n");
- update(state);
+ draw(state);
}
void startActivity(ActivityId act, Verbosity lvl, ActivityType type,
@@ -167,7 +183,12 @@ public:
if (type == actSubstitute) {
auto name = storePathToName(getS(fields, 0));
- i->s = fmt("fetching " ANSI_BOLD "%s" ANSI_NORMAL " from %s", name, getS(fields, 1));
+ auto sub = getS(fields, 1);
+ i->s = fmt(
+ hasPrefix(sub, "local")
+ ? "copying " ANSI_BOLD "%s" ANSI_NORMAL " from %s"
+ : "fetching " ANSI_BOLD "%s" ANSI_NORMAL " from %s",
+ name, sub);
}
if (type == actQueryPathInfo) {
@@ -180,7 +201,7 @@ public:
|| (type == actCopyPath && hasAncestor(*state, actSubstitute, parent)))
i->visible = false;
- update(*state);
+ update();
}
/* Check whether an activity has an ancestore with the specified
@@ -215,7 +236,7 @@ public:
state->its.erase(i);
}
- update(*state);
+ update();
}
void result(ActivityId act, ResultType type, const std::vector<Field> & fields) override
@@ -225,7 +246,7 @@ public:
if (type == resFileLinked) {
state->filesLinked++;
state->bytesLinked += getI(fields, 0);
- update(*state);
+ update();
}
else if (type == resBuildLogLine) {
@@ -238,25 +259,25 @@ public:
info.lastLine = lastLine;
state->activities.emplace_back(info);
i->second = std::prev(state->activities.end());
- update(*state);
+ update();
}
}
else if (type == resUntrustedPath) {
state->untrustedPaths++;
- update(*state);
+ update();
}
else if (type == resCorruptedPath) {
state->corruptedPaths++;
- update(*state);
+ update();
}
else if (type == resSetPhase) {
auto i = state->its.find(act);
assert(i != state->its.end());
i->second->phase = getS(fields, 0);
- update(*state);
+ update();
}
else if (type == resProgress) {
@@ -267,7 +288,7 @@ public:
actInfo.expected = getI(fields, 1);
actInfo.running = getI(fields, 2);
actInfo.failed = getI(fields, 3);
- update(*state);
+ update();
}
else if (type == resSetExpected) {
@@ -279,17 +300,16 @@ public:
state->activitiesByType[type].expected -= j;
j = getI(fields, 1);
state->activitiesByType[type].expected += j;
- update(*state);
+ update();
}
}
void update()
{
- auto state(state_.lock());
- update(*state);
+ updateCV.notify_one();
}
- void update(State & state)
+ void draw(State & state)
{
if (!state.active) return;
diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc
new file mode 100644
index 000000000..758bbbc68
--- /dev/null
+++ b/src/nix/upgrade-nix.cc
@@ -0,0 +1,131 @@
+#include "command.hh"
+#include "store-api.hh"
+#include "download.hh"
+#include "eval.hh"
+#include "attr-path.hh"
+
+using namespace nix;
+
+struct CmdUpgradeNix : StoreCommand
+{
+ Path profileDir;
+
+ CmdUpgradeNix()
+ {
+ mkFlag()
+ .longName("profile")
+ .shortName('p')
+ .labels({"profile-dir"})
+ .description("the Nix profile to upgrade")
+ .dest(&profileDir);
+ }
+
+ std::string name() override
+ {
+ return "upgrade-nix";
+ }
+
+ std::string description() override
+ {
+ return "upgrade Nix to the latest stable version";
+ }
+
+ Examples examples() override
+ {
+ return {
+ Example{
+ "To upgrade Nix to the latest stable version:",
+ "nix upgrade-nix"
+ },
+ Example{
+ "To upgrade Nix in a specific profile:",
+ "nix upgrade-nix -p /nix/var/nix/profiles/per-user/alice/profile"
+ },
+ };
+ }
+
+ void run(ref<Store> store) override
+ {
+ settings.pureEval = true;
+
+ if (profileDir == "")
+ profileDir = getProfileDir(store);
+
+ printInfo("upgrading Nix in profile '%s'", profileDir);
+
+ Path storePath;
+ {
+ Activity act(*logger, lvlInfo, actUnknown, "querying latest Nix version");
+ storePath = getLatestNix(store);
+ }
+
+ {
+ Activity act(*logger, lvlInfo, actUnknown, fmt("downloading '%s'...", storePath));
+ store->ensurePath(storePath);
+ }
+
+ {
+ Activity act(*logger, lvlInfo, actUnknown, fmt("verifying that '%s' works...", storePath));
+ auto program = storePath + "/bin/nix-env";
+ auto s = runProgram(program, false, {"--version"});
+ if (s.find("Nix") == std::string::npos)
+ throw Error("could not verify that '%s' works", program);
+ }
+
+ {
+ Activity act(*logger, lvlInfo, actUnknown, fmt("installing '%s' into profile '%s'...", storePath, profileDir));
+ runProgram(settings.nixBinDir + "/nix-env", false,
+ {"--profile", profileDir, "-i", storePath, "--no-sandbox"});
+ }
+ }
+
+ /* Return the profile in which Nix is installed. */
+ Path getProfileDir(ref<Store> store)
+ {
+ Path where;
+
+ for (auto & dir : tokenizeString<Strings>(getEnv("PATH"), ":"))
+ if (pathExists(dir + "/nix-env")) {
+ where = dir;
+ break;
+ }
+
+ if (where == "")
+ throw Error("couldn't figure out how Nix is installed, so I can't upgrade it");
+
+ printInfo("found Nix in '%s'", where);
+
+ if (hasPrefix(where, "/run/current-system"))
+ throw Error("Nix on NixOS must be upgraded via 'nixos-rebuild'");
+
+ Path profileDir;
+ Path userEnv;
+
+ if (baseNameOf(where) != "bin" ||
+ !hasSuffix(userEnv = canonPath(profileDir = dirOf(where), true), "user-environment"))
+ throw Error("directory '%s' does not appear to be part of a Nix profile", where);
+
+ if (!store->isValidPath(userEnv))
+ throw Error("directory '%s' is not in the Nix store", userEnv);
+
+ return profileDir;
+ }
+
+ /* Return the store path of the latest stable Nix. */
+ Path getLatestNix(ref<Store> store)
+ {
+ // FIXME: use nixos.org?
+ auto req = DownloadRequest("https://github.com/NixOS/nixpkgs/raw/master/nixos/modules/installer/tools/nix-fallback-paths.nix");
+ auto res = getDownloader()->download(req);
+
+ EvalState state(Strings(), store);
+ auto v = state.allocValue();
+ state.eval(state.parseExprFromString(*res.data, "/no-such-path"), *v);
+ Bindings & bindings(*state.allocBindings(0));
+ auto v2 = findAlongAttrPath(state, settings.thisSystem, bindings, *v);
+
+ return state.forceString(*v2);
+ }
+};
+
+static RegisterCommand r1(make_ref<CmdUpgradeNix>());
diff --git a/tests/common.sh.in b/tests/common.sh.in
index 186f9d6b9..195205988 100644
--- a/tests/common.sh.in
+++ b/tests/common.sh.in
@@ -11,7 +11,6 @@ export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
export NIX_STATE_DIR=$TEST_ROOT/var/nix
export NIX_CONF_DIR=$TEST_ROOT/etc
-export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests
export _NIX_TEST_SHARED=$TEST_ROOT/shared
if [[ -n $NIX_STORE ]]; then
export _NIX_TEST_NO_SANDBOX=1
diff --git a/tests/fixed.sh b/tests/fixed.sh
index cac3f0be9..8f51403a7 100644
--- a/tests/fixed.sh
+++ b/tests/fixed.sh
@@ -5,15 +5,22 @@ clearStore
export IMPURE_VAR1=foo
export IMPURE_VAR2=bar
+path=$(nix-store -q $(nix-instantiate fixed.nix -A good.0))
+
+echo 'testing bad...'
+nix-build fixed.nix -A bad --no-out-link && fail "should fail"
+
+# Building with the bad hash should produce the "good" output path as
+# a side-effect.
+[[ -e $path ]]
+nix path-info --json $path | grep fixed:md5:2qk15sxzzjlnpjk9brn7j8ppcd
+
echo 'testing good...'
nix-build fixed.nix -A good --no-out-link
echo 'testing good2...'
nix-build fixed.nix -A good2 --no-out-link
-echo 'testing bad...'
-nix-build fixed.nix -A bad --no-out-link && fail "should fail"
-
echo 'testing reallyBad...'
nix-instantiate fixed.nix -A reallyBad && fail "should fail"
diff --git a/tests/nix-copy-closure.nix b/tests/nix-copy-closure.nix
index 0bf5b42d8..be0a4a683 100644
--- a/tests/nix-copy-closure.nix
+++ b/tests/nix-copy-closure.nix
@@ -2,7 +2,7 @@
{ nixpkgs, system, nix }:
-with import (nixpkgs + /nixos/lib/testing.nix) { inherit system; };
+with import (nixpkgs + "/nixos/lib/testing.nix") { inherit system; };
makeTest (let pkgA = pkgs.cowsay; pkgB = pkgs.wget; pkgC = pkgs.hello; in {
diff --git a/tests/restricted.sh b/tests/restricted.sh
index 6c0392fac..0605383cc 100644
--- a/tests/restricted.sh
+++ b/tests/restricted.sh
@@ -36,3 +36,5 @@ ln -sfn $(pwd)/restricted.nix $TEST_ROOT/restricted.nix
(! nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I $TEST_ROOT)
(! nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I .)
nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I $TEST_ROOT -I .
+
+[[ $(nix eval --raw --restrict-eval -I . '(builtins.readFile "${import ./simple.nix}/hello")') == 'Hello World!' ]]
diff --git a/version b/version
index 35d51f33b..415b19fc3 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.12 \ No newline at end of file
+2.0 \ No newline at end of file