forked from lix-project/lix
* -u' ->
-e'.
* `--link' / `-l' flag to specify the switch symlink to use (by default, /nix/var/nix/links/current).
This commit is contained in:
parent
0a753e182a
commit
a81b621202
|
@ -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
|
||||||
|
|
|
@ -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,9 +397,11 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue