Imported Upstream version 0.6.15
[platform/upstream/libsolv.git] / src / solver.c
index c6cad6b..2e28b7d 100644 (file)
@@ -217,13 +217,24 @@ autouninstall(Solver *solv, Id *problem)
          Rule *r;
          if (m && !MAPTST(m, v - solv->updaterules))
            continue;
-         /* check if identical to feature rule, we don't like that */
+         /* check if identical to feature rule, we don't like that (except for orphans) */
          r = solv->rules + solv->featurerules + (v - solv->updaterules);
          if (!r->p)
            {
              /* update rule == feature rule */
              if (v > lastfeature)
                lastfeature = v;
+             /* prefer orphaned packages in dup mode */
+             if (solv->keep_orphans)
+               {
+                 r = solv->rules + v;
+                 if (!r->d && r->p == (solv->installed->start + (v - solv->updaterules)))
+                   {
+                     lastfeature = v;
+                     lastupdate = 0;
+                     break;
+                   }
+               }
              continue;
            }
          if (v > lastupdate)
@@ -2714,7 +2725,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
 
       if (!solv->decisioncnt_orphan)
         solv->decisioncnt_orphan = solv->decisionq.count;
-      if (solv->dupmap_all && solv->installed)
+      if (solv->installed && (solv->orphaned.count || solv->brokenorphanrules))
        {
          int installedone = 0;
 
@@ -3350,7 +3361,7 @@ solver_solve(Solver *solv, Queue *job)
   Solvable *s;
   Rule *r;
   int now, solve_start;
-  int hasdupjob = 0;
+  int needduprules = 0;
   int hasbestinstalljob = 0;
 
   solve_start = solv_timems(0);
@@ -3561,6 +3572,19 @@ solver_solve(Solver *solv, Queue *job)
                  MAPSET(&solv->droporphanedmap, p - installed->start);
                }
              break;
+           case SOLVER_ALLOWUNINSTALL:
+             if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid))
+               solv->allowuninstall_all = 1;
+             FOR_JOB_SELECT(p, pp, select, what)
+               {
+                 s = pool->solvables + p;
+                 if (s->repo != installed)
+                   continue;
+                 if (!solv->allowuninstallmap.size)
+                   map_grow(&solv->allowuninstallmap, installed->end - installed->start);
+                 MAPSET(&solv->allowuninstallmap, p - installed->start);
+               }
+             break;
            default:
              break;
            }
@@ -3608,8 +3632,10 @@ solver_solve(Solver *solv, Queue *job)
              if (how & SOLVER_FORCEBEST)
                solv->bestupdatemap_all = 1;
            }
-         if (!solv->dupmap_all || solv->allowuninstall)
-           hasdupjob = 1;
+         if ((how & SOLVER_TARGETED) != 0)
+           needduprules = 1;
+         if (!solv->dupmap_all || solv->allowuninstall || solv->allowuninstall_all || solv->allowuninstallmap.size || solv->keep_orphans)
+           needduprules = 1;
          break;
        default:
          break;
@@ -3664,7 +3690,7 @@ solver_solve(Solver *solv, Queue *job)
 
   /* create dup maps if needed. We need the maps early to create our
    * update rules */
-  if (hasdupjob)
+  if (needduprules)
     solver_createdupmaps(solv);
 
   /*
@@ -3723,9 +3749,13 @@ solver_solve(Solver *solv, Queue *job)
           * check for and remove duplicate
           */
          r = solv->rules + solv->nrules - 1;           /* r: update rule */
-          if (!r->p)
-           continue;
          sr = r - (installed->end - installed->start); /* sr: feature rule */
+          if (!r->p)
+           {
+             if (sr->p)
+               memset(sr, 0, sizeof(*sr));             /* no feature rules without update rules */
+             continue;
+           }
          /* it's also orphaned if the feature rule consists just of the installed package */
          if (!solv->dupmap_all && sr->p == i && !sr->d && !sr->w2)
            queue_push(&solv->orphaned, i);
@@ -3917,17 +3947,6 @@ solver_solve(Solver *solv, Queue *job)
          break;
        case SOLVER_ALLOWUNINSTALL:
          POOL_DEBUG(SOLV_DEBUG_JOB, "job: allowuninstall %s\n", solver_select2str(pool, select, what));
-         if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid))
-           solv->allowuninstall_all = 1;
-         FOR_JOB_SELECT(p, pp, select, what)
-           {
-             s = pool->solvables + p;
-             if (s->repo != installed)
-               continue;
-             if (!solv->allowuninstallmap.size)
-               map_grow(&solv->allowuninstallmap, installed->end - installed->start);
-             MAPSET(&solv->allowuninstallmap, p - installed->start);
-           }
          break;
        default:
          POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n");
@@ -3966,7 +3985,7 @@ solver_solve(Solver *solv, Queue *job)
   else
     solv->infarchrules = solv->infarchrules_end = solv->nrules;
 
-  if (hasdupjob)
+  if (needduprules)
     solver_addduprules(solv, &addedmap);
   else
     solv->duprules = solv->duprules_end = solv->nrules;
@@ -3976,7 +3995,7 @@ solver_solve(Solver *solv, Queue *job)
   else
     solv->bestrules = solv->bestrules_end = solv->nrules;
 
-  if (hasdupjob)
+  if (needduprules)
     solver_freedupmaps(solv);  /* no longer needed */
 
   if (solv->do_yum_obsoletes)