X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=src%2Fpolicy.c;h=823a00878e9c7534da3a503b6e88eef48a086432;hb=18ebbaf4f619e79231f5ad18a2ab8c135d22ef56;hp=fadfcdae4d65546f7137c0ba676153365213b858;hpb=1a93853889c819ac2d3c8e83e856f4775e664b00;p=platform%2Fupstream%2Flibsolv.git diff --git a/src/policy.c b/src/policy.c index fadfcda..823a008 100644 --- a/src/policy.c +++ b/src/policy.c @@ -21,9 +21,11 @@ #include "policy.h" #include "poolvendor.h" #include "poolarch.h" +#include "linkedpkg.h" #include "cplxdeps.h" + /*-----------------------------------------------------------------*/ /* @@ -54,11 +56,11 @@ prune_to_best_version_sortcmp(const void *ap, const void *bp, void *dp) } if (sa->arch != sb->arch) { - int aa, ab; - aa = (sa->arch <= pool->lastarch) ? pool->id2arch[sa->arch] : 0; - ab = (sb->arch <= pool->lastarch) ? pool->id2arch[sb->arch] : 0; + unsigned int aa, ab; + aa = pool_arch2score(pool, sa->arch); + ab = pool_arch2score(pool, sb->arch); if (aa != ab && aa > 1 && ab > 1) - return aa - ab; /* lowest score first */ + return aa < ab ? -1 : 1; /* lowest score first */ } /* the same name, bring installed solvables to the front */ @@ -143,7 +145,7 @@ solver_prune_installed_dup_packages(Solver *solv, Queue *plist) Solvable *s = pool->solvables + p; if (s->repo != pool->installed && s->repo->priority < bestprio) continue; - if (s->repo == pool->installed && (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)))) + if (s->repo == pool->installed && (solv->dupinvolvedmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)))) { Id p2, pp2; int keepit = 0; @@ -179,7 +181,7 @@ static inline void solver_prune_to_highest_prio(Solver *solv, Queue *plist) { prune_to_highest_prio(solv->pool, plist); - if (plist->count > 1 && solv->pool->installed && (solv->dupmap_all || solv->dupinvolvedmap.size)) + if (plist->count > 1 && solv->pool->installed && (solv->dupinvolvedmap_all || solv->dupinvolvedmap.size)) solver_prune_installed_dup_packages(solv, plist); } @@ -200,14 +202,14 @@ solver_prune_to_highest_prio_per_name(Solver *solv, Queue *plist) { if (pool->solvables[plist->elements[i]].name != name) { + name = pool->solvables[plist->elements[i]].name; if (pq.count > 2) solver_prune_to_highest_prio(solv, &pq); for (k = 0; k < pq.count; k++) plist->elements[j++] = pq.elements[k]; queue_empty(&pq); - queue_push(&pq, plist->elements[i]); - name = pool->solvables[pq.elements[0]].name; } + queue_push(&pq, plist->elements[i]); } if (pq.count > 2) solver_prune_to_highest_prio(solv, &pq); @@ -451,6 +453,21 @@ prefer_suggested(Solver *solv, Queue *plist) } } +static int +sort_by_favor_cmp(const void *ap, const void *bp, void *dp) +{ + const Id *a = ap, *b = bp, *d = dp; + return d[b[0]] - d[a[0]]; +} + +/* bring favored packages to front and disfavored packages to back */ +void +policy_prefer_favored(Solver *solv, Queue *plist) +{ + if (solv->favormap && plist->count > 1) + solv_sort(plist->elements, plist->count, sizeof(Id), sort_by_favor_cmp, solv->favormap); +} + /* * prune to recommended/suggested packages. * does not prune installed packages (they are also somewhat recommended). @@ -561,8 +578,7 @@ prune_to_best_arch(const Pool *pool, Queue *plist) for (i = 0; i < plist->count; i++) { s = pool->solvables + plist->elements[i]; - a = s->arch; - a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; + a = pool_arch2score(pool, s->arch); if (a && a != 1 && (!bestscore || a < bestscore)) bestscore = a; } @@ -571,10 +587,9 @@ prune_to_best_arch(const Pool *pool, Queue *plist) for (i = j = 0; i < plist->count; i++) { s = pool->solvables + plist->elements[i]; - a = s->arch; - if (a > pool->lastarch) + a = pool_arch2score(pool, s->arch); + if (!a) continue; - a = pool->id2arch[a]; /* a == 1 -> noarch */ if (a != 1 && ((a ^ bestscore) & 0xffff0000) != 0) continue; @@ -783,6 +798,8 @@ move_installed_to_front(Pool *pool, Queue *plist) Solvable *s; Id p, pp; + if (!pool->installed) + return; for (i = j = 0; i < plist->count; i++) { s = pool->solvables + plist->elements[i]; @@ -816,6 +833,26 @@ move_installed_to_front(Pool *pool, Queue *plist) } } +static int +pool_buildversioncmp(Pool *pool, Solvable *s1, Solvable *s2) +{ + const char *bv1 = solvable_lookup_str(s1, SOLVABLE_BUILDVERSION); + const char *bv2 = solvable_lookup_str(s2, SOLVABLE_BUILDVERSION); + if (!bv1 && !bv2) + return 0; + return pool_evrcmp_str(pool, bv1 ? bv1 : "" , bv2 ? bv2 : "", EVRCMP_COMPARE); +} + +static int +pool_buildflavorcmp(Pool *pool, Solvable *s1, Solvable *s2) +{ + const char *f1 = solvable_lookup_str(s1, SOLVABLE_BUILDFLAVOR); + const char *f2 = solvable_lookup_str(s2, SOLVABLE_BUILDFLAVOR); + if (!f1 && !f2) + return 0; + return pool_evrcmp_str(pool, f1 ? f1 : "" , f2 ? f2 : "", EVRCMP_COMPARE); +} + /* * prune_to_best_version * @@ -825,7 +862,7 @@ move_installed_to_front(Pool *pool, Queue *plist) void prune_to_best_version(Pool *pool, Queue *plist) { - int i, j; + int i, j, r; Solvable *s, *best; if (plist->count < 2) /* no need to prune for a single entry */ @@ -841,9 +878,9 @@ prune_to_best_version(Pool *pool, Queue *plist) { s = pool->solvables + plist->elements[i]; - POOL_DEBUG(SOLV_DEBUG_POLICY, "- %s[%s]\n", - pool_solvable2str(pool, s), - (pool->installed && s->repo == pool->installed) ? "installed" : "not installed"); + POOL_DEBUG(SOLV_DEBUG_POLICY, "- %s [%d]%s\n", + pool_solvable2str(pool, s), plist->elements[i], + (pool->installed && s->repo == pool->installed) ? "I" : ""); if (!best) /* if no best yet, the current is best */ { @@ -858,12 +895,17 @@ prune_to_best_version(Pool *pool, Queue *plist) best = s; /* take current as new best */ continue; } - - if (best->evr != s->evr) /* compare evr */ - { - if (pool_evrcmp(pool, best->evr, s->evr, EVRCMP_COMPARE) < 0) - best = s; - } + r = best->evr != s->evr ? pool_evrcmp(pool, best->evr, s->evr, EVRCMP_COMPARE) : 0; +#ifdef ENABLE_LINKED_PKGS + if (r == 0 && has_package_link(pool, s)) + r = pool_link_evrcmp(pool, best, s); +#endif + if (r == 0 && pool->disttype == DISTTYPE_CONDA) + r = pool_buildversioncmp(pool, best, s); + if (r == 0 && pool->disttype == DISTTYPE_CONDA) + r = pool_buildflavorcmp(pool, best, s); + if (r < 0) + best = s; } plist->elements[j++] = best - pool->solvables; /* finish last group */ plist->count = j; @@ -877,8 +919,6 @@ prune_to_best_version(Pool *pool, Queue *plist) else prune_obsoleted(pool, plist); } - if (plist->count > 1 && pool->installed) - move_installed_to_front(pool, plist); } @@ -895,23 +935,7 @@ sort_by_name_evr_sortcmp(const void *ap, const void *bp, void *dp) return 0; a = aa[2] < 0 ? -aa[2] : aa[2]; b = bb[2] < 0 ? -bb[2] : bb[2]; - if (pool->disttype != DISTTYPE_DEB && a != b) - { - /* treat release-less versions different */ - const char *as = pool_id2str(pool, a); - const char *bs = pool_id2str(pool, b); - if (strchr(as, '-')) - { - if (!strchr(bs, '-')) - return -2; - } - else - { - if (strchr(bs, '-')) - return 2; - } - } - r = pool_evrcmp(pool, b, a, EVRCMP_COMPARE); + r = pool_evrcmp(pool, b, a, pool->disttype != DISTTYPE_DEB ? EVRCMP_MATCH_RELEASE : EVRCMP_COMPARE); if (!r && (aa[2] < 0 || bb[2] < 0)) { if (bb[2] >= 0) @@ -919,9 +943,7 @@ sort_by_name_evr_sortcmp(const void *ap, const void *bp, void *dp) if (aa[2] >= 0) return -1; } - if (r) - return r < 0 ? -1 : 1; - return 0; + return r; } /* common end of sort_by_srcversion and sort_by_common_dep */ @@ -1109,6 +1131,163 @@ dislike_old_versions(Pool *pool, Queue *plist) } } + +/* special lang package handling for urpm */ +/* see https://bugs.mageia.org/show_bug.cgi?id=18315 */ + +static int +urpm_reorder_cmp(const void *ap, const void *bp, void *dp) +{ + return ((Id *)bp)[1] - ((Id *)ap)[1]; +} + +static void +urpm_reorder(Solver *solv, Queue *plist) +{ + Pool *pool = solv->pool; + int i, count = plist->count; + /* add locale score to packages */ + queue_insertn(plist, count, count, 0); + for (i = count - 1; i >= 0; i--) + { + Solvable *s = pool->solvables + plist->elements[i]; + int score = 1; + const char *sn = pool_id2str(pool, s->name); + + if (!strncmp(sn, "kernel-", 7)) + { + const char *devel = strstr(sn, "-devel-"); + if (devel && strlen(sn) < 256) + { + char kn[256]; + Id p, pp, knid; + memcpy(kn, sn, devel - sn); + strcpy(kn + (devel - sn), devel + 6); + knid = pool_str2id(pool, kn, 0); + if (knid) + { + FOR_PROVIDES(p, pp, knid) + { + if (solv->decisionmap[p] > 0) + { + score = 4; + break; + } + else if (pool->installed && pool->solvables[p].repo == pool->installed) + score = 3; + } + } + } + } + else if ((sn = strstr(sn, "-kernel-")) != 0) + { + sn += 8; + if (strlen(sn) < 256 - 8 && *sn >= '0' && *sn <= '9' && sn[1] == '.') + { + const char *flavor = strchr(sn, '-'); + if (flavor) + { + const char *release = strchr(flavor + 1, '-'); + if (release) + { + char kn[256]; + Id p, pp, knid; + memcpy(kn, "kernel", 7); + memcpy(kn + 6, flavor, release - flavor + 1); + memcpy(kn + 6 + (release - flavor) + 1, sn, flavor - sn); + strcpy(kn + 6 + (release + 1 - sn), release); + knid = pool_str2id(pool, kn, 0); + if (knid) + { + FOR_PROVIDES(p, pp, knid) + { + if (solv->decisionmap[p] > 0) + { + score = 4; + break; + } + if (pool->installed && pool->solvables[p].repo == pool->installed) + score = 3; + } + } + } + } + } + } + if (score == 1 && s->requires) + { + Id id, *idp, p, pp; + const char *deps; + for (idp = s->repo->idarraydata + s->requires; (id = *idp) != 0; idp++) + { + while (ISRELDEP(id)) + { + Reldep *rd = GETRELDEP(pool, id); + id = rd->name; + } + deps = strstr(pool_id2str(pool, id), "locales-"); + if (!deps) + continue; + if (!strncmp(deps + 8, "en", 2)) + score = 2; + else + { + score = 0; + FOR_PROVIDES(p, pp, id) + { + if (solv->decisionmap[p] > 0) + { + score = 4; + break; + } + if (pool->installed && pool->solvables[p].repo == pool->installed) + score = 3; + } + break; + } + } + } + plist->elements[i * 2] = plist->elements[i]; + plist->elements[i * 2 + 1] = score; + } + solv_sort(plist->elements, count, sizeof(Id) * 2, urpm_reorder_cmp, pool); + for (i = 0; i < count; i++) + plist->elements[i] = plist->elements[2 * i]; + queue_truncate(plist, count); +} + +/* support multiple favor groups by calling policy_filter_unwanted on + * each of them and combining the result */ +static void +policy_filter_unwanted_favored(Solver *solv, Queue *plist, int mode) +{ + int i, j, f; + Queue qin, qprune; + queue_init_clone(&qin, plist); + queue_empty(plist); + /* sort by favor group */ + solv_sort(qin.elements, qin.count, sizeof(Id), sort_by_favor_cmp, solv->favormap); + /* go over groups */ + queue_init(&qprune); + for (i = 0; i < qin.count; i = j) + { + /* find end of group */ + f = solv->favormap[qin.elements[i]]; + for (j = i + 1; j < qin.count; j++) + if (solv->favormap[qin.elements[j]] != f) + break; + /* prune this group */ + queue_empty(&qprune); + queue_insertn(&qprune, 0, j, qin.elements); + policy_filter_unwanted(solv, &qprune, mode | POLICY_MODE_FAVOR_REC); + for (i = 0; i < qprune.count; i++) + if (solv->favormap[qprune.elements[i]] == f) + queue_push(plist, qprune.elements[i]); + } + queue_free(&qprune); + queue_free(&qin); +} + /* * POLICY_MODE_CHOOSE: default, do all pruning steps * POLICY_MODE_RECOMMEND: leave out prune_to_recommended @@ -1118,6 +1297,32 @@ void policy_filter_unwanted(Solver *solv, Queue *plist, int mode) { Pool *pool = solv->pool; + if (mode == POLICY_MODE_SUPPLEMENT) + { + /* reorder only */ + dislike_old_versions(pool, plist); + sort_by_common_dep(pool, plist); + if (solv->urpmreorder) + urpm_reorder(solv, plist); + prefer_suggested(solv, plist); + policy_prefer_favored(solv, plist); + return; + } + if (mode & POLICY_MODE_FAVOR_REC) + mode ^= POLICY_MODE_FAVOR_REC; + else if (solv->favormap && plist->count > 1) + { + /* check if we have multiple favor groups */ + int i, f = solv->favormap[plist->elements[0]]; + for (i = 1; i < plist->count; i++) + if (solv->favormap[plist->elements[i]] != f) + break; + if (i < plist->count) + { + policy_filter_unwanted_favored(solv, plist, mode); + return; + } + } if (plist->count > 1) { if (mode != POLICY_MODE_SUGGEST) @@ -1140,11 +1345,32 @@ policy_filter_unwanted(Solver *solv, Queue *plist, int mode) #endif dislike_old_versions(pool, plist); sort_by_common_dep(pool, plist); + move_installed_to_front(pool, plist); + if (solv->urpmreorder) + urpm_reorder(solv, plist); prefer_suggested(solv, plist); + policy_prefer_favored(solv, plist); } } } +void +pool_best_solvables(Pool *pool, Queue *plist, int flags) +{ + if (plist->count > 1) + prune_to_highest_prio(pool, plist); + if (plist->count > 1) + prune_to_best_arch(pool, plist); + if (plist->count > 1) + prune_to_best_version(pool, plist); + if (plist->count > 1) + { + dislike_old_versions(pool, plist); + sort_by_common_dep(pool, plist); + move_installed_to_front(pool, plist); + } +} + /* check if there is an illegal architecture change if * installed solvable s1 is replaced by s2 */ @@ -1159,8 +1385,8 @@ policy_illegal_archchange(Solver *solv, Solvable *s1, Solvable *s2) return 0; if (!pool->id2arch) return 0; - a1 = a1 <= pool->lastarch ? pool->id2arch[a1] : 0; - a2 = a2 <= pool->lastarch ? pool->id2arch[a2] : 0; + a1 = pool_arch2score(pool, a1); + a2 = pool_arch2score(pool, a2); if (((a1 ^ a2) & 0xffff0000) != 0) return 1; return 0; @@ -1200,7 +1426,7 @@ policy_is_illegal(Solver *solv, Solvable *is, Solvable *s, int ignore) { Pool *pool = solv->pool; int ret = 0; - int duppkg = solv->dupmap_all ? 1 : 0; + int duppkg = solv->dupinvolvedmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, is - pool->solvables)); if (!(ignore & POLICY_ILLEGAL_DOWNGRADE) && !(duppkg ? solv->dup_allowdowngrade : solv->allowdowngrade)) { if (is->name == s->name && pool_evrcmp(pool, is->evr, s->evr, EVRCMP_COMPARE) > 0)