diff options
42 files changed, 428 insertions, 250 deletions
diff --git a/configure.ac b/configure.ac index c37f76870c55..fba53e81603c 100644 --- a/configure.ac +++ b/configure.ac @@ -171,6 +171,7 @@ NEED_PROG(bzip2, bzip2) AC_PATH_PROG(dot, dot) AC_PATH_PROG(dblatex, dblatex) AC_PATH_PROG(gzip, gzip) +AC_PATH_PROG(pv, pv, pv) # Test that Perl has the open/fork feature (Perl 5.8.0 and beyond). diff --git a/corepkgs/buildenv.nix b/corepkgs/buildenv.nix index 6e2bee10b1e7..641231dd9ee1 100644 --- a/corepkgs/buildenv.nix +++ b/corepkgs/buildenv.nix @@ -1,10 +1,10 @@ with import <nix/config.nix>; -{ system, derivations, manifest }: +{ derivations, manifest }: derivation { name = "user-environment"; - system = system; + system = builtins.currentSystem; builder = perl; args = [ "-w" ./buildenv.pl ]; diff --git a/corepkgs/nar.nix b/corepkgs/nar.nix index 70a4af2f9ddb..5be8be10c166 100644 --- a/corepkgs/nar.nix +++ b/corepkgs/nar.nix @@ -20,11 +20,12 @@ let in -{ system, storePath, hashAlgo }: +{ storePath, hashAlgo }: derivation { name = "nar"; + system = builtins.currentSystem; builder = shell; args = [ "-e" builder ]; - inherit system storePath hashAlgo; + inherit storePath hashAlgo; } diff --git a/corepkgs/unpack-channel.nix b/corepkgs/unpack-channel.nix index 5e6ccf23fd47..170f3ab07c77 100644 --- a/corepkgs/unpack-channel.nix +++ b/corepkgs/unpack-channel.nix @@ -1,11 +1,11 @@ with import <nix/config.nix>; -{ system, inputs }: +{ name, channelName, src }: derivation { - name = "channels"; + system = builtins.currentSystem; builder = shell; args = [ "-e" ./unpack-channel.sh ]; - inherit system inputs bzip2 tar tr; + inherit name channelName src bzip2 tar tr; PATH = "${nixBinDir}:${coreutils}"; } diff --git a/corepkgs/unpack-channel.sh b/corepkgs/unpack-channel.sh index 7c244a6a8552..f42b0870ae18 100644 --- a/corepkgs/unpack-channel.sh +++ b/corepkgs/unpack-channel.sh @@ -1,30 +1,4 @@ mkdir $out -mkdir $out/tmp -cd $out/tmp - -inputs=($inputs) -for ((n = 0; n < ${#inputs[*]}; n += 2)); do - channelName=${inputs[n]} - channelTarball=${inputs[n+1]} - - echo "unpacking channel $channelName" - - $bzip2 -d < $channelTarball | $tar xf - - - if test -e */channel-name; then - channelName="$(cat */channel-name)" - fi - - nr=1 - attrName=$(echo $channelName | $tr -- '- ' '__') - dirName=$attrName - while test -e ../$dirName; do - nr=$((nr+1)) - dirName=$attrName-$nr - done - - mv * ../$dirName # !!! hacky -done - -cd .. -rmdir tmp +cd $out +$bzip2 -d < $src | $tar xf - +mv * $out/$channelName diff --git a/doc/manual/Makefile.am b/doc/manual/Makefile.am index 55450c9a5990..33cb27e054bd 100644 --- a/doc/manual/Makefile.am +++ b/doc/manual/Makefile.am @@ -1,5 +1,5 @@ -XMLLINT = $(xmllint) $(xmlflags) -XSLTPROC = $(xsltproc) $(xmlflags) \ +XMLLINT = $(xmllint) --nonet $(xmlflags) +XSLTPROC = $(xsltproc) --nonet $(xmlflags) \ --param section.autolabel 1 \ --param section.label.includes.component.label 1 \ --param html.stylesheet \'style.css\' \ @@ -29,29 +29,41 @@ MANUAL_SRCS = manual.xml introduction.xml installation.xml \ package-management.xml writing-nix-expressions.xml builtins.xml \ build-farm.xml \ $(man1_MANS:.1=.xml) $(man8_MANS:.8=.xml) \ - troubleshooting.xml bugs.xml opt-common.xml opt-common-syn.xml \ + troubleshooting.xml bugs.xml opt-common.xml opt-common-syn.xml opt-inst-syn.xml \ env-common.xml quick-start.xml nix-lang-ref.xml glossary.xml \ conf-file.xml release-notes.xml \ style.css images +# Do XInclude processing. +manual.xmli: $(MANUAL_SRCS) version.txt + $(XMLLINT) --xinclude $< -o $@.tmp + mv $@.tmp $@ + # Note: RelaxNG validation requires xmllint >= 2.7.4. -manual.is-valid: $(MANUAL_SRCS) version.txt - $(XMLLINT) --noout --nonet --xinclude --noxincludenode --relaxng $(docbookrng)/docbook.rng $< +manual.is-valid: manual.xmli + $(XSLTPROC) --novalid --stringparam profile.condition manual \ + $(docbookxsl)/profiling/profile.xsl $< 2> /dev/null | \ + $(XMLLINT) --noout --relaxng $(docbookrng)/docbook.rng - touch $@ version.txt: echo -n $(VERSION) > version.txt -man $(MANS): $(MANUAL_SRCS) manual.is-valid - $(XSLTPROC) --nonet --xinclude $(docbookxsl)/manpages/docbook.xsl manual.xml +man $(MANS): manual.is-valid + $(XSLTPROC) --stringparam profile.condition manpage \ + $(docbookxsl)/profiling/profile.xsl manual.xmli 2> /dev/null | \ + $(XSLTPROC) $(docbookxsl)/manpages/docbook.xsl - manual.html: $(MANUAL_SRCS) manual.is-valid images - $(XSLTPROC) --nonet --xinclude --output manual.html \ - $(docbookxsl)/html/docbook.xsl manual.xml + $(XSLTPROC) --xinclude --stringparam profile.condition manual \ + $(docbookxsl)/profiling/profile.xsl manual.xml | \ + $(XSLTPROC) --output manual.html $(docbookxsl)/html/docbook.xsl - manual.pdf: $(MANUAL_SRCS) manual.is-valid images if test "$(dblatex)" != ""; then \ - $(dblatex) $(dblatex_opts) manual.xml; \ + $(XSLTPROC) --xinclude --stringparam profile.condition manual \ + $(docbookxsl)/profiling/profile.xsl manual.xml | \ + $(dblatex) -o manual.pdf $(dblatex_opts) -; \ else \ echo "Please install dblatex and rerun configure."; \ exit 1; \ @@ -64,12 +76,12 @@ NEWS_OPTS = \ --stringparam header.rule 0 NEWS.html: release-notes.xml - $(XSLTPROC) --nonet --xinclude --output $@ $(NEWS_OPTS) \ + $(XSLTPROC) --xinclude --output $@ $(NEWS_OPTS) \ $(docbookxsl)/html/docbook.xsl release-notes.xml NEWS.txt: release-notes.xml - $(XSLTPROC) --nonet --xinclude quote-literals.xsl release-notes.xml | \ - $(XSLTPROC) --nonet --output $@.tmp.html $(NEWS_OPTS) \ + $(XSLTPROC) --xinclude quote-literals.xsl release-notes.xml | \ + $(XSLTPROC) --output $@.tmp.html $(NEWS_OPTS) \ $(docbookxsl)/html/docbook.xsl - LANG=en_US $(w3m) -dump $@.tmp.html > $@ rm $@.tmp.html @@ -96,7 +108,7 @@ images: cp $(docbookxsl)/images/callouts/*.gif images/callouts chmod -R +w images -KEEP = manual.html manual.is-valid version.txt $(MANS) NEWS.html NEWS.txt +KEEP = manual.html manual.xmli manual.is-valid version.txt $(MANS) NEWS.html NEWS.txt EXTRA_DIST = $(MANUAL_SRCS) $(FIGURES) $(KEEP) diff --git a/doc/manual/env-common.xml b/doc/manual/env-common.xml index 99acc5949044..f52e2633de78 100644 --- a/doc/manual/env-common.xml +++ b/doc/manual/env-common.xml @@ -7,7 +7,7 @@ <para>Most Nix commands interpret the following environment variables:</para> -<variablelist> +<variablelist xml:id="env-common"> <varlistentry><term><envar>NIX_IGNORE_SYMLINK_STORE</envar></term> diff --git a/doc/manual/installation.xml b/doc/manual/installation.xml index 15c156dab5e7..5e29abe9f5f8 100644 --- a/doc/manual/installation.xml +++ b/doc/manual/installation.xml @@ -47,17 +47,17 @@ for Red Hat, SuSE, and Fedora Core are also available.</para> <para>Alternatively, the most recent sources of Nix can be obtained from its <link -xlink:href="https://svn.nixos.org/repos/nix/nix/trunk">Subversion +xlink:href="https://github.com/NixOS/nix">git repository</link>. For example, the following command will check out the latest revision into a directory called <filename>nix</filename>:</para> <screen> -$ svn checkout https://svn.nixos.org/repos/nix/nix/trunk nix</screen> +$ git clone https://github.com/NixOS/nix</screen> <para>Likewise, specific releases can be obtained from the <link -xlink:href="https://svn.nixos.org/repos/nix/nix/tags">tags -directory</link> of the repository.</para> +xlink:href="https://github.com/NixOS/nix/tags">tags +</link> of the repository.</para> </section> diff --git a/doc/manual/manual.xml b/doc/manual/manual.xml index 95f80686008d..fa80a3651dcf 100644 --- a/doc/manual/manual.xml +++ b/doc/manual/manual.xml @@ -14,8 +14,7 @@ <surname>Dolstra</surname> </personname> <affiliation> - <orgname>Delft University of Technology</orgname> - <orgdiv>Department of Software Technology</orgdiv> + <orgname>LogicBlox</orgname> </affiliation> <contrib>Author</contrib> </author> diff --git a/doc/manual/nix-build.xml b/doc/manual/nix-build.xml index 465635f67125..e3508d92ce0e 100644 --- a/doc/manual/nix-build.xml +++ b/doc/manual/nix-build.xml @@ -75,11 +75,11 @@ or renamed. So don’t rename the symlink.</para></warning> <refsection><title>Options</title> -<para>See also <xref linkend="sec-common-options" />. All options not -listed here are passed to <command>nix-store --realise</command>, -except for <option>--arg</option> and <option>--attr</option> / -<option>-A</option> which are passed to -<command>nix-instantiate</command>.</para> +<para>All options not listed here are passed to <command>nix-store +--realise</command>, except for <option>--arg</option> and +<option>--attr</option> / <option>-A</option> which are passed to +<command>nix-instantiate</command>. <phrase condition="manual">See +also <xref linkend="sec-common-options" />.</phrase></para> <variablelist> @@ -122,6 +122,10 @@ except for <option>--arg</option> and <option>--attr</option> / </variablelist> +<variablelist condition="manpage"> + <xi:include href="opt-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='opt-common']/*)" /> +</variablelist> + </refsection> @@ -141,4 +145,13 @@ firefox firefox-config</screen> </refsection> +<refsection condition="manpage"><title>Environment variables</title> + +<variablelist> + <xi:include href="env-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='env-common']/*)" /> +</variablelist> + +</refsection> + + </refentry> diff --git a/doc/manual/nix-channel.xml b/doc/manual/nix-channel.xml index 024add8601e8..22d8900d8f1c 100644 --- a/doc/manual/nix-channel.xml +++ b/doc/manual/nix-channel.xml @@ -19,7 +19,7 @@ <cmdsynopsis> <command>nix-channel</command> <group choice='req'> - <arg choice='plain'><option>--add</option> <replaceable>url</replaceable></arg> + <arg choice='plain'><option>--add</option> <replaceable>url</replaceable> <arg choice='opt'><replaceable>name</replaceable></arg></arg> <arg choice='plain'><option>--remove</option> <replaceable>url</replaceable></arg> <arg choice='plain'><option>--list</option></arg> <arg choice='plain'><option>--update</option></arg> @@ -31,32 +31,39 @@ <para>A Nix channel is mechanism that allows you to automatically stay up-to-date with a set of pre-built Nix expressions. A Nix channel is -just a URL that points to a place that contains a set of Nix -expressions, as well as a <command>nix-push</command> manifest. See -also <xref linkend="sec-channels" />.</para> +just a URL that points to a place containing a set of Nix expressions +and a <command>nix-push</command> manifest. <phrase +condition="manual">See also <xref linkend="sec-channels" +/>.</phrase></para> <para>This command has the following operations: <variablelist> - <varlistentry><term><option>--add</option> <replaceable>url</replaceable></term> + <varlistentry><term><option>--add</option> <replaceable>url</replaceable> [<replaceable>name</replaceable>]</term> - <listitem><para>Adds <replaceable>url</replaceable> to the list of - subscribed channels.</para></listitem> + <listitem><para>Adds a channel named + <replaceable>name</replaceable> with URL + <replaceable>url</replaceable> to the list of subscribed channels. + If <replaceable>name</replaceable> is omitted, it defaults to the + last component of <replaceable>url</replaceable>, with the + suffixes <literal>-stable</literal> or + <literal>-unstable</literal> removed.</para></listitem> </varlistentry> - <varlistentry><term><option>--remove</option> <replaceable>url</replaceable></term> + <varlistentry><term><option>--remove</option> <replaceable>name</replaceable></term> - <listitem><para>Removes <replaceable>url</replaceable> from the - list of subscribed channels.</para></listitem> + <listitem><para>Removes the channel named + <replaceable>name</replaceable> from the list of subscribed + channels.</para></listitem> </varlistentry> <varlistentry><term><option>--list</option></term> - <listitem><para>Prints the URLs of all subscribed channels on - standard output.</para></listitem> + <listitem><para>Prints the names and URLs of all subscribed + channels on standard output.</para></listitem> </varlistentry> @@ -64,7 +71,7 @@ also <xref linkend="sec-channels" />.</para> <listitem><para>Downloads the Nix expressions of all subscribed channels, makes them the default for <command>nix-env</command> - operations (by symlinking them in the directory + operations (by symlinking them from the directory <filename>~/.nix-defexpr</filename>), and performs a <command>nix-pull</command> on the manifests of all channels to make pre-built binaries available.</para></listitem> @@ -75,8 +82,8 @@ also <xref linkend="sec-channels" />.</para> </para> -<para>Note that <option>--add</option> and <option>--remove</option> -do not automatically perform an update.</para> +<para>Note that <option>--add</option> does not automatically perform +an update.</para> <para>The list of subscribed channels is stored in <filename>~/.nix-channels</filename>.</para> @@ -90,4 +97,15 @@ respectively.</para> </refsection> +<refsection><title>Examples</title> + +<para>To subscribe to the Nixpkgs channel and install the GNU Hello package:</para> + +<screen> +$ nix-channel --add http://nixos.org/releases/nixpkgs/channels/nixpkgs-unstable +$ nix-channel --update +$ nix-env -iA nixpkgs.hello</screen> + +</refsection> + </refentry> diff --git a/doc/manual/nix-copy-closure.xml b/doc/manual/nix-copy-closure.xml index 45cfc0f34245..4b5ce755c67d 100644 --- a/doc/manual/nix-copy-closure.xml +++ b/doc/manual/nix-copy-closure.xml @@ -26,6 +26,7 @@ <arg><option>--gzip</option></arg> <arg><option>--bzip2</option></arg> <arg><option>--xz</option></arg> + <arg><option>--show-progress</option></arg> <arg><option>--include-outputs</option></arg> <arg choice='plain'> <replaceable>user@</replaceable><replaceable>machine</replaceable> @@ -110,6 +111,13 @@ 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 included diff --git a/doc/manual/nix-env.xml b/doc/manual/nix-env.xml index a03afaf5c007..02a51c6e9006 100644 --- a/doc/manual/nix-env.xml +++ b/doc/manual/nix-env.xml @@ -18,7 +18,7 @@ <refsynopsisdiv> <cmdsynopsis> <command>nix-env</command> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="opt-common-syn.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(/db:nop/*)" /> + <xi:include href="opt-common-syn.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(/db:nop/*)" /> <arg><option>--arg</option> <replaceable>name</replaceable> <replaceable>value</replaceable></arg> <arg><option>--argstr</option> <replaceable>name</replaceable> <replaceable>value</replaceable></arg> <arg> @@ -71,8 +71,8 @@ be performed. These are documented below.</para> <para>This section lists the options that are common to all operations. These options are allowed for every subcommand, though -they may not always have an effect. See also <xref -linkend="sec-common-options" />.</para> +they may not always have an effect. <phrase condition="manual">See +also <xref linkend="sec-common-options" />.</phrase></para> <variablelist> @@ -121,16 +121,18 @@ linkend="sec-common-options" />.</para> <varlistentry><term><option>--system-filter</option> <replaceable>system</replaceable></term> <listitem><para>By default, operations such as <option>--query - --available</option> only include derivations matching the current - platform. This option allows you to use derivations for the - specified platform <replaceable>system</replaceable>. The special - value <literal>*</literal> causes derivations for any platform to - be included.</para></listitem> + --available</option> show derivations matching any platform. This + option allows you to use derivations for the specified platform + <replaceable>system</replaceable>.</para></listitem> </varlistentry> </variablelist> +<variablelist condition="manpage"> + <xi:include href="opt-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='opt-common']/*)" /> +</variablelist> + </refsection> @@ -1250,5 +1252,13 @@ error: no generation older than the current (91) exists</screen> </refsection> +<refsection condition="manpage"><title>Environment variables</title> + +<variablelist> + <xi:include href="env-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='env-common']/*)" /> +</variablelist> + +</refsection> + </refentry> diff --git a/doc/manual/nix-instantiate.xml b/doc/manual/nix-instantiate.xml index ba89af425586..618b61f159dc 100644 --- a/doc/manual/nix-instantiate.xml +++ b/doc/manual/nix-instantiate.xml @@ -36,6 +36,7 @@ <option>--eval-only</option> <arg><option>--strict</option></arg> </arg> + <arg choice='plain'><option>--find-file</option></arg> </group> <arg><option>--xml</option></arg> </arg> @@ -49,8 +50,9 @@ <para>The command <command>nix-instantiate</command> generates <link linkend="gloss-derivation">store derivations</link> from (high-level) Nix expressions. It loads and evaluates the Nix expressions in each -of <replaceable>files</replaceable>. Each top-level expression should -evaluate to a derivation, a list of derivations, or a set of +of <replaceable>files</replaceable> (which defaults to +<replaceable>./default.nix</replaceable>). Each top-level expression +should evaluate to a derivation, a list of derivations, or a set of derivations. The paths of the resulting store derivations are printed on standard output.</para> @@ -64,8 +66,8 @@ store derivation instantiation from Nix expressions automatically). It is most commonly used for implementing new deployment policies.</para> -<para>See also <xref linkend="sec-common-options" /> for a list of -common options.</para> +<para condition="manual">See also <xref linkend="sec-common-options" +/> for a list of common options.</para> </refsection> @@ -100,6 +102,19 @@ common options.</para> </varlistentry> + <varlistentry><term><option>--find-file</option></term> + + <listitem><para>Look up the given files in Nix’s search path (as + specified by the <envar>NIX_PATH</envar> environment variable). + If found, print the corresponding absolute paths on standard + output. For instance, if <envar>NIX_PATH</envar> is + <literal>nixpkgs=/home/alice/nixpkgs</literal>, then + <literal>nix-instantiate --find-file nixpkgs/default.nix</literal> + will print + <literal>/home/alice/nixpkgs/default.nix</literal>.</para></listitem> + + </varlistentry> + <varlistentry><term><option>--xml</option></term> <listitem><para>When used with <option>--parse-only</option> and @@ -127,6 +142,10 @@ common options.</para> </variablelist> +<variablelist condition="manpage"> + <xi:include href="opt-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='opt-common']/*)" /> +</variablelist> + </refsection> @@ -198,4 +217,13 @@ $ echo 'rec { x = "foo"; y = x; }' | nix-instantiate --eval-only --xml --strict </refsection> +<refsection condition="manpage"><title>Environment variables</title> + +<variablelist> + <xi:include href="env-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='env-common']/*)" /> +</variablelist> + +</refsection> + + </refentry> diff --git a/doc/manual/nix-store.xml b/doc/manual/nix-store.xml index a32559c033f4..6cc765bf27ca 100644 --- a/doc/manual/nix-store.xml +++ b/doc/manual/nix-store.xml @@ -48,8 +48,9 @@ be performed. These are documented below.</para> <para>This section lists the options that are common to all operations. These options are allowed for every subcommand, though -they may not always have an effect. See also <xref -linkend="sec-common-options" /> for a list of common options.</para> +they may not always have an effect. <phrase condition="manual">See +also <xref linkend="sec-common-options" /> for a list of common +options.</phrase></para> <variablelist> @@ -57,8 +58,9 @@ linkend="sec-common-options" /> for a list of common options.</para> <listitem><para>Causes the result of a realisation (<option>--realise</option> and <option>--force-realise</option>) - to be registered as a root of the garbage collector (see <xref - linkend="ssec-gc-roots" />). The root is stored in + to be registered as a root of the garbage collector<phrase + condition="manual"> (see <xref linkend="ssec-gc-roots" + />)</phrase>. The root is stored in <replaceable>path</replaceable>, which must be inside a directory that is scanned for roots by the garbage collector (i.e., typically in a subdirectory of @@ -112,6 +114,10 @@ lrwxrwxrwx 1 ... 2005-03-13 21:10 /home/eelco/bla/result -> /nix/store/1r1134 </variablelist> +<variablelist condition="manpage"> + <xi:include href="opt-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='opt-common']/*)" /> +</variablelist> + </refsection> @@ -212,7 +218,6 @@ linkend="sec-nix-build"><command>nix-build</command></link> does.</para> <arg choice='plain'><option>--delete</option></arg> </group> <arg><option>--max-freed</option> <replaceable>bytes</replaceable></arg> - <arg><option>--max-links</option> <replaceable>nrlinks</replaceable></arg> </cmdsynopsis> </refsection> @@ -280,16 +285,6 @@ options control what gets deleted and in what order: </varlistentry> - <varlistentry><term><option>--max-links</option> <replaceable>nrlinks</replaceable></term> - - <listitem><para>Keep deleting paths until the hard link count on - <filename>/nix/store</filename> is less than - <replaceable>nrlinks</replaceable>, then stop. This is useful for - very large Nix stores on filesystems with a 32000 subdirectories - limit (like <literal>ext3</literal>).</para></listitem> - - </varlistentry> - </variablelist> </para> @@ -1053,7 +1048,7 @@ backups and when migrating to different database schemas.</para> <!--######################################################################--> -<refsection><title>Operation <option>--dump-db</option></title> +<refsection><title>Operation <option>--load-db</option></title> <refsection> <title>Synopsis</title> @@ -1074,4 +1069,13 @@ loads it into the Nix database.</para> </refsection> +<refsection condition="manpage"><title>Environment variables</title> + +<variablelist> + <xi:include href="env-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='env-common']/*)" /> +</variablelist> + +</refsection> + + </refentry> diff --git a/doc/manual/opt-common.xml b/doc/manual/opt-common.xml index c36c6df41003..92b76c01f103 100644 --- a/doc/manual/opt-common.xml +++ b/doc/manual/opt-common.xml @@ -5,7 +5,7 @@ <para>Most Nix commands accept the following command-line options:</para> -<variablelist> +<variablelist xml:id="opt-common"> <varlistentry><term><option>--help</option></term> diff --git a/perl/lib/Nix/CopyClosure.pm b/perl/lib/Nix/CopyClosure.pm index 08573b2ab1f1..79c6dfcccbf4 100644 --- a/perl/lib/Nix/CopyClosure.pm +++ b/perl/lib/Nix/CopyClosure.pm @@ -6,11 +6,12 @@ use Nix::Store; sub copyTo { - my ($sshHost, $sshOpts, $storePaths, $compressor, $decompressor, $includeOutputs, $dryRun, $sign) = @_; + my ($sshHost, $sshOpts, $storePaths, $compressor, $decompressor, $includeOutputs, $dryRun, $sign, $progressViewer) = @_; $compressor = "$compressor |" if $compressor ne ""; $decompressor = "$decompressor |" if $decompressor ne ""; - + $progressViewer = "$progressViewer |" if $progressViewer ne ""; + # Get the closure of this path. my @closure = reverse(topoSortPaths(computeFSClosure(0, $includeOutputs, map { followLinksToStorePath $_ } @{$storePaths}))); @@ -34,7 +35,7 @@ sub copyTo { if (scalar @missing > 0) { print STDERR "copying ", scalar @missing, " missing paths to ‘$sshHost’...\n"; unless ($dryRun) { - open SSH, "| $compressor ssh $sshHost @{$sshOpts} '$decompressor nix-store --import' > /dev/null" or die; + open SSH, "| $compressor $progressViewer ssh $sshHost @{$sshOpts} '$decompressor nix-store --import' > /dev/null" or die; exportPaths(fileno(SSH), $sign, @missing); close SSH or die "copying store paths to remote machine `$sshHost' failed: $?"; } diff --git a/perl/lib/Nix/Manifest.pm b/perl/lib/Nix/Manifest.pm index 909604a44938..532a900978f2 100644 --- a/perl/lib/Nix/Manifest.pm +++ b/perl/lib/Nix/Manifest.pm @@ -343,10 +343,10 @@ EOF my $version = readManifest_($manifest, \&addNARToDB, \&addPatchToDB); if ($version < 3) { - die "you have an old-style or corrupt manifest `$manifestLink'; please delete it"; + die "you have an old-style or corrupt manifest `$manifestLink'; please delete it\n"; } if ($version >= 10) { - die "manifest `$manifestLink' is too new; please delete it or upgrade Nix"; + die "manifest `$manifestLink' is too new; please delete it or upgrade Nix\n"; } } diff --git a/release.nix b/release.nix index 6b571644d994..3f4c4876123f 100644 --- a/release.nix +++ b/release.nix @@ -19,7 +19,7 @@ let inherit officialRelease; buildInputs = - [ curl bison24 flex2535 perl libxml2 libxslt w3m bzip2 + [ curl bison25 flex2535 perl libxml2 libxslt w3m bzip2 tetex dblatex nukeReferences pkgconfig sqlite git ]; diff --git a/scripts/nix-build.in b/scripts/nix-build.in index b36ec0208b41..35b186bb715d 100755 --- a/scripts/nix-build.in +++ b/scripts/nix-build.in @@ -14,6 +14,10 @@ my @instArgs = (); my @buildArgs = (); my @exprs = (); +my $shell = $ENV{SHELL} || "/bin/sh"; +my $envCommand = "p=\$PATH; source \$stdenv/setup; PATH=\$PATH:\$p; exec $shell"; +my @envExclude = (); + my $tmpDir = tempdir("nix-build.XXXXXX", CLEANUP => 1, TMPDIR => 1) or die "cannot create a temporary directory"; @@ -41,7 +45,12 @@ Flags: --drv-link NAME: create symlink NAME instead of `derivation' --no-out-link: do not create the `result' symlink --out-link / -o NAME: create symlink NAME instead of `result' - --attr ATTR: select a specific attribution from the Nix expression + --attr / -A ATTR: select a specific attribute from the Nix expression + + --run-env: build dependencies of the specified derivation, then start a + shell with the environment of the derivation + --command: command to run with `--run-env' + --exclude: regexp specifying dependencies to be excluded by `--run-env' Any additional flags are passed to `nix-store'. EOF @@ -125,6 +134,18 @@ EOF $runEnv = 1; } + elsif ($arg eq "--command") { + $n++; + die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV; + $envCommand = $ARGV[$n]; + } + + elsif ($arg eq "--exclude") { + $n++; + die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV; + push @envExclude, $ARGV[$n]; + } + elsif (substr($arg, 0, 1) eq "-") { push @buildArgs, $arg; } @@ -155,7 +176,8 @@ foreach my $expr (@exprs) { my $drv = derivationFromPath($drvPath); # Build or fetch all dependencies of the derivation. - system("$Nix::Config::binDir/nix-store -r @buildArgs @{$drv->{inputDrvs}} @{$drv->{inputSrcs}} > /dev/null") == 0 + my @inputDrvs = grep { my $x = $_; (grep { $x =~ $_ } @envExclude) == 0 } @{$drv->{inputDrvs}}; + system("$Nix::Config::binDir/nix-store -r @buildArgs @inputDrvs @{$drv->{inputSrcs}} > /dev/null") == 0 or die "$0: failed to build all dependencies\n"; # Set the environment. @@ -168,7 +190,7 @@ foreach my $expr (@exprs) { # convenience, source $stdenv/setup to setup additional # environment variables. Also don't lose the current $PATH # directories. - exec($ENV{SHELL}, "-c", "p=\$PATH; source \$stdenv/setup; PATH=\$PATH:\$p; exec $ENV{SHELL}"); + exec($ENV{SHELL}, "-c", $envCommand); die; } diff --git a/scripts/nix-channel.in b/scripts/nix-channel.in index ebfc246cfa30..524ffa656451 100755 --- a/scripts/nix-channel.in +++ b/scripts/nix-channel.in @@ -1,6 +1,8 @@ #! @perl@ -w @perlFlags@ use strict; +use File::Basename; +use File::Path qw(make_path); use Nix::Config; my $manifestDir = $Nix::Config::manifestDir; @@ -11,67 +13,67 @@ my $channelCache = "$Nix::Config::stateDir/channel-cache"; mkdir $channelCache, 0755 unless -e $channelCache; $ENV{'NIX_DOWNLOAD_CACHE'} = $channelCache if -W $channelCache; - # Figure out the name of the `.nix-channels' file to use. -my $home = $ENV{"HOME"}; -die '$HOME not set' unless defined $home; +my $home = $ENV{"HOME"} or die '$HOME not set\n'; my $channelsList = "$home/.nix-channels"; - my $nixDefExpr = "$home/.nix-defexpr"; - -my @channels; +# Figure out the name of the channels profile. +my $userName = getpwuid($<) or die "cannot figure out user name"; +my $profile = "$Nix::Config::stateDir/profiles/per-user/$userName/channels"; +make_path(dirname $profile, mode => 0755); + +my %channels; -# Reads the list of channels from the file $channelsList; +# Reads the list of channels. sub readChannels { return if (!-f $channelsList); open CHANNELS, "<$channelsList" or die "cannot open `$channelsList': $!"; while (<CHANNELS>) { chomp; next if /^\s*\#/; - push @channels, $_; + my ($url, $name) = split ' ', $_; + $url =~ s/\/*$//; # remove trailing slashes + $name = basename $url unless defined $name; + $channels{$name} = $url; } close CHANNELS; } -# Writes the list of channels to the file $channelsList; +# Writes the list of channels. sub writeChannels { open CHANNELS, ">$channelsList" or die "cannot open `$channelsList': $!"; - foreach my $url (@channels) { - print CHANNELS "$url\n"; + foreach my $name (keys %channels) { + print CHANNELS "$channels{$name} $name\n"; } close CHANNELS; } -# Adds a channel to the file $channelsList; +# Adds a channel. sub addChannel { - my $url = shift; + my ($url, $name) = @_; readChannels; - foreach my $url2 (@channels) { - return if $url eq $url2; - } - push @channels, $url; + $channels{$name} = $url; writeChannels; } -# Remove a channel from the file $channelsList; +# Remove a channel. sub removeChannel { - my $url = shift; - my @left = (); + my ($name) = @_; readChannels; - foreach my $url2 (@channels) { - push @left, $url2 if $url ne $url2; - } - @channels = @left; + delete $channels{$name}; writeChannels; + + system("$Nix::Config::binDir/nix-env --profile '$profile' -e '$name'") == 0 + or die "cannot remove channel `$name'"; } -# Fetch Nix expressions and pull cache manifests from the subscribed +# Fetch Nix expressions and pull manifests from the subscribed # channels. sub update { readChannels; @@ -82,64 +84,62 @@ sub update { # Do we have write permission to the manifests directory? die "$0: you do not have write permission to `$manifestDir'!\n" unless -W $manifestDir; - # Pull cache manifests. - foreach my $url (@channels) { - #print "pulling cache manifest from `$url'\n"; + # Download each channel. + my $exprs = ""; + foreach my $name (keys %channels) { + my $url = $channels{$name}; + my $origUrl = "$url/MANIFEST"; + + # Check if $url is a redirect. If so, follow it now to ensure + # consistency if the redirection is changed between + # downloading the manifest and the tarball. + my $headers = `$Nix::Config::curl --silent --head '$url'`; + die "$0: unable to check `$url'\n" if $? != 0; + $headers =~ s/\r//g; + $url = $1 if $headers =~ /^Location:\s*(.*)\s*$/m; + + # Pull the channel manifest. + $ENV{'NIX_ORIG_URL'} = $origUrl; system("$Nix::Config::binDir/nix-pull", "--skip-wrong-store", "$url/MANIFEST") == 0 - or die "cannot pull cache manifest from `$url'"; - } - - # Create a Nix expression that fetches and unpacks the channel Nix - # expressions. - - my $inputs = "["; - foreach my $url (@channels) { - $url =~ /\/([^\/]+)\/?$/; - my $channelName = $1; - $channelName = "unnamed" unless defined $channelName; + or die "cannot pull manifest from `$url'\n"; + # Download the channel tarball. my $fullURL = "$url/nixexprs.tar.bz2"; - print "downloading Nix expressions from `$fullURL'...\n"; - $ENV{"PRINT_PATH"} = 1; - $ENV{"QUIET"} = 1; - my ($hash, $path) = `$Nix::Config::binDir/nix-prefetch-url '$fullURL'`; + print STDERR "downloading Nix expressions from `$fullURL'...\n"; + my ($hash, $path) = `PRINT_PATH=1 QUIET=1 $Nix::Config::binDir/nix-prefetch-url '$fullURL'`; die "cannot fetch `$fullURL'" if $? != 0; chomp $path; - $inputs .= '"' . $channelName . '"' . " " . $path . " "; - } - $inputs .= "]"; - # Figure out a name for the GC root. - my $userName = getpwuid($<); - die "who ARE you? go away" unless defined $userName; + # If the URL contains a version number, append it to the name + # attribute (so that "nix-env -q" on the channels profile + # shows something useful). + my $cname = $name; + $cname .= $1 if basename($url) =~ /(-\d.*)$/; - my $rootFile = "$Nix::Config::stateDir/gcroots/per-user/$userName/channels"; - - # Build the Nix expression. - print "unpacking channel Nix expressions...\n"; - my $outPath = `\\ - $Nix::Config::binDir/nix-build --out-link '$rootFile' --drv-link '$rootFile'.tmp \\ - '<nix/unpack-channel.nix>' \\ - --argstr system @system@ --arg inputs '$inputs'` - or die "cannot unpack the channels"; - chomp $outPath; + $exprs .= "'f: f { name = \"$cname\"; channelName = \"$name\"; src = builtins.storePath \"$path\"; }' "; + } - unlink "$rootFile.tmp"; + # Unpack the channel tarballs into the Nix store and install them + # into the channels profile. + print STDERR "unpacking channels...\n"; + system("$Nix::Config::binDir/nix-env --profile '$profile' " . + "-f '<nix/unpack-channel.nix>' -i -E $exprs --quiet") == 0 + or die "cannot unpack the channels"; # Make the channels appear in nix-env. unlink $nixDefExpr if -l $nixDefExpr; # old-skool ~/.nix-defexpr mkdir $nixDefExpr or die "cannot create directory `$nixDefExpr'" if !-e $nixDefExpr; my $channelLink = "$nixDefExpr/channels"; unlink $channelLink; # !!! not atomic - symlink($outPath, $channelLink) or die "cannot symlink `$channelLink' to `$outPath'"; + symlink($profile, $channelLink) or die "cannot symlink `$channelLink' to `$profile'"; } sub usageError { print STDERR <<EOF; Usage: - nix-channel --add URL - nix-channel --remove URL + nix-channel --add URL [CHANNEL-NAME] + nix-channel --remove CHANNEL-NAME nix-channel --list nix-channel --update EOF @@ -154,22 +154,29 @@ while (scalar @ARGV) { my $arg = shift @ARGV; if ($arg eq "--add") { - usageError if scalar @ARGV != 1; - addChannel (shift @ARGV); + usageError if scalar @ARGV < 1 || scalar @ARGV > 2; + my $url = shift @ARGV; + my $name = shift @ARGV; + unless (defined $name) { + $name = basename $url; + $name =~ s/-unstable//; + $name =~ s/-stable//; + } + addChannel($url, $name); last; } if ($arg eq "--remove") { usageError if scalar @ARGV != 1; - removeChannel (shift @ARGV); + removeChannel(shift @ARGV); last; } if ($arg eq "--list") { usageError if scalar @ARGV != 0; readChannels; - foreach my $url (@channels) { - print "$url\n"; + foreach my $name (keys %channels) { + print "$name $channels{$name}\n"; } last; } diff --git a/scripts/nix-copy-closure.in b/scripts/nix-copy-closure.in index 1ed24d285208..12a83cff979c 100755 --- a/scripts/nix-copy-closure.in +++ b/scripts/nix-copy-closure.in @@ -23,6 +23,8 @@ my $sign = 0; my $compressor = ""; my $decompressor = ""; +my $progressViewer = ""; + my $toMode = 1; my $includeOutputs = 0; @@ -60,6 +62,9 @@ while (@ARGV) { elsif ($arg eq "--include-outputs") { $includeOutputs = 1; } + elsif ($arg eq "--show-progress") { + $progressViewer = "@pv@"; + } elsif ($arg eq "--dry-run") { $dryRun = 1; } @@ -76,7 +81,7 @@ openSSHConnection $sshHost or die "$0: unable to start SSH\n"; if ($toMode) { # Copy TO the remote machine. - Nix::CopyClosure::copyTo($sshHost, [ @sshOpts ], [ @storePaths ], $compressor, $decompressor, $includeOutputs, $dryRun, $sign); + Nix::CopyClosure::copyTo($sshHost, [ @sshOpts ], [ @storePaths ], $compressor, $decompressor, $includeOutputs, $dryRun, $sign, $progressViewer); } else { # Copy FROM the remote machine. @@ -101,9 +106,10 @@ else { # Copy FROM the remote machine. print STDERR "copying ", scalar @missing, " missing paths from ‘$sshHost’...\n"; $compressor = "| $compressor" if $compressor ne ""; $decompressor = "$decompressor |" if $decompressor ne ""; + $progressViewer = "$progressViewer |" if $progressViewer ne ""; unless ($dryRun) { my $extraOpts = $sign ? "--sign" : ""; - system("set -f; ssh $sshHost @sshOpts 'nix-store --export $extraOpts @missing $compressor' | $decompressor $Nix::Config::binDir/nix-store --import > /dev/null") == 0 + system("set -f; ssh $sshHost @sshOpts 'nix-store --export $extraOpts @missing $compressor' | $progressViewer $decompressor $Nix::Config::binDir/nix-store --import > /dev/null") == 0 or die "copying store paths from remote machine `$sshHost' failed: $?"; } } diff --git a/scripts/nix-generate-patches.in b/scripts/nix-generate-patches.in index 4cb843382b52..969af916d8e6 100755 --- a/scripts/nix-generate-patches.in +++ b/scripts/nix-generate-patches.in @@ -39,4 +39,14 @@ generatePatches \%srcNarFiles, \%dstNarFiles, \%srcPatches, \%dstPatches, propagatePatches \%srcPatches, \%dstNarFiles, \%dstPatches; +# Optionally add all new patches to the manifest in $NIX_ALL_PATCHES. +my $allPatchesFile = $ENV{"NIX_ALL_PATCHES"}; +if (defined $allPatchesFile) { + my (%dummy, %allPatches); + readManifest("$patchesPath/all-patches", \%dummy, \%allPatches) + if -f $allPatchesFile; + copyPatches \%dstPatches, \%allPatches; + writeManifest($allPatchesFile, {}, \%allPatches, 0); +} + writeManifest $dstManifest, \%dstNarFiles, \%dstPatches; diff --git a/scripts/nix-pull.in b/scripts/nix-pull.in index 136a5c9fa4bd..8d5db2f57c68 100755 --- a/scripts/nix-pull.in +++ b/scripts/nix-pull.in @@ -50,7 +50,7 @@ sub processURL { my $manifest; # First see if a bzipped manifest is available. - if (system("$Nix::Config::curl --fail --silent --head '$url'.bz2 > /dev/null") == 0) { + if (system("$Nix::Config::curl --fail --silent --location --head '$url'.bz2 > /dev/null") == 0) { print "fetching list of Nix archives at `$url.bz2'...\n"; $manifest = downloadFile "$url.bz2"; } @@ -72,7 +72,7 @@ sub processURL { my $urlFile = "$manifestDir/$baseName-$hash.url"; open URL, ">$urlFile" or die "cannot create `$urlFile'"; - print URL "$url"; + print URL ($ENV{'NIX_ORIG_URL'} || $url); close URL; my $finalPath = "$manifestDir/$baseName-$hash.nixmanifest"; diff --git a/scripts/nix-push.in b/scripts/nix-push.in index 1e0918abd6ac..a1c02190bd6c 100755 --- a/scripts/nix-push.in +++ b/scripts/nix-push.in @@ -103,7 +103,7 @@ foreach my $storePath (@storePaths) { # Construct a Nix expression that creates a Nix archive. my $nixexpr = "(import <nix/nar.nix> " . - "{ storePath = builtins.storePath \"$storePath\"; system = \"@system@\"; hashAlgo = \"$hashAlgo\"; }) "; + "{ storePath = builtins.storePath \"$storePath\"; hashAlgo = \"$hashAlgo\"; }) "; print NIX $nixexpr; } diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 449123a1f82c..095e288430f6 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -8,6 +8,8 @@ %parse-param { ParseData * data } %lex-param { yyscan_t scanner } %lex-param { ParseData * data } +%expect 1 +%expect-rr 1 %code requires { diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 467f16597440..77e968ddd08e 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1793,11 +1793,25 @@ void DerivationGoal::startBuilder() if (chdir(tmpDir.c_str()) == -1) throw SysError(format("changing into `%1%'") % tmpDir); + /* Close all other file descriptors. */ + closeMostFDs(set<int>()); + #ifdef CAN_DO_LINUX32_BUILDS + /* Change the personality to 32-bit if we're doing an + i686-linux build on an x86_64-linux machine. */ if (drv.platform == "i686-linux" && thisSystem == "x86_64-linux") { if (personality(0x0008 | 0x8000000 /* == PER_LINUX32_3GB */) == -1) throw SysError("cannot set i686-linux personality"); } + + /* Impersonate a Linux 2.6 machine to get some determinism + in builds that depend on the kernel version. */ + if ((drv.platform == "i686-linux" || drv.platform == "x86_64-linux") && + queryBoolSetting("build-impersonate-linux-26", true)) + { + int cur = personality(0xffffffff); + if (cur != -1) personality(cur | 0x0020000 /* == UNAME26 */); + } #endif /* Fill in the environment. */ diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 95c7154110b3..f6ed7dd2264e 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -1,6 +1,7 @@ #include "globals.hh" #include "misc.hh" #include "local-store.hh" +#include "immutable.hh" #include <boost/shared_ptr.hpp> @@ -55,24 +56,22 @@ int LocalStore::openGCLock(LockType lockType) } -void createSymlink(const Path & link, const Path & target, bool careful) +void createSymlink(const Path & link, const Path & target) { /* Create directories up to `gcRoot'. */ createDirs(dirOf(link)); - /* !!! shouldn't removing and creating the symlink be atomic? */ - - /* Remove the old symlink. */ - if (pathExists(link)) { - if (careful && (!isLink(link) || !isInStore(readLink(link)))) - throw Error(format("cannot create symlink `%1%'; already exists") % link); - unlink(link.c_str()); - } - - /* And create the new one. */ - if (symlink(target.c_str(), link.c_str()) == -1) + /* Create the new symlink. */ + Path tempLink = (format("%1%.tmp-%2%-%3%") + % link % getpid() % rand()).str(); + if (symlink(target.c_str(), tempLink.c_str()) == -1) throw SysError(format("symlinking `%1%' to `%2%'") - % link % target); + % tempLink % target); + + /* Atomically replace the old one. */ + if (rename(tempLink.c_str(), link.c_str()) == -1) + throw SysError(format("cannot rename `%1%' to `%2%'") + % tempLink % link); } @@ -87,7 +86,7 @@ void LocalStore::addIndirectRoot(const Path & path) string hash = printHash32(hashString(htSHA1, path)); Path realRoot = canonPath((format("%1%/%2%/auto/%3%") % nixStateDir % gcRootsDir % hash).str()); - createSymlink(realRoot, path, false); + createSymlink(realRoot, path); } @@ -104,7 +103,11 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath, "(are you running nix-build inside the store?)") % gcRoot); if (indirect) { - createSymlink(gcRoot, storePath, true); + /* Don't clobber the the link if it already exists and doesn't + point to the Nix store. */ + if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot)))) + throw Error(format("cannot create symlink `%1%'; already exists") % gcRoot); + createSymlink(gcRoot, storePath); store.addIndirectRoot(gcRoot); } @@ -119,7 +122,7 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath, % gcRoot % rootsDir); } - createSymlink(gcRoot, storePath, false); + createSymlink(gcRoot, storePath); } /* Check that the root can be found by the garbage collector. @@ -396,11 +399,11 @@ struct LocalStore::GCState PathSet deleted; PathSet live; PathSet busy; + PathSet invalidated; bool gcKeepOutputs; bool gcKeepDerivations; - GCState(GCResults & results_) : results(results_) - { - } + unsigned long long bytesInvalidated; + GCState(GCResults & results_) : results(results_), bytesInvalidated(0) { } }; @@ -418,12 +421,27 @@ bool LocalStore::isActiveTempFile(const GCState & state, && state.tempRoots.find(string(path, 0, path.size() - suffix.size())) != state.tempRoots.end(); } - + +void LocalStore::deleteGarbage(GCState & state, const Path & path) +{ + printMsg(lvlInfo, format("deleting `%1%'") % path); + unsigned long long bytesFreed, blocksFreed; + deletePathWrapped(path, bytesFreed, blocksFreed); + state.results.bytesFreed += bytesFreed; + state.results.blocksFreed += blocksFreed; +} + + bool LocalStore::tryToDelete(GCState & state, const Path & path) { checkInterrupt(); - - if (!pathExists(path)) return true; + + struct stat st; + if (lstat(path.c_str(), &st)) { + if (errno == ENOENT) return true; + throw SysError(format("getting status of %1%") % path); + } + if (state.deleted.find(path) != state.deleted.end()) return true; if (state.live.find(path) != state.live.end()) return false; @@ -502,28 +520,39 @@ bool LocalStore::tryToDelete(GCState & state, const Path & path) /* The path is garbage, so delete it. */ if (shouldDelete(state.options.action)) { - printMsg(lvlInfo, format("deleting `%1%'") % path); - unsigned long long bytesFreed, blocksFreed; - deleteFromStore(path, bytesFreed, blocksFreed); - state.results.bytesFreed += bytesFreed; - state.results.blocksFreed += blocksFreed; + /* If it's a valid path that's not a regular file or symlink, + invalidate it, rename it, and schedule it for deletion. + The renaming is to ensure that later (when we're not + holding the global GC lock) we can delete the path without + being afraid that the path has become alive again. + Otherwise delete it right away. */ + if (isValidPath(path)) { + if (S_ISDIR(st.st_mode)) { + printMsg(lvlInfo, format("invalidating `%1%'") % path); + // Estimate the amount freed using the narSize field. + state.bytesInvalidated += queryPathInfo(path).narSize; + invalidatePathChecked(path); + makeMutable(path.c_str()); + // Mac OS X cannot rename directories if they are read-only. + if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1) + throw SysError(format("making `%1%' writable") % path); + Path tmp = (format("%1%-gc-%2%") % path % getpid()).str(); + if (rename(path.c_str(), tmp.c_str())) + throw SysError(format("unable to rename `%1%' to `%2%'") % path % tmp); + state.invalidated.insert(tmp); + } else { + invalidatePathChecked(path); + deleteGarbage(state, path); + } + } else + deleteGarbage(state, path); - if (state.options.maxFreed && state.results.bytesFreed > state.options.maxFreed) { - printMsg(lvlInfo, format("deleted more than %1% bytes; stopping") % state.options.maxFreed); + if (state.options.maxFreed && state.results.bytesFreed + state.bytesInvalidated > state.options.maxFreed) { + printMsg(lvlInfo, format("deleted or invalidated more than %1% bytes; stopping") % state.options.maxFreed); throw GCLimitReached(); } - if (state.options.maxLinks) { - struct stat st; - if (stat(nixStore.c_str(), &st) == -1) - throw SysError(format("statting `%1%'") % nixStore); - if (st.st_nlink < state.options.maxLinks) { - printMsg(lvlInfo, format("link count on the store has dropped below %1%; stopping") % state.options.maxLinks); - throw GCLimitReached(); - } - } - } else printMsg(lvlTalkative, format("would delete `%1%'") % path); @@ -645,6 +674,14 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) } catch (GCLimitReached & e) { } } + + /* Allow other processes to add to the store from here on. */ + fdGCLock.close(); + + /* Delete the invalidated paths now that the lock has been + released. */ + foreach (PathSet::iterator, i, state.invalidated) + deleteGarbage(state, *i); } diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index ca541e1cce2e..f04436b7f659 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1386,11 +1386,8 @@ Paths LocalStore::importPaths(bool requireSignature, Source & source) } -void LocalStore::deleteFromStore(const Path & path, unsigned long long & bytesFreed, - unsigned long long & blocksFreed) +void LocalStore::invalidatePathChecked(const Path & path) { - bytesFreed = 0; - assertStorePath(path); while (1) { @@ -1410,8 +1407,6 @@ void LocalStore::deleteFromStore(const Path & path, unsigned long long & bytesFr break; } catch (SQLiteBusy & e) { }; } - - deletePathWrapped(path, bytesFreed, blocksFreed); } diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 2739c4eea69d..8e3cbe5ce11b 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -164,10 +164,6 @@ public: void collectGarbage(const GCOptions & options, GCResults & results); - /* Delete a path from the Nix store. */ - void deleteFromStore(const Path & path, unsigned long long & bytesFreed, - unsigned long long & blocksFreed); - /* Optimise the disk space usage of the Nix store by hard-linking files with the same contents. */ void optimiseStore(bool dryRun, OptimiseStats & stats); @@ -238,6 +234,9 @@ private: void invalidatePath(const Path & path); + /* Delete a path from the Nix store. */ + void invalidatePathChecked(const Path & path); + void verifyPath(const Path & path, const PathSet & store, PathSet & done, PathSet & validPaths); @@ -249,6 +248,8 @@ private: struct GCState; + void deleteGarbage(GCState & state, const Path & path); + bool tryToDelete(GCState & state, const Path & path); bool isActiveTempFile(const GCState & state, diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index c77a12870513..0b8fa36f6df4 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -466,7 +466,7 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results) writeStrings(options.pathsToDelete, to); writeInt(options.ignoreLiveness, to); writeLongLong(options.maxFreed, to); - writeInt(options.maxLinks, to); + writeInt(0, to); if (GET_PROTOCOL_MINOR(daemonVersion) >= 5) { /* removed options */ writeInt(0, to); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 36ade2170876..19bc048abd02 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -13,7 +13,6 @@ GCOptions::GCOptions() action = gcDeleteDead; ignoreLiveness = false; maxFreed = 0; - maxLinks = 0; } diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 61bcaf50507f..a62a648168f9 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -53,10 +53,6 @@ struct GCOptions no limit. */ unsigned long long maxFreed; - /* Stop after the number of hard links to the Nix store directory - has dropped below `maxLinks'. */ - unsigned int maxLinks; - GCOptions(); }; diff --git a/src/nix-env/help.txt b/src/nix-env/help.txt index 605bf2810a42..0ebdca9b22a5 100644 --- a/src/nix-env/help.txt +++ b/src/nix-env/help.txt @@ -69,6 +69,8 @@ Options: --file / -f FILE: use Nix expression FILE for installation, etc. --verbose / -v: verbose operation (may be repeated) --keep-failed / -K: keep temporary directories of failed builds + --keep-going / -k: build as many dependencies as possible, even if + some dependencies fail to build --preserve-installed: do not replace currently installed versions in `-i' --system-filter SYSTEM: only use derivations for specified platform --prebuilt-only / -b: only use derivations whose prebuilt binaries are diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index 0dcdcc0d186f..4480a17aa923 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -118,7 +118,6 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, builder with the manifest as argument. */ Value args, topLevel; state.mkAttrs(args, 3); - mkString(*state.allocAttr(args, state.sSystem), thisSystem); mkString(*state.allocAttr(args, state.symbols.create("manifest")), manifestFile, singleton<PathSet>(manifestFile)); args.attrs->push_back(Attr(state.symbols.create("derivations"), &manifest)); diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index 8f3a290f3a6a..d86c9fc84572 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -79,6 +79,7 @@ void run(Strings args) EvalState state; Strings files; bool readStdin = false; + bool findFile = false; bool evalOnly = false; bool parseOnly = false; bool xmlOutput = false; @@ -100,6 +101,8 @@ void run(Strings args) readOnlyMode = true; parseOnly = evalOnly = true; } + else if (arg == "--find-file") + findFile = true; else if (arg == "--attr" || arg == "-A") { if (i == args.end()) throw UsageError("`--attr' requires an argument"); @@ -130,13 +133,23 @@ void run(Strings args) if (attrPaths.empty()) attrPaths.push_back(""); + if (findFile) { + foreach (Strings::iterator, i, files) { + Path p = state.findFile(*i); + if (p == "") throw Error(format("unable to find `%1%'") % *i); + std::cout << p << std::endl; + } + return; + } + store = openStore(); if (readStdin) { Expr * e = parseStdin(state); processExpr(state, attrPaths, parseOnly, strict, autoArgs, evalOnly, xmlOutput, xmlOutputSourceLocation, e); - } + } else if (files.empty()) + files.push_back("./default.nix"); foreach (Strings::iterator, i, files) { Expr * e = state.parseExprFromFile(lookupFileArg(state, *i)); diff --git a/src/nix-store/help.txt b/src/nix-store/help.txt index f3e65a5283b9..ed4a29a67e17 100644 --- a/src/nix-store/help.txt +++ b/src/nix-store/help.txt @@ -65,5 +65,7 @@ Options: --verbose / -v: verbose operation (may be repeated) --keep-failed / -K: keep temporary directories of failed builds + --keep-going / -k: build as many dependencies as possible, even if + some dependencies fail to build --add-root: add garbage collector roots for the result diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 404da2c51f51..fa96725b1b48 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -562,7 +562,6 @@ static void opGC(Strings opFlags, Strings opArgs) long long maxFreed = getIntArg<long long>(*i, i, opFlags.end()); options.maxFreed = maxFreed >= 1 ? maxFreed : 1; } - else if (*i == "--max-links") options.maxLinks = getIntArg<unsigned int>(*i, i, opFlags.end()); else throw UsageError(format("bad sub-operation `%1%' in GC") % *i); if (!opArgs.empty()) throw UsageError("no arguments expected"); diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc index f5201ab6a561..4b0c9e319130 100644 --- a/src/nix-worker/nix-worker.cc +++ b/src/nix-worker/nix-worker.cc @@ -477,7 +477,7 @@ static void performOp(unsigned int clientVersion, options.pathsToDelete = readStorePaths<PathSet>(from); options.ignoreLiveness = readInt(from); options.maxFreed = readLongLong(from); - options.maxLinks = readInt(from); + readInt(from); // obsolete field if (GET_PROTOCOL_MINOR(clientVersion) >= 5) { /* removed options */ readInt(from); @@ -697,6 +697,8 @@ static void daemonLoop() if (fdSocket == -1) throw SysError("cannot create Unix domain socket"); + closeOnExec(fdSocket); + string socketPath = nixStateDir + DEFAULT_SOCKET_PATH; createDirs(dirOf(socketPath)); @@ -751,6 +753,8 @@ static void daemonLoop() throw SysError("accepting connection"); } + closeOnExec(remote); + /* Get the identity of the caller, if possible. */ uid_t clientUid = -1; pid_t clientPid = -1; diff --git a/substitute.mk b/substitute.mk index 9009b4249485..d28b330a673d 100644 --- a/substitute.mk +++ b/substitute.mk @@ -22,6 +22,7 @@ -e "s^@sed\@^$(sed)^g" \ -e "s^@tar\@^$(tar)^g" \ -e "s^@gzip\@^$(gzip)^g" \ + -e "s^@pv\@^$(pv)^g" \ -e "s^@tr\@^$(tr)^g" \ -e "s^@dot\@^$(dot)^g" \ -e "s^@xmllint\@^$(xmllint)^g" \ diff --git a/tests/common.sh.in b/tests/common.sh.in index 0f46e5f4ec21..031a0d66d1b8 100644 --- a/tests/common.sh.in +++ b/tests/common.sh.in @@ -35,7 +35,7 @@ readLink() { clearProfiles() { profiles="$NIX_STATE_DIR"/profiles - rm -f $profiles/* + rm -rf $profiles } clearStore() { diff --git a/tests/nix-channel.sh b/tests/nix-channel.sh index 4819b57c91c0..eb1d572953d7 100644 --- a/tests/nix-channel.sh +++ b/tests/nix-channel.sh @@ -9,9 +9,9 @@ rm -f $TEST_ROOT/.nix-channels export HOME=$TEST_ROOT # Test add/list/remove. -nix-channel --add http://foo/bar +nix-channel --add http://foo/bar xyzzy nix-channel --list | grep -q http://foo/bar -nix-channel --remove http://foo/bar +nix-channel --remove xyzzy [ -e $TEST_ROOT/.nix-channels ] [ "$(cat $TEST_ROOT/.nix-channels)" = '' ] |