about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/manual/release-notes.xml6
-rw-r--r--src/libexpr/get-drvs.cc9
-rw-r--r--src/libexpr/get-drvs.hh1
-rw-r--r--src/nix-env/nix-env.cc51
4 files changed, 54 insertions, 13 deletions
diff --git a/doc/manual/release-notes.xml b/doc/manual/release-notes.xml
index da8c47588b9b..43358fe5537a 100644
--- a/doc/manual/release-notes.xml
+++ b/doc/manual/release-notes.xml
@@ -70,10 +70,16 @@
   info about installed packages in user environments.  <option>-q
   --xml --meta</option> to show all meta info.</para></listitem>
 
+  
   <listitem><para>TODO: <command>nix-env</command>
   <option>--set-flag</option>.  Specific flags:
   <literal>active</literal>, <literal>priority</literal>,
   <literal>keep</literal>.</para></listitem>
+
+  
+  <listitem><para>TODO: <command>nix-env</command> <option>-i</option>
+  / <option>-u</option> take package priorities into
+  account.</para></listitem>
   
 
   <listitem><para><command>nix-env -q</command> now has a flag
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index bd0ec4781cfe..daa987fe713b 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 920197d1fb37..46dc51a568af 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 9f965bd2872f..7733ab16b9ec 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;
                     }