From: Michael Schroeder Date: Tue, 18 Dec 2018 15:40:00 +0000 (+0100) Subject: Make disfavoring recommended packages work if strong recommends is enabled X-Git-Tag: 0.7.3~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=841ea42d1c53a8dcf22eeb0dde73925f201dde0b;p=thirdparty%2Flibsolv.git Make disfavoring recommended packages work if strong recommends is enabled Unfortunately this needs a new rule type, which is just the original recommends rule minus the disfavored packages. --- diff --git a/ext/testcase.c b/ext/testcase.c index 3c5df4d4..31fe4e9c 100644 --- a/ext/testcase.c +++ b/ext/testcase.c @@ -2025,6 +2025,8 @@ testcase_solverresult(Solver *solv, int resultflags) /* map choice rules back to pkg rules */ if (solver_ruleclass(solv, id) == SOLVER_RULE_CHOICE) id = solver_rule2pkgrule(solv, id); + if (solver_ruleclass(solv, id) == SOLVER_RULE_RECOMMENDS) + id = solver_rule2pkgrule(solv, id); solver_allruleinfos(solv, id, &rq); for (i = 0; i < rq.count; i += 4) { diff --git a/src/rules.c b/src/rules.c index e8f8ea0d..1c11151a 100644 --- a/src/rules.c +++ b/src/rules.c @@ -2740,13 +2740,11 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp) return SOLVER_RULE_YUMOBS; } if (rid >= solv->choicerules && rid < solv->choicerules_end) - { - return SOLVER_RULE_CHOICE; - } + return SOLVER_RULE_CHOICE; + if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end) + return SOLVER_RULE_RECOMMENDS; if (rid >= solv->learntrules) - { - return SOLVER_RULE_LEARNT; - } + return SOLVER_RULE_LEARNT; return SOLVER_RULE_UNKNOWN; } @@ -2773,6 +2771,8 @@ solver_ruleclass(Solver *solv, Id rid) return SOLVER_RULE_YUMOBS; if (rid >= solv->choicerules && rid < solv->choicerules_end) return SOLVER_RULE_CHOICE; + if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end) + return SOLVER_RULE_RECOMMENDS; if (rid >= solv->learntrules && rid < solv->nrules) return SOLVER_RULE_LEARNT; return SOLVER_RULE_UNKNOWN; @@ -2835,6 +2835,8 @@ solver_rule2pkgrule(Solver *solv, Id rid) { if (rid >= solv->choicerules && rid < solv->choicerules_end) return solv->choicerules_ref[rid - solv->choicerules]; + if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end) + return solv->recommendsrules_info[rid - solv->recommendsrules]; return 0; } @@ -3634,6 +3636,54 @@ for (j = 0; j < qq.count; j++) POOL_DEBUG(SOLV_DEBUG_STATS, "yumobs rule creation took %d ms\n", solv_timems(now)); } +/* recommendsrules are a copy of some recommends package rule but + * with some disfavored literals removed */ +void +solver_addrecommendsrules(Solver *solv) +{ + Pool *pool = solv->pool; + int i, havedis, havepos; + Id p, pp; + Queue q, infoq; + + solv->recommendsrules = solv->nrules; + queue_init(&q); + queue_init(&infoq); + for (i = 0; i < solv->recommendsruleq->count; i++) + { + int rid = solv->recommendsruleq->elements[i]; + Rule *r = solv->rules + rid; + queue_empty(&q); + havedis = havepos = 0; + FOR_RULELITERALS(p, pp, r) + { + if (p > 0 && solv->favormap[p] < 0) + havedis = 1; + else + { + if (p > 0) + havepos = 1; + queue_push(&q, p); + } + } + if (!havedis) + continue; + solver_disablerule(solv, r); + if (!havepos || q.count < 2) + continue; + if (q.count == 2) + solver_addrule(solv, q.elements[0], q.elements[1], 0); + else + solver_addrule(solv, q.elements[0], 0, pool_ids2whatprovides(pool, q.elements + 1, q.count - 1)); + queue_push(&infoq, rid); + } + if (infoq.count) + solv->recommendsrules_info = solv_memdup2(infoq.elements, infoq.count, sizeof(Id)); + queue_free(&infoq); + queue_free(&q); + solv->recommendsrules_end = solv->nrules; +} + void solver_breakorphans(Solver *solv) { diff --git a/src/rules.h b/src/rules.h index a3c01353..1db0551c 100644 --- a/src/rules.h +++ b/src/rules.h @@ -71,7 +71,8 @@ typedef enum { SOLVER_RULE_CHOICE = 0x700, SOLVER_RULE_LEARNT = 0x800, SOLVER_RULE_BEST = 0x900, - SOLVER_RULE_YUMOBS = 0xa00 + SOLVER_RULE_YUMOBS = 0xa00, + SOLVER_RULE_RECOMMENDS = 0xb00 } SolverRuleinfo; #define SOLVER_RULE_TYPEMASK 0xff00 @@ -133,6 +134,9 @@ extern void solver_addbestrules(struct s_Solver *solv, int havebestinstalljobs); /* yumobs rules */ extern void solver_addyumobsrules(struct s_Solver *solv); +/* recommends rules */ +extern void solver_addrecommendsrules(struct s_Solver *solv); + /* 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 e020bb13..9d987759 100644 --- a/src/solver.c +++ b/src/solver.c @@ -845,18 +845,19 @@ static void disable_recommendsrules(Solver *solv, Queue *weakq) { Pool *pool = solv->pool; - int i; + int i, rid; for (i = 0; i < weakq->count; i++) { - Rule *r; - if (!queue_contains(solv->recommendsruleq, weakq->elements[i])) - continue; - r = solv->rules + weakq->elements[i]; - if (r->d >= 0) + rid = weakq->elements[i]; + if ((rid >= solv->recommendsrules && rid < solv->recommendsrules_end) || queue_contains(solv->recommendsruleq, rid)) { - POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling "); - solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, r); - solver_disablerule(solv, r); + Rule *r = solv->rules + rid; + if (r->d >= 0) + { + POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling "); + solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, r); + solver_disablerule(solv, r); + } } } } @@ -904,6 +905,18 @@ disable_weakrules(Solver *solv, Queue *weakq) for (i = 0; i < weakq->count; i++) if (weakq->elements[i] > lastweak) lastweak = weakq->elements[i]; + if (lastweak >= solv->recommendsrules && lastweak < solv->recommendsrules_end) + { + lastweak = 0; + for (i = 0; i < weakq->count; i++) + if (weakq->elements[i] < solv->recommendsrules && weakq->elements[i] > lastweak) + lastweak = weakq->elements[i]; + if (lastweak < solv->pkgrules_end) + { + disable_recommendsrules(solv, weakq); + return; + } + } if (lastweak < solv->pkgrules_end && solv->strongrecommends && solv->recommendsruleq && queue_contains(solv->recommendsruleq, lastweak)) { disable_recommendsrules(solv, weakq); @@ -1397,6 +1410,7 @@ solver_free(Solver *solv) solv_free(solv->choicerules_ref); solv_free(solv->bestrules_pkg); solv_free(solv->yumobsrules_info); + solv_free(solv->recommendsrules_info); solv_free(solv->instbuddy); solv_free(solv); } @@ -3129,10 +3143,6 @@ addedmap2deduceq(Solver *solv, Map *addedmap) for (; i < pool->nsolvables; i++) if (MAPTST(addedmap, i)) queue_push(&solv->addedmap_deduceq, i); - j = 0; - for (i = 2; i < pool->nsolvables; i++) - if (MAPTST(addedmap, i)) - j++; } static void @@ -3284,6 +3294,7 @@ solver_solve(Solver *solv, Queue *job) queue_empty(&solv->ruleassertions); solv->bestrules_pkg = solv_free(solv->bestrules_pkg); solv->yumobsrules_info = solv_free(solv->yumobsrules_info); + solv->recommendsrules_info = solv_free(solv->recommendsrules_info); solv->choicerules_ref = solv_free(solv->choicerules_ref); if (solv->noupdate.size) map_empty(&solv->noupdate); @@ -3354,9 +3365,9 @@ solver_solve(Solver *solv, Queue *job) */ initialnrules = solv->pkgrules_end ? solv->pkgrules_end : 1; if (initialnrules > 1) - deduceq2addedmap(solv, &addedmap); + deduceq2addedmap(solv, &addedmap); /* also enables all pkg rules */ if (solv->nrules != initialnrules) - solver_shrinkrules(solv, initialnrules); + solver_shrinkrules(solv, initialnrules); /* shrink to just pkg rules */ solv->lastpkgrule = 0; solv->pkgrules_end = 0; @@ -3908,6 +3919,11 @@ solver_solve(Solver *solv, Queue *job) else solv->yumobsrules = solv->yumobsrules_end = solv->nrules; + if (solv->havedisfavored && solv->strongrecommends) + solver_addrecommendsrules(solv); + else + solv->recommendsrules = solv->recommendsrules_end = solv->nrules; + if (1) solver_addchoicerules(solv); else @@ -4777,6 +4793,8 @@ solver_alternative2str(Solver *solv, int type, Id id, Id from) char buf[64]; if (solver_ruleclass(solv, id) == SOLVER_RULE_CHOICE) id = solver_rule2pkgrule(solv, id); + if (solver_ruleclass(solv, id) == SOLVER_RULE_RECOMMENDS) + id = solver_rule2pkgrule(solv, id); rtype = solver_ruleinfo(solv, id, &depfrom, &depto, &dep); if ((rtype & SOLVER_RULE_TYPEMASK) == SOLVER_RULE_JOB) { diff --git a/src/solver.h b/src/solver.h index 10b4506d..e372794c 100644 --- a/src/solver.h +++ b/src/solver.h @@ -80,6 +80,10 @@ struct s_Solver { Id choicerules_end; Id *choicerules_ref; + Id recommendsrules; /* rules from recommends pkg rules with disfavored literals */ + Id recommendsrules_end; + Id *recommendsrules_info; /* the original pkg rule rule */ + Id learntrules; /* learnt rules, (end == nrules) */ Map noupdate; /* don't try to update these diff --git a/src/solverdebug.c b/src/solverdebug.c index bb74ef61..b1b55f48 100644 --- a/src/solverdebug.c +++ b/src/solverdebug.c @@ -128,6 +128,8 @@ solver_printruleclass(Solver *solv, int type, Rule *r) POOL_DEBUG(type, "FEATURE "); else if (p >= solv->yumobsrules && p < solv->yumobsrules_end) POOL_DEBUG(type, "YUMOBS "); + else if (p >= solv->recommendsrules && p < solv->recommendsrules_end) + POOL_DEBUG(type, "RECOMMENDS "); solver_printrule(solv, type, r); }