nix-instantiate: Add a flag --expr / -E to read expressions from the command line

This is basically a shortcut for ‘echo 'expr...' | nix-instantiate -’.
Also supported by nix-build and nix-shell.
This commit is contained in:
Eelco Dolstra 2014-02-19 16:30:19 +01:00
parent e707a8a526
commit c31836008e
6 changed files with 148 additions and 95 deletions

View file

@ -164,6 +164,16 @@ $ nix-build '<nixpkgs>' -A openssl.man
</screen> </screen>
This will create a symlink <literal>result-man</literal>.</para> This will create a symlink <literal>result-man</literal>.</para>
<para>Build a Nix expression given on the command line:
<screen>
$ nix-build -E 'with import &lt;nixpkgs> { }; runCommand "foo" { } "echo bar > $out"'
$ cat ./result
bar
</screen>
</para>
</refsection> </refsection>

View file

@ -18,7 +18,15 @@
<refsynopsisdiv> <refsynopsisdiv>
<cmdsynopsis> <cmdsynopsis>
<command>nix-instantiate</command> <command>nix-instantiate</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/*)" /> <group>
<arg choice='plain'><option>--parse-only</option></arg>
<arg choice='plain'>
<option>--eval-only</option>
<arg><option>--strict</option></arg>
<arg><option>--xml</option></arg>
</arg>
</group>
<arg><option>--read-write-mode</option></arg>
<arg><option>--arg</option> <replaceable>name</replaceable> <replaceable>value</replaceable></arg> <arg><option>--arg</option> <replaceable>name</replaceable> <replaceable>value</replaceable></arg>
<arg> <arg>
<group choice='req'> <group choice='req'>
@ -29,18 +37,14 @@
</arg> </arg>
<arg><option>--add-root</option> <replaceable>path</replaceable></arg> <arg><option>--add-root</option> <replaceable>path</replaceable></arg>
<arg><option>--indirect</option></arg> <arg><option>--indirect</option></arg>
<arg>
<group choice='req'> <group choice='req'>
<arg choice='plain'><option>--parse-only</option></arg> <arg choice='plain'><option>--expr</option></arg>
<arg choice='plain'> <arg choice='plain'><option>-E</option></arg>
<option>--eval-only</option>
<arg><option>--strict</option></arg>
<arg><option>--read-write-mode</option></arg>
</arg>
<arg choice='plain'><option>--find-file</option></arg>
</group> </group>
<arg><option>--xml</option></arg> <arg choice='plain' rep='repeat'><replaceable>files</replaceable></arg>
</arg> <sbr/>
<command>nix-instantiate</command>
<arg choice='plain'><option>--file-file</option></arg>
<arg choice='plain' rep='repeat'><replaceable>files</replaceable></arg> <arg choice='plain' rep='repeat'><replaceable>files</replaceable></arg>
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -50,8 +54,8 @@
<para>The command <command>nix-instantiate</command> generates <link <para>The command <command>nix-instantiate</command> generates <link
linkend="gloss-derivation">store derivations</link> from (high-level) linkend="gloss-derivation">store derivations</link> from (high-level)
Nix expressions. It loads and evaluates the Nix expressions in each Nix expressions. It evaluates the Nix expressions in each of
of <replaceable>files</replaceable> (which defaults to <replaceable>files</replaceable> (which defaults to
<replaceable>./default.nix</replaceable>). Each top-level expression <replaceable>./default.nix</replaceable>). Each top-level expression
should evaluate to a derivation, a list of derivations, or a set of should evaluate to a derivation, a list of derivations, or a set of
derivations. The paths of the resulting store derivations are printed derivations. The paths of the resulting store derivations are printed
@ -61,12 +65,6 @@ on standard output.</para>
<literal>-</literal>, then a Nix expression will be read from standard <literal>-</literal>, then a Nix expression will be read from standard
input.</para> input.</para>
<para>Most users and developers dont need to use this command
(<command>nix-env</command> and <command>nix-build</command> perform
store derivation instantiation from Nix expressions automatically).
It is most commonly used for implementing new deployment
policies.</para>
<para condition="manual">See also <xref linkend="sec-common-options" <para condition="manual">See also <xref linkend="sec-common-options"
/> for a list of common options.</para> /> for a list of common options.</para>
@ -86,7 +84,6 @@ policies.</para>
</varlistentry> </varlistentry>
<varlistentry><term><option>--parse-only</option></term> <varlistentry><term><option>--parse-only</option></term>
<listitem><para>Just parse the input files, and print their <listitem><para>Just parse the input files, and print their
@ -180,19 +177,34 @@ dr-xr-xr-x 2 eelco users 4096 1970-01-01 01:00 lib
</para> </para>
<para>You can also give a Nix expression on the command line:
<screen>
$ nix-instantiate -E 'with import &lt;nixpkgs> { }; hello'
/nix/store/j8s4zyv75a724q38cb0r87rlczaiag4y-hello-2.8.drv
</screen>
This is equivalent to:
<screen>
$ nix-instantiate '&lt;nixpkgs>' -A hello
</screen>
</para>
<para>Parsing and evaluating Nix expressions: <para>Parsing and evaluating Nix expressions:
<screen> <screen>
$ echo '"foo" + "bar"' | nix-instantiate --parse-only - $ nix-instantiate --parse-only -E '1 + 2'
OpPlus(Str("foo"),Str("bar")) 1 + 2
$ echo '"foo" + "bar"' | nix-instantiate --eval-only - $ nix-instantiate --eval-only -E '1 + 2'
Str("foobar") 3
$ echo '"foo" + "bar"' | nix-instantiate --eval-only --xml - $ nix-instantiate --eval-only --xml -E '1 + 2'
<![CDATA[<?xml version='1.0' encoding='utf-8'?> <![CDATA[<?xml version='1.0' encoding='utf-8'?>
<expr> <expr>
<string value="foobar" /> <int value="3" />
</expr>]]></screen> </expr>]]></screen>
</para> </para>
@ -200,7 +212,7 @@ $ echo '"foo" + "bar"' | nix-instantiate --eval-only --xml -
<para>The difference between non-strict and strict evaluation: <para>The difference between non-strict and strict evaluation:
<screen> <screen>
$ echo 'rec { x = "foo"; y = x; }' | nix-instantiate --eval-only --xml - $ nix-instantiate --eval-only --xml -E 'rec { x = "foo"; y = x; }'
<replaceable>...</replaceable><![CDATA[ <replaceable>...</replaceable><![CDATA[
<attr name="x"> <attr name="x">
<string value="foo" /> <string value="foo" />
@ -214,7 +226,7 @@ Note that <varname>y</varname> is left unevaluated (the XML
representation doesnt attempt to show non-normal forms). representation doesnt attempt to show non-normal forms).
<screen> <screen>
$ echo 'rec { x = "foo"; y = x; }' | nix-instantiate --eval-only --xml --strict - $ nix-instantiate --eval-only --xml --strict -E 'rec { x = "foo"; y = x; }'
<replaceable>...</replaceable><![CDATA[ <replaceable>...</replaceable><![CDATA[
<attr name="x"> <attr name="x">
<string value="foo" /> <string value="foo" />

View file

@ -61,11 +61,11 @@ the derivation attribute
<programlisting> <programlisting>
shellHook = shellHook =
'' ''
echo "Hello shell!" echo "Hello shell"
''; '';
</programlisting> </programlisting>
will cause <command>nix-shell</command> to print <literal>Hello shell!</literal>.</para> will cause <command>nix-shell</command> to print <literal>Hello shell</literal>.</para>
</refsection> </refsection>
@ -132,11 +132,11 @@ interactive shell in which to build it:
<screen> <screen>
$ nix-shell '&lt;nixpkgs>' -A pan $ nix-shell '&lt;nixpkgs>' -A pan
$ unpackPhase [nix-shell]$ unpackPhase
$ cd pan-* [nix-shell]$ cd pan-*
$ configurePhase [nix-shell]$ configurePhase
$ buildPhase [nix-shell]$ buildPhase
$ ./pan/gui/pan [nix-shell]$ ./pan/gui/pan
</screen> </screen>
To clear the environment first, and do some additional automatic To clear the environment first, and do some additional automatic
@ -147,6 +147,14 @@ $ nix-shell '&lt;nixpkgs>' -A pan --pure \
--command 'export NIX_DEBUG=1; export NIX_CORES=8; return' --command 'export NIX_DEBUG=1; export NIX_CORES=8; return'
</screen> </screen>
Nix expressions can also be given on the command line. For instance,
the following starts a shell containing the packages
<literal>sqlite</literal> and <literal>libX11</literal>:
<screen>
$ nix-shell -E 'with import &lt;nixpkgs> { }; runCommand "dummy" { buildInputs = [ sqlite xorg.libX11 ]; } ""'
</screen>
</para> </para>
</refsection> </refsection>

View file

@ -310,10 +310,10 @@
<varlistentry xml:id="opt-attr"><term><option>--attr</option> / <option>-A</option> <varlistentry xml:id="opt-attr"><term><option>--attr</option> / <option>-A</option>
<replaceable>attrPath</replaceable></term> <replaceable>attrPath</replaceable></term>
<listitem><para>In <command>nix-env</command>, <listitem><para>Select an attribute from the top-level Nix
<command>nix-instantiate</command> and <command>nix-build</command>, expression being evaluated. (<command>nix-env</command>,
<option>--attr</option> allows you to select an attribute from the <command>nix-instantiate</command>, <command>nix-build</command> and
top-level Nix expression being evaluated. The <emphasis>attribute <command>nix-shell</command> only.) The <emphasis>attribute
path</emphasis> <replaceable>attrPath</replaceable> is a sequence of path</emphasis> <replaceable>attrPath</replaceable> is a sequence of
attribute names separated by dots. For instance, given a top-level attribute names separated by dots. For instance, given a top-level
Nix expression <replaceable>e</replaceable>, the attribute path Nix expression <replaceable>e</replaceable>, the attribute path
@ -333,6 +333,16 @@
</varlistentry> </varlistentry>
<varlistentry><term><option>--expr</option> / <option>-E</option></term>
<listitem><para>Interpret the command line arguments as a list of
Nix expressions to be parsed and evaluated, rather than as a list
of file names of Nix expressions.
(<command>nix-instantiate</command>, <command>nix-build</command>
and <command>nix-shell</command> only.)</para></listitem>
</varlistentry>
<varlistentry><term><option>--show-trace</option></term> <varlistentry><term><option>--show-trace</option></term>
<listitem><para>Causes Nix to print out a stack trace in case of Nix <listitem><para>Causes Nix to print out a stack trace in case of Nix

View file

@ -11,6 +11,7 @@ my $dryRun = 0;
my $verbose = 0; my $verbose = 0;
my $runEnv = $0 =~ /nix-shell$/; my $runEnv = $0 =~ /nix-shell$/;
my $pure = 0; my $pure = 0;
my $fromArgs = 0;
my @instArgs = (); my @instArgs = ();
my @buildArgs = (); my @buildArgs = ();
@ -49,7 +50,7 @@ for (my $n = 0; $n < scalar @ARGV; $n++) {
$drvLink = "./derivation"; $drvLink = "./derivation";
} }
elsif ($arg eq "--no-out-link" or $arg eq "--no-link") { elsif ($arg eq "--no-out-link" || $arg eq "--no-link") {
$outLink = "$tmpDir/result"; $outLink = "$tmpDir/result";
} }
@ -59,13 +60,13 @@ for (my $n = 0; $n < scalar @ARGV; $n++) {
$drvLink = $ARGV[$n]; $drvLink = $ARGV[$n];
} }
elsif ($arg eq "--out-link" or $arg eq "-o") { elsif ($arg eq "--out-link" || $arg eq "-o") {
$n++; $n++;
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV; die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
$outLink = $ARGV[$n]; $outLink = $ARGV[$n];
} }
elsif ($arg eq "--attr" or $arg eq "-A" or $arg eq "-I") { elsif ($arg eq "--attr" || $arg eq "-A" || $arg eq "-I") {
$n++; $n++;
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV; die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
push @instArgs, ($arg, $ARGV[$n]); push @instArgs, ($arg, $ARGV[$n]);
@ -91,7 +92,7 @@ for (my $n = 0; $n < scalar @ARGV; $n++) {
$n += 2; $n += 2;
} }
elsif ($arg eq "--max-jobs" or $arg eq "-j" or $arg eq "--max-silent-time" or $arg eq "--log-type" or $arg eq "--cores" or $arg eq "--timeout") { elsif ($arg eq "--max-jobs" || $arg eq "-j" || $arg eq "--max-silent-time" || $arg eq "--log-type" || $arg eq "--c||es" || $arg eq "--timeout") {
$n++; $n++;
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV; die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
push @buildArgs, ($arg, $ARGV[$n]); push @buildArgs, ($arg, $ARGV[$n]);
@ -110,7 +111,7 @@ for (my $n = 0; $n < scalar @ARGV; $n++) {
@exprs = ("-"); @exprs = ("-");
} }
elsif ($arg eq "--verbose" or substr($arg, 0, 2) eq "-v") { elsif ($arg eq "--verbose" || substr($arg, 0, 2) eq "-v") {
push @buildArgs, $arg; push @buildArgs, $arg;
push @instArgs, $arg; push @instArgs, $arg;
$verbose = 1; $verbose = 1;
@ -144,6 +145,11 @@ for (my $n = 0; $n < scalar @ARGV; $n++) {
elsif ($arg eq "--pure") { $pure = 1; } elsif ($arg eq "--pure") { $pure = 1; }
elsif ($arg eq "--impure") { $pure = 0; } elsif ($arg eq "--impure") { $pure = 0; }
elsif ($arg eq "--expr" || $arg eq "-E") {
$fromArgs = 1;
push @instArgs, "--expr";
}
elsif (substr($arg, 0, 1) eq "-") { elsif (substr($arg, 0, 1) eq "-") {
push @buildArgs, $arg; push @buildArgs, $arg;
} }
@ -153,8 +159,10 @@ for (my $n = 0; $n < scalar @ARGV; $n++) {
} }
} }
if (!$fromArgs) {
@exprs = ("shell.nix") if scalar @exprs == 0 && $runEnv && -e "shell.nix"; @exprs = ("shell.nix") if scalar @exprs == 0 && $runEnv && -e "shell.nix";
@exprs = ("default.nix") if scalar @exprs == 0; @exprs = ("default.nix") if scalar @exprs == 0;
}
$ENV{'IN_NIX_SHELL'} = 1 if $runEnv; $ENV{'IN_NIX_SHELL'} = 1 if $runEnv;

View file

@ -89,6 +89,7 @@ void run(Strings args)
EvalState state; EvalState state;
Strings files; Strings files;
bool readStdin = false; bool readStdin = false;
bool fromArgs = false;
bool findFile = false; bool findFile = false;
bool evalOnly = false; bool evalOnly = false;
bool parseOnly = false; bool parseOnly = false;
@ -104,6 +105,8 @@ void run(Strings args)
if (arg == "-") if (arg == "-")
readStdin = true; readStdin = true;
else if (arg == "--expr" || arg == "-E")
fromArgs = true;
else if (arg == "--eval-only") else if (arg == "--eval-only")
evalOnly = true; evalOnly = true;
else if (arg == "--read-write-mode") else if (arg == "--read-write-mode")
@ -162,11 +165,13 @@ void run(Strings args)
Expr * e = parseStdin(state); Expr * e = parseStdin(state);
processExpr(state, attrPaths, parseOnly, strict, autoArgs, processExpr(state, attrPaths, parseOnly, strict, autoArgs,
evalOnly, xmlOutput, xmlOutputSourceLocation, e); evalOnly, xmlOutput, xmlOutputSourceLocation, e);
} else if (files.empty()) } else if (files.empty() && !fromArgs)
files.push_back("./default.nix"); files.push_back("./default.nix");
foreach (Strings::iterator, i, files) { foreach (Strings::iterator, i, files) {
Expr * e = state.parseExprFromFile(resolveExprPath(lookupFileArg(state, *i))); Expr * e = fromArgs
? state.parseExprFromString(*i, absPath("."))
: state.parseExprFromFile(resolveExprPath(lookupFileArg(state, *i)));
processExpr(state, attrPaths, parseOnly, strict, autoArgs, processExpr(state, attrPaths, parseOnly, strict, autoArgs,
evalOnly, xmlOutput, xmlOutputSourceLocation, e); evalOnly, xmlOutput, xmlOutputSourceLocation, e);
} }