* In --upgrade': added flags --lt', --leq', --always' to specify

whether we want to upgrade if the current version is less than the
  available version (default), when it is less or equal, or always.
  
* Added a flag `--dry-run' to show what would happen in `--install',
  `--uninstall', and `--upgrade', without actually performing the
  operation.
This commit is contained in:
Eelco Dolstra 2004-02-09 11:59:39 +00:00
parent 06a75a7e0c
commit 618aa69b01
4 changed files with 81 additions and 24 deletions

View file

@ -22,6 +22,16 @@ name `*' may be used to indicate all derivations.
--version: output version information --version: output version information
--help: display help --help: display help
Install / upgrade / uninstall flags:
--dry-run: show what would be done, but don't do it
Upgrade flags:
--lt: upgrade unless the current version is older (default)
--leq: upgrade unless the current version is older or current
--always: upgrade regardless of current version
Query types: Query types:
--name: print derivation names (default) --name: print derivation names (default)

View file

@ -16,6 +16,7 @@ struct Globals
Path profile; Path profile;
Path nixExprPath; Path nixExprPath;
EvalState state; EvalState state;
bool dryRun;
}; };
@ -201,7 +202,8 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs,
static void installDerivations(EvalState & state, static void installDerivations(EvalState & state,
Path nePath, DrvNames & selectors, const Path & profile) Path nePath, DrvNames & selectors, const Path & profile,
bool dryRun)
{ {
debug(format("installing derivations from `%1%'") % nePath); debug(format("installing derivations from `%1%'") % nePath);
@ -239,6 +241,8 @@ static void installDerivations(EvalState & state,
queryInstalled(state, installedDrvs, profile); queryInstalled(state, installedDrvs, profile);
selectedDrvs.insert(installedDrvs.begin(), installedDrvs.end()); selectedDrvs.insert(installedDrvs.begin(), installedDrvs.end());
if (dryRun) return;
createUserEnv(state, selectedDrvs, profile); createUserEnv(state, selectedDrvs, profile);
} }
@ -252,12 +256,16 @@ static void opInstall(Globals & globals,
DrvNames drvNames = drvNamesFromArgs(opArgs); DrvNames drvNames = drvNamesFromArgs(opArgs);
installDerivations(globals.state, globals.nixExprPath, installDerivations(globals.state, globals.nixExprPath,
drvNames, globals.profile); drvNames, globals.profile, globals.dryRun);
} }
typedef enum { utLt, utLeq, utAlways } UpgradeType;
static void upgradeDerivations(EvalState & state, static void upgradeDerivations(EvalState & state,
Path nePath, DrvNames & selectors, const Path & profile) Path nePath, DrvNames & selectors, const Path & profile,
UpgradeType upgradeType, bool dryRun)
{ {
debug(format("upgrading derivations from `%1%'") % nePath); debug(format("upgrading derivations from `%1%'") % nePath);
@ -293,30 +301,50 @@ static void upgradeDerivations(EvalState & state,
} }
} }
if (!upgrade) {
newDrvs.insert(*i);
continue;
}
/* If yes, find the derivation in the input Nix expression /* If yes, find the derivation in the input Nix expression
with the same name and the highest version number. */ with the same name and satisfying the version constraints
DrvInfos::iterator bestDrv = i; specified by upgradeType. If there are multiple matches,
DrvName bestName = drvName; take the one with highest version. */
if (upgrade) { DrvInfos::iterator bestDrv = availDrvs.end();
for (DrvInfos::iterator j = availDrvs.begin(); DrvName bestName;
j != availDrvs.end(); ++j) for (DrvInfos::iterator j = availDrvs.begin();
{ j != availDrvs.end(); ++j)
DrvName newName(j->second.name); {
if (newName.name == bestName.name && DrvName newName(j->second.name);
compareVersions(newName.version, bestName.version) > 0) if (newName.name == drvName.name) {
bestDrv = j; int d = compareVersions(drvName.version, newName.version);
if (upgradeType == utLt && d < 0 ||
upgradeType == utLeq && d <= 0 ||
upgradeType == utAlways)
{
if (bestDrv == availDrvs.end() ||
compareVersions(
bestName.version, newName.version) < 0)
{
bestDrv = j;
bestName = newName;
}
}
} }
} }
if (bestDrv != i) { if (bestDrv != availDrvs.end() &&
i->second.drvPath != bestDrv->second.drvPath)
{
printMsg(lvlInfo, printMsg(lvlInfo,
format("upgrading `%1%' to `%2%'") format("upgrading `%1%' to `%2%'")
% i->second.name % bestDrv->second.name); % i->second.name % bestDrv->second.name);
} newDrvs.insert(*bestDrv);
} else newDrvs.insert(*i);
newDrvs.insert(*bestDrv);
} }
if (dryRun) return;
createUserEnv(state, newDrvs, profile); createUserEnv(state, newDrvs, profile);
} }
@ -324,19 +352,23 @@ static void upgradeDerivations(EvalState & state,
static void opUpgrade(Globals & globals, static void opUpgrade(Globals & globals,
Strings opFlags, Strings opArgs) Strings opFlags, Strings opArgs)
{ {
if (opFlags.size() > 0) UpgradeType upgradeType = utLt;
throw UsageError(format("unknown flags `%1%'") % opFlags.front()); for (Strings::iterator i = opFlags.begin();
if (opArgs.size() < 1) throw UsageError("Nix file expected"); i != opFlags.end(); ++i)
if (*i == "--lt") upgradeType = utLt;
else if (*i == "--leq") upgradeType = utLeq;
else if (*i == "--always") upgradeType = utAlways;
else throw UsageError(format("unknown flag `%1%'") % *i);
DrvNames drvNames = drvNamesFromArgs(opArgs); DrvNames drvNames = drvNamesFromArgs(opArgs);
upgradeDerivations(globals.state, globals.nixExprPath, upgradeDerivations(globals.state, globals.nixExprPath,
drvNames, globals.profile); drvNames, globals.profile, upgradeType, globals.dryRun);
} }
static void uninstallDerivations(EvalState & state, DrvNames & selectors, static void uninstallDerivations(EvalState & state, DrvNames & selectors,
Path & profile) Path & profile, bool dryRun)
{ {
DrvInfos installedDrvs; DrvInfos installedDrvs;
queryInstalled(state, installedDrvs, profile); queryInstalled(state, installedDrvs, profile);
@ -354,6 +386,8 @@ static void uninstallDerivations(EvalState & state, DrvNames & selectors,
} }
} }
if (dryRun) return;
createUserEnv(state, installedDrvs, profile); createUserEnv(state, installedDrvs, profile);
} }
@ -366,7 +400,8 @@ static void opUninstall(Globals & globals,
DrvNames drvNames = drvNamesFromArgs(opArgs); DrvNames drvNames = drvNamesFromArgs(opArgs);
uninstallDerivations(globals.state, drvNames, globals.profile); uninstallDerivations(globals.state, drvNames,
globals.profile, globals.dryRun);
} }
@ -575,6 +610,7 @@ void run(Strings args)
Globals globals; Globals globals;
globals.nixExprPath = getDefNixExprPath(); globals.nixExprPath = getDefNixExprPath();
globals.dryRun = false;
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;
@ -611,6 +647,10 @@ void run(Strings args)
op = opRollback; op = opRollback;
else if (arg == "--list-generations") else if (arg == "--list-generations")
op = opListGenerations; op = opListGenerations;
else if (arg == "--dry-run") {
printMsg(lvlInfo, "(dry run; not doing anything)");
globals.dryRun = true;
}
else if (arg[0] == '-') else if (arg[0] == '-')
opFlags.push_back(arg); opFlags.push_back(arg);
else else

View file

@ -1,6 +1,12 @@
#include "names.hh" #include "names.hh"
DrvName::DrvName()
{
name = "";
}
/* Parse a derivation name. The `name' part of a derivation name is /* Parse a derivation name. The `name' part of a derivation name is
everything up to but not including the first dash *not* followed by everything up to but not including the first dash *not* followed by
a letter. The `version' part is the rest (excluding the separating a letter. The `version' part is the rest (excluding the separating

View file

@ -14,6 +14,7 @@ struct DrvName
string version; string version;
unsigned int hits; unsigned int hits;
DrvName();
DrvName(const string & s); DrvName(const string & s);
bool matches(DrvName & n); bool matches(DrvName & n);
}; };