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;
}