Imported Upstream version 0.7.5
[platform/upstream/libsolv.git] / src / policy.c
index a38dea0..823a008 100644 (file)
@@ -454,86 +454,18 @@ prefer_suggested(Solver *solv, Queue *plist)
 }
 
 static int
-sort_by_favorq_cmp(const void *ap, const void *bp, void *dp)
+sort_by_favor_cmp(const void *ap, const void *bp, void *dp)
 {
   const Id *a = ap, *b = bp, *d = dp;
   return d[b[0]] - d[a[0]];
 }
 
-static void
-sort_by_favorq(Queue *favorq, Id *el, int cnt)
-{
-  int i;
-  /* map to offsets into favorq */
-  for (i = 0; i < cnt; i++)
-    {
-      Id p = el[i];
-      /* lookup p in sorted favorq */
-      int med = 0, low = 0;
-      int high = favorq->count / 2;
-      while (low != high)
-       {
-         med = (low + high) / 2;
-         Id pp = favorq->elements[2 * med];
-         if (pp < p)
-           low = med;
-         else if (pp > p)
-           high = med;
-         else
-           break;
-       }
-      while(med && favorq->elements[2 * med - 2] == p)
-       med--;
-      if (favorq->elements[2 * med] == p)
-        el[i] = 2 * med + 1;
-      else
-        el[i] = 0;     /* hmm */
-    }
-  /* sort by position */
-  solv_sort(el, cnt, sizeof(Id), sort_by_favorq_cmp, favorq->elements);
-  /* map back */
-  for (i = 0; i < cnt; i++)
-    if (el[i])
-      el[i] = favorq->elements[el[i] - 1];
-}
-
 /* bring favored packages to front and disfavored packages to back */
 void
 policy_prefer_favored(Solver *solv, Queue *plist)
 {
-  int i, fav, disfav, count;
-  if (!solv->favormap.size)
-    return;
-  for (i = fav = disfav = 0, count = plist->count; i < count; i++)
-    {
-      Id p = plist->elements[i];
-      if (!MAPTST(&solv->favormap, p))
-       continue;
-      if (solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, p))
-       {
-         /* disfavored package. bring to back */
-        if (i < plist->count - 1)
-           {
-             memmove(plist->elements + i, plist->elements + i + 1, (plist->count - 1 - i) * sizeof(Id));
-             plist->elements[plist->count - 1] = p;
-           }
-         i--;
-         count--;
-         disfav++;
-       }
-      else
-       {
-         /* favored package. bring to front */
-         if (i > fav)
-           memmove(plist->elements + fav + 1, plist->elements + fav, (i - fav) * sizeof(Id));
-         plist->elements[fav++] = p;
-       }
-    }
-  /* if we have multiple favored/disfavored packages, sort by favorq index */
-  if (fav > 1)
-    sort_by_favorq(solv->favorq, plist->elements, fav);
-  if (disfav > 1)
-    sort_by_favorq(solv->favorq, plist->elements + plist->count - disfav, disfav);
+  if (solv->favormap && plist->count > 1)
+    solv_sort(plist->elements, plist->count, sizeof(Id), sort_by_favor_cmp, solv->favormap);
 }
 
 /*
@@ -866,6 +798,8 @@ move_installed_to_front(Pool *pool, Queue *plist)
   Solvable *s;
   Id p, pp;
 
+  if (!pool->installed)
+    return;
   for (i = j = 0; i < plist->count; i++)
     {
       s = pool->solvables + plist->elements[i];
@@ -899,6 +833,26 @@ move_installed_to_front(Pool *pool, Queue *plist)
     }
 }
 
+static int
+pool_buildversioncmp(Pool *pool, Solvable *s1, Solvable *s2)
+{
+  const char *bv1 = solvable_lookup_str(s1, SOLVABLE_BUILDVERSION);
+  const char *bv2 = solvable_lookup_str(s2, SOLVABLE_BUILDVERSION);
+  if (!bv1 && !bv2)
+    return 0;
+  return pool_evrcmp_str(pool, bv1 ? bv1 : "" , bv2 ? bv2 : "", EVRCMP_COMPARE);
+}
+
+static int
+pool_buildflavorcmp(Pool *pool, Solvable *s1, Solvable *s2)
+{
+  const char *f1 = solvable_lookup_str(s1, SOLVABLE_BUILDFLAVOR);
+  const char *f2 = solvable_lookup_str(s2, SOLVABLE_BUILDFLAVOR);
+  if (!f1 && !f2)
+    return 0;
+  return pool_evrcmp_str(pool, f1 ? f1 : "" , f2 ? f2 : "", EVRCMP_COMPARE);
+}
+
 /*
  * prune_to_best_version
  *
@@ -924,9 +878,9 @@ prune_to_best_version(Pool *pool, Queue *plist)
     {
       s = pool->solvables + plist->elements[i];
 
-      POOL_DEBUG(SOLV_DEBUG_POLICY, "- %s[%s]\n",
-                pool_solvable2str(pool, s),
-                (pool->installed && s->repo == pool->installed) ? "installed" : "not installed");
+      POOL_DEBUG(SOLV_DEBUG_POLICY, "- %s [%d]%s\n",
+                pool_solvable2str(pool, s), plist->elements[i], 
+                (pool->installed && s->repo == pool->installed) ? "I" : "");
 
       if (!best)               /* if no best yet, the current is best */
         {
@@ -946,6 +900,10 @@ prune_to_best_version(Pool *pool, Queue *plist)
       if (r == 0 && has_package_link(pool, s))
         r = pool_link_evrcmp(pool, best, s);
 #endif
+      if (r == 0 && pool->disttype == DISTTYPE_CONDA)
+       r = pool_buildversioncmp(pool, best, s);
+      if (r == 0 && pool->disttype == DISTTYPE_CONDA)
+       r = pool_buildflavorcmp(pool, best, s);
       if (r < 0)
        best = s;
     }
@@ -961,8 +919,6 @@ prune_to_best_version(Pool *pool, Queue *plist)
       else
         prune_obsoleted(pool, plist);
     }
-  if (plist->count > 1 && pool->installed)
-    move_installed_to_front(pool, plist);
 }
 
 
@@ -1236,7 +1192,7 @@ urpm_reorder(Solver *solv, Queue *plist)
                    {
                      char kn[256];
                      Id p, pp, knid;
-                     memcpy(kn, "kernel", 8);
+                     memcpy(kn, "kernel", 7);
                      memcpy(kn + 6, flavor, release - flavor + 1);
                      memcpy(kn + 6 + (release - flavor) + 1, sn, flavor - sn);
                      strcpy(kn + 6 + (release + 1 - sn), release);
@@ -1300,6 +1256,37 @@ urpm_reorder(Solver *solv, Queue *plist)
   queue_truncate(plist, count);
 }
 
+/* support multiple favor groups by calling policy_filter_unwanted on
+ * each of them and combining the result */
+static void
+policy_filter_unwanted_favored(Solver *solv, Queue *plist, int mode)
+{
+  int i, j, f;
+  Queue qin, qprune;
+  queue_init_clone(&qin, plist);
+  queue_empty(plist);
+  /* sort by favor group */
+  solv_sort(qin.elements, qin.count, sizeof(Id), sort_by_favor_cmp, solv->favormap);
+  /* go over groups */
+  queue_init(&qprune);
+  for (i = 0; i < qin.count; i = j)
+    {
+      /* find end of group */
+      f = solv->favormap[qin.elements[i]];
+      for (j = i + 1; j < qin.count; j++)
+       if (solv->favormap[qin.elements[j]] != f)
+         break;
+      /* prune this group */
+      queue_empty(&qprune);
+      queue_insertn(&qprune, 0, j, qin.elements);
+      policy_filter_unwanted(solv, &qprune, mode | POLICY_MODE_FAVOR_REC);
+      for (i = 0; i < qprune.count; i++)
+       if (solv->favormap[qprune.elements[i]] == f)
+         queue_push(plist, qprune.elements[i]);
+    }
+  queue_free(&qprune);
+  queue_free(&qin);
+}
 
 /*
  *  POLICY_MODE_CHOOSE:     default, do all pruning steps
@@ -1321,6 +1308,21 @@ policy_filter_unwanted(Solver *solv, Queue *plist, int mode)
       policy_prefer_favored(solv, plist);
       return;
     }
+  if (mode & POLICY_MODE_FAVOR_REC)
+    mode ^= POLICY_MODE_FAVOR_REC;
+  else if (solv->favormap && plist->count > 1)
+    {
+      /* check if we have multiple favor groups */
+      int i, f = solv->favormap[plist->elements[0]];
+      for (i = 1; i < plist->count; i++)
+       if (solv->favormap[plist->elements[i]] != f)
+         break;
+      if (i < plist->count)
+       {
+         policy_filter_unwanted_favored(solv, plist, mode);
+         return;
+       }
+    }
   if (plist->count > 1)
     {
       if (mode != POLICY_MODE_SUGGEST)
@@ -1343,6 +1345,7 @@ policy_filter_unwanted(Solver *solv, Queue *plist, int mode)
 #endif
          dislike_old_versions(pool, plist);
          sort_by_common_dep(pool, plist);
+         move_installed_to_front(pool, plist);
          if (solv->urpmreorder)
            urpm_reorder(solv, plist);
          prefer_suggested(solv, plist);
@@ -1364,6 +1367,7 @@ pool_best_solvables(Pool *pool, Queue *plist, int flags)
     {
       dislike_old_versions(pool, plist);
       sort_by_common_dep(pool, plist);
+      move_installed_to_front(pool, plist);
     }
 }