]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Move replace solution types from the bindings to the library
authorMichael Schroeder <mls@suse.de>
Wed, 21 Dec 2022 12:52:41 +0000 (13:52 +0100)
committerMichael Schroeder <mls@suse.de>
Wed, 21 Dec 2022 13:06:16 +0000 (14:06 +0100)
This adds two new functions:

solver_all_solutionelements()
return a queue with (type,p,rp) solution triplets.

solver_solutionelementtype2str()
this is similar to solver_solutionelement2str(), but also takes a
type parameter so that the replace types result in different strings.

Make use of the two functions in the example solver to
show how they work.

bindings/solv.i
examples/solv/solv.c
src/libsolv.ver
src/problems.c
src/problems.h
src/solverdebug.c

index 5d82832b18c051d391ae661dd667128a85f36646..ef3f31c2ce8c7702cef0e0cd07035e990183a27c 100644 (file)
@@ -773,13 +773,6 @@ typedef int bool;
 #define RARRAY_LEN(ary) (RARRAY(ary)->len)
 #endif
 
-#define SOLVER_SOLUTION_ERASE                   -100
-#define SOLVER_SOLUTION_REPLACE                 -101
-#define SOLVER_SOLUTION_REPLACE_DOWNGRADE       -102
-#define SOLVER_SOLUTION_REPLACE_ARCHCHANGE      -103
-#define SOLVER_SOLUTION_REPLACE_VENDORCHANGE    -104
-#define SOLVER_SOLUTION_REPLACE_NAMECHANGE      -105
-
 typedef void *AppObjectPtr;
 typedef Id DepId;
 
@@ -839,7 +832,6 @@ typedef struct {
   Solver *solv;
   Id problemid;
   Id solutionid;
-  Id id;
 
   Id type;
   Id p;
@@ -1273,7 +1265,6 @@ typedef struct {
   Solver *const solv;
   Id const problemid;
   Id const solutionid;
-  Id const id;
   Id const type;
 } Solutionelement;
 
@@ -1283,7 +1274,7 @@ typedef struct {
   Id const type;
   Id const dep_id;
   Id const chosen_id;
-  int level;
+  int const level;
 } Alternative;
 
 %nodefaultctor Transaction;
@@ -3463,94 +3454,32 @@ returnself(matchsolvable)
   int element_count() {
     return solver_solutionelement_count($self->solv, $self->problemid, $self->id);
   }
-
-  %typemap(out) Queue elements Queue2Array(Solutionelement *, 4, new_Solutionelement(arg1->solv, arg1->problemid, arg1->id, id, idp[1], idp[2], idp[3]));
+  %typemap(out) Queue elements Queue2Array(Solutionelement *, 3, new_Solutionelement(arg1->solv, arg1->problemid, arg1->id, id, idp[1], idp[2]));
   %newobject elements;
   Queue elements(bool expandreplaces=0) {
     Queue q;
-    int i, cnt;
     queue_init(&q);
-    cnt = solver_solutionelement_count($self->solv, $self->problemid, $self->id);
-    for (i = 1; i <= cnt; i++)
-      {
-        Id p, rp, type;
-        solver_next_solutionelement($self->solv, $self->problemid, $self->id, i - 1, &p, &rp);
-        if (p > 0) {
-          type = rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_ERASE;
-        } else {
-          type = p;
-          p = rp;
-          rp = 0;
-        }
-        if (type == SOLVER_SOLUTION_REPLACE && expandreplaces) {
-          int illegal = policy_is_illegal(self->solv, self->solv->pool->solvables + p, self->solv->pool->solvables + rp, 0);
-          if (illegal) {
-            if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0) {
-              queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_DOWNGRADE);
-              queue_push2(&q, p, rp);
-            }
-            if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0) {
-              queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_ARCHCHANGE);
-              queue_push2(&q, p, rp);
-            }
-            if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0) {
-              queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_VENDORCHANGE);
-              queue_push2(&q, p, rp);
-            }
-            if ((illegal & POLICY_ILLEGAL_NAMECHANGE) != 0) {
-              queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_NAMECHANGE);
-              queue_push2(&q, p, rp);
-            }
-            continue;
-          }
-        }
-        queue_push2(&q, i, type);
-        queue_push2(&q, p, rp);
-      }
+    solver_all_solutionelements($self->solv, $self->problemid, $self->id, expandreplaces, &q);
     return q;
   }
 }
 
 %extend Solutionelement {
-  Solutionelement(Solver *solv, Id problemid, Id solutionid, Id id, Id type, Id p, Id rp) {
+  Solutionelement(Solver *solv, Id problemid, Id solutionid, Id type, Id p, Id rp) {
     Solutionelement *e;
     e = solv_calloc(1, sizeof(*e));
     e->solv = solv;
     e->problemid = problemid;
     e->solutionid = solutionid;
-    e->id = id;
     e->type = type;
     e->p = p;
     e->rp = rp;
     return e;
   }
   const char *str() {
-    Id p = $self->type;
-    Id rp = $self->p;
-    int illegal = 0;
-    if (p == SOLVER_SOLUTION_ERASE)
-      {
-        p = rp;
-        rp = 0;
-      }
-    else if (p == SOLVER_SOLUTION_REPLACE)
-      {
-        p = rp;
-        rp = $self->rp;
-      }
-    else if (p == SOLVER_SOLUTION_REPLACE_DOWNGRADE)
-      illegal = POLICY_ILLEGAL_DOWNGRADE;
-    else if (p == SOLVER_SOLUTION_REPLACE_ARCHCHANGE)
-      illegal = POLICY_ILLEGAL_ARCHCHANGE;
-    else if (p == SOLVER_SOLUTION_REPLACE_VENDORCHANGE)
-      illegal = POLICY_ILLEGAL_VENDORCHANGE;
-    else if (p == SOLVER_SOLUTION_REPLACE_NAMECHANGE)
-      illegal = POLICY_ILLEGAL_NAMECHANGE;
-    if (illegal)
-      return pool_tmpjoin($self->solv->pool, "allow ", policy_illegal2str($self->solv, illegal, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp), 0);
-    return solver_solutionelement2str($self->solv, p, rp);
-  }
-  %typemap(out) Queue replaceelements Queue2Array(Solutionelement *, 1, new_Solutionelement(arg1->solv, arg1->problemid, arg1->solutionid, arg1->id, id, arg1->p, arg1->rp));
+    return solver_solutionelementtype2str($self->solv, $self->type, $self->p, $self->rp);
+  }
+  %typemap(out) Queue replaceelements Queue2Array(Solutionelement *, 1, new_Solutionelement(arg1->solv, arg1->problemid, arg1->solutionid, id, arg1->p, arg1->rp));
   %newobject replaceelements;
   Queue replaceelements() {
     Queue q;
@@ -4375,19 +4304,19 @@ rb_eval_string(
     }
   %}
   Queue choices_raw() {
-    Queue r;
-    queue_init_clone(&r, &$self->choices);
-    return r;
+    Queue q;
+    queue_init_clone(&q, &$self->choices);
+    return q;
   }
   %typemap(out) Queue choices Queue2Array(XSolvable *, 1, new_XSolvable(arg1->solv->pool, id));
   Queue choices() {
     int i;
-    Queue r;
-    queue_init_clone(&r, &$self->choices);
-    for (i = 0; i < r.count; i++)
-      if (r.elements[i] < 0)
-        r.elements[i] = -r.elements[i];
-    return r;
+    Queue q;
+    queue_init_clone(&q, &$self->choices);
+    for (i = 0; i < q.count; i++)
+      if (q.elements[i] < 0)
+        q.elements[i] = -q.elements[i];
+    return q;
   }
 #if defined(SWIGPERL) || defined(SWIGTCL)
   %rename("str") __str__;
index 99d56056530a033e2f022a77b813022c5230b786..f7c0468b99ab9a0afef76745cc66e6664144c78d 100644 (file)
@@ -788,14 +788,26 @@ rerunsolver:
       for (problem = 1; problem <= pcnt; problem++)
        {
          int take = 0;
+         Id rid;
          printf("Problem %d/%d:\n", problem, pcnt);
-         solver_printprobleminfo(solv, problem);
+         rid = solver_findproblemrule(solv, problem);
+         if (rid)
+           {
+             Id source, target, dep;
+             SolverRuleinfo type = solver_ruleinfo(solv, rid, &source, &target, &dep);
+             printf("%s\n", solver_problemruleinfo2str(solv, type, source, target, dep));
+           }
          printf("\n");
          scnt = solver_solution_count(solv, problem);
          for (solution = 1; solution <= scnt; solution++)
            {
+             Queue sq;
              printf("Solution %d:\n", solution);
-             solver_printsolution(solv, problem, solution);
+             queue_init(&sq);
+             solver_all_solutionelements(solv, problem, solution, 1, &sq);
+             for (i = 0; i < sq.count; i += 3)
+               printf("  - %s\n", solver_solutionelementtype2str(solv, sq.elements[i], sq.elements[i + 1], sq.elements[i + 2]));
+             queue_free(&sq);
              printf("\n");
            }
          for (;;)
index 402c256780fcd5fe073c8db0c1f0a123c67d2f5d..b9f9f960d0f949c22c8cfb71a3b55ce52b1f7ffc 100644 (file)
@@ -342,6 +342,7 @@ SOLV_1.0 {
                solvable_trivial_installable_queue;
                solvable_trivial_installable_repo;
                solvable_unset;
+               solver_all_solutionelements;
                solver_allruleinfos;
                solver_allweakdepinfos;
                solver_alternative2str;
@@ -414,6 +415,7 @@ SOLV_1.0 {
                solver_set_flag;
                solver_solution_count;
                solver_solutionelement2str;
+               solver_solutionelementtype2str;
                solver_solutionelement_count;
                solver_solutionelement_internalid;
                solver_solutionelement_extrajobflags;
index 58dd4de9f94b629cbd97689c51f5f1beffe19b42..b0a421c2392148ee124393319ae805a89435d7d7 100644 (file)
@@ -22,6 +22,7 @@
 #include "pool.h"
 #include "util.h"
 #include "evr.h"
+#include "policy.h"
 #include "solverdebug.h"
 
 /**********************************************************************************/
@@ -986,6 +987,7 @@ solver_solutionelement_internalid(Solver *solv, Id problem, Id solution)
   return solv->solutions.elements[solidx + 2 * solv->solutions.elements[solidx] + 3];
 }
 
+/* currently just SOLVER_CLEANDEPS */
 Id
 solver_solutionelement_extrajobflags(Solver *solv, Id problem, Id solution)
 {
@@ -1040,6 +1042,56 @@ solver_next_solutionelement(Solver *solv, Id problem, Id solution, Id element, I
   return element + 1;
 }
 
+static inline void
+queue_push3(Queue *q, Id id1, Id id2, Id id3)
+{
+  queue_push(q, id1);
+  queue_push2(q, id2, id3);
+}
+
+static void
+add_expanded_replace(Solver *solv, Id p, Id rp, Queue *q)
+{
+  int illegal = policy_is_illegal(solv, solv->pool->solvables + p, solv->pool->solvables + rp, 0);
+  if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0)
+    queue_push3(q, SOLVER_SOLUTION_REPLACE_DOWNGRADE, p, rp);
+  if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0)
+    queue_push3(q, SOLVER_SOLUTION_REPLACE_ARCHCHANGE, p, rp);
+  if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0)
+    queue_push3(q, SOLVER_SOLUTION_REPLACE_VENDORCHANGE, p, rp);
+  if ((illegal & POLICY_ILLEGAL_NAMECHANGE) != 0)
+    queue_push3(q, SOLVER_SOLUTION_REPLACE_NAMECHANGE, p, rp);
+  if (!illegal || (illegal & ~(POLICY_ILLEGAL_DOWNGRADE | POLICY_ILLEGAL_ARCHCHANGE | POLICY_ILLEGAL_VENDORCHANGE | POLICY_ILLEGAL_NAMECHANGE)))
+    queue_push3(q, SOLVER_SOLUTION_REPLACE, p, rp);
+}
+
+/* solutionelements are (type, p, rp) triplets */
+void
+solver_all_solutionelements(Solver *solv, Id problem, Id solution, int expandreplaces, Queue *q)
+{
+  int i, cnt;
+  Id solidx = solv->problems.elements[problem * 2 - 1];
+  solidx = solv->solutions.elements[solidx + solution];
+  queue_empty(q);
+  if (!solidx)
+    return;
+  cnt = solv->solutions.elements[solidx++];
+  for (i = 0; i < cnt; i++)
+    {
+      Id p = solv->solutions.elements[solidx++];
+      Id rp = solv->solutions.elements[solidx++];
+      if (p > 0)
+       {
+         if (rp && expandreplaces)
+           add_expanded_replace(solv, p, rp, q);
+         else
+           queue_push3(q, rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_ERASE, p, rp);
+       }
+      else
+        queue_push3(q, p, rp, 0);
+    }
+}
+
 void
 solver_take_solutionelement(Solver *solv, Id p, Id rp, Id extrajobflags, Queue *job)
 {
@@ -1057,6 +1109,11 @@ solver_take_solutionelement(Solver *solv, Id p, Id rp, Id extrajobflags, Queue *
       job->elements[rp] = 0;
       return;
     }
+  if (p == SOLVER_SOLUTION_ERASE)
+    {
+      p = rp;
+      rp = 0;
+    }
   if (rp <= 0 && p <= 0)
     return;    /* just in case */
   if (rp > 0)
@@ -1402,62 +1459,66 @@ solver_problem2str(Solver *solv, Id problem)
 }
 
 const char *
-solver_solutionelement2str(Solver *solv, Id p, Id rp)
+solver_solutionelementtype2str(Solver *solv, int type, Id p, Id rp)
 {
   Pool *pool = solv->pool;
-  if (p == SOLVER_SOLUTION_JOB || p == SOLVER_SOLUTION_POOLJOB)
-    {
-      Id how, what;
-      if (p == SOLVER_SOLUTION_JOB)
-       rp += solv->pooljobcnt;
-      how = solv->job.elements[rp - 1];
-      what = solv->job.elements[rp];
-      return pool_tmpjoin(pool, "do not ask to ", pool_job2str(pool, how, what, 0), 0);
-    }
-  else if (p == SOLVER_SOLUTION_INFARCH)
+  Solvable *s;
+  const char *str;
+
+  switch (type)
     {
-      Solvable *s = pool->solvables + rp;
+    case SOLVER_SOLUTION_JOB:
+    case SOLVER_SOLUTION_POOLJOB:
+      if (type == SOLVER_SOLUTION_JOB)
+       p += solv->pooljobcnt;
+      return pool_tmpjoin(pool, "do not ask to ", pool_job2str(pool, solv->job.elements[p - 1], solv->job.elements[p], 0), 0);
+    case SOLVER_SOLUTION_INFARCH:
+      s = pool->solvables + p;
       if (solv->installed && s->repo == solv->installed)
         return pool_tmpjoin(pool, "keep ", pool_solvable2str(pool, s), " despite the inferior architecture");
       else
         return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " despite the inferior architecture");
-    }
-  else if (p == SOLVER_SOLUTION_DISTUPGRADE)
-    {
-      Solvable *s = pool->solvables + rp;
+    case SOLVER_SOLUTION_DISTUPGRADE:
+      s = pool->solvables + p;
       if (solv->installed && s->repo == solv->installed)
         return pool_tmpjoin(pool, "keep obsolete ", pool_solvable2str(pool, s), 0);
       else
         return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " from excluded repository");
-    }
-  else if (p == SOLVER_SOLUTION_BEST)
-    {
-      Solvable *s = pool->solvables + rp;
+    case SOLVER_SOLUTION_BEST:
+      s = pool->solvables + p;
       if (solv->installed && s->repo == solv->installed)
         return pool_tmpjoin(pool, "keep old ", pool_solvable2str(pool, s), 0);
       else
         return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " despite the old version");
+    case SOLVER_SOLUTION_BLACK:
+      return pool_tmpjoin(pool, "install ", pool_solvid2str(pool, p), 0);
+    case SOLVER_SOLUTION_STRICTREPOPRIORITY:
+      return pool_tmpjoin(pool, "install ", pool_solvid2str(pool, p), " despite the repo priority");
+
+    /* replace types: p -> rp */
+    case SOLVER_SOLUTION_ERASE:
+      return pool_tmpjoin(pool, "allow deinstallation of ", pool_solvid2str(pool, p), 0);
+    case SOLVER_SOLUTION_REPLACE:
+      str = pool_tmpjoin(pool, "allow replacement of ", pool_solvid2str(pool, p), 0);
+      return pool_tmpappend(pool, str, " with ", pool_solvid2str(pool, rp));
+    case SOLVER_SOLUTION_REPLACE_DOWNGRADE:
+      return pool_tmpjoin(pool, "allow ", policy_illegal2str(solv, POLICY_ILLEGAL_DOWNGRADE, pool->solvables + p, pool->solvables + rp), 0);
+    case SOLVER_SOLUTION_REPLACE_ARCHCHANGE:
+      return pool_tmpjoin(pool, "allow ", policy_illegal2str(solv, POLICY_ILLEGAL_ARCHCHANGE, pool->solvables + p, pool->solvables + rp), 0);
+    case SOLVER_SOLUTION_REPLACE_VENDORCHANGE:
+      return pool_tmpjoin(pool, "allow ", policy_illegal2str(solv, POLICY_ILLEGAL_VENDORCHANGE, pool->solvables + p, pool->solvables + rp), 0);
+    case SOLVER_SOLUTION_REPLACE_NAMECHANGE:
+      return pool_tmpjoin(pool, "allow ", policy_illegal2str(solv, POLICY_ILLEGAL_NAMECHANGE, pool->solvables + p, pool->solvables + rp), 0);
+    default:
+      break;
     }
-  else if (p == SOLVER_SOLUTION_BLACK)
-    {
-      Solvable *s = pool->solvables + rp;
-      return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), 0);
-    }
-  else if (p > 0 && rp == 0)
-    return pool_tmpjoin(pool, "allow deinstallation of ", pool_solvid2str(pool, p), 0);
-  else if (p == SOLVER_SOLUTION_STRICTREPOPRIORITY)
-    {
-      Solvable *s = pool->solvables + rp;
-      return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " despite the repo priority");
-    }
-  else if (p > 0 && rp > 0)
-    {
-      const char *sp = pool_solvid2str(pool, p);
-      const char *srp = pool_solvid2str(pool, rp);
-      const char *str = pool_tmpjoin(pool, "allow replacement of ", sp, 0);
-      return pool_tmpappend(pool, str, " with ", srp);
-    }
-  else
-    return "bad solution element";
+  return "bad solution element";
 }
 
+const char *
+solver_solutionelement2str(Solver *solv, Id p, Id rp)
+{
+  if (p > 0)
+    return solver_solutionelementtype2str(solv, rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_ERASE, p, rp);
+  return solver_solutionelementtype2str(solv, p, rp, 0);
+}
index f9b1efc3cfebcf6d66f02679d8874c5dbd106952..9e4ad1ffead8054c774ac72756fc1d512fd68eca 100644 (file)
@@ -29,6 +29,13 @@ struct s_Solver;
 #define SOLVER_SOLUTION_POOLJOB                (-4)
 #define SOLVER_SOLUTION_BLACK          (-5)
 #define SOLVER_SOLUTION_STRICTREPOPRIORITY     (-6)
+/* replace solution types */
+#define SOLVER_SOLUTION_ERASE                   (-100)
+#define SOLVER_SOLUTION_REPLACE                 (-101)
+#define SOLVER_SOLUTION_REPLACE_DOWNGRADE       (-102)
+#define SOLVER_SOLUTION_REPLACE_ARCHCHANGE      (-103)
+#define SOLVER_SOLUTION_REPLACE_VENDORCHANGE    (-104)
+#define SOLVER_SOLUTION_REPLACE_NAMECHANGE      (-105)
 
 void solver_recordproblem(struct s_Solver *solv, Id rid);
 void solver_fixproblem(struct s_Solver *solv, Id rid);
@@ -45,6 +52,7 @@ unsigned int solver_solutionelement_count(struct s_Solver *solv, Id problem, Id
 Id solver_solutionelement_internalid(struct s_Solver *solv, Id problem, Id solution);
 Id solver_solutionelement_extrajobflags(struct s_Solver *solv, Id problem, Id solution);
 Id solver_next_solutionelement(struct s_Solver *solv, Id problem, Id solution, Id element, Id *p, Id *rp);
+void solver_all_solutionelements(struct s_Solver *solv, Id problem, Id solution, int expandreplaces, Queue *q);
 
 void solver_take_solutionelement(struct s_Solver *solv, Id p, Id rp, Id extrajobflags, Queue *job);
 void solver_take_solution(struct s_Solver *solv, Id problem, Id solution, Queue *job);
@@ -55,6 +63,7 @@ void solver_findallproblemrules(struct s_Solver *solv, Id problem, Queue *rules)
 extern const char *solver_problemruleinfo2str(struct s_Solver *solv, SolverRuleinfo type, Id source, Id target, Id dep);
 extern const char *solver_problem2str(struct s_Solver *solv, Id problem);
 extern const char *solver_solutionelement2str(struct s_Solver *solv, Id p, Id rp);
+extern const char *solver_solutionelementtype2str(struct s_Solver *solv, int type, Id p, Id rp);
 
 #ifdef __cplusplus
 }
index 5902cdb44142bf96c07144a5ab23f9c791f27ad0..1c53d4e7f58b44c0a7a8abe7fbaa175e0123791a 100644 (file)
@@ -505,43 +505,17 @@ solver_printcompleteprobleminfo(Solver *solv, Id problem)
   queue_free(&q);
 }
 
-static int illegals[] = {
-  POLICY_ILLEGAL_DOWNGRADE,
-  POLICY_ILLEGAL_NAMECHANGE,
-  POLICY_ILLEGAL_ARCHCHANGE,
-  POLICY_ILLEGAL_VENDORCHANGE,
-  0
-};
-
 void
 solver_printsolution(Solver *solv, Id problem, Id solution)
 {
   Pool *pool = solv->pool;
-  Id p, rp, element;
-
-  element = 0;
-  while ((element = solver_next_solutionelement(solv, problem, solution, element, &p, &rp)) != 0)
-    {
-      if (p > 0 && rp > 0)
-       {
-         /* for replacements we want to know why it was illegal */
-         Solvable *s = pool->solvables + p, *rs = pool->solvables + rp;
-         int illegal = policy_is_illegal(solv, s, rs, 0);
-         if (illegal)
-           {
-             int i;
-             for (i = 0; illegals[i]; i++)
-               if ((illegal & illegals[i]) != 0)
-                 {
-                   POOL_DEBUG(SOLV_DEBUG_RESULT, "  - allow %s\n", policy_illegal2str(solv, illegals[i], s, rs));
-                   illegal ^= illegals[i];
-                 }
-             if (!illegal)
-               continue;
-           }
-       }
-      POOL_DEBUG(SOLV_DEBUG_RESULT, "  - %s\n", solver_solutionelement2str(solv, p, rp));
-    }
+  Queue q;
+  int i;
+  queue_init(&q);
+  solver_all_solutionelements(solv, problem, solution, 1, &q);
+  for (i = 0; i < q.count; i += 3)
+    POOL_DEBUG(SOLV_DEBUG_RESULT, "  - %s\n", solver_solutionelementtype2str(solv, q.elements[i], q.elements[i + 1], q.elements[i + 2]));
+  queue_free(&q);
 }
 
 void