]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Add SOLVER_FLAG_STRONG_RECOMMENDS option
authorMichael Schroeder <mls@suse.de>
Fri, 18 Nov 2016 12:54:00 +0000 (13:54 +0100)
committerMichael Schroeder <mls@suse.de>
Fri, 18 Nov 2016 12:54:00 +0000 (13:54 +0100)
Create weak rules for recommends. This makes the solver
backtrack to fulfill recommends dependecies (i.e. update
packages, choose different alternatives...).

Needs testcases.

bindings/solv.i
ext/testcase.c
src/rules.c
src/rules.h
src/solver.c
src/solver.h

index a8f9d64cddaec91bc22afc8d15772921b84ede84..9e0a81766baad1c38f55fcd2c544170491279eab 100644 (file)
@@ -3287,6 +3287,7 @@ rb_eval_string(
   static const int SOLVER_FLAG_YUM_OBSOLETES = SOLVER_FLAG_YUM_OBSOLETES;
   static const int SOLVER_FLAG_NEED_UPDATEPROVIDE = SOLVER_FLAG_NEED_UPDATEPROVIDE;
   static const int SOLVER_FLAG_FOCUS_BEST = SOLVER_FLAG_FOCUS_BEST;
+  static const int SOLVER_FLAG_STRONG_RECOMMENDS = SOLVER_FLAG_STRONG_RECOMMENDS;
 
   static const int SOLVER_REASON_UNRELATED = SOLVER_REASON_UNRELATED;
   static const int SOLVER_REASON_UNIT_RULE = SOLVER_REASON_UNIT_RULE;
index a56c4dbf372eff13826d272b467ab73a87464360..ce090b66471bb9fb1e39be8bd2f03e38d274f44f 100644 (file)
@@ -116,6 +116,7 @@ static struct solverflags2str {
   { SOLVER_FLAG_NEED_UPDATEPROVIDE,         "needupdateprovide", 0 },
   { SOLVER_FLAG_URPM_REORDER,               "urpmreorder", 0 },
   { SOLVER_FLAG_FOCUS_BEST,                 "focusbest", 0 },
+  { SOLVER_FLAG_STRONG_RECOMMENDS,          "strongrecommends", 0 },
   { 0, 0, 0 }
 };
 
index 67f10d8989fd009dac469e0bf98686a0e43efb28..33f5350a0e82644c821b2c9ac9410313c1381c05 100644 (file)
@@ -114,24 +114,27 @@ unifyrules_sortcmp(const void *ap, const void *bp, void *dp)
 
   x = a->p - b->p;
   if (x)
-    return x;                         /* p differs */
+    return x;                          /* p differs */
 
   /* identical p */
-  if (a->d == 0 && b->d == 0)
-    return a->w2 - b->w2;             /* assertion: return w2 diff */
+  if (a->d == 0 && b->d == 0)          /* both assertions or binary */
+    return a->w2 - b->w2;
 
-  if (a->d == 0)                      /* a is assertion, b not */
+  if (a->d == 0)                       /* a is assertion or binary, b not */
     {
       x = a->w2 - pool->whatprovidesdata[b->d];
       return x ? x : -1;
     }
 
-  if (b->d == 0)                      /* b is assertion, a not */
+  if (b->d == 0)                       /* b is assertion or binary, a not */
     {
       x = pool->whatprovidesdata[a->d] - b->w2;
       return x ? x : 1;
     }
 
+  if (a->d == b->d)
+    return 0;
+
   /* compare whatprovidesdata */
   ad = pool->whatprovidesdata + a->d;
   bd = pool->whatprovidesdata + b->d;
@@ -161,22 +164,31 @@ solver_unifyrules(Solver *solv)
   int i, j;
   Rule *ir, *jr;
 
-  if (solv->nrules <= 2)              /* nothing to unify */
+  if (solv->nrules <= 2)               /* nothing to unify */
     return;
 
+  if (solv->recommendsruleq)
+    {
+      /* mis-use n2 as recommends rule marker */
+      for (i = 1, ir = solv->rules + i; i < solv->nrules; i++, ir++)
+       ir->n2 = 0;
+      for (i = 0; i < solv->recommendsruleq->count; i++)
+       solv->rules[solv->recommendsruleq->elements[i]].n2 = 1;
+    }
+
   /* sort rules first */
   solv_sort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp, solv->pool);
 
-  /* prune rules
-   * i = unpruned
-   * j = pruned
-   */
+  /* prune rules */
   jr = 0;
   for (i = j = 1, ir = solv->rules + i; i < solv->nrules; i++, ir++)
     {
       if (jr && !unifyrules_sortcmp(ir, jr, pool))
-       continue;                      /* prune! */
-      jr = solv->rules + j++;         /* keep! */
+       {
+         jr->n2 &= ir->n2;             /* bitwise-and recommends marker */
+         continue;                     /* prune! */
+       }
+      jr = solv->rules + j++;          /* keep! */
       if (ir != jr)
         *jr = *ir;
     }
@@ -185,8 +197,19 @@ solver_unifyrules(Solver *solv)
   POOL_DEBUG(SOLV_DEBUG_STATS, "pruned rules from %d to %d\n", solv->nrules, j);
 
   /* adapt rule buffer */
-  solv->nrules = j;
-  solv->rules = solv_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK);
+  solver_shrinkrules(solv, j);
+
+  if (solv->recommendsruleq)
+    {
+      /* rebuild recommendsruleq */
+      queue_empty(solv->recommendsruleq);
+      for (i = 1, ir = solv->rules + i; i < solv->nrules; i++, ir++)
+       if (ir->n2)
+         {
+           ir->n2 = 0;
+           queue_push(solv->recommendsruleq, i);
+         }
+    }
 
   /*
    * debug: log rule statistics
@@ -300,7 +323,7 @@ solver_addrule(Solver *solv, Id p, Id p2, Id d)
    * the work for unifyrules a bit easier */
   if (!solv->pkgrules_end)             /* we add pkg rules */
     {
-      r = solv->rules + solv->nrules - 1;
+      r = solv->rules + solv->lastpkgrule;
       if (d)
        {
          Id *dp;
@@ -335,6 +358,7 @@ solver_addrule(Solver *solv, Id p, Id p2, Id d)
          if (p == -p2)
            return 0;                   /* rule is self-fulfilling */
        }
+      solv->lastpkgrule = solv->nrules;
     }
 
   solv->rules = solv_extend(solv->rules, solv->nrules, 1, sizeof(Rule), RULES_BLOCK);
@@ -359,6 +383,7 @@ solver_shrinkrules(Solver *solv, int nrules)
 {
   solv->nrules = nrules;
   solv->rules = solv_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK);
+  solv->lastpkgrule = 0;
 }
 
 /******************************************************************************
@@ -572,13 +597,15 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w
              if (!dp[j])
                continue;
            }
+         if (type == SOLVER_RULE_PKG_RECOMMENDS && !*dp)
+           continue;
          /* check if the rule contains both p and -p */
          for (j = 0; dp[j] != 0; j++)
            if (dp[j] == p)
              break;
          if (dp[j])
            continue;
-         addpkgrule(solv, -p, 0, dp - pool->whatprovidesdata, SOLVER_RULE_PKG_REQUIRES, dep);
+         addpkgrule(solv, -p, 0, dp - pool->whatprovidesdata, type, dep);
          /* push all non-visited providers on the work queue */
          if (m)
            for (; *dp; dp++)
@@ -858,6 +885,48 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m)
            }
        }
 
+      if (s->recommends && solv->strongrecommends)
+       {
+         int start = solv->nrules;
+         solv->lastpkgrule = 0;
+         reqp = s->repo->idarraydata + s->recommends;
+         while ((req = *reqp++) != 0)            /* go through all recommends */
+           {
+#ifdef ENABLE_COMPLEX_DEPS
+             if (pool_is_complex_dep(pool, req))
+               {
+                 /* we have AND/COND deps, normalize */
+                 add_complex_deprules(solv, n, req, SOLVER_RULE_PKG_RECOMMENDS, dontfix, &workq, m);
+                 continue;
+               }
+#endif
+             dp = pool_whatprovides_ptr(pool, req);
+             if (*dp == SYSTEMSOLVABLE || !*dp)          /* always installed or not installable */
+               continue;
+             for (i = 0; dp[i] != 0; i++)
+               if (n == dp[i])
+                 break;
+             if (dp[i])
+               continue;               /* provided by itself, no need to add rule */
+             addpkgrule(solv, -n, 0, dp - pool->whatprovidesdata, SOLVER_RULE_PKG_RECOMMENDS, req);
+             if (m)
+               for (; *dp; dp++)
+                 if (!MAPTST(m, *dp))
+                   queue_push(&workq, *dp);
+           }
+         if (!solv->ruleinfoq && start < solv->nrules)
+           {
+             if (!solv->recommendsruleq)
+               {
+                 solv->recommendsruleq = solv_calloc(1, sizeof(Queue));
+                 queue_init(solv->recommendsruleq);
+               }
+             for (i = start; i < solv->nrules; i++)
+               queue_push(solv->recommendsruleq, i);
+             solv->lastpkgrule = 0;
+           }
+       }
+
       /* that's all we check for src packages */
       if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
        continue;
index 29325ea53589c441e141c07be3bee1f69e44fdb0..db52199c67a0dcad716620e48ccfde55bfe7ed55 100644 (file)
@@ -58,6 +58,7 @@ typedef enum {
   SOLVER_RULE_PKG_OBSOLETES,
   SOLVER_RULE_PKG_IMPLICIT_OBSOLETES,
   SOLVER_RULE_PKG_INSTALLED_OBSOLETES,
+  SOLVER_RULE_PKG_RECOMMENDS,
   SOLVER_RULE_UPDATE = 0x200,
   SOLVER_RULE_FEATURE = 0x300,
   SOLVER_RULE_JOB = 0x400,
index efe3342820cebe263ddb031dd0f31bc660ec9424..08ad92d1fed8818aeec4045f7b4eb137c4ec2368 100644 (file)
@@ -1624,6 +1624,7 @@ solver_free(Solver *solv)
   queuep_free(&solv->suggestscplxq);
   queuep_free(&solv->brokenorphanrules);
   queuep_free(&solv->favorq);
+  queuep_free(&solv->recommendsruleq);
 
   map_free(&solv->recommendsmap);
   map_free(&solv->suggestsmap);
@@ -1708,6 +1709,8 @@ solver_get_flag(Solver *solv, int flag)
     return solv->needupdateprovide;
   case SOLVER_FLAG_URPM_REORDER:
     return solv->urpmreorder;
+  case SOLVER_FLAG_STRONG_RECOMMENDS:
+    return solv->strongrecommends;
   default:
     break;
   }
@@ -1792,6 +1795,9 @@ solver_set_flag(Solver *solv, int flag, int value)
   case SOLVER_FLAG_URPM_REORDER:
     solv->urpmreorder = value;
     break;
+  case SOLVER_FLAG_STRONG_RECOMMENDS:
+    solv->strongrecommends = value;
+    break;
   default:
     break;
   }
@@ -3627,6 +3633,7 @@ solver_solve(Solver *solv, Queue *job)
   if (solv->nrules != initialnrules)
     solver_shrinkrules(solv, initialnrules);
   solv->nrules = initialnrules;
+  solv->lastpkgrule = 0;
   solv->pkgrules_end = 0;
 
   if (installed)
@@ -3840,6 +3847,7 @@ solver_solve(Solver *solv, Queue *job)
   if (solv->nrules > initialnrules)
     solver_unifyrules(solv);                   /* remove duplicate pkg rules */
   solv->pkgrules_end = solv->nrules;           /* mark end of pkg rules */
+  solv->lastpkgrule = 0;
 
   if (solv->nrules > initialnrules)
     addedmap2deduceq(solv, &addedmap);         /* so that we can recreate the addedmap */
@@ -4215,7 +4223,7 @@ solver_solve(Solver *solv, Queue *job)
   POOL_DEBUG(SOLV_DEBUG_STATS, "overall rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024);
 
   /* create weak map */
-  if (solv->weakruleq.count)
+  if (solv->weakruleq.count || solv->recommendsruleq)
     {
       map_grow(&solv->weakrulemap, solv->nrules);
       for (i = 0; i < solv->weakruleq.count; i++)
@@ -4223,6 +4231,14 @@ solver_solve(Solver *solv, Queue *job)
          p = solv->weakruleq.elements[i];
          MAPSET(&solv->weakrulemap, p);
        }
+      if (solv->recommendsruleq)
+       {
+         for (i = 0; i < solv->recommendsruleq->count; i++)
+           {
+             p = solv->recommendsruleq->elements[i];
+             MAPSET(&solv->weakrulemap, p);
+           }
+       }
     }
 
   /* enable cleandepsmap creation if we have updatepkgs */
index be240c9de0401a851b58e23386c693412085aa3d..8f0b0dbe422df99bb29c75ac30f445577590654d 100644 (file)
@@ -44,6 +44,7 @@ struct _Solver {
    */
   Rule *rules;                         /* all rules */
   Id nrules;                           /* [Offset] index of the last rule */
+  Id lastpkgrule;                      /* last package rule we added */
 
   Queue ruleassertions;                        /* Queue of all assertion rules */
 
@@ -163,6 +164,7 @@ struct _Solver {
   int focus_best;                      /* true: resolve job dependencies first */
   int do_yum_obsoletes;                        /* true: add special yumobs rules */
   int urpmreorder;                     /* true: do special urpm package reordering */
+  int strongrecommends;                        /* true: create weak rules for recommends */
 
   Map dupmap;                          /* dup these packages*/
   int dupmap_all;                      /* dup all packages */
@@ -201,6 +203,8 @@ struct _Solver {
 
   int installedpos;                    /* for resolve_installed */
   int do_extra_reordering;             /* reorder for future installed packages */
+
+  Queue *recommendsruleq;              /* pkg rules comming from recommends */
 #endif /* LIBSOLV_INTERNAL */
 };
 
@@ -308,6 +312,7 @@ typedef struct _Solver Solver;
 #define SOLVER_FLAG_NEED_UPDATEPROVIDE         22
 #define SOLVER_FLAG_URPM_REORDER               23
 #define SOLVER_FLAG_FOCUS_BEST                 24
+#define SOLVER_FLAG_STRONG_RECOMMENDS          25
 
 #define GET_USERINSTALLED_NAMES                        (1 << 0)        /* package names instead of ids */
 #define GET_USERINSTALLED_INVERTED             (1 << 1)        /* autoinstalled */