* nix-env: allow ~/.nix-defexpr to be a directory. If it is, then the
Nix expressions in that directory are combined into an attribute set {file1 = import file1; file2 = import file2; ...}, i.e. each Nix expression is an attribute with the file name as the attribute name. Also recurses into directories. * nix-env: removed the "--import" (-I) option which set the ~/.nix-defexpr symlink. * nix-channel: don't use "nix-env --import", instead symlink ~/.nix-defexpr/channels. So finally nix-channel --update doesn't override any default Nix expressions but combines with them. This means that you can have (say) a local Nixpkgs SVN tree and use it as a default for nix-env: $ ln -s .../path-to-nixpkgs-tree ~/.nix-defexpr/nixpkgs_svn and be subscribed to channels (including Nixpkgs) at the same time. (If there is any ambiguity, the -A flag can be used to disambiguate, e.g. "nix-env -i -A nixpkgs_svn.pan".)
This commit is contained in:
parent
3339f85447
commit
055608227f
6 changed files with 66 additions and 78 deletions
|
@ -4,9 +4,6 @@
|
||||||
@coreutils@/mkdir $out/tmp
|
@coreutils@/mkdir $out/tmp
|
||||||
cd $out/tmp
|
cd $out/tmp
|
||||||
|
|
||||||
expr=$out/default.nix
|
|
||||||
echo '{' > $expr
|
|
||||||
|
|
||||||
inputs=($inputs)
|
inputs=($inputs)
|
||||||
for ((n = 0; n < ${#inputs[*]}; n += 2)); do
|
for ((n = 0; n < ${#inputs[*]}; n += 2)); do
|
||||||
channelName=${inputs[n]}
|
channelName=${inputs[n]}
|
||||||
|
@ -15,19 +12,15 @@ for ((n = 0; n < ${#inputs[*]}; n += 2)); do
|
||||||
@bunzip2@ < $channelTarball | @tar@ xf -
|
@bunzip2@ < $channelTarball | @tar@ xf -
|
||||||
|
|
||||||
nr=1
|
nr=1
|
||||||
dirName=$channelName
|
attrName=$(echo $channelName | @tr@ -- '- ' '__')
|
||||||
|
dirName=$attrName
|
||||||
while test -e ../$dirName; do
|
while test -e ../$dirName; do
|
||||||
nr=$((nr+1))
|
nr=$((nr+1))
|
||||||
dirName=$channelName-$nr
|
dirName=$attrName-$nr
|
||||||
done
|
done
|
||||||
|
|
||||||
@coreutils@/mv * ../$dirName # !!! hacky
|
@coreutils@/mv * ../$dirName # !!! hacky
|
||||||
|
|
||||||
attrName=$(echo $dirName | @tr@ -- '- ' '__')
|
|
||||||
echo "$attrName = let e = import ./$dirName; in if builtins.isFunction e then e {} else e;" >> $expr
|
|
||||||
done
|
done
|
||||||
|
|
||||||
echo '} // {_combineChannels = true;}' >> $expr
|
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
@coreutils@/rmdir tmp
|
@coreutils@/rmdir tmp
|
||||||
|
|
|
@ -142,14 +142,14 @@ linkend="sec-common-options" />.</para>
|
||||||
<variablelist>
|
<variablelist>
|
||||||
|
|
||||||
<varlistentry><term><filename>~/.nix-defexpr</filename></term>
|
<varlistentry><term><filename>~/.nix-defexpr</filename></term>
|
||||||
|
|
||||||
|
<!-- !!! .nix-defexpr can be a directory now -->
|
||||||
|
|
||||||
<listitem><para>The default Nix expression used by the
|
<listitem><para>The default Nix expression used by the
|
||||||
<option>--install</option>, <option>--upgrade</option>, and
|
<option>--install</option>, <option>--upgrade</option>, and
|
||||||
<option>--query --available</option> operations to obtain
|
<option>--query --available</option> operations to obtain
|
||||||
derivations. It is generally a symbolic link to some other
|
derivations. The <option>--file</option> option may be used to
|
||||||
location set using the <option>--import</option> operation. The
|
override this default.</para></listitem>
|
||||||
<option>--file</option> option may be used to override this
|
|
||||||
default.</para></listitem>
|
|
||||||
|
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
@ -1061,43 +1061,4 @@ error: no generation older than the current (91) exists</screen>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!--######################################################################-->
|
|
||||||
|
|
||||||
<refsection><title>Operation <option>--import</option></title>
|
|
||||||
|
|
||||||
<refsection><title>Synopsis</title>
|
|
||||||
|
|
||||||
<cmdsynopsis>
|
|
||||||
<command>nix-env</command>
|
|
||||||
<group choice='req'>
|
|
||||||
<arg choice='plain'><option>--import</option></arg>
|
|
||||||
<arg choice='plain'><option>-I</option></arg>
|
|
||||||
</group>
|
|
||||||
<arg choice='req'><replaceable>path</replaceable></arg>
|
|
||||||
</cmdsynopsis>
|
|
||||||
|
|
||||||
</refsection>
|
|
||||||
|
|
||||||
|
|
||||||
<refsection><title>Description</title>
|
|
||||||
|
|
||||||
<para>This operation makes <replaceable>path</replaceable> the default
|
|
||||||
active Nix expression for the user. That is, the symlink
|
|
||||||
<filename>~/.nix-userenv</filename> is made to point to
|
|
||||||
<replaceable>path</replaceable>.</para>
|
|
||||||
|
|
||||||
</refsection>
|
|
||||||
|
|
||||||
|
|
||||||
<refsection><title>Examples</title>
|
|
||||||
|
|
||||||
<screen>
|
|
||||||
$ nix-env -I ~/nixpkgs-0.5/</screen>
|
|
||||||
|
|
||||||
</refsection>
|
|
||||||
|
|
||||||
</refsection>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|
|
@ -18,6 +18,8 @@ $ENV{'NIX_DOWNLOAD_CACHE'} = $channelCache if -W $channelCache;
|
||||||
my $home = $ENV{"HOME"};
|
my $home = $ENV{"HOME"};
|
||||||
die '$HOME not set' unless defined $home;
|
die '$HOME not set' unless defined $home;
|
||||||
my $channelsList = "$home/.nix-channels";
|
my $channelsList = "$home/.nix-channels";
|
||||||
|
|
||||||
|
my $nixDefExpr = "$home/.nix-defexpr";
|
||||||
|
|
||||||
|
|
||||||
my @channels;
|
my @channels;
|
||||||
|
@ -136,9 +138,12 @@ sub update {
|
||||||
|
|
||||||
unlink "$rootFile.tmp";
|
unlink "$rootFile.tmp";
|
||||||
|
|
||||||
# Make it the default Nix expression for `nix-env'.
|
# Make the channels appear in nix-env.
|
||||||
system("@bindir@/nix-env", "--import", "$outPath") == 0
|
unlink $nixDefExpr if -l $nixDefExpr; # old-skool ~/.nix-defexpr
|
||||||
or die "cannot pull set default Nix expression to `$outPath'";
|
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'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -171,8 +171,8 @@ static void getDerivations(EvalState & state, Expr e,
|
||||||
ATermMap drvMap(ATgetLength(es));
|
ATermMap drvMap(ATgetLength(es));
|
||||||
queryAllAttrs(e, drvMap);
|
queryAllAttrs(e, drvMap);
|
||||||
|
|
||||||
/* !!! undocumented hackery to support
|
/* !!! undocumented hackery to support combining channels in
|
||||||
corepkgs/channels/unpack.sh. */
|
nix-env.cc. */
|
||||||
Expr e2 = drvMap.get(toATerm("_combineChannels"));
|
Expr e2 = drvMap.get(toATerm("_combineChannels"));
|
||||||
bool combineChannels = e2 && evalBool(state, e2);
|
bool combineChannels = e2 && evalBool(state, e2);
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,7 @@ bool pathExists(const Path & path)
|
||||||
|
|
||||||
Path readLink(const Path & path)
|
Path readLink(const Path & path)
|
||||||
{
|
{
|
||||||
|
checkInterrupt();
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (lstat(path.c_str(), &st))
|
if (lstat(path.c_str(), &st))
|
||||||
throw SysError(format("getting status of `%1%'") % path);
|
throw SysError(format("getting status of `%1%'") % path);
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,11 +74,53 @@ void printHelp()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool isNixExpr(const Path & path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if (stat(path.c_str(), &st) == -1)
|
||||||
|
throw SysError(format("getting information about `%1%'") % path);
|
||||||
|
|
||||||
|
return !S_ISDIR(st.st_mode) || pathExists(path + "/default.nix");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void getAllExprs(EvalState & state,
|
||||||
|
const Path & path, ATermMap & attrs)
|
||||||
|
{
|
||||||
|
Strings names = readDirectory(path);
|
||||||
|
|
||||||
|
for (Strings::iterator i = names.begin(); i != names.end(); ++i) {
|
||||||
|
Path path2 = path + "/" + *i;
|
||||||
|
if (isNixExpr(path2))
|
||||||
|
attrs.set(toATerm(*i), makeAttrRHS(
|
||||||
|
parseExprFromFile(state, absPath(path2)), makeNoPos()));
|
||||||
|
else
|
||||||
|
getAllExprs(state, path2, attrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Expr loadSourceExpr(EvalState & state, const Path & path)
|
||||||
|
{
|
||||||
|
if (isNixExpr(path)) return parseExprFromFile(state, absPath(path));
|
||||||
|
|
||||||
|
/* The path is a directory. Put the Nix expressions in the
|
||||||
|
directory in an attribute set, with the file name of each
|
||||||
|
expression as the attribute name. Recurse into subdirectories
|
||||||
|
(but keep the attribute set flat, not nested, to make it easier
|
||||||
|
for a user to have a ~/.nix-defexpr directory that includes
|
||||||
|
some system-wide directory). */
|
||||||
|
ATermMap attrs;
|
||||||
|
attrs.set(toATerm("_combineChannels"), makeAttrRHS(eTrue, makeNoPos()));
|
||||||
|
getAllExprs(state, path, attrs);
|
||||||
|
return makeAttrs(attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void loadDerivations(EvalState & state, Path nixExprPath,
|
static void loadDerivations(EvalState & state, Path nixExprPath,
|
||||||
string systemFilter, const ATermMap & autoArgs, DrvInfos & elems)
|
string systemFilter, const ATermMap & autoArgs, DrvInfos & elems)
|
||||||
{
|
{
|
||||||
getDerivations(state,
|
getDerivations(state, loadSourceExpr(state, nixExprPath), "", autoArgs, elems);
|
||||||
parseExprFromFile(state, absPath(nixExprPath)), "", autoArgs, elems);
|
|
||||||
|
|
||||||
/* Filter out all derivations not applicable to the current
|
/* Filter out all derivations not applicable to the current
|
||||||
system. */
|
system. */
|
||||||
|
@ -365,9 +409,7 @@ static void queryInstSources(EvalState & state,
|
||||||
(import ./foo.nix)' = `(import ./foo.nix).bar'. */
|
(import ./foo.nix)' = `(import ./foo.nix).bar'. */
|
||||||
case srcNixExprs: {
|
case srcNixExprs: {
|
||||||
|
|
||||||
|
Expr e1 = loadSourceExpr(state, instSource.nixExprPath);
|
||||||
Expr e1 = parseExprFromFile(state,
|
|
||||||
absPath(instSource.nixExprPath));
|
|
||||||
|
|
||||||
for (Strings::const_iterator i = args.begin();
|
for (Strings::const_iterator i = args.begin();
|
||||||
i != args.end(); ++i)
|
i != args.end(); ++i)
|
||||||
|
@ -429,7 +471,7 @@ static void queryInstSources(EvalState & state,
|
||||||
i != args.end(); ++i)
|
i != args.end(); ++i)
|
||||||
getDerivations(state,
|
getDerivations(state,
|
||||||
findAlongAttrPath(state, *i, instSource.autoArgs,
|
findAlongAttrPath(state, *i, instSource.autoArgs,
|
||||||
parseExprFromFile(state, instSource.nixExprPath)),
|
loadSourceExpr(state, instSource.nixExprPath)),
|
||||||
"", instSource.autoArgs, elems);
|
"", instSource.autoArgs, elems);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1218,18 +1260,6 @@ static void opDeleteGenerations(Globals & globals,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void opDefaultExpr(Globals & globals,
|
|
||||||
Strings opFlags, Strings opArgs)
|
|
||||||
{
|
|
||||||
if (opFlags.size() > 0)
|
|
||||||
throw UsageError(format("unknown flag `%1%'") % opFlags.front());
|
|
||||||
if (opArgs.size() != 1)
|
|
||||||
throw UsageError(format("exactly one argument expected"));
|
|
||||||
|
|
||||||
switchLink(getDefNixExprPath(), absPath(opArgs.front()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static string needArg(Strings::iterator & i,
|
static string needArg(Strings::iterator & i,
|
||||||
Strings & args, const string & arg)
|
Strings & args, const string & arg)
|
||||||
{
|
{
|
||||||
|
@ -1286,8 +1316,6 @@ void run(Strings args)
|
||||||
op = opSet;
|
op = opSet;
|
||||||
else if (arg == "--query" || arg == "-q")
|
else if (arg == "--query" || arg == "-q")
|
||||||
op = opQuery;
|
op = opQuery;
|
||||||
else if (arg == "--import" || arg == "-I") /* !!! bad name */
|
|
||||||
op = opDefaultExpr;
|
|
||||||
else if (arg == "--profile" || arg == "-p")
|
else if (arg == "--profile" || arg == "-p")
|
||||||
globals.profile = absPath(needArg(i, args, arg));
|
globals.profile = absPath(needArg(i, args, arg));
|
||||||
else if (arg == "--file" || arg == "-f")
|
else if (arg == "--file" || arg == "-f")
|
||||||
|
|
Loading…
Reference in a new issue