forked from lix-project/lix
* nix-env: a tool to manage user environments.
* Replace all directory reading code by a generic readDirectory() function.
This commit is contained in:
parent
fd7ac09f10
commit
9898746ef3
|
@ -36,6 +36,7 @@ AC_CONFIG_FILES([Makefile
|
||||||
src/nix-hash/Makefile
|
src/nix-hash/Makefile
|
||||||
src/libexpr/Makefile
|
src/libexpr/Makefile
|
||||||
src/nix-instantiate/Makefile
|
src/nix-instantiate/Makefile
|
||||||
|
src/nix-env/Makefile
|
||||||
scripts/Makefile
|
scripts/Makefile
|
||||||
corepkgs/Makefile
|
corepkgs/Makefile
|
||||||
corepkgs/fetchurl/Makefile
|
corepkgs/fetchurl/Makefile
|
||||||
|
|
72
corepkgs/buildenv/builder.pl
Executable file
72
corepkgs/buildenv/builder.pl
Executable file
|
@ -0,0 +1,72 @@
|
||||||
|
#! /usr/bin/perl -w
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Cwd;
|
||||||
|
|
||||||
|
my $selfdir = $ENV{"out"};
|
||||||
|
mkdir "$selfdir", 0755 || die "error creating $selfdir";
|
||||||
|
|
||||||
|
# For each activated package, create symlinks.
|
||||||
|
|
||||||
|
sub createLinks {
|
||||||
|
my $srcdir = shift;
|
||||||
|
my $dstdir = shift;
|
||||||
|
|
||||||
|
my @srcfiles = glob("$srcdir/*");
|
||||||
|
|
||||||
|
foreach my $srcfile (@srcfiles) {
|
||||||
|
my $basename = $srcfile;
|
||||||
|
$basename =~ s/^.*\///g; # strip directory
|
||||||
|
my $dstfile = "$dstdir/$basename";
|
||||||
|
if ($srcfile =~ /\/envpkgs$/) {
|
||||||
|
} elsif (-d $srcfile) {
|
||||||
|
# !!! hack for resolving name clashes
|
||||||
|
if (!-e $dstfile) {
|
||||||
|
mkdir $dstfile, 0755 ||
|
||||||
|
die "error creating directory $dstfile";
|
||||||
|
}
|
||||||
|
-d $dstfile or die "$dstfile is not a directory";
|
||||||
|
createLinks($srcfile, $dstfile);
|
||||||
|
} elsif (-l $dstfile) {
|
||||||
|
my $target = readlink($dstfile);
|
||||||
|
die "collission between $srcfile and $target";
|
||||||
|
} else {
|
||||||
|
# print "linking $dstfile to $srcfile\n";
|
||||||
|
symlink($srcfile, $dstfile) ||
|
||||||
|
die "error creating link $dstfile";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my %done;
|
||||||
|
|
||||||
|
sub addPkg {
|
||||||
|
my $pkgdir = shift;
|
||||||
|
|
||||||
|
return if (defined $done{$pkgdir});
|
||||||
|
$done{$pkgdir} = 1;
|
||||||
|
|
||||||
|
# print "merging $pkgdir\n";
|
||||||
|
|
||||||
|
createLinks("$pkgdir", "$selfdir");
|
||||||
|
|
||||||
|
# if (-f "$pkgdir/envpkgs") {
|
||||||
|
# my $envpkgs = `cat $pkgdir/envpkgs`;
|
||||||
|
# chomp $envpkgs;
|
||||||
|
# my @envpkgs = split / +/, $envpkgs;
|
||||||
|
# foreach my $envpkg (@envpkgs) {
|
||||||
|
# addPkg($envpkg);
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
}
|
||||||
|
|
||||||
|
my @args = split ' ', $ENV{"derivations"};
|
||||||
|
|
||||||
|
while (scalar @args > 0) {
|
||||||
|
my $drvpath = shift @args;
|
||||||
|
print "adding $drvpath\n";
|
||||||
|
addPkg($drvpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
symlink($ENV{"manifest"}, "$selfdir/manifest") or die "cannot create manifest";
|
||||||
|
|
9
corepkgs/buildenv/default.nix
Normal file
9
corepkgs/buildenv/default.nix
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{system, derivations, manifest}:
|
||||||
|
|
||||||
|
derivation {
|
||||||
|
name = "user-environment";
|
||||||
|
system = system;
|
||||||
|
builder = ./builder.pl;
|
||||||
|
derivations = derivations;
|
||||||
|
manifest = manifest;
|
||||||
|
}
|
|
@ -1,2 +1,2 @@
|
||||||
SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \
|
SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \
|
||||||
libexpr nix-instantiate
|
libexpr nix-instantiate nix-env
|
||||||
|
|
|
@ -68,6 +68,8 @@ struct Cleanup : TermFun
|
||||||
|
|
||||||
Expr parseExprFromFile(Path path)
|
Expr parseExprFromFile(Path path)
|
||||||
{
|
{
|
||||||
|
assert(path[0] == '/');
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Perhaps this is already an imploded parse tree? */
|
/* Perhaps this is already an imploded parse tree? */
|
||||||
Expr e = ATreadFromNamedFile(path.c_str());
|
Expr e = ATreadFromNamedFile(path.c_str());
|
||||||
|
|
|
@ -19,6 +19,7 @@ static void initAndRun(int argc, char * * argv)
|
||||||
nixStore = NIX_STORE_DIR;
|
nixStore = NIX_STORE_DIR;
|
||||||
nixDataDir = NIX_DATA_DIR;
|
nixDataDir = NIX_DATA_DIR;
|
||||||
nixLogDir = NIX_LOG_DIR;
|
nixLogDir = NIX_LOG_DIR;
|
||||||
|
nixStateDir = (string) NIX_STATE_DIR;
|
||||||
nixDBPath = (string) NIX_STATE_DIR + "/db";
|
nixDBPath = (string) NIX_STATE_DIR + "/db";
|
||||||
|
|
||||||
/* Put the arguments in a vector. */
|
/* Put the arguments in a vector. */
|
||||||
|
|
|
@ -166,7 +166,7 @@ void Database::open(const string & path)
|
||||||
/* The following code provides automatic recovery of the
|
/* The following code provides automatic recovery of the
|
||||||
database environment. Recovery is necessary when a process
|
database environment. Recovery is necessary when a process
|
||||||
dies while it has the database open. To detect this,
|
dies while it has the database open. To detect this,
|
||||||
processes atomically increment a counter when the open the
|
processes atomically increment a counter when they open the
|
||||||
database, and decrement it when they close it. If we see
|
database, and decrement it when they close it. If we see
|
||||||
that counter is > 0 but no processes are accessing the
|
that counter is > 0 but no processes are accessing the
|
||||||
database---determined by attempting to obtain a write lock
|
database---determined by attempting to obtain a write lock
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
string nixStore = "/UNINIT";
|
string nixStore = "/UNINIT";
|
||||||
string nixDataDir = "/UNINIT";
|
string nixDataDir = "/UNINIT";
|
||||||
string nixLogDir = "/UNINIT";
|
string nixLogDir = "/UNINIT";
|
||||||
|
string nixStateDir = "/UNINIT";
|
||||||
string nixDBPath = "/UNINIT";
|
string nixDBPath = "/UNINIT";
|
||||||
|
|
||||||
bool keepFailed = false;
|
bool keepFailed = false;
|
||||||
|
|
|
@ -16,6 +16,9 @@ extern string nixDataDir; /* !!! fix */
|
||||||
/* nixLogDir is the directory where we log various operations. */
|
/* nixLogDir is the directory where we log various operations. */
|
||||||
extern string nixLogDir;
|
extern string nixLogDir;
|
||||||
|
|
||||||
|
/* nixStateDir is the directory where state is stored. */
|
||||||
|
extern string nixStateDir;
|
||||||
|
|
||||||
/* nixDBPath is the path name of our Berkeley DB environment. */
|
/* nixDBPath is the path name of our Berkeley DB environment. */
|
||||||
extern string nixDBPath;
|
extern string nixDBPath;
|
||||||
|
|
||||||
|
|
|
@ -36,14 +36,10 @@ void checkPath(const string & path,
|
||||||
throw SysError(format("getting attributes of path `%1%'") % path);
|
throw SysError(format("getting attributes of path `%1%'") % path);
|
||||||
|
|
||||||
if (S_ISDIR(st.st_mode)) {
|
if (S_ISDIR(st.st_mode)) {
|
||||||
AutoCloseDir dir = opendir(path.c_str());
|
Strings names = readDirectory(path);
|
||||||
|
for (Strings::iterator i = names.begin(); i != names.end(); i++) {
|
||||||
struct dirent * dirent;
|
search(*i, ids, seen);
|
||||||
while (errno = 0, dirent = readdir(dir)) {
|
checkPath(path + "/" + *i, ids, seen);
|
||||||
string name = dirent->d_name;
|
|
||||||
if (name == "." || name == "..") continue;
|
|
||||||
search(name, ids, seen);
|
|
||||||
checkPath(path + "/" + name, ids, seen);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,23 +51,12 @@ static void dump(const string & path, DumpSink & sink);
|
||||||
|
|
||||||
static void dumpEntries(const Path & path, DumpSink & sink)
|
static void dumpEntries(const Path & path, DumpSink & sink)
|
||||||
{
|
{
|
||||||
AutoCloseDir dir = opendir(path.c_str());
|
Strings names = readDirectory(path);
|
||||||
if (!dir) throw SysError("opening directory " + path);
|
vector<string> names2(names.begin(), names.end());
|
||||||
|
sort(names2.begin(), names2.end());
|
||||||
|
|
||||||
vector<string> names;
|
for (vector<string>::iterator it = names2.begin();
|
||||||
|
it != names2.end(); it++)
|
||||||
struct dirent * dirent;
|
|
||||||
while (errno = 0, dirent = readdir(dir)) {
|
|
||||||
string name = dirent->d_name;
|
|
||||||
if (name == "." || name == "..") continue;
|
|
||||||
names.push_back(name);
|
|
||||||
}
|
|
||||||
if (errno) throw SysError("reading directory " + path);
|
|
||||||
|
|
||||||
sort(names.begin(), names.end());
|
|
||||||
|
|
||||||
for (vector<string>::iterator it = names.begin();
|
|
||||||
it != names.end(); it++)
|
|
||||||
{
|
{
|
||||||
writeString("entry", sink);
|
writeString("entry", sink);
|
||||||
writeString("(", sink);
|
writeString("(", sink);
|
||||||
|
|
|
@ -108,6 +108,25 @@ bool pathExists(const Path & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Strings readDirectory(const Path & path)
|
||||||
|
{
|
||||||
|
Strings names;
|
||||||
|
|
||||||
|
AutoCloseDir dir = opendir(path.c_str());
|
||||||
|
if (!dir) throw SysError(format("opening directory `%1%'") % path);
|
||||||
|
|
||||||
|
struct dirent * dirent;
|
||||||
|
while (errno = 0, dirent = readdir(dir)) { /* sic */
|
||||||
|
string name = dirent->d_name;
|
||||||
|
if (name == "." || name == "..") continue;
|
||||||
|
names.push_back(name);
|
||||||
|
}
|
||||||
|
if (errno) throw SysError(format("reading directory `%1%'") % path);
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void deletePath(const Path & path)
|
void deletePath(const Path & path)
|
||||||
{
|
{
|
||||||
printMsg(lvlVomit, format("deleting path `%1%'") % path);
|
printMsg(lvlVomit, format("deleting path `%1%'") % path);
|
||||||
|
@ -117,18 +136,7 @@ void deletePath(const Path & path)
|
||||||
throw SysError(format("getting attributes of path `%1%'") % path);
|
throw SysError(format("getting attributes of path `%1%'") % path);
|
||||||
|
|
||||||
if (S_ISDIR(st.st_mode)) {
|
if (S_ISDIR(st.st_mode)) {
|
||||||
Strings names;
|
Strings names = readDirectory(path);
|
||||||
|
|
||||||
{
|
|
||||||
AutoCloseDir dir = opendir(path.c_str());
|
|
||||||
|
|
||||||
struct dirent * dirent;
|
|
||||||
while (errno = 0, dirent = readdir(dir)) {
|
|
||||||
string name = dirent->d_name;
|
|
||||||
if (name == "." || name == "..") continue;
|
|
||||||
names.push_back(name);
|
|
||||||
}
|
|
||||||
} /* scoped to ensure that dir is closed at this point */
|
|
||||||
|
|
||||||
/* Make the directory writable. */
|
/* Make the directory writable. */
|
||||||
if (!(st.st_mode & S_IWUSR)) {
|
if (!(st.st_mode & S_IWUSR)) {
|
||||||
|
@ -136,7 +144,7 @@ void deletePath(const Path & path)
|
||||||
throw SysError(format("making `%1%' writable"));
|
throw SysError(format("making `%1%' writable"));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Strings::iterator i = names.begin(); i != names.end(); i++)
|
for (Strings::iterator i = names.begin(); i != names.end(); ++i)
|
||||||
deletePath(path + "/" + *i);
|
deletePath(path + "/" + *i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,14 +165,9 @@ void makePathReadOnly(const Path & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (S_ISDIR(st.st_mode)) {
|
if (S_ISDIR(st.st_mode)) {
|
||||||
AutoCloseDir dir = opendir(path.c_str());
|
Strings names = readDirectory(path);
|
||||||
|
for (Strings::iterator i = names.begin(); i != names.end(); ++i)
|
||||||
struct dirent * dirent;
|
makePathReadOnly(path + "/" + *i);
|
||||||
while (errno = 0, dirent = readdir(dir)) {
|
|
||||||
string name = dirent->d_name;
|
|
||||||
if (name == "." || name == "..") continue;
|
|
||||||
makePathReadOnly(path + "/" + name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,10 @@ string baseNameOf(const Path & path);
|
||||||
/* Return true iff the given path exists. */
|
/* Return true iff the given path exists. */
|
||||||
bool pathExists(const Path & path);
|
bool pathExists(const Path & path);
|
||||||
|
|
||||||
|
/* Read the contents of a directory. The entries `.' and `..' are
|
||||||
|
removed. */
|
||||||
|
Strings readDirectory(const Path & path);
|
||||||
|
|
||||||
/* Delete a path; i.e., in the case of a directory, it is deleted
|
/* Delete a path; i.e., in the case of a directory, it is deleted
|
||||||
recursively. Don't use this at home, kids. */
|
recursively. Don't use this at home, kids. */
|
||||||
void deletePath(const Path & path);
|
void deletePath(const Path & path);
|
||||||
|
|
11
src/nix-env/Makefile.am
Normal file
11
src/nix-env/Makefile.am
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
bin_PROGRAMS = nix-env
|
||||||
|
|
||||||
|
nix_env_SOURCES = main.cc
|
||||||
|
nix_env_LDADD = ../libmain/libmain.a ../libexpr/libexpr.a \
|
||||||
|
../libstore/libstore.a ../libutil/libutil.a \
|
||||||
|
../boost/format/libformat.a -L../../externals/inst/lib -ldb_cxx \
|
||||||
|
-lsglr -lATB -lconversion -lasfix2 -lmept -lATerm
|
||||||
|
|
||||||
|
AM_CXXFLAGS = \
|
||||||
|
-I.. -I../../externals/inst/include -I../libutil -I../libstore \
|
||||||
|
-I../libexpr -I../libmain
|
270
src/nix-env/main.cc
Normal file
270
src/nix-env/main.cc
Normal file
|
@ -0,0 +1,270 @@
|
||||||
|
#include "globals.hh"
|
||||||
|
#include "normalise.hh"
|
||||||
|
#include "shared.hh"
|
||||||
|
#include "parser.hh"
|
||||||
|
#include "eval.hh"
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (* Operation) (EvalState & state,
|
||||||
|
Strings opFlags, Strings opArgs);
|
||||||
|
|
||||||
|
|
||||||
|
struct DrvInfo
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
Path drvPath;
|
||||||
|
Path outPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef map<string, DrvInfo> DrvInfos;
|
||||||
|
|
||||||
|
|
||||||
|
bool parseDerivation(EvalState & state, Expr e, DrvInfo & drv)
|
||||||
|
{
|
||||||
|
ATMatcher m;
|
||||||
|
|
||||||
|
e = evalExpr(state, e);
|
||||||
|
if (!(atMatch(m, e) >> "Attrs")) return false;
|
||||||
|
Expr a = queryAttr(e, "type");
|
||||||
|
if (!a || evalString(state, a) != "derivation") return false;
|
||||||
|
|
||||||
|
a = queryAttr(e, "name");
|
||||||
|
if (!a) throw badTerm("derivation name missing", e);
|
||||||
|
drv.name = evalString(state, a);
|
||||||
|
|
||||||
|
a = queryAttr(e, "drvPath");
|
||||||
|
if (!a) throw badTerm("derivation path missing", e);
|
||||||
|
drv.drvPath = evalPath(state, a);
|
||||||
|
|
||||||
|
a = queryAttr(e, "outPath");
|
||||||
|
if (!a) throw badTerm("output path missing", e);
|
||||||
|
drv.outPath = evalPath(state, a);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool parseDerivations(EvalState & state, Expr e, DrvInfos & drvs)
|
||||||
|
{
|
||||||
|
e = evalExpr(state, e);
|
||||||
|
|
||||||
|
ATermMap drvMap;
|
||||||
|
queryAllAttrs(e, drvMap);
|
||||||
|
|
||||||
|
for (ATermIterator i(drvMap.keys()); i; ++i) {
|
||||||
|
DrvInfo drv;
|
||||||
|
debug(format("evaluating attribute `%1%'") % *i);
|
||||||
|
if (parseDerivation(state, drvMap.get(*i), drv))
|
||||||
|
drvs[drv.name] = drv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loadDerivations(EvalState & state, Path nePath, DrvInfos & drvs)
|
||||||
|
{
|
||||||
|
Expr e = parseExprFromFile(absPath(nePath));
|
||||||
|
if (!parseDerivations(state, e, drvs))
|
||||||
|
throw badTerm("expected set of derivations", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Path getLinksDir()
|
||||||
|
{
|
||||||
|
return canonPath(nixStateDir + "/links");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Path createLink(Path outPath, Path drvPath)
|
||||||
|
{
|
||||||
|
Path linksDir = getLinksDir();
|
||||||
|
|
||||||
|
unsigned int num = 0;
|
||||||
|
|
||||||
|
Strings names = readDirectory(linksDir);
|
||||||
|
for (Strings::iterator i = names.begin(); i != names.end(); ++i) {
|
||||||
|
istringstream s(*i);
|
||||||
|
unsigned int n;
|
||||||
|
if (s >> n && s.eof() && n > num) num = n + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Path linkPath = (format("%1%/%2%") % linksDir % num).str();
|
||||||
|
|
||||||
|
if (symlink(outPath.c_str(), linkPath.c_str()) != 0)
|
||||||
|
throw SysError(format("creating symlink `%1%'") % linkPath);
|
||||||
|
|
||||||
|
return linkPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void installDerivations(EvalState & state,
|
||||||
|
Path nePath, Strings drvNames)
|
||||||
|
{
|
||||||
|
debug(format("installing derivations from `%1%'") % nePath);
|
||||||
|
|
||||||
|
/* Fetch all derivations from the input file. */
|
||||||
|
DrvInfos availDrvs;
|
||||||
|
loadDerivations(state, nePath, availDrvs);
|
||||||
|
|
||||||
|
/* Filter out the ones we're not interested in. */
|
||||||
|
DrvInfos selectedDrvs;
|
||||||
|
for (Strings::iterator i = drvNames.begin();
|
||||||
|
i != drvNames.end(); ++i)
|
||||||
|
{
|
||||||
|
DrvInfos::iterator j = availDrvs.find(*i);
|
||||||
|
if (j == availDrvs.end())
|
||||||
|
throw Error(format("unknown derivation `%1%'") % *i);
|
||||||
|
else
|
||||||
|
selectedDrvs[j->first] = j->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the environment builder expression. */
|
||||||
|
Expr envBuilder = parseExprFromFile("/home/eelco/nix/corepkgs/buildenv"); /* !!! */
|
||||||
|
|
||||||
|
/* Construct the whole top level derivation. */
|
||||||
|
ATermList inputs = ATempty;
|
||||||
|
for (DrvInfos::iterator i = selectedDrvs.begin();
|
||||||
|
i != selectedDrvs.end(); ++i)
|
||||||
|
{
|
||||||
|
ATerm t = ATmake(
|
||||||
|
"Attrs(["
|
||||||
|
"Bind(\"type\", Str(\"derivation\")), "
|
||||||
|
"Bind(\"name\", Str(<str>)), "
|
||||||
|
"Bind(\"drvPath\", Path(<str>)), "
|
||||||
|
"Bind(\"outPath\", Path(<str>))"
|
||||||
|
"])",
|
||||||
|
i->second.name.c_str(),
|
||||||
|
i->second.drvPath.c_str(),
|
||||||
|
i->second.outPath.c_str());
|
||||||
|
inputs = ATinsert(inputs, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
ATerm inputs2 = ATmake("List(<term>)", ATreverse(inputs));
|
||||||
|
|
||||||
|
/* Also write a copy of the list of inputs to the store; we need
|
||||||
|
it for future modifications of the environment. */
|
||||||
|
Path inputsFile = writeTerm(inputs2, "-env-inputs");
|
||||||
|
|
||||||
|
Expr topLevel = ATmake(
|
||||||
|
"Call(<term>, Attrs(["
|
||||||
|
"Bind(\"system\", Str(<str>)), "
|
||||||
|
"Bind(\"derivations\", <term>), " // !!! redundant
|
||||||
|
"Bind(\"manifest\", Path(<str>))"
|
||||||
|
"]))",
|
||||||
|
envBuilder, thisSystem.c_str(), inputs2, inputsFile.c_str());
|
||||||
|
|
||||||
|
/* Instantiate it. */
|
||||||
|
debug(format("evaluating builder expression `%1%'") % topLevel);
|
||||||
|
DrvInfo topLevelDrv;
|
||||||
|
if (!parseDerivation(state, topLevel, topLevelDrv))
|
||||||
|
abort();
|
||||||
|
|
||||||
|
/* Realise the resulting store expression. */
|
||||||
|
debug(format("realising user environment"));
|
||||||
|
Path nfPath = normaliseStoreExpr(topLevelDrv.drvPath);
|
||||||
|
realiseClosure(nfPath);
|
||||||
|
|
||||||
|
/* Switch the current user environment to the output path. */
|
||||||
|
debug(format("switching to new user environment"));
|
||||||
|
Path linkPath = createLink(topLevelDrv.outPath, topLevelDrv.drvPath);
|
||||||
|
// switchLink(current"), link);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void opInstall(EvalState & state,
|
||||||
|
Strings opFlags, Strings opArgs)
|
||||||
|
{
|
||||||
|
if (opArgs.size() < 1) throw UsageError("Nix expression expected");
|
||||||
|
|
||||||
|
Path nePath = opArgs.front();
|
||||||
|
opArgs.pop_front();
|
||||||
|
|
||||||
|
installDerivations(state, nePath,
|
||||||
|
Strings(opArgs.begin(), opArgs.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void opQuery(EvalState & state,
|
||||||
|
Strings opFlags, Strings opArgs)
|
||||||
|
{
|
||||||
|
enum { qName } query = qName;
|
||||||
|
enum { sInstalled, sAvailable } source = sInstalled;
|
||||||
|
|
||||||
|
for (Strings::iterator i = opFlags.begin();
|
||||||
|
i != opFlags.end(); ++i)
|
||||||
|
if (*i == "--name") query = qName;
|
||||||
|
else if (*i == "--installed") source = sInstalled;
|
||||||
|
else if (*i == "--available" || *i == "-f") source = sAvailable;
|
||||||
|
else throw UsageError(format("unknown flag `%1%'") % *i);
|
||||||
|
|
||||||
|
/* Obtain derivation information from the specified source. */
|
||||||
|
DrvInfos drvs;
|
||||||
|
|
||||||
|
switch (source) {
|
||||||
|
|
||||||
|
case sInstalled:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sAvailable: {
|
||||||
|
Path nePath = opArgs.front();
|
||||||
|
opArgs.pop_front();
|
||||||
|
loadDerivations(state, nePath, drvs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform the specified query on the derivations. */
|
||||||
|
switch (query) {
|
||||||
|
|
||||||
|
case qName: {
|
||||||
|
if (opArgs.size() != 0) throw UsageError("no arguments expected");
|
||||||
|
for (DrvInfos::iterator i = drvs.begin(); i != drvs.end(); ++i)
|
||||||
|
cout << format("%1%\n") % i->second.name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void run(Strings args)
|
||||||
|
{
|
||||||
|
EvalState state;
|
||||||
|
Strings opFlags, opArgs;
|
||||||
|
Operation op = 0;
|
||||||
|
|
||||||
|
for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
|
||||||
|
string arg = *i;
|
||||||
|
|
||||||
|
Operation oldOp = op;
|
||||||
|
|
||||||
|
if (arg == "--install" || arg == "-i")
|
||||||
|
op = opInstall;
|
||||||
|
if (arg == "--query" || arg == "-q")
|
||||||
|
op = opQuery;
|
||||||
|
else if (arg == "--verbose" || arg == "-v")
|
||||||
|
verbosity = (Verbosity) ((int) verbosity + 1);
|
||||||
|
else if (arg[0] == '-')
|
||||||
|
opFlags.push_back(arg);
|
||||||
|
else
|
||||||
|
opArgs.push_back(arg);
|
||||||
|
|
||||||
|
if (oldOp && oldOp != op)
|
||||||
|
throw UsageError("only one operation may be specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!op) throw UsageError("no operation specified");
|
||||||
|
|
||||||
|
openDB();
|
||||||
|
|
||||||
|
op(state, opFlags, opArgs);
|
||||||
|
|
||||||
|
printEvalStats(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string programId = "nix-env";
|
|
@ -251,9 +251,8 @@ void run(Strings args)
|
||||||
Strings opFlags, opArgs;
|
Strings opFlags, opArgs;
|
||||||
Operation op = 0;
|
Operation op = 0;
|
||||||
|
|
||||||
for (Strings::iterator it = args.begin(); it != args.end(); )
|
for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
|
||||||
{
|
string arg = *i;
|
||||||
string arg = *it++;
|
|
||||||
|
|
||||||
Operation oldOp = op;
|
Operation oldOp = op;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue