diff --git a/doc/manual/release-notes.xml b/doc/manual/release-notes.xml index da8c47588..43358fe55 100644 --- a/doc/manual/release-notes.xml +++ b/doc/manual/release-notes.xml @@ -70,10 +70,16 @@ info about installed packages in user environments. to show all meta info. + TODO: nix-env . Specific flags: active, priority, keep. + + + TODO: nix-env + / take package priorities into + account. nix-env -q now has a flag diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index bd0ec4781..daa987fe7 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -60,6 +60,15 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const } +string DrvInfo::queryMetaInfo(EvalState & state, const string & name) const +{ + /* !!! evaluates all meta attributes => inefficient */ + MetaInfo meta = queryMetaInfo(state); + MetaInfo::iterator i = meta.find(name); + return i == meta.end() ? "" : i->second; +} + + void DrvInfo::setMetaInfo(const MetaInfo & meta) { ATermMap metaAttrs; diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh index 920197d1f..46dc51a56 100644 --- a/src/libexpr/get-drvs.hh +++ b/src/libexpr/get-drvs.hh @@ -34,6 +34,7 @@ public: string queryDrvPath(EvalState & state) const; string queryOutPath(EvalState & state) const; MetaInfo queryMetaInfo(EvalState & state) const; + string queryMetaInfo(EvalState & state, const string & name) const; void setDrvPath(const string & s) { diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 9f965bd28..7733ab16b 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -232,6 +232,16 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems, } +static int comparePriorities(EvalState & state, + const DrvInfo & drv1, const DrvInfo & drv2) +{ + int prio1, prio2; + if (!string2Int(drv1.queryMetaInfo(state, "priority"), prio1)) prio1 = 0; + if (!string2Int(drv2.queryMetaInfo(state, "priority"), prio2)) prio2 = 0; + return prio2 - prio1; /* higher number = lower priority, so negate */ +} + + static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, const Strings & args, bool newestOnly) @@ -258,8 +268,10 @@ static DrvInfos filterBySelector(EvalState & state, } /* If `newestOnly', if a selector matches multiple derivations - with the same name, pick the one with the highest version. - If there are multiple derivations with the same name *and* + with the same name, pick the one with the highest priority. + If there are multiple derivations with the same priority, + pick the one with the highest version. If there are + multiple derivations with the same priority and name and version, then pick the first one. */ if (newestOnly) { @@ -270,13 +282,22 @@ static DrvInfos filterBySelector(EvalState & state, for (Matches::iterator j = matches.begin(); j != matches.end(); ++j) { DrvName drvName(j->first.name); + int d = 1; + Newest::iterator k = newest.find(drvName.name); + if (k != newest.end()) { - int d = compareVersions(drvName.version, DrvName(k->second.first.name).version); - if (d > 0) newest[drvName.name] = *j; - else if (d == 0) multiple.insert(j->first.name); - } else + d = comparePriorities(state, j->first, k->second.first); + if (d == 0) + d = compareVersions(drvName.version, DrvName(k->second.first.name).version); + } + + if (d > 0) { newest[drvName.name] = *j; + multiple.erase(j->first.name); + } else if (d == 0) { + multiple.insert(j->first.name); + } } matches.clear(); @@ -549,9 +570,10 @@ static void upgradeDerivations(Globals & globals, if (meta["keep"] == "true") continue; /* Find the derivation in the input Nix expression with the - same name and satisfying the version constraints specified + same name that satisfies the version constraints specified by upgradeType. If there are multiple matches, take the - one with highest version. */ + one with the highest priority. If there are still multiple + matches, take the one with the highest version. */ DrvInfos::iterator bestElem = availElems.end(); DrvName bestName; for (DrvInfos::iterator j = availElems.begin(); @@ -559,16 +581,19 @@ static void upgradeDerivations(Globals & globals, { DrvName newName(j->name); if (newName.name == drvName.name) { - int d = compareVersions(drvName.version, newName.version); + int d = comparePriorities(globals.state, *i, *j); + if (d == 0) d = compareVersions(drvName.version, newName.version); if (upgradeType == utLt && d < 0 || upgradeType == utLeq && d <= 0 || upgradeType == utEq && d == 0 || upgradeType == utAlways) { - if ((bestElem == availElems.end() || - compareVersions( - bestName.version, newName.version) < 0)) - { + 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) { bestElem = j; bestName = newName; }