implement SOLVER_FLAG_BREAK_ORPHANS
authorMichael Schroeder <mls@suse.de>
Thu, 17 Apr 2014 12:18:42 +0000 (14:18 +0200)
committerMichael Schroeder <mls@suse.de>
Thu, 17 Apr 2014 12:18:42 +0000 (14:18 +0200)
src/problems.c
src/rules.c
src/rules.h
src/solver.c
src/solver.h

index 7258c04..bb00aa6 100644 (file)
@@ -160,6 +160,10 @@ enableweakrules(Solver *solv)
        continue;
       solver_enablerule(solv, r);
     }
+  /* make sure broken orphan rules stay disabled */
+  if (solv->brokenorphanrules)
+    for (i = 0; i < solv->brokenorphanrules->count; i++)
+      solver_disablerule(solv, solv->rules + solv->brokenorphanrules->elements[i]);
 }
 
 
index b86ad77..78cc1e0 100644 (file)
@@ -4329,4 +4329,96 @@ solver_get_unneeded(Solver *solv, Queue *unneededq, int filtered)
   map_free(&cleandepsmap);
 }
 
-/* EOF */
+
+void
+solver_breakorphans(Solver *solv)
+{
+  Pool *pool = solv->pool;
+  Repo *installed = solv->installed;
+  int i, rid;
+  Map m;
+
+  if (!installed || solv->droporphanedmap_all)
+    return;
+  solv->brokenorphanrules = solv_calloc(1, sizeof(Queue));
+  queue_init(solv->brokenorphanrules);
+  map_init(&m, installed->end - installed->start);
+  for (i = 0; i < solv->orphaned.count; i++)
+    {
+      Id p = solv->orphaned.elements[i];
+      if (pool->solvables[p].repo != installed)
+       continue;
+      if (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - installed->start))
+       continue;
+      MAPSET(&m, p - installed->start);
+    }
+  for (rid = 1; rid < solv->rpmrules_end ; rid++)
+    {
+      Id p, *dp;
+      Rule *r = solv->rules + rid;
+      /* ignore non-deps and simple conflicts */
+      if (r->p >= 0 || ((r->d == 0 || r->d == -1) && r->w2 < 0))
+       continue;
+      p = -r->p;
+      if (p < installed->start || p >= installed->end || !MAPTST(&m, p - installed->start))
+       {
+         /* need to check other literals */
+         if (r->d == 0 || r->d == -1)
+           continue;
+         for (dp = pool->whatprovidesdata + (r->d < 0 ? -r->d - 1 : r->d); *dp < 0; dp++)
+           {
+             p = -*dp;
+             if (p >= installed->start && p < installed->end && MAPTST(&m, p - installed->start))
+               break;
+           }
+         if (*dp >= 0)
+           continue;
+       }
+      /* ok, disable this rule */
+      queue_push(solv->brokenorphanrules, rid);
+      if (r->d >= 0)
+       solver_disablerule(solv, r);
+    }
+  map_free(&m);
+  if (!solv->brokenorphanrules->count)
+    {
+      queue_free(solv->brokenorphanrules);
+      solv->brokenorphanrules = solv_free(solv->brokenorphanrules);
+    }
+}
+
+void
+solver_check_brokenorphanrules(Solver *solv, Queue *dq)
+{
+  Pool *pool = solv->pool;
+  int i;
+  Id l, pp;
+  
+  queue_empty(dq);
+  if (!solv->brokenorphanrules)
+    return;
+  for (i = 0; i < solv->brokenorphanrules->count; i++)
+    {
+      int rid = solv->brokenorphanrules->elements[i];
+      Rule *r = solv->rules + rid;
+      FOR_RULELITERALS(l, pp, r)
+       {
+         if (l < 0)
+           {
+             if (solv->decisionmap[-l] <= 0)
+               break;
+           }
+         else
+           {
+             if (solv->decisionmap[l] > 0 && pool->solvables[l].repo != solv->installed)
+               break;
+           }
+       }
+      if (l)
+       continue;
+      FOR_RULELITERALS(l, pp, r)
+        if (l > 0 && solv->decisionmap[l] == 0 && pool->solvables[l].repo != solv->installed)
+         queue_pushunique(dq, l);
+    }
+}
+
index 15de00f..06048e4 100644 (file)
@@ -142,6 +142,9 @@ extern Id   solver_rule2job(struct _Solver *solv, Id rid, Id *whatp);
 extern Id   solver_rule2solvable(struct _Solver *solv, Id rid);
 extern void solver_rule2rules(struct _Solver *solv, Id rid, Queue *q, int recursive);
 
+/* orphan handling */
+extern void solver_breakorphans(struct _Solver *solv);
+extern void solver_check_brokenorphanrules(struct _Solver *solv, Queue *dq);
 
 #ifdef __cplusplus
 }
index 054567e..282dd78 100644 (file)
@@ -1573,6 +1573,7 @@ solver_free(Solver *solv)
   queuep_free(&solv->installsuppdepq);
   queuep_free(&solv->recommendscplxq);
   queuep_free(&solv->suggestscplxq);
+  queuep_free(&solv->brokenorphanrules);
 
   map_free(&solv->recommendsmap);
   map_free(&solv->suggestsmap);
@@ -2687,6 +2688,26 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
                break;
              continue;         /* back to main loop */
            }
+          if (solv->brokenorphanrules)
+           {
+             solver_check_brokenorphanrules(solv, &dq);
+             if (dq.count)
+               {
+                 policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE);
+                 for (i = 0; i < dq.count; i++)
+                   {
+                     p = dq.elements[i];
+                     POOL_DEBUG(SOLV_DEBUG_POLICY, "installing orphaned dep %s\n", pool_solvid2str(pool, p));
+                     olevel = level;
+                     level = setpropagatelearn(solv, level, p, 0, 0);
+                     if (level < olevel)
+                       break;
+                   }
+                 if (level == 0)
+                   break;
+                 continue;
+               }
+           }
        }
 
      /* one final pass to make sure we decided all installed packages */
@@ -3303,6 +3324,7 @@ solver_solve(Solver *solv, Queue *job)
       queuep_free(&solv->suggestscplxq);
       solv->recommends_index = 0;
     }
+  queuep_free(&solv->brokenorphanrules);
   solv->specialupdaters = solv_free(solv->specialupdaters);
 
 
@@ -3880,6 +3902,10 @@ solver_solve(Solver *solv, Queue *job)
   /* disable update rules that conflict with our job */
   solver_disablepolicyrules(solv);
 
+  /* break orphans if requested */
+  if (solv->dupmap_all && solv->orphaned.count && solv->break_orphans)
+    solver_breakorphans(solv);
+
   /* make initial decisions based on assertion rules */
   makeruledecisions(solv);
   POOL_DEBUG(SOLV_DEBUG_SOLVER, "problems so far: %d\n", solv->problems.count);
index 3316e76..c8f51fc 100644 (file)
@@ -187,6 +187,7 @@ struct _Solver {
   Id *instbuddy;                       /* buddies of installed packages */
   int keep_orphans;                    /* how to treat orphans */
   int break_orphans;                   /* how to treat orphans */
+  Queue *brokenorphanrules;            /* broken rules of orphaned packages */
 #endif /* LIBSOLV_INTERNAL */
 };