]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
implement strict repo priority
authorAdrien DELSALLE <ad.delsalle@gmail.com>
Tue, 6 Jul 2021 16:46:52 +0000 (18:46 +0200)
committerAdrien DELSALLE <ad.delsalle@gmail.com>
Mon, 9 Aug 2021 12:08:29 +0000 (14:08 +0200)
add specific rule
add solver flag
add problem message/debug

src/problems.c
src/rules.c
src/rules.h
src/solver.c
src/solver.h
src/solverdebug.c

index a6b9394fd40fb5eba631ba5afe1cbdcd0219979b..a4960ef44445d4cc5c0a2ee3a29ecc0a1e5d3552 100644 (file)
@@ -1068,10 +1068,10 @@ solver_take_solution(Solver *solv, Id problem, Id solution, Queue *job)
  */
 
 static void
-findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp, Id *jobrp, Id *blkrp, Map *rseen)
+findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp, Id *jobrp, Id *blkrp, Id *scprp, Map *rseen)
 {
   Id rid, d;
-  Id lreqr, lconr, lsysr, ljobr, lblkr;
+  Id lreqr, lconr, lsysr, ljobr, lblkr, lscpr;
   Rule *r;
   Id jobassert = 0;
   int i, reqset = 0;   /* 0: unset, 1: installed, 2: jobassert, 3: assert */
@@ -1093,7 +1093,7 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp,
 
   /* the problem rules are somewhat ordered from "near to the problem" to
    * "near to the job" */
-  lreqr = lconr = lsysr = ljobr = lblkr = 0;
+  lreqr = lconr = lsysr = ljobr = lblkr = lscpr = 0;
   while ((rid = solv->learnt_pool.elements[idx++]) != 0)
     {
       assert(rid > 0);
@@ -1102,7 +1102,7 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp,
          if (MAPTST(rseen, rid - solv->learntrules))
            continue;
          MAPSET(rseen, rid - solv->learntrules);
-         findproblemrule_internal(solv, solv->learnt_why.elements[rid - solv->learntrules], &lreqr, &lconr, &lsysr, &ljobr, &lblkr, rseen);
+         findproblemrule_internal(solv, solv->learnt_why.elements[rid - solv->learntrules], &lreqr, &lconr, &lsysr, &ljobr, &lblkr, &lscpr, rseen);
        }
       else if ((rid >= solv->jobrules && rid < solv->jobrules_end) || (rid >= solv->infarchrules && rid < solv->infarchrules_end) || (rid >= solv->duprules && rid < solv->duprules_end) || (rid >= solv->bestrules && rid < solv->bestrules_end) || (rid >= solv->yumobsrules && rid < solv->yumobsrules_end))
        {
@@ -1119,6 +1119,11 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp,
          if (!*blkrp)
            *blkrp = rid;
        }
+      else if (rid >= solv->strictrepopriorules && rid < solv->strictrepopriorules_end)
+       {
+         if (!*scprp)
+           *scprp = rid;
+       }
       else
        {
          assert(rid < solv->pkgrules_end);
@@ -1183,6 +1188,8 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp,
     *sysrp = lsysr;
   if (!*blkrp && lblkr)
     *blkrp = lblkr;
+  if (!*scprp && lscpr)
+    *scprp = lscpr;
 }
 
 /*
@@ -1197,12 +1204,12 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp,
 Id
 solver_findproblemrule(Solver *solv, Id problem)
 {
-  Id reqr, conr, sysr, jobr, blkr;
+  Id reqr, conr, sysr, jobr, blkr, srpr;
   Id idx = solv->problems.elements[2 * problem - 2];
   Map rseen;
-  reqr = conr = sysr = jobr = blkr = 0;
+  reqr = conr = sysr = jobr = blkr = srpr = 0;
   map_init(&rseen, solv->learntrules ? solv->nrules - solv->learntrules : 0);
-  findproblemrule_internal(solv, idx, &reqr, &conr, &sysr, &jobr, &blkr, &rseen);
+  findproblemrule_internal(solv, idx, &reqr, &conr, &sysr, &jobr, &blkr, &srpr, &rseen);
   map_free(&rseen);
   /* check if the request is about a not-installed package requiring a installed
    * package conflicting with the non-installed package. In that case return the conflict */
@@ -1232,6 +1239,8 @@ solver_findproblemrule(Solver *solv, Id problem)
     return conr;       /* some conflict */
   if (blkr)
     return blkr;       /* a blacklisted package */
+  if (srpr)
+    return srpr;       /* a strict repo priority */
   if (sysr)
     return sysr;       /* an update rule */
   if (jobr)
@@ -1350,6 +1359,8 @@ solver_problemruleinfo2str(Solver *solv, SolverRuleinfo type, Id source, Id targ
       return pool_tmpappend(pool, s, pool_dep2str(pool, dep), 0);
     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");
     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));
index b1b5f09cb6a12486b0e3668e7cb6cc318fa0fe41..0dcce68e9ae9367ea7715664ad42e727d093f232 100644 (file)
@@ -2992,6 +2992,12 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp)
        *fromp = -r->p;
       return SOLVER_RULE_BLACK;
     }
+  if (rid >= solv->strictrepopriorules && rid < solv->strictrepopriorules_end)
+    {
+      if (fromp)
+       *fromp = -r->p;
+      return SOLVER_RULE_STRICT_REPO_PRIORITY;
+    }
   if (rid >= solv->choicerules && rid < solv->choicerules_end)
     return SOLVER_RULE_CHOICE;
   if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
@@ -3028,8 +3034,8 @@ solver_ruleclass(Solver *solv, Id rid)
     return SOLVER_RULE_CHOICE;
   if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
     return SOLVER_RULE_RECOMMENDS;
-  if (rid >= solv->blackrules && rid < solv->blackrules_end)
-    return SOLVER_RULE_BLACK;
+  if (rid >= solv->strictrepopriorules && rid < solv->strictrepopriorules_end)
+    return SOLVER_RULE_STRICT_REPO_PRIORITY;
   if (rid >= solv->learntrules && rid < solv->nrules)
     return SOLVER_RULE_LEARNT;
   return SOLVER_RULE_UNKNOWN;
@@ -4135,6 +4141,54 @@ 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)
+               {
+               MAPCLR(&priomap, p2);
+                       continue;
+               }
+               if (s2->repo->priority > max_prio)
+                       max_prio = s2->repo->priority;
+               }
+               
+    FOR_PROVIDES(p2, pp2, s->name)
+               {
+               Solvable *s2 = pool->solvables + p2;
+               if (!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 3fcede076013806fdd9821a623cedbd1955ab40e..043d0a0b2fd6d4017510199410f953cc4e661ac1 100644 (file)
@@ -74,7 +74,8 @@ typedef enum {
   SOLVER_RULE_BEST = 0x900,
   SOLVER_RULE_YUMOBS = 0xa00,
   SOLVER_RULE_RECOMMENDS = 0xb00,
-  SOLVER_RULE_BLACK = 0xc00
+  SOLVER_RULE_BLACK = 0xc00,
+  SOLVER_RULE_STRICT_REPO_PRIORITY = 0xd00
 } SolverRuleinfo;
 
 #define SOLVER_RULE_TYPEMASK    0xff00
@@ -142,6 +143,9 @@ extern void solver_addblackrules(struct s_Solver *solv);
 /* recommends rules */
 extern void solver_addrecommendsrules(struct s_Solver *solv);
 
+/* channel priority rules */
+extern void solver_addstrictrepopriorules(struct s_Solver *solv, Map *addedmap);
+
 /* policy rule disabling/reenabling */
 extern void solver_disablepolicyrules(struct s_Solver *solv);
 extern void solver_reenablepolicyrules(struct s_Solver *solv, int jobidx);
index 89a2ed10f85cf10c14ca9fa2053a8fccafd259dd..25ff2d40e7c7edfc20f7bfe9a9fb23e6b1aa8a1c 100644 (file)
@@ -1473,6 +1473,8 @@ solver_get_flag(Solver *solv, int flag)
     return solv->install_also_updates;
   case SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED:
     return solv->only_namespace_recommended;
+  case SOLVER_FLAG_STRICT_REPO_PRIORITY:
+    return solv->strict_repo_priority;
   default:
     break;
   }
@@ -1566,6 +1568,9 @@ solver_set_flag(Solver *solv, int flag, int value)
   case SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED:
     solv->only_namespace_recommended = value;
     break;
+  case SOLVER_FLAG_STRICT_REPO_PRIORITY:
+    solv->strict_repo_priority = value;
+    break;
   default:
     break;
   }
@@ -4062,6 +4067,11 @@ solver_solve(Solver *solv, Queue *job)
   else
     solv->recommendsrules = solv->recommendsrules_end = solv->nrules;
 
+  if (solv->strict_repo_priority)
+    solver_addstrictrepopriorules(solv, &addedmap);
+  else
+    solv->strictrepopriorules = solv->strictrepopriorules_end = solv->nrules;
+
   if (1)
     solver_addchoicerules(solv);
   else
@@ -4077,7 +4087,19 @@ solver_solve(Solver *solv, Queue *job)
   map_free(&installcandidatemap);
   queue_free(&q);
 
-  POOL_DEBUG(SOLV_DEBUG_STATS, "%d pkg rules, 2 * %d update rules, %d job rules, %d infarch rules, %d dup rules, %d choice rules, %d best rules, %d yumobs rules\n", solv->pkgrules_end - 1, solv->updaterules_end - solv->updaterules, solv->jobrules_end - solv->jobrules, solv->infarchrules_end - solv->infarchrules, solv->duprules_end - solv->duprules, solv->choicerules_end - solv->choicerules, solv->bestrules_end - solv->bestrules, solv->yumobsrules_end - solv->yumobsrules);
+  POOL_DEBUG(SOLV_DEBUG_STATS, "%d pkg rules, 2 * %d update rules, %d job rules, %d infarch rules, %d dup rules, %d choice rules, %d best rules, %d yumobs rules\n"
+  "%d black rules, %d recommends rules, %d repo priority rules\n",
+   solv->pkgrules_end - 1, 
+   solv->updaterules_end - solv->updaterules, 
+   solv->jobrules_end - solv->jobrules, 
+   solv->infarchrules_end - solv->infarchrules, 
+   solv->duprules_end - solv->duprules, 
+   solv->choicerules_end - solv->choicerules, 
+   solv->bestrules_end - solv->bestrules, 
+   solv->yumobsrules_end - solv->yumobsrules,
+   solv->blackrules_end - solv->blackrules,
+   solv->recommendsrules_end - solv->recommendsrules,
+   solv->strictrepopriorules_end - solv->strictrepopriorules);
   POOL_DEBUG(SOLV_DEBUG_STATS, "overall rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024);
 
   /* create weak map */
index 2dec2590a226b2f056b86190f261073dbefe8cf4..5de13c9c078cf04364bb73350105cbb3caf7f2bc 100644 (file)
@@ -79,6 +79,9 @@ struct s_Solver {
   Id blackrules;                       /* rules from blacklisted packages */
   Id blackrules_end;
 
+  Id strictrepopriorules;                      /* rules from strict priority repositories */
+  Id strictrepopriorules_end;
+
   Id choicerules;                      /* choice rules (always weak) */
   Id choicerules_end;
   Id *choicerules_info;                        /* the rule we used to generate the choice rule */
@@ -175,6 +178,7 @@ struct s_Solver {
   int strongrecommends;                        /* true: create weak rules for recommends */
   int install_also_updates;            /* true: do not prune install job rules to installed packages */
   int only_namespace_recommended;      /* true: only install packages recommended by namespace */
+  int strict_repo_priority;                    /* true: only use packages from highest precedence/priority */
 
   int process_orphans;                 /* true: do special orphan processing */
   Map dupmap;                          /* dup to those packages */
@@ -326,6 +330,7 @@ typedef struct s_Solver Solver;
 #define SOLVER_FLAG_STRONG_RECOMMENDS          25
 #define SOLVER_FLAG_INSTALL_ALSO_UPDATES       26
 #define SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED 27
+#define SOLVER_FLAG_STRICT_REPO_PRIORITY       28
 
 #define GET_USERINSTALLED_NAMES                        (1 << 0)        /* package names instead of ids */
 #define GET_USERINSTALLED_INVERTED             (1 << 1)        /* autoinstalled */
index 0b2879b08dfba5cba2a05b7edd9b44b5655defd3..040d9e5db2a8d3cda9da6b1abc34f6b7173a8c8e 100644 (file)
@@ -130,6 +130,8 @@ solver_printruleclass(Solver *solv, int type, Rule *r)
     POOL_DEBUG(type, "YUMOBS ");
   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 ");
   else if (p >= solv->recommendsrules && p < solv->recommendsrules_end)
     POOL_DEBUG(type, "RECOMMENDS ");
   solver_printrule(solv, type, r);