]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Make disfavoring recommended packages work if strong recommends is enabled
authorMichael Schroeder <mls@suse.de>
Tue, 18 Dec 2018 15:40:00 +0000 (16:40 +0100)
committerMichael Schroeder <mls@suse.de>
Tue, 18 Dec 2018 15:40:00 +0000 (16:40 +0100)
Unfortunately this needs a new rule type, which is just the original
recommends rule minus the disfavored packages.

ext/testcase.c
src/rules.c
src/rules.h
src/solver.c
src/solver.h
src/solverdebug.c

index 3c5df4d4af45b0c0e5103ac95e4b01a7d3e7d8ca..31fe4e9c30257944fab8a1c3f6e537e3ab37e4b7 100644 (file)
@@ -2025,6 +2025,8 @@ testcase_solverresult(Solver *solv, int resultflags)
              /* map choice rules back to pkg rules */
              if (solver_ruleclass(solv, id) == SOLVER_RULE_CHOICE)
                id = solver_rule2pkgrule(solv, id);
+             if (solver_ruleclass(solv, id) == SOLVER_RULE_RECOMMENDS)
+               id = solver_rule2pkgrule(solv, id);
              solver_allruleinfos(solv, id, &rq);
              for (i = 0; i < rq.count; i += 4)
                {
index e8f8ea0dc8437b750d6d923b60b68d8fc2176574..1c11151a8a71cf67eceb53652c1cb62f92d963ae 100644 (file)
@@ -2740,13 +2740,11 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp)
       return SOLVER_RULE_YUMOBS;
     }
   if (rid >= solv->choicerules && rid < solv->choicerules_end)
-    {
-      return SOLVER_RULE_CHOICE;
-    }
+    return SOLVER_RULE_CHOICE;
+  if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
+    return SOLVER_RULE_RECOMMENDS;
   if (rid >= solv->learntrules)
-    {
-      return SOLVER_RULE_LEARNT;
-    }
+    return SOLVER_RULE_LEARNT;
   return SOLVER_RULE_UNKNOWN;
 }
 
@@ -2773,6 +2771,8 @@ solver_ruleclass(Solver *solv, Id rid)
     return SOLVER_RULE_YUMOBS;
   if (rid >= solv->choicerules && rid < solv->choicerules_end)
     return SOLVER_RULE_CHOICE;
+  if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
+    return SOLVER_RULE_RECOMMENDS;
   if (rid >= solv->learntrules && rid < solv->nrules)
     return SOLVER_RULE_LEARNT;
   return SOLVER_RULE_UNKNOWN;
@@ -2835,6 +2835,8 @@ solver_rule2pkgrule(Solver *solv, Id rid)
 {
   if (rid >= solv->choicerules && rid < solv->choicerules_end)
     return solv->choicerules_ref[rid - solv->choicerules];
+  if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
+    return solv->recommendsrules_info[rid - solv->recommendsrules];
   return 0;
 }
 
@@ -3634,6 +3636,54 @@ for (j = 0; j < qq.count; j++)
   POOL_DEBUG(SOLV_DEBUG_STATS, "yumobs rule creation took %d ms\n", solv_timems(now));
 }
 
+/* recommendsrules are a copy of some recommends package rule but
+ * with some disfavored literals removed */
+void
+solver_addrecommendsrules(Solver *solv)
+{
+  Pool *pool = solv->pool;
+  int i, havedis, havepos;
+  Id p, pp;
+  Queue q, infoq;
+
+  solv->recommendsrules = solv->nrules;
+  queue_init(&q);
+  queue_init(&infoq);
+  for (i = 0; i < solv->recommendsruleq->count; i++)
+    {
+      int rid = solv->recommendsruleq->elements[i];
+      Rule *r = solv->rules + rid;
+      queue_empty(&q);
+      havedis = havepos = 0;
+      FOR_RULELITERALS(p, pp, r)
+       {
+         if (p > 0 && solv->favormap[p] < 0)
+           havedis = 1;
+         else
+           {
+             if (p > 0)
+               havepos = 1;
+             queue_push(&q, p);
+           }
+       }
+      if (!havedis)
+       continue;
+      solver_disablerule(solv, r);
+      if (!havepos || q.count < 2)
+       continue;
+      if (q.count == 2)
+       solver_addrule(solv, q.elements[0], q.elements[1], 0);
+      else
+       solver_addrule(solv, q.elements[0], 0, pool_ids2whatprovides(pool, q.elements + 1, q.count - 1));
+      queue_push(&infoq, rid);
+    }
+  if (infoq.count)
+    solv->recommendsrules_info = solv_memdup2(infoq.elements, infoq.count, sizeof(Id));
+  queue_free(&infoq);
+  queue_free(&q);
+  solv->recommendsrules_end = solv->nrules;
+}
+
 void
 solver_breakorphans(Solver *solv)
 {
index a3c01353f40dbc31d5cf77a1bf856e8c282d8f2a..1db0551c18b01110d8381ec9e51c0408a896a9f8 100644 (file)
@@ -71,7 +71,8 @@ typedef enum {
   SOLVER_RULE_CHOICE = 0x700,
   SOLVER_RULE_LEARNT = 0x800,
   SOLVER_RULE_BEST = 0x900,
-  SOLVER_RULE_YUMOBS = 0xa00
+  SOLVER_RULE_YUMOBS = 0xa00,
+  SOLVER_RULE_RECOMMENDS = 0xb00
 } SolverRuleinfo;
 
 #define SOLVER_RULE_TYPEMASK    0xff00
@@ -133,6 +134,9 @@ extern void solver_addbestrules(struct s_Solver *solv, int havebestinstalljobs);
 /* yumobs rules */
 extern void solver_addyumobsrules(struct s_Solver *solv);
 
+/* recommends rules */
+extern void solver_addrecommendsrules(struct s_Solver *solv);
+
 /* policy rule disabling/reenabling */
 extern void solver_disablepolicyrules(struct s_Solver *solv);
 extern void solver_reenablepolicyrules(struct s_Solver *solv, int jobidx);
index e020bb13af0fc753e308cdd9364f18907c0a9122..9d987759471ce7f6af2e6761df1f6585f196ea20 100644 (file)
@@ -845,18 +845,19 @@ static void
 disable_recommendsrules(Solver *solv, Queue *weakq)
 {
   Pool *pool = solv->pool;
-  int i;
+  int i, rid;
   for (i = 0; i < weakq->count; i++)
     {
-      Rule *r;
-      if (!queue_contains(solv->recommendsruleq, weakq->elements[i]))
-       continue;
-      r = solv->rules + weakq->elements[i];
-      if (r->d >= 0)
+      rid = weakq->elements[i];
+      if ((rid >= solv->recommendsrules && rid < solv->recommendsrules_end) || queue_contains(solv->recommendsruleq, rid))
        {
-         POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling ");
-         solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, r);
-         solver_disablerule(solv, r);
+         Rule *r = solv->rules + rid;
+         if (r->d >= 0)
+           {
+             POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling ");
+             solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, r);
+             solver_disablerule(solv, r);
+           }
        }
     }
 }
@@ -904,6 +905,18 @@ disable_weakrules(Solver *solv, Queue *weakq)
   for (i = 0; i < weakq->count; i++)
     if (weakq->elements[i] > lastweak)
       lastweak = weakq->elements[i];
+  if (lastweak >= solv->recommendsrules && lastweak < solv->recommendsrules_end)
+    {
+      lastweak = 0;
+      for (i = 0; i < weakq->count; i++)
+       if (weakq->elements[i] < solv->recommendsrules && weakq->elements[i] > lastweak)
+         lastweak = weakq->elements[i];
+      if (lastweak < solv->pkgrules_end)
+       {
+         disable_recommendsrules(solv, weakq);
+         return;
+       }
+    }
   if (lastweak < solv->pkgrules_end && solv->strongrecommends && solv->recommendsruleq && queue_contains(solv->recommendsruleq, lastweak))
     {
       disable_recommendsrules(solv, weakq);
@@ -1397,6 +1410,7 @@ solver_free(Solver *solv)
   solv_free(solv->choicerules_ref);
   solv_free(solv->bestrules_pkg);
   solv_free(solv->yumobsrules_info);
+  solv_free(solv->recommendsrules_info);
   solv_free(solv->instbuddy);
   solv_free(solv);
 }
@@ -3129,10 +3143,6 @@ addedmap2deduceq(Solver *solv, Map *addedmap)
   for (; i < pool->nsolvables; i++)
     if (MAPTST(addedmap, i))
       queue_push(&solv->addedmap_deduceq, i);
-  j = 0;
-  for (i = 2; i < pool->nsolvables; i++)
-    if (MAPTST(addedmap, i))
-      j++;
 }
 
 static void
@@ -3284,6 +3294,7 @@ solver_solve(Solver *solv, Queue *job)
   queue_empty(&solv->ruleassertions);
   solv->bestrules_pkg = solv_free(solv->bestrules_pkg);
   solv->yumobsrules_info = solv_free(solv->yumobsrules_info);
+  solv->recommendsrules_info = solv_free(solv->recommendsrules_info);
   solv->choicerules_ref = solv_free(solv->choicerules_ref);
   if (solv->noupdate.size)
     map_empty(&solv->noupdate);
@@ -3354,9 +3365,9 @@ solver_solve(Solver *solv, Queue *job)
    */
   initialnrules = solv->pkgrules_end ? solv->pkgrules_end : 1;
   if (initialnrules > 1)
-    deduceq2addedmap(solv, &addedmap);
+    deduceq2addedmap(solv, &addedmap);         /* also enables all pkg rules */
   if (solv->nrules != initialnrules)
-    solver_shrinkrules(solv, initialnrules);
+    solver_shrinkrules(solv, initialnrules);   /* shrink to just pkg rules */
   solv->lastpkgrule = 0;
   solv->pkgrules_end = 0;
 
@@ -3908,6 +3919,11 @@ solver_solve(Solver *solv, Queue *job)
   else
     solv->yumobsrules = solv->yumobsrules_end = solv->nrules;
 
+  if (solv->havedisfavored && solv->strongrecommends)
+    solver_addrecommendsrules(solv);
+  else
+    solv->recommendsrules = solv->recommendsrules_end = solv->nrules;
+
   if (1)
     solver_addchoicerules(solv);
   else
@@ -4777,6 +4793,8 @@ solver_alternative2str(Solver *solv, int type, Id id, Id from)
       char buf[64];
       if (solver_ruleclass(solv, id) == SOLVER_RULE_CHOICE)
        id = solver_rule2pkgrule(solv, id);
+      if (solver_ruleclass(solv, id) == SOLVER_RULE_RECOMMENDS)
+       id = solver_rule2pkgrule(solv, id);
       rtype = solver_ruleinfo(solv, id, &depfrom, &depto, &dep);
       if ((rtype & SOLVER_RULE_TYPEMASK) == SOLVER_RULE_JOB)
        {
index 10b4506d46f033c0a64db49d27338aaad3f894eb..e372794c683652b49b30b88af10685de18a2b963 100644 (file)
@@ -80,6 +80,10 @@ struct s_Solver {
   Id choicerules_end;
   Id *choicerules_ref;
 
+  Id recommendsrules;                  /* rules from recommends pkg rules with disfavored literals */
+  Id recommendsrules_end;
+  Id *recommendsrules_info;            /* the original pkg rule rule */
+
   Id learntrules;                      /* learnt rules, (end == nrules) */
 
   Map noupdate;                                /* don't try to update these
index bb74ef613fef65c9a4aedb5b412e9746dcf0df74..b1b55f484ae2eb2e31334c38b18576135982b22e 100644 (file)
@@ -128,6 +128,8 @@ solver_printruleclass(Solver *solv, int type, Rule *r)
     POOL_DEBUG(type, "FEATURE ");
   else if (p >= solv->yumobsrules && p < solv->yumobsrules_end)
     POOL_DEBUG(type, "YUMOBS ");
+  else if (p >= solv->recommendsrules && p < solv->recommendsrules_end)
+    POOL_DEBUG(type, "RECOMMENDS ");
   solver_printrule(solv, type, r);
 }