]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Finish strict repo priority support
authorMichael Schroeder <mls@suse.de>
Fri, 15 Oct 2021 09:03:12 +0000 (11:03 +0200)
committerMichael Schroeder <mls@suse.de>
Fri, 15 Oct 2021 09:03:12 +0000 (11:03 +0200)
- add flag to bindings
- support flag/ruletype in testcases
- support strict repo prio problems in solution generation
- implement automatic disabling of strict repo rules due to install jobs
- add a testcase

bindings/solv.i
ext/testcase.c
src/problems.c
src/problems.h
src/rules.c
src/solverdebug.c
test/testcases/strictrepoprio/strictrepoprio.t [new file with mode: 0644]

index 61c6fc825d3f6249fc1fbef5e789ae01adc41e31..3a6bac468219fec83602612e5cc33ee423ab5878 100644 (file)
@@ -3571,6 +3571,7 @@ returnself(matchsolvable)
   static const int SOLVER_FLAG_STRONG_RECOMMENDS = SOLVER_FLAG_STRONG_RECOMMENDS;
   static const int SOLVER_FLAG_INSTALL_ALSO_UPDATES = SOLVER_FLAG_INSTALL_ALSO_UPDATES;
   static const int SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED = SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED;
+  static const int SOLVER_FLAG_STRICT_REPO_PRIORITY = SOLVER_FLAG_STRICT_REPO_PRIORITY;
 
   static const int SOLVER_REASON_UNRELATED = SOLVER_REASON_UNRELATED;
   static const int SOLVER_REASON_UNIT_RULE = SOLVER_REASON_UNIT_RULE;
index e3b245c88a2b2e501377f8cb576517e8e050577b..7a9e785950f39861a6511246aa5760ec4053ac98 100644 (file)
@@ -135,6 +135,7 @@ static struct solverflags2str {
   { SOLVER_FLAG_STRONG_RECOMMENDS,          "strongrecommends", 0 },
   { SOLVER_FLAG_INSTALL_ALSO_UPDATES,       "installalsoupdates", 0 },
   { SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED, "onlynamespacerecommended", 0 },
+  { SOLVER_FLAG_STRICT_REPO_PRIORITY,       "strictrepopriority", 0 },
   { 0, 0, 0 }
 };
 
@@ -1194,6 +1195,7 @@ static struct rclass2str {
   { SOLVER_RULE_YUMOBS, "yumobs" },
   { SOLVER_RULE_BLACK, "black" },
   { SOLVER_RULE_RECOMMENDS, "recommends" },
+  { SOLVER_RULE_STRICT_REPO_PRIORITY, "strictrepoprio" },
   { 0, 0 }
 };
 
index a4960ef44445d4cc5c0a2ee3a29ecc0a1e5d3552..558eb20653c586287ca7d5b2f9dcf22fb58b9a1e 100644 (file)
@@ -725,6 +725,12 @@ convertsolution(Solver *solv, Id why, Queue *solutionq)
       assert(solv->rules[why].p < 0);
       queue_push(solutionq, -solv->rules[why].p);
     }
+  if (why >= solv->strictrepopriorules && why < solv->strictrepopriorules_end)
+    {
+      queue_push(solutionq, SOLVER_SOLUTION_STRICTREPOPRIORITY);
+      assert(solv->rules[why].p < 0);
+      queue_push(solutionq, -solv->rules[why].p);
+    }
 }
 
 /*
@@ -1360,7 +1366,7 @@ solver_problemruleinfo2str(Solver *solv, SolverRuleinfo type, Id source, Id targ
     case SOLVER_RULE_BLACK:
       return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " can only be installed by a direct request");
     case SOLVER_RULE_STRICT_REPO_PRIORITY:
-      return pool_tmpjoin(pool, "package '", pool_solvid2str(pool, source), "' is excluded by strict repo priority");
+      return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " is excluded by strict repo priority");
     case SOLVER_RULE_PKG_CONSTRAINS:
       s = pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), 0);
       s = pool_tmpappend(pool, s, " has constraint ", pool_dep2str(pool, dep));
@@ -1426,6 +1432,11 @@ solver_solutionelement2str(Solver *solv, Id p, Id rp)
     }
   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);
index 45e4e7c6c09166ca66a155dcf9f394f73ef03ce4..f9b1efc3cfebcf6d66f02679d8874c5dbd106952 100644 (file)
@@ -28,6 +28,7 @@ struct s_Solver;
 #define SOLVER_SOLUTION_BEST           (-3)
 #define SOLVER_SOLUTION_POOLJOB                (-4)
 #define SOLVER_SOLUTION_BLACK          (-5)
+#define SOLVER_SOLUTION_STRICTREPOPRIORITY     (-6)
 
 void solver_recordproblem(struct s_Solver *solv, Id rid);
 void solver_fixproblem(struct s_Solver *solv, Id rid);
index 94a0bb6e007263051cfcbe11f29f862bb3821feb..a260c2dea1477435032ac69cc4af81a45dacaaa6 100644 (file)
@@ -2255,6 +2255,89 @@ solver_addblackrules(Solver *solv)
   solv->blackrules_end = solv->nrules;
 }
 
+/***********************************************************************
+ ***
+ ***  Strict repo prio rule part
+ ***/
+
+/* add rules to exclude solvables provided by lower
+ * precedence repositories */
+void solver_addstrictrepopriorules(struct s_Solver *solv, Map *addedmap)
+{
+  Pool *pool = solv->pool;
+  Solvable *s;
+  Id p, p2, pp2;
+  Map priomap;
+  int max_prio;
+
+  map_init_clone(&priomap, addedmap);
+  solv->strictrepopriorules = solv->nrules;
+
+  FOR_POOL_SOLVABLES(p)
+  {
+    if (!MAPTST(&priomap, p))
+      continue;
+
+    s = pool->solvables + p;
+    max_prio = s->repo->priority;
+    FOR_PROVIDES(p2, pp2, s->name)
+      {
+       Solvable *s2 = pool->solvables + p2;
+       if (s->name != s2->name)
+         continue;
+       if (s2->repo->priority > max_prio)
+         max_prio = s2->repo->priority;
+      }
+         
+    FOR_PROVIDES(p2, pp2, s->name)
+      {
+       Solvable *s2 = pool->solvables + p2;
+       if (s->name != s2->name || !MAPTST(&priomap, p2))
+         continue;
+       MAPCLR(&priomap, p2);
+       if (pool->installed && s2->repo == pool->installed)
+         continue;
+       if (s2->repo->priority < max_prio)
+         solver_addrule(solv, -p2, 0, 0);
+      }
+  }
+  solv->strictrepopriorules_end = solv->nrules;
+  map_free(&priomap);
+}
+
+static inline void
+disablerepopriorule(Solver *solv, Id name)
+{
+  Pool *pool = solv->pool;
+  Rule *r;
+  int i;
+  for (i = solv->strictrepopriorules, r = solv->rules + i; i < solv->strictrepopriorules_end; i++, r++)
+    {
+      if (r->p < 0 && r->d >= 0 && pool->solvables[-r->p].name == name)
+       solver_disablerule(solv, r);
+    }
+}
+
+static inline void
+reenablerepopriorule(Solver *solv, Id name)
+{
+  Pool *pool = solv->pool;
+  Rule *r;
+  int i;
+  for (i = solv->strictrepopriorules, r = solv->rules + i; i < solv->strictrepopriorules_end; i++, r++)
+    {
+      if (r->p < 0 && r->d < 0 && pool->solvables[-r->p].name == name)
+       {
+         solver_enablerule(solv, r);
+         IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS)
+           {
+             POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling ");
+             solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r);
+           }
+       }
+    }
+}
+
 /***********************************************************************
  ***
  ***  Policy rule disabling/reenabling
@@ -2264,10 +2347,11 @@ solver_addblackrules(Solver *solv)
  ***
  ***/
 
-#define DISABLE_UPDATE 1
-#define DISABLE_INFARCH        2
-#define DISABLE_DUP    3
-#define DISABLE_BLACK  4
+#define DISABLE_UPDATE  1
+#define DISABLE_INFARCH         2
+#define DISABLE_DUP     3
+#define DISABLE_BLACK   4
+#define DISABLE_REPOPRIO 5
 
 static void
 jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
@@ -2367,6 +2451,26 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
                }
            }
        }
+      if ((set & SOLVER_SETREPO) != 0 && solv->strictrepopriorules != solv->strictrepopriorules_end)
+       {
+         if (select == SOLVER_SOLVABLE)
+           queue_push2(q, DISABLE_REPOPRIO, pool->solvables[what].name);
+         else
+           {
+             int qcnt = q->count;
+             FOR_JOB_SELECT(p, pp, select, what)
+               {
+                 s = pool->solvables + p;
+                 /* unify names */
+                 for (i = qcnt; i < q->count; i += 2)
+                   if (q->elements[i + 1] == s->name)
+                     break;
+                 if (i < q->count)
+                   continue;
+                 queue_push2(q, DISABLE_REPOPRIO, s->name);
+               }
+           }
+       }
       if ((set & SOLVER_SETEVR) != 0 && solv->blackrules != solv->blackrules_end)
         {
          if (select == SOLVER_SOLVABLE)
@@ -2553,6 +2657,9 @@ solver_disablepolicyrules(Solver *solv)
        case DISABLE_BLACK:
          disableblackrule(solv, arg);
          break;
+       case DISABLE_REPOPRIO:
+         disablerepopriorule(solv, arg);
+         break;
        default:
          break;
        }
@@ -2659,6 +2766,9 @@ solver_reenablepolicyrules(Solver *solv, int jobidx)
        case DISABLE_BLACK:
          reenableblackrule(solv, arg);
          break;
+       case DISABLE_REPOPRIO:
+         reenablerepopriorule(solv, arg);
+         break;
        }
     }
   queue_free(&q);
@@ -4141,51 +4251,6 @@ solver_addrecommendsrules(Solver *solv)
   solv->recommendsrules_end = solv->nrules;
 }
 
-/* add rules to exclude solvables provided by lower
- * precedence repositories */
-void solver_addstrictrepopriorules(struct s_Solver *solv, Map *addedmap)
-{
-  Pool *pool = solv->pool;
-       Solvable *s;
-       Id p, p2, pp2;
-       Map priomap;
-       int max_prio;
-
-       map_init_clone(&priomap, addedmap);
-       solv->strictrepopriorules = solv->nrules;
-
-       FOR_POOL_SOLVABLES(p)
-       {
-               if (!MAPTST(&priomap, p))
-                       continue;
-
-               s = pool->solvables + p;
-               max_prio = s->repo->priority;
-               FOR_PROVIDES(p2, pp2, s->name)
-               {
-               Solvable *s2 = pool->solvables + p2;
-               if (s->name != s2->name)
-                       continue;
-               if (s2->repo->priority > max_prio)
-                       max_prio = s2->repo->priority;
-               }
-               
-       FOR_PROVIDES(p2, pp2, s->name)
-               {
-               Solvable *s2 = pool->solvables + p2;
-        if (s->name != s2->name || !MAPTST(&priomap, p2))
-          continue;
-        MAPCLR(&priomap, p2);
-               if (pool->installed && s2->repo == pool->installed)
-                       continue;
-        if (s2->repo->priority < max_prio)
-          solver_addrule(solv, -p2, 0, 0);
-               }
-       }
-       solv->strictrepopriorules_end = solv->nrules;
-       map_free(&priomap);
-}
-
 void
 solver_breakorphans(Solver *solv)
 {
index 040d9e5db2a8d3cda9da6b1abc34f6b7173a8c8e..5902cdb44142bf96c07144a5ab23f9c791f27ad0 100644 (file)
@@ -131,7 +131,7 @@ solver_printruleclass(Solver *solv, int type, Rule *r)
   else if (p >= solv->blackrules && p < solv->blackrules_end)
     POOL_DEBUG(type, "BLACK ");
   else if (p >= solv->strictrepopriorules && p < solv->strictrepopriorules_end)
-    POOL_DEBUG(type, "PRIOS ");
+    POOL_DEBUG(type, "REPOPRIO ");
   else if (p >= solv->recommendsrules && p < solv->recommendsrules_end)
     POOL_DEBUG(type, "RECOMMENDS ");
   solver_printrule(solv, type, r);
diff --git a/test/testcases/strictrepoprio/strictrepoprio.t b/test/testcases/strictrepoprio/strictrepoprio.t
new file mode 100644 (file)
index 0000000..d749d19
--- /dev/null
@@ -0,0 +1,22 @@
+repo system 0 empty
+repo available 0 testtags <inline>
+#>=Pkg: A 2 1 noarch
+repo available 1 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Req: B
+system i686 rpm system
+
+solverflags strictrepopriority
+job install name A
+result transaction,problems <inline>
+#>problem 30c1639e info nothing provides B needed by A-1-1.noarch
+#>problem 30c1639e solution 23f73f5b deljob install name A
+#>problem 30c1639e solution 5dd1416b allow A-2-1.noarch@available
+
+nextjob
+
+solverflags strictrepopriority
+job install pkg A-2-1.noarch@available
+result transaction,problems <inline>
+#>install A-2-1.noarch@available
+