]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Do not minimize from an installed to an uninstalled package when checking recommends
authorMichael Schroeder <mls@suse.de>
Wed, 6 Sep 2023 12:10:17 +0000 (14:10 +0200)
committerMichael Schroeder <mls@suse.de>
Wed, 6 Sep 2023 12:10:17 +0000 (14:10 +0200)
Also prune to installed packages (or their update candidates)
when doing extra reordering, i.e. when the update roles are
not yet resolved.

Fixes issue #539

src/solver.c

index 6c1203cac6b37334cbd1ce86595a689443705f66..bdce9a9d7114ed40e6d7a49241acc338e153cfef 100644 (file)
@@ -1135,6 +1135,58 @@ queue_prunezeros(Queue *q)
   queue_truncate(q, j);
 }
 
+static int
+replaces_installed_package(Pool *pool, Id p, Map *noupdate)
+{
+  Repo *installed = pool->installed;
+  Solvable *s = pool->solvables + p, *s2;
+  Id p2, pp2;
+  Id obs, *obsp;
+
+  if (s->repo == installed && !(noupdate && MAPTST(noupdate, p - installed->start)))
+    return 1;
+  FOR_PROVIDES(p2, pp2, s->name)
+    {
+      s2 = pool->solvables + p2;
+      if (s2->repo == installed && s2->name == s->name && !(noupdate && MAPTST(noupdate, p - installed->start)))
+       return 1;
+    }
+  if (!s->obsoletes)
+    return 0;
+  obsp = s->repo->idarraydata + s->obsoletes;
+  while ((obs = *obsp++) != 0)
+    {
+      FOR_PROVIDES(p2, pp2, obs)
+       {
+         s2 = pool->solvables + p2;
+         if (s2->repo != pool->installed || (noupdate && MAPTST(noupdate, p - installed->start)))
+           continue;
+         if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, s2, obs))
+           continue;
+         if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2))
+           continue;
+         return 1;
+       }
+    }
+  return 0;
+}
+
+static void
+prune_dq_for_future_installed(Solver *solv, Queue *dq)
+{
+  Pool *pool = solv->pool;
+  int i, j;
+  for (i = j = 0; i < dq->count; i++)
+    {
+      Id p = dq->elements[i];
+      if (replaces_installed_package(pool, p, &solv->noupdate))
+        dq->elements[j++] = p;
+    }
+  if (j)
+    queue_truncate(dq, j);
+}
+
+
 static void
 reorder_dq_for_future_installed(Solver *solv, int level, Queue *dq)
 {
@@ -1314,9 +1366,13 @@ selectandinstall(Solver *solv, int level, Queue *dq, int disablerules, Id ruleid
   if (dq->count > 1)
     policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE);
   /* if we're resolving rules and didn't resolve the installed packages yet,
-   * do some special supplements ordering */
+   * do some special pruning and supplements ordering */
   if (dq->count > 1 && solv->do_extra_reordering)
-    reorder_dq_for_future_installed(solv, level, dq);
+    {
+      prune_dq_for_future_installed(solv, dq);
+      if (dq->count > 1)
+       reorder_dq_for_future_installed(solv, level, dq);
+    }
   /* check if the candidates are all connected via yumobs rules */
   if (dq->count > 1 && solv->yumobsrules_end > solv->yumobsrules)
     prune_yumobs(solv, dq, ruleid);
@@ -2980,6 +3036,8 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
                        continue;
                      if (solv->favormap && solv->favormap[p] > solv->favormap[solv->branches.elements[lastsi]])
                        continue;       /* current selection is more favored */
+                     if (replaces_installed_package(pool, p, &solv->noupdate))
+                       continue;       /* current selection replaces an installed package */
                      if (!(MAPTST(&solv->recommendsmap, p) || solver_is_supplementing(solv, pool->solvables + p)))
                        {
                          lasti = lastsi;
@@ -4671,7 +4729,7 @@ pool_job2solvables(Pool *pool, Queue *pkgs, Id how, Id what)
 int
 pool_isemptyupdatejob(Pool *pool, Id how, Id what)
 {
-  Id p, pp, pi, pip;
+  Id p, pp;
   Id select = how & SOLVER_SELECTMASK;
   if ((how & SOLVER_JOBMASK) != SOLVER_UPDATE)
     return 0;
@@ -4684,34 +4742,8 @@ pool_isemptyupdatejob(Pool *pool, Id how, Id what)
       return 0;
   /* hard work */
   FOR_JOB_SELECT(p, pp, select, what)
-    {
-      Solvable *s = pool->solvables + p;
-      FOR_PROVIDES(pi, pip, s->name)
-       {
-         Solvable *si = pool->solvables + pi;
-         if (si->repo != pool->installed || si->name != s->name)
-           continue;
-         return 0;
-       }
-      if (s->obsoletes)
-       {
-         Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
-         while ((obs = *obsp++) != 0)
-           {
-             FOR_PROVIDES(pi, pip, obs)
-               {
-                 Solvable *si = pool->solvables + pi;
-                 if (si->repo != pool->installed)
-                   continue;
-                 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, si, obs))
-                   continue;
-                 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, si))
-                   continue;
-                 return 0;
-               }
-           }
-       }
-    }
+    if (replaces_installed_package(pool, p, 0))
+      return 0;
   return 1;
 }