X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Frules.c;h=212df32203af77bd6e9c4a1523f15fe8db0411db;hb=5f5ff9576322b449fca131df791f4748e412df5f;hp=cb8d17dd55a6ad8e06936c7d9f8f86260eaa6fcf;hpb=f1a786b6fe3fc2d53f03b25e303dc45ed7e22ba6;p=platform%2Fupstream%2Flibsolv.git diff --git a/src/rules.c b/src/rules.c index cb8d17d..212df32 100644 --- a/src/rules.c +++ b/src/rules.c @@ -613,7 +613,7 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w } else { - Id *qele; + Id *qele, d; int qcnt; qele = bq.elements + i; @@ -653,7 +653,17 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w break; if (j < qcnt) continue; - addpkgrule(solv, qele[0], 0, pool_ids2whatprovides(pool, qele + 1, qcnt - 1), type, dep); + d = pool_ids2whatprovides(pool, qele + 1, qcnt - 1); + if (solv->ruleinfoq && qele[0] != p) + { + int oldcount = solv->ruleinfoq->count; + addpkgrule(solv, qele[0], 0, d, type, dep); + /* fixup from element of ruleinfo */ + if (solv->ruleinfoq->count > oldcount) + solv->ruleinfoq->elements[oldcount + 1] = p; + } + else + addpkgrule(solv, qele[0], 0, d, type, dep); if (m) for (j = 0; j < qcnt; j++) if (qele[j] > 0 && !MAPTST(m, qele[j])) @@ -665,6 +675,34 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w #endif +#ifdef ENABLE_CONDA +void +add_conda_constrains_rule(Solver *solv, Id n, Id dep, int dontfix) +{ + Pool *pool = solv->pool; + Reldep *rd; + Id p, pp, pdep; + if (!ISRELDEP(dep)) + return; + rd = GETRELDEP(pool, dep); + pdep = pool_whatprovides(pool, dep); + FOR_PROVIDES(p, pp, rd->name) + { + Id p2; + if (p == n) + continue; + if (dontfix && pool->solvables[p].repo == solv->installed) + continue; + while ((p2 = pool->whatprovidesdata[pdep]) != 0 && p2 < p) + pdep++; + if (p == p2) + pdep++; + else + addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_CONSTRAINS, dep); + } +} +#endif + /*------------------------------------------------------------------- * * add dependency rules for solvable @@ -693,8 +731,8 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) Queue workq; /* list of solvables we still have to work on */ Id workqbuf[64]; - Queue prereqq; /* list of pre-req ids to ignore */ - Id prereqbuf[16]; + Queue depq; /* list of pre-req ids to ignore */ + Id depqbuf[16]; int i; int dontfix; /* ignore dependency errors for installed solvables */ @@ -710,7 +748,7 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) queue_init_buffer(&workq, workqbuf, sizeof(workqbuf)/sizeof(*workqbuf)); queue_push(&workq, s - pool->solvables); /* push solvable Id to work queue */ - queue_init_buffer(&prereqq, prereqbuf, sizeof(prereqbuf)/sizeof(*prereqbuf)); + queue_init_buffer(&depq, depqbuf, sizeof(depqbuf)/sizeof(*depqbuf)); /* loop until there's no more work left */ while (workq.count) @@ -770,20 +808,18 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) { if (installed && s->repo == installed) { - if (prereqq.count) - queue_empty(&prereqq); - solvable_lookup_idarray(s, SOLVABLE_PREREQ_IGNOREINST, &prereqq); - filterpre = prereqq.count; + solvable_lookup_idarray(s, SOLVABLE_PREREQ_IGNOREINST, &depq); + filterpre = depq.count; } continue; } if (filterpre) { - /* check if this id is filtered. assumes that prereqq.count is small */ - for (i = 0; i < prereqq.count; i++) - if (req == prereqq.elements[i]) + /* check if this id is filtered. assumes that depq.count is small */ + for (i = 0; i < depq.count; i++) + if (req == depq.elements[i]) break; - if (i < prereqq.count) + if (i < depq.count) { POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s: ignoring filtered pre-req dependency %s\n", pool_solvable2str(pool, s), pool_dep2str(pool, req)); continue; @@ -896,6 +932,15 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) } } +#ifdef ENABLE_CONDA + if (pool->disttype == DISTTYPE_CONDA) + { + solvable_lookup_idarray(s, SOLVABLE_CONSTRAINS, &depq); + for (i = 0; i < depq.count; i++) + add_conda_constrains_rule(solv, n, depq.elements[i], dontfix); + } +#endif + /* that's all we check for src packages */ if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) continue; @@ -1099,7 +1144,7 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) } } } - queue_free(&prereqq); + queue_free(&depq); queue_free(&workq); } @@ -1621,13 +1666,16 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) } } if (first) - continue; + continue; /* not the first in the group */ + + if (!bestscore) + continue; /* did not find a score for this group */ /* speed up common case where installed package already has best arch */ if (allowedarchs.count == 1 && bests && allowedarchs.elements[0] == bests->arch) allowedarchs.count--; /* installed arch is best */ - if (allowedarchs.count && pool->implicitobsoleteusescolors && installed && bestscore) + if (allowedarchs.count && pool->implicitobsoleteusescolors && installed) { /* need an extra pass for lockstep checking: we only allow to keep an inferior arch * if the corresponding installed package is not lock-stepped */ @@ -1672,7 +1720,7 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) if (ps->name != s->name || !MAPTST(addedmap, p)) continue; a = pool_arch2score(pool, ps->arch); - if (a != 1 && bestscore && ((a ^ bestscore) & 0xffff0000) != 0) + if (a != 1 && ((a ^ bestscore) & 0xffff0000) != 0) { if (installed && ps->repo == installed) { @@ -2691,7 +2739,8 @@ addpkgruleinfo(Solver *solv, Id p, Id p2, Id d, int type, Id dep) if (*odp) return; } - if (p < 0 && pool->whatprovidesdata[d] < 0 && type == SOLVER_RULE_PKG_CONFLICTS) + /* set p2 for multiversion conflicts */ + if (p < 0 && pool->whatprovidesdata[d] < 0 && pool->whatprovidesdata[d + 1] >= 0 && type == SOLVER_RULE_PKG_CONFLICTS) p2 = pool->whatprovidesdata[d]; } else @@ -3138,6 +3187,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) { @@ -3154,20 +3275,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; - int i, j, rid, havechoice; - Id p, d, pp; - Id p2, pp2; - Solvable *s, *s2; + Queue q, qi, qcheck, qcheck2, infoq; + int i, j, rid, havechoice, negcnt; + 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) @@ -3176,10 +3339,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); @@ -3211,80 +3374,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 */ @@ -3292,13 +3403,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]); @@ -3340,9 +3468,12 @@ solver_addchoicerules(Solver *solv) qi.elements[j] = 0; } /* empty map again */ + negcnt = 0; FOR_RULELITERALS(p, pp, r) if (p > 0) MAPCLR(&m, p); + else + negcnt++; if (i == qi.count) { #if 0 @@ -3351,7 +3482,14 @@ solver_addchoicerules(Solver *solv) #endif continue; } - + /* add neg elements to the front */ + if (negcnt > 1) + { + i = 0; + FOR_RULELITERALS(p, pp, r) + if (p < 0 && p != r->p) + queue_insert(&q, i++, p); + } /* don't add identical rules */ if (lastaddedp == r->p && lastaddedcnt == q.count) { @@ -3382,6 +3520,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);