X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Frules.c;h=a260c2dea1477435032ac69cc4af81a45dacaaa6;hb=11600c0259c8cd27ad8c87b16421e65030b4b126;hp=ffa29887e8f7b572c25b60c45caf43e566749a0e;hpb=2792a56227313bb9f16bd70604e79f47e9650885;p=platform%2Fupstream%2Flibsolv.git diff --git a/src/rules.c b/src/rules.c index ffa2988..a260c2d 100644 --- a/src/rules.c +++ b/src/rules.c @@ -2257,6 +2257,89 @@ solver_addblackrules(Solver *solv) /*********************************************************************** *** + *** 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 *** *** Disable all policy rules that conflict with our jobs. If a job @@ -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); @@ -2992,6 +3102,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 +3144,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; @@ -3187,6 +3303,78 @@ solver_choicerulecheck(Solver *solv, Id pi, Rule *r, Map *m, Queue *q) return 1; /* none of the new packages provided it */ } +static int +solver_choicerulecheck2(Solver *solv, Id pi, Id pt, Queue *q) +{ + Pool *pool = solv->pool; + Rule *ur; + Id p, pp; + int i; + + if (!q->count || q->elements[0] != pi) + { + if (q->count) + queue_empty(q); + ur = solv->rules + solv->updaterules + (pi - pool->installed->start); + if (!ur->p) + ur = solv->rules + solv->featurerules + (pi - pool->installed->start); + if (!ur->p) + return 1; /* orphaned, thus newest */ + queue_push2(q, pi, 0); + FOR_RULELITERALS(p, pp, ur) + if (p > 0 && p != pi) + queue_push(q, p); + queue_push(q, pi); + } + if (q->count <= 3) + return q->count == 3 && q->elements[2] == pt ? 1 : 0; + if (!q->elements[1]) + { + queue_deleten(q, 0, 2); + policy_filter_unwanted(solv, q, POLICY_MODE_CHOOSE); + queue_unshift(q, 1); /* filter mark */ + queue_unshift(q, pi); + } + for (i = 2; i < q->count; i++) + if (q->elements[i] == pt) + return 1; + return 0; /* not newest */ +} + +static int +solver_choicerulecheck3(Solver *solv, Id pt, Queue *q) +{ + Pool *pool = solv->pool; + Id p, pp; + int i; + + if (!q->count || q->elements[0] != pt) + { + Solvable *s = pool->solvables + pt; + if (q->count) + queue_empty(q); + /* no installed package, so check all with same name */ + queue_push2(q, pt, 0); + FOR_PROVIDES(p, pp, s->name) + if (pool->solvables[p].name == s->name && p != pt) + queue_push(q, p); + queue_push(q, pt); + } + if (q->count <= 3) + return q->count == 3 && q->elements[2] == pt ? 1 : 0; + if (!q->elements[1]) + { + queue_deleten(q, 0, 2); + policy_filter_unwanted(solv, q, POLICY_MODE_CHOOSE); + queue_unshift(q, 1); /* filter mark */ + queue_unshift(q, pt); + } + for (i = 2; i < q->count; i++) + if (q->elements[i] == pt) + return 1; + return 0; /* not newest */ +} + static inline void queue_removeelement(Queue *q, Id el) { @@ -3203,20 +3391,62 @@ queue_removeelement(Queue *q, Id el) } } +static Id +choicerule_find_installed(Pool *pool, Id p) +{ + Solvable *s = pool->solvables + p; + Id p2, pp2; + + if (!s->repo) + return 0; + if (s->repo == pool->installed) + return p; + FOR_PROVIDES(p2, pp2, s->name) + { + Solvable *s2 = pool->solvables + p2; + if (s2->repo != pool->installed) + continue; + if (!pool->implicitobsoleteusesprovides && s->name != s2->name) + continue; + if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, s2)) + continue; + return p2; + } + if (s->obsoletes) + { + Id obs, *obsp = s->repo->idarraydata + s->obsoletes; + while ((obs = *obsp++) != 0) + { + FOR_PROVIDES(p2, pp2, obs) + { + Solvable *s2 = pool->solvables + p2; + if (s2->repo != pool->installed) + continue; + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs)) + continue; + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) + continue; + return p2; + } + } + } + return 0; +} + void solver_addchoicerules(Solver *solv) { Pool *pool = solv->pool; Map m, mneg; Rule *r; - Queue q, qi, qcheck, infoq; + Queue q, qi, qcheck, qcheck2, infoq; int i, j, rid, havechoice, negcnt; - Id p, d, pp; - Id p2, pp2; - Solvable *s, *s2; + Id p, d, pp, p2; + Solvable *s; Id lastaddedp, lastaddedd; int lastaddedcnt; unsigned int now; + int isnewest = 0; solv->choicerules = solv->nrules; if (!pool->installed) @@ -3225,10 +3455,10 @@ solver_addchoicerules(Solver *solv) return; } now = solv_timems(0); - solv->choicerules_info = solv_calloc(solv->pkgrules_end, sizeof(Id)); queue_init(&q); queue_init(&qi); queue_init(&qcheck); + queue_init(&qcheck2); queue_init(&infoq); map_init(&m, pool->nsolvables); map_init(&mneg, pool->nsolvables); @@ -3260,80 +3490,28 @@ solver_addchoicerules(Solver *solv) continue; if (s->repo == pool->installed) { + queue_push2(&qi, p, p); queue_push(&q, p); continue; } - /* check if this package is "blocked" by a installed package */ - s2 = 0; - FOR_PROVIDES(p2, pp2, s->name) - { - s2 = pool->solvables + p2; - if (s2->repo != pool->installed) - continue; - if (!pool->implicitobsoleteusesprovides && s->name != s2->name) - continue; - if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, s2)) - continue; - break; - } + /* find an installed package p2 that we can update/downgrade to p */ + p2 = choicerule_find_installed(pool, p); if (p2) { - /* found installed package p2 that we can update to p */ if (MAPTST(&mneg, p)) continue; - if (policy_is_illegal(solv, s2, s, 0)) - continue; -#if 0 - if (solver_choicerulecheck(solv, p2, r, &m)) + if (policy_is_illegal(solv, pool->solvables + p2, s, 0)) continue; - queue_push(&qi, p2); -#else queue_push2(&qi, p2, p); -#endif queue_push(&q, p); continue; } - if (s->obsoletes) - { - Id obs, *obsp = s->repo->idarraydata + s->obsoletes; - s2 = 0; - while ((obs = *obsp++) != 0) - { - FOR_PROVIDES(p2, pp2, obs) - { - s2 = pool->solvables + p2; - if (s2->repo != pool->installed) - continue; - if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs)) - continue; - if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) - continue; - break; - } - if (p2) - break; - } - if (obs) - { - /* found installed package p2 that we can update to p */ - if (MAPTST(&mneg, p)) - continue; - if (policy_is_illegal(solv, s2, s, 0)) - continue; -#if 0 - if (solver_choicerulecheck(solv, p2, r, &m)) - continue; - queue_push(&qi, p2); -#else - queue_push2(&qi, p2, p); -#endif - queue_push(&q, p); - continue; - } - } /* package p is independent of the installed ones */ havechoice = 1; } +#if 0 + printf("havechoice: %d qcount %d qicount %d\n", havechoice, q.count, qi.count); +#endif if (!havechoice || !q.count || !qi.count) continue; /* no choice */ @@ -3341,13 +3519,30 @@ solver_addchoicerules(Solver *solv) if (p > 0) MAPSET(&m, p); + isnewest = 1; + FOR_RULELITERALS(p, pp, r) + { + if (p > 0) + break; + p2 = choicerule_find_installed(pool, -p); + if (p2 && !solver_choicerulecheck2(solv, p2, -p, &qcheck2)) + { + isnewest = 0; + break; + } + if (!p2 && !solver_choicerulecheck3(solv, -p, &qcheck2)) + { + isnewest = 0; + break; + } + } /* do extra checking */ for (i = j = 0; i < qi.count; i += 2) { p2 = qi.elements[i]; if (!p2) continue; - if (solver_choicerulecheck(solv, p2, r, &m, &qcheck)) + if (isnewest && solver_choicerulecheck(solv, p2, r, &m, &qcheck)) { /* oops, remove element p from q */ queue_removeelement(&q, qi.elements[i + 1]); @@ -3441,6 +3636,7 @@ solver_addchoicerules(Solver *solv) queue_free(&q); queue_free(&qi); queue_free(&qcheck); + queue_free(&qcheck2); queue_free(&infoq); map_free(&m); map_free(&mneg);