From: Adrien DELSALLE Date: Tue, 6 Jul 2021 16:46:52 +0000 (+0200) Subject: implement strict repo priority X-Git-Tag: 0.7.21~23^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=91be77ea69548808f94339928b5c92f5d9398a54;p=thirdparty%2Flibsolv.git implement strict repo priority add specific rule add solver flag add problem message/debug --- diff --git a/src/problems.c b/src/problems.c index a6b9394f..a4960ef4 100644 --- a/src/problems.c +++ b/src/problems.c @@ -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)); diff --git a/src/rules.c b/src/rules.c index b1b5f09c..0dcce68e 100644 --- a/src/rules.c +++ b/src/rules.c @@ -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) { diff --git a/src/rules.h b/src/rules.h index 3fcede07..043d0a0b 100644 --- a/src/rules.h +++ b/src/rules.h @@ -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); diff --git a/src/solver.c b/src/solver.c index 89a2ed10..25ff2d40 100644 --- a/src/solver.c +++ b/src/solver.c @@ -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 */ diff --git a/src/solver.h b/src/solver.h index 2dec2590..5de13c9c 100644 --- a/src/solver.h +++ b/src/solver.h @@ -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 */ diff --git a/src/solverdebug.c b/src/solverdebug.c index 0b2879b0..040d9e5d 100644 --- a/src/solverdebug.c +++ b/src/solverdebug.c @@ -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);