- fix old FIXME by not pruning installed packages
authorMichael Schroeder <mls@suse.de>
Mon, 17 Nov 2008 14:40:37 +0000 (14:40 +0000)
committerMichael Schroeder <mls@suse.de>
Mon, 17 Nov 2008 14:40:37 +0000 (14:40 +0000)
- add repo sub-priority, used for comparing and not pruning
  useful for prefering some source url

src/policy.c
src/policy.h
src/repo.h
src/solver.c

index ab3dd46..37d2134 100644 (file)
@@ -22,7 +22,7 @@
 #include "poolarch.h"
 
 
-static Solver *prune_best_version_arch_sortcmp_data;
+static Solver *prune_to_best_version_sortcmp_data;
 
 /*-----------------------------------------------------------------*/
 
@@ -32,21 +32,25 @@ static Solver *prune_best_version_arch_sortcmp_data;
  */
 
 static int
-prune_best_version_arch_sortcmp(const void *ap, const void *bp)
+prune_to_best_version_sortcmp(const void *ap, const void *bp)
 {
-  Solver *solv = prune_best_version_arch_sortcmp_data;
+  Solver *solv = prune_to_best_version_sortcmp_data;
   Pool *pool = solv->pool;
   int r;
   Id a = *(Id *)ap;
   Id b = *(Id *)bp;
-  r = pool->solvables[a].name - pool->solvables[b].name;
+  Solvable *sa, *sb;
+
+  sa = pool->solvables + a;
+  sb = pool->solvables + b;
+  r = sa->name - sb->name;
   if (r)
     {
       const char *na, *nb;
       /* different names. We use real strcmp here so that the result
        * is not depending on some random solvable order */
-      na = id2str(pool, pool->solvables[a].name);
-      nb = id2str(pool, pool->solvables[b].name);
+      na = id2str(pool, sa->name);
+      nb = id2str(pool, sb->name);
       /* bring patterns to the front */
       /* XXX: no longer needed? */
       if (!strncmp(na, "pattern:", 8))
@@ -61,22 +65,29 @@ prune_best_version_arch_sortcmp(const void *ap, const void *bp)
        }
       return strcmp(na, nb);
     }
-  /* the same name */
-  if (pool->solvables[a].evr == pool->solvables[b].evr && solv->installed)
+  /* the same name, bring installed solvables to the front */
+  if (solv->installed)
     {
-       /* prefer installed solvables */
-      if (pool->solvables[a].repo == solv->installed)
-       return -1;
-      if (pool->solvables[b].repo == solv->installed)
+      if (sa->repo == solv->installed)
+       {
+         if (sb->repo != solv->installed)
+           return -1;
+       }
+      else if (sb->repo == solv->installed)
        return 1;       
     }
+  /* sort by repository sub-prio (installed repo handled above) */
+  r = (sb->repo ? sb->repo->subpriority : 0) - (sa->repo ? sa->repo->subpriority : 0);
+  if (r)
+    return r;
+  /* no idea about the order, sort by id */
   return a - b;
 }
 
 
 /*
- * prune to repository with highest priority
- * 
+ * prune to repository with highest priority.
+ * does not prune installed solvables.
  */
 
 static void
@@ -90,13 +101,15 @@ prune_to_highest_prio(Pool *pool, Queue *plist)
   for (i = 0; i < plist->count; i++)  /* find highest prio in queue */
     {
       s = pool->solvables + plist->elements[i];
+      if (pool->installed && s->repo == pool->installed)
+       continue;
       if (i == 0 || s->repo->priority > bestprio)
        bestprio = s->repo->priority;
     }
   for (i = j = 0; i < plist->count; i++) /* remove all with lower prio */
     {
       s = pool->solvables + plist->elements[i];
-      if (s->repo->priority == bestprio)
+      if (s->repo->priority == bestprio || (pool->installed && s->repo == pool->installed))
        plist->elements[j++] = plist->elements[i];
     }
   plist->count = j;
@@ -104,20 +117,33 @@ prune_to_highest_prio(Pool *pool, Queue *plist)
 
 
 /*
- * prune_to_recommended
- *
- * XXX: should we prune to requires/suggests that are already
- * fulfilled by other packages?
+ * prune to recommended/suggested packages.
+ * does not prune installed packages (they are also somewhat recommended).
  */
 
 static void
 prune_to_recommended(Solver *solv, Queue *plist)
 {
   Pool *pool = solv->pool;
-  int i, j;
+  int i, j, k, ninst;
   Solvable *s;
   Id p, pp, rec, *recp, sug, *sugp;
 
+  ninst = 0;
+  if (pool->installed)
+    {
+      for (i = 0; i < plist->count; i++)
+       {
+         p = plist->elements[i];
+         s = pool->solvables + p;
+         if (pool->installed && s->repo == pool->installed)
+           ninst++;
+       }
+    }
+  if (plist->count - ninst < 2)
+    return;
+
+  /* update our recommendsmap/suggestsmap */
   if (solv->recommends_index < 0)
     {
       MAPZERO(&solv->recommendsmap);
@@ -145,34 +171,67 @@ prune_to_recommended(Solver *solv, Queue *plist)
              MAPSET(&solv->suggestsmap, p);
        }
     }
+
   /* prune to recommended/supplemented */
+  ninst = 0;
   for (i = j = 0; i < plist->count; i++)
     {
       p = plist->elements[i];
-      if (MAPTST(&solv->recommendsmap, p))
+      s = pool->solvables + p;
+      if (pool->installed && s->repo == pool->installed)
        {
-         plist->elements[j++] = p;
+         ninst++;
+         if (j)
+           plist->elements[j++] = p;
          continue;
        }
-      if (solver_is_supplementing(solv, pool->solvables + p))
-        plist->elements[j++] = p;
+      if (!MAPTST(&solv->recommendsmap, p))
+       if (!solver_is_supplementing(solv, s))
+         continue;
+      if (!j && ninst)
+       {
+         for (k = 0; j < ninst; k++)
+           {
+             s = pool->solvables + plist->elements[k];
+             if (pool->installed && s->repo == pool->installed)
+               plist->elements[j++] = plist->elements[k];
+           }
+       }
+      plist->elements[j++] = p;
     }
   if (j)
     plist->count = j;
 
-  /* prune to suggested/enhanced*/
-  if (plist->count < 2)
+  /* anything left to prune? */
+  if (plist->count - ninst < 2)
     return;
+
+  /* prune to suggested/enhanced*/
+  ninst = 0;
   for (i = j = 0; i < plist->count; i++)
     {
       p = plist->elements[i];
-      if (MAPTST(&solv->suggestsmap, p))
+      s = pool->solvables + p;
+      if (pool->installed && s->repo == pool->installed)
        {
-         plist->elements[j++] = p;
+         ninst++;
+         if (j)
+           plist->elements[j++] = p;
          continue;
        }
-      if (solver_is_enhancing(solv, pool->solvables + p))
-        plist->elements[j++] = p;
+      if (!MAPTST(&solv->suggestsmap, p))
+        if (!solver_is_enhancing(solv, s))
+         continue;
+      if (!j && ninst)
+       {
+         for (k = 0; j < ninst; k++)
+           {
+             s = pool->solvables + plist->elements[k];
+             if (pool->installed && s->repo == pool->installed)
+               plist->elements[j++] = plist->elements[k];
+           }
+       }
+      plist->elements[j++] = p;
     }
   if (j)
     plist->count = j;
@@ -217,14 +276,12 @@ prune_to_best_arch(Pool *pool, Queue *plist)
  *
  * sort list of packages (given through plist) by name and evr
  * return result through plist
- *
  */
-
 void
 prune_to_best_version(Solver *solv, Queue *plist)
 {
   Pool *pool = solv->pool;
-  Id best = ID_NULL;
+  Id best;
   int i, j;
   Solvable *s;
 
@@ -232,9 +289,9 @@ prune_to_best_version(Solver *solv, Queue *plist)
     return;
   POOL_DEBUG(SAT_DEBUG_POLICY, "prune_to_best_version %d\n", plist->count);
 
-  prune_best_version_arch_sortcmp_data = solv;
+  prune_to_best_version_sortcmp_data = solv;
   /* sort by name first, prefer installed */
-  qsort(plist->elements, plist->count, sizeof(Id), prune_best_version_arch_sortcmp);
+  qsort(plist->elements, plist->count, sizeof(Id), prune_to_best_version_sortcmp);
 
   /* delete obsoleted. hmm, looks expensive! */
   /* FIXME maybe also check provides depending on noupdateprovide? */
@@ -264,12 +321,14 @@ prune_to_best_version(Solver *solv, Queue *plist)
            }
        }
     }
+  /* delete zeroed out queue entries */
   for (i = j = 0; i < plist->count; i++)
     if (plist->elements[i])
       plist->elements[j++] = plist->elements[i];
   plist->count = j;
 
   /* now find best 'per name' */
+  best = 0;
   for (i = j = 0; i < plist->count; i++)
     {
       s = pool->solvables + plist->elements[i];
@@ -327,17 +386,13 @@ prune_best_arch_name_version(Solver *solv, Pool *pool, Queue *plist)
 
 
 void
-policy_filter_unwanted(Solver *solv, Queue *plist, Id inst, int mode)
+policy_filter_unwanted(Solver *solv, Queue *plist, int mode)
 {
   Pool *pool = solv->pool;
   if (plist->count > 1 && mode != POLICY_MODE_SUGGEST)
     prune_to_highest_prio(pool, plist);
   if (plist->count > 1 && mode == POLICY_MODE_CHOOSE)
     prune_to_recommended(solv, plist);
-  /* FIXME: do this different! */
-  if (inst)
-    queue_push(plist, inst);
-
   prune_best_arch_name_version(solv, pool, plist);
 }
 
index 9050a3e..5574572 100644 (file)
@@ -55,7 +55,7 @@ extern void prune_to_best_version(Solver *solv, Queue *plist);
  *     candidates : List of candidates (This list depends on other
  *                  restrictions like architecture and vendor policies too)
  */   
-extern void policy_filter_unwanted(Solver *solv, Queue *plist, Id inst, int mode);
+extern void policy_filter_unwanted(Solver *solv, Queue *plist, int mode);
 extern int  policy_illegal_archchange(Solver *solv, Solvable *s1, Solvable *s2);
 extern int  policy_illegal_vendorchange(Solver *solv, Solvable *s1, Solvable *s2);
 extern void policy_findupdatepackages(Solver *solv,
index 7f81d27..8c097ef 100644 (file)
@@ -28,6 +28,7 @@ typedef struct _Repo {
   int nsolvables;              /* number of solvables repo is contributing to pool */
 
   int priority;                        /* priority of this repo */
+  int subpriority;             /* sub-priority of this repo, used just for sorting, not pruning */
 
   Id *idarraydata;             /* array of metadata Ids, solvable dependencies are offsets into this array */
   int idarraysize;
index 175cd18..6747c10 100644 (file)
@@ -2308,42 +2308,36 @@ setpropagatelearn(Solver *solv, int level, Id decision, int disablerules)
  */
 
 static int
-selectandinstall(Solver *solv, int level, Queue *dq, Id inst, int disablerules)
+selectandinstall(Solver *solv, int level, Queue *dq, int disablerules)
 {
   Pool *pool = solv->pool;
   Id p;
   int i;
 
-  /* FIXME: do we really need that inst handling? */
-  if (solv->distupgrade && inst && dq->count)
-    {
-      policy_filter_unwanted(solv, dq, 0, POLICY_MODE_CHOOSE);
-      for (i = 0; i < dq->count; i++)
-       if (solvable_identical(pool, pool->solvables + inst, pool->solvables + dq->elements[i]))
-         dq->elements[i] = inst;
-    }
-  else
-    {
-      if (dq->count > 1 || inst)
-       policy_filter_unwanted(solv, dq, inst, POLICY_MODE_CHOOSE);
-    }
-
-  i = 0;
+  if (dq->count > 1)
+    policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE);
   if (dq->count > 1)
     {
+      /* XXX: didn't we already do that? */
+      /* XXX: shouldn't we prefer installed packages? */
+      /* XXX: move to policy.c? */
       /* choose the supplemented one */
       for (i = 0; i < dq->count; i++)
        if (solver_is_supplementing(solv, pool->solvables + dq->elements[i]))
-         break;
-      if (i == dq->count)
-       {
-         for (i = 1; i < dq->count; i++)
-           queue_push(&solv->branches, dq->elements[i]);
-         queue_push(&solv->branches, -level);
-         i = 0;
-       }
+         {
+           dq->elements[0] = dq->elements[i];
+           dq->count = 1;
+           break;
+         }
+    }
+  if (dq->count > 1)
+    {
+      /* multiple candidates, open a branch */
+      for (i = 1; i < dq->count; i++)
+       queue_push(&solv->branches, dq->elements[i]);
+      queue_push(&solv->branches, -level);
     }
-  p = dq->elements[i];
+  p = dq->elements[0];
 
   POOL_DEBUG(SAT_DEBUG_POLICY, "installing %s\n", solvable2str(pool, pool->solvables + p));
 
@@ -2553,7 +2547,7 @@ run_solver(Solver *solv, int disablerules, int doweak)
                    dq.count = k;
                }
              olevel = level;
-             level = selectandinstall(solv, level, &dq, 0, disablerules);
+             level = selectandinstall(solv, level, &dq, disablerules);
              if (level == 0)
                {
                  queue_free(&dq);
@@ -2628,10 +2622,11 @@ run_solver(Solver *solv, int disablerules, int doweak)
                  if (!d)
                    continue;
                  queue_empty(&dq);
+                 queue_push(&dq, i);
                  while ((p = pool->whatprovidesdata[d++]) != 0)
                    if (solv->decisionmap[p] >= 0)
                      queue_push(&dq, p);
-                 policy_filter_unwanted(solv, &dq, i, POLICY_MODE_CHOOSE);
+                 policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE);
                  p = dq.elements[0];
                  if (p != i && solv->decisionmap[p] == 0)
                    {
@@ -2680,7 +2675,6 @@ run_solver(Solver *solv, int disablerules, int doweak)
          for (i = solv->installed->start, r = solv->rules + solv->updaterules; i < solv->installed->end; i++, r++)
            {
              Rule *rr;
-             Id inst;
              s = pool->solvables + i;
                
                /* skip if not installed (can't update) */
@@ -2713,16 +2707,8 @@ run_solver(Solver *solv, int disablerules, int doweak)
                }
              if (p || !dq.count)       /* already fulfilled or empty */
                continue;
-             if (dq.elements[0] == i)
-               inst = queue_shift(&dq);
-             else
-               inst = 0;
              olevel = level;
-             /* FIXME: it is handled a bit different because we do not want
-              * to have it pruned just because it is not recommened.
-              * we should not prune installed packages instead.
-              */
-             level = selectandinstall(solv, level, &dq, inst, disablerules);
+             level = selectandinstall(solv, level, &dq, disablerules);
              if (level == 0)
                {
                  queue_free(&dq);
@@ -2815,7 +2801,7 @@ run_solver(Solver *solv, int disablerules, int doweak)
          assert(dq.count > 1);
 
          olevel = level;
-         level = selectandinstall(solv, level, &dq, 0, disablerules);
+         level = selectandinstall(solv, level, &dq, disablerules);
          if (level == 0)
            {
              queue_free(&dq);
@@ -2921,7 +2907,7 @@ run_solver(Solver *solv, int disablerules, int doweak)
          if (dq.count)
            {
              if (dq.count > 1)
-               policy_filter_unwanted(solv, &dq, 0, POLICY_MODE_RECOMMEND);
+               policy_filter_unwanted(solv, &dq, POLICY_MODE_RECOMMEND);
              p = dq.elements[0];
              POOL_DEBUG(SAT_DEBUG_POLICY, "installing recommended %s\n", solvable2str(pool, pool->solvables + p));
              queue_push(&solv->recommendations, p);
@@ -4588,7 +4574,7 @@ solver_solve(Solver *solv, Queue *job)
            queue_pushunique(&solv->recommendations, i);
        }
       /* we use MODE_SUGGEST here so that repo prio is ignored */
-      policy_filter_unwanted(solv, &solv->recommendations, 0, POLICY_MODE_SUGGEST);
+      policy_filter_unwanted(solv, &solv->recommendations, POLICY_MODE_SUGGEST);
     }
 
   /*
@@ -4649,7 +4635,7 @@ solver_solve(Solver *solv, Queue *job)
            }
          queue_push(&solv->suggestions, i);
        }
-      policy_filter_unwanted(solv, &solv->suggestions, 0, POLICY_MODE_SUGGEST);
+      policy_filter_unwanted(solv, &solv->suggestions, POLICY_MODE_SUGGEST);
     }
 
   if (redoq.count)