From 64f9b511be8a77ba98c0dd40df022b7d299293d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20=C4=8Cun=C3=A1t?= Date: Thu, 17 Sep 2015 10:34:54 +0200 Subject: [PATCH] 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. --- src/nix-env/nix-env.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 97a2bbdb7..ddbba2484 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -570,14 +570,16 @@ static void upgradeDerivations(Globals & globals, constraints specified by upgradeType. If there are multiple matches, take the one with the highest 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(); - DrvName bestName; + string bestVersion; for (auto j = availElems.begin(); j != availElems.end(); ++j) { + if (comparePriorities(*globals.state, i, *j) > 0) + continue; DrvName newName(j->name); if (newName.name == drvName.name) { - int d = comparePriorities(*globals.state, i, *j); - if (d == 0) d = compareVersions(drvName.version, newName.version); + int d = compareVersions(drvName.version, newName.version); if ((upgradeType == utLt && d < 0) || (upgradeType == utLeq && d <= 0) || (upgradeType == utEq && d == 0) || @@ -586,11 +588,11 @@ static void upgradeDerivations(Globals & globals, int d2 = -1; if (bestElem != availElems.end()) { 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))) { bestElem = j; - bestName = newName; + bestVersion = newName.version; } } }