* -u' -> -e'.

* `--link' / `-l' flag to specify the switch symlink to use (by default, 
  /nix/var/nix/links/current).
This commit is contained in:
Eelco Dolstra 2003-12-21 22:34:41 +00:00
parent 0a753e182a
commit a81b621202
2 changed files with 58 additions and 39 deletions

View file

@ -5,7 +5,7 @@ nix-env [OPTIONS...] [ARGUMENTS...]
Operations: Operations:
--install / -i FILE: add a derivation to the user environment --install / -i FILE: add a derivation to the user environment
--uninstall / -u: remove a derivation to the user environment --uninstall / -e: remove a derivation to the user environment
--query / -q: perform a query on an environment or Nix expression --query / -q: perform a query on an environment or Nix expression
The previous operations take a list of derivation names. The special The previous operations take a list of derivation names. The special
@ -27,5 +27,6 @@ Query sources:
Options: Options:
--link / -l LINK: use symlink LINK instead of (...)/current
--verbose / -v: verbose operation (may be repeated) --verbose / -v: verbose operation (may be repeated)
--keep-failed / -K: keep temporary directories of failed builds --keep-failed / -K: keep temporary directories of failed builds

View file

@ -6,7 +6,14 @@
#include "help.txt.hh" #include "help.txt.hh"
typedef void (* Operation) (EvalState & state, struct Globals
{
Path linkPath;
EvalState state;
};
typedef void (* Operation) (Globals & globals,
Strings opFlags, Strings opArgs); Strings opFlags, Strings opArgs);
@ -103,15 +110,10 @@ static Path getLinksDir()
} }
static Path getCurrentPath() void queryInstalled(EvalState & state, DrvInfos & drvs,
const Path & userEnv)
{ {
return getLinksDir() + "/current"; Path path = userEnv + "/manifest";
}
void queryInstalled(EvalState & state, DrvInfos & drvs)
{
Path path = getCurrentPath() + "/manifest";
if (!pathExists(path)) return; /* not an error, assume nothing installed */ if (!pathExists(path)) return; /* not an error, assume nothing installed */
@ -123,7 +125,7 @@ void queryInstalled(EvalState & state, DrvInfos & drvs)
} }
Path createLink(Path outPath, Path drvPath) Path createGeneration(Path outPath, Path drvPath)
{ {
Path linksDir = getLinksDir(); Path linksDir = getLinksDir();
@ -136,20 +138,20 @@ Path createLink(Path outPath, Path drvPath)
if (s >> n && s.eof() && n >= num) num = n + 1; if (s >> n && s.eof() && n >= num) num = n + 1;
} }
Path linkPath; Path generation;
while (1) { while (1) {
linkPath = (format("%1%/%2%") % linksDir % num).str(); generation = (format("%1%/%2%") % linksDir % num).str();
if (symlink(outPath.c_str(), linkPath.c_str()) == 0) break; if (symlink(outPath.c_str(), generation.c_str()) == 0) break;
if (errno != EEXIST) if (errno != EEXIST)
throw SysError(format("creating symlink `%1%'") % linkPath); throw SysError(format("creating symlink `%1%'") % generation);
/* Somebody beat us to it, retry with a higher number. */ /* Somebody beat us to it, retry with a higher number. */
num++; num++;
} }
writeStringToFile(linkPath + "-src.id", drvPath); writeStringToFile(generation + "-src.id", drvPath);
return linkPath; return generation;
} }
@ -169,7 +171,8 @@ void switchLink(Path link, Path target)
} }
void createUserEnv(EvalState & state, const DrvInfos & drvs) void createUserEnv(EvalState & state, const DrvInfos & drvs,
const Path & linkPath)
{ {
/* Get the environment builder expression. */ /* Get the environment builder expression. */
Expr envBuilder = parseExprFromFile(nixDataDir + "/nix/corepkgs/buildenv"); /* !!! */ Expr envBuilder = parseExprFromFile(nixDataDir + "/nix/corepkgs/buildenv"); /* !!! */
@ -221,8 +224,9 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs)
/* Switch the current user environment to the output path. */ /* Switch the current user environment to the output path. */
debug(format("switching to new user environment")); debug(format("switching to new user environment"));
Path linkPath = createLink(topLevelDrv.outPath, topLevelDrv.drvPath); Path generation = createGeneration(
switchLink(getLinksDir() + "/current", linkPath); topLevelDrv.outPath, topLevelDrv.drvPath);
switchLink(linkPath, generation);
} }
@ -239,7 +243,7 @@ NameMap mapByNames(DrvInfos & drvs)
void installDerivations(EvalState & state, void installDerivations(EvalState & state,
Path nePath, Strings drvNames) Path nePath, Strings drvNames, const Path & linkPath)
{ {
debug(format("installing derivations from `%1%'") % nePath); debug(format("installing derivations from `%1%'") % nePath);
@ -267,30 +271,33 @@ void installDerivations(EvalState & state,
/* Add in the already installed derivations. */ /* Add in the already installed derivations. */
DrvInfos installedDrvs; DrvInfos installedDrvs;
queryInstalled(state, installedDrvs); queryInstalled(state, installedDrvs, linkPath);
selectedDrvs.insert(installedDrvs.begin(), installedDrvs.end()); selectedDrvs.insert(installedDrvs.begin(), installedDrvs.end());
createUserEnv(state, selectedDrvs); createUserEnv(state, selectedDrvs, linkPath);
} }
static void opInstall(EvalState & state, static void opInstall(Globals & globals,
Strings opFlags, Strings opArgs) Strings opFlags, Strings opArgs)
{ {
if (opFlags.size() > 0)
throw UsageError(format("unknown flags `%1%'") % opFlags.front());
if (opArgs.size() < 1) throw UsageError("Nix file expected"); if (opArgs.size() < 1) throw UsageError("Nix file expected");
Path nePath = opArgs.front(); Path nePath = opArgs.front();
opArgs.pop_front(); opArgs.pop_front();
installDerivations(state, nePath, installDerivations(globals.state, nePath,
Strings(opArgs.begin(), opArgs.end())); Strings(opArgs.begin(), opArgs.end()), globals.linkPath);
} }
void uninstallDerivations(EvalState & state, Strings drvNames) void uninstallDerivations(EvalState & state, Strings drvNames,
Path & linkPath)
{ {
DrvInfos installedDrvs; DrvInfos installedDrvs;
queryInstalled(state, installedDrvs); queryInstalled(state, installedDrvs, linkPath);
NameMap nameMap = mapByNames(installedDrvs); NameMap nameMap = mapByNames(installedDrvs);
@ -304,18 +311,21 @@ void uninstallDerivations(EvalState & state, Strings drvNames)
installedDrvs.erase(j->second); installedDrvs.erase(j->second);
} }
createUserEnv(state, installedDrvs); createUserEnv(state, installedDrvs, linkPath);
} }
static void opUninstall(EvalState & state, static void opUninstall(Globals & globals,
Strings opFlags, Strings opArgs) Strings opFlags, Strings opArgs)
{ {
uninstallDerivations(state, opArgs); if (opFlags.size() > 0)
throw UsageError(format("unknown flags `%1%'") % opFlags.front());
uninstallDerivations(globals.state, opArgs, globals.linkPath);
} }
static void opQuery(EvalState & state, static void opQuery(Globals & globals,
Strings opFlags, Strings opArgs) Strings opFlags, Strings opArgs)
{ {
enum { qName, qDrvPath, qStatus } query = qName; enum { qName, qDrvPath, qStatus } query = qName;
@ -336,14 +346,14 @@ static void opQuery(EvalState & state,
switch (source) { switch (source) {
case sInstalled: case sInstalled:
queryInstalled(state, drvs); queryInstalled(globals.state, drvs, globals.linkPath);
break; break;
case sAvailable: { case sAvailable: {
if (opArgs.size() < 1) throw UsageError("Nix file expected"); if (opArgs.size() < 1) throw UsageError("Nix file expected");
Path nePath = opArgs.front(); Path nePath = opArgs.front();
opArgs.pop_front(); opArgs.pop_front();
loadDerivations(state, nePath, drvs); loadDerivations(globals.state, nePath, drvs);
break; break;
} }
@ -369,7 +379,7 @@ static void opQuery(EvalState & state,
case qStatus: { case qStatus: {
DrvInfos installed; DrvInfos installed;
queryInstalled(state, installed); queryInstalled(globals.state, installed, globals.linkPath);
for (DrvInfos::iterator i = drvs.begin(); i != drvs.end(); ++i) { for (DrvInfos::iterator i = drvs.begin(); i != drvs.end(); ++i) {
cout << format("%1%%2% %3%\n") cout << format("%1%%2% %3%\n")
@ -387,10 +397,12 @@ static void opQuery(EvalState & state,
void run(Strings args) void run(Strings args)
{ {
EvalState state;
Strings opFlags, opArgs; Strings opFlags, opArgs;
Operation op = 0; Operation op = 0;
Globals globals;
globals.linkPath = getLinksDir() + "/current";
for (Strings::iterator i = args.begin(); i != args.end(); ++i) { for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
string arg = *i; string arg = *i;
@ -398,10 +410,16 @@ void run(Strings args)
if (arg == "--install" || arg == "-i") if (arg == "--install" || arg == "-i")
op = opInstall; op = opInstall;
else if (arg == "--uninstall" || arg == "-u") else if (arg == "--uninstall" || arg == "-e")
op = opUninstall; op = opUninstall;
else if (arg == "--query" || arg == "-q") else if (arg == "--query" || arg == "-q")
op = opQuery; op = opQuery;
else if (arg == "--link" || arg == "-l") {
++i;
if (i == args.end()) throw UsageError(
format("`%1%' requires an argument") % arg);
globals.linkPath = absPath(*i);
}
else if (arg[0] == '-') else if (arg[0] == '-')
opFlags.push_back(arg); opFlags.push_back(arg);
else else
@ -415,9 +433,9 @@ void run(Strings args)
openDB(); openDB();
op(state, opFlags, opArgs); op(globals, opFlags, opArgs);
printEvalStats(state); printEvalStats(globals.state);
} }