nix-env --upgrade: avoid unexpected downgrades

Until now, if one explicitly installed a low-priority version,
nix-env --upgrade would downgrade it by default and even with --leq.
Let's never accept an upgrade with version not matching the upgradeType.
Additionally, let's never decrease the priority of an installed package;
you can use --install to force that.

Also refactor to use variable bestVersion instead of bestName,
as only version was used from it.
This commit is contained in:
Vladimír Čunát 2015-09-17 10:34:54 +02:00
parent 55b1146150
commit 64f9b511be

View file

@ -570,14 +570,16 @@ static void upgradeDerivations(Globals & globals,
constraints specified by upgradeType. If there are constraints specified by upgradeType. If there are
multiple matches, take the one with the highest multiple matches, take the one with the highest
priority. If there are still multiple matches, priority. If there are still multiple matches,
take the one with the highest version. */ take the one with the highest version.
Do not upgrade if it would decrease the priority. */
DrvInfos::iterator bestElem = availElems.end(); DrvInfos::iterator bestElem = availElems.end();
DrvName bestName; string bestVersion;
for (auto j = availElems.begin(); j != availElems.end(); ++j) { for (auto j = availElems.begin(); j != availElems.end(); ++j) {
if (comparePriorities(*globals.state, i, *j) > 0)
continue;
DrvName newName(j->name); DrvName newName(j->name);
if (newName.name == drvName.name) { if (newName.name == drvName.name) {
int d = comparePriorities(*globals.state, i, *j); int d = compareVersions(drvName.version, newName.version);
if (d == 0) d = compareVersions(drvName.version, newName.version);
if ((upgradeType == utLt && d < 0) || if ((upgradeType == utLt && d < 0) ||
(upgradeType == utLeq && d <= 0) || (upgradeType == utLeq && d <= 0) ||
(upgradeType == utEq && d == 0) || (upgradeType == utEq && d == 0) ||
@ -586,11 +588,11 @@ static void upgradeDerivations(Globals & globals,
int d2 = -1; int d2 = -1;
if (bestElem != availElems.end()) { if (bestElem != availElems.end()) {
d2 = comparePriorities(*globals.state, *bestElem, *j); d2 = comparePriorities(*globals.state, *bestElem, *j);
if (d2 == 0) d2 = compareVersions(bestName.version, newName.version); if (d2 == 0) d2 = compareVersions(bestVersion, newName.version);
} }
if (d2 < 0 && (!globals.prebuiltOnly || isPrebuilt(*globals.state, *j))) { if (d2 < 0 && (!globals.prebuiltOnly || isPrebuilt(*globals.state, *j))) {
bestElem = j; bestElem = j;
bestName = newName; bestVersion = newName.version;
} }
} }
} }