{
Pool *pool = solv->pool;
Queue q;
- queue_init(&q);
Id p;
int i, qcnt;
#if 0
printf("check_complex_dep %s\n", pool_dep2str(pool, dep));
#endif
+ queue_init(&q);
i = pool_normalize_complex_dep(pool, dep, &q, CPLXDEPS_EXPAND);
if (i == 0 || i == 1)
{
}
static int
-sort_by_favorq_cmp(const void *ap, const void *bp, void *dp)
+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]];
}
-static void
-sort_by_favorq(Queue *favorq, Id *el, int cnt)
-{
- int i;
- /* map to offsets into favorq */
- for (i = 0; i < cnt; i++)
- {
- Id p = el[i];
- /* lookup p in sorted favorq */
- int med = 0, low = 0;
- int high = favorq->count / 2;
- while (low != high)
- {
- med = (low + high) / 2;
- Id pp = favorq->elements[2 * med];
- if (pp < p)
- low = med;
- else if (pp > p)
- high = med;
- else
- break;
- }
- while(med && favorq->elements[2 * med - 2] == p)
- med--;
- if (favorq->elements[2 * med] == p)
- el[i] = 2 * med + 1;
- else
- el[i] = 0; /* hmm */
- }
- /* sort by position */
- solv_sort(el, cnt, sizeof(Id), sort_by_favorq_cmp, favorq->elements);
- /* map back */
- for (i = 0; i < cnt; i++)
- if (el[i])
- el[i] = favorq->elements[el[i] - 1];
-}
-
/* bring favored packages to front and disfavored packages to back */
void
policy_prefer_favored(Solver *solv, Queue *plist)
{
- int i, fav, disfav, count;
- if (!solv->favormap.size)
- return;
- for (i = fav = disfav = 0, count = plist->count; i < count; i++)
- {
- Id p = plist->elements[i];
- if (!MAPTST(&solv->favormap, p))
- continue;
- if (solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, p))
- {
- /* disfavored package. bring to back */
- if (i < plist->count - 1)
- {
- memmove(plist->elements + i, plist->elements + i + 1, (plist->count - 1 - i) * sizeof(Id));
- plist->elements[plist->count - 1] = p;
- }
- i--;
- count--;
- disfav++;
- }
- else
- {
- /* favored package. bring to front */
- if (i > fav)
- memmove(plist->elements + fav + 1, plist->elements + fav, (i - fav) * sizeof(Id));
- plist->elements[fav++] = p;
- }
- }
- /* if we have multiple favored/disfavored packages, sort by favorq index */
- if (fav > 1)
- sort_by_favorq(solv->favorq, plist->elements, fav);
- if (disfav > 1)
- sort_by_favorq(solv->favorq, plist->elements + plist->count - disfav, disfav);
+ if (solv->favormap && plist->count > 1)
+ solv_sort(plist->elements, plist->count, sizeof(Id), sort_by_favor_cmp, solv->favormap);
}
/*
}
}
+#ifdef ENABLE_CONDA
+static int
+pool_featurecountcmp(Pool *pool, Solvable *s1, Solvable *s2)
+{
+ unsigned int cnt1, cnt2;
+ cnt1 = solvable_lookup_count(s1, SOLVABLE_TRACK_FEATURES);
+ cnt2 = solvable_lookup_count(s2, SOLVABLE_TRACK_FEATURES);
+ return cnt1 == cnt2 ? 0 : cnt1 > cnt2 ? -1 : 1;
+}
+
+static int
+pool_buildversioncmp(Pool *pool, Solvable *s1, Solvable *s2)
+{
+ const char *bv1, *bv2;
+ bv1 = solvable_lookup_str(s1, SOLVABLE_BUILDVERSION);
+ 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);
+}
+#endif
+
/*
* prune_to_best_version
*
best = s; /* take current as new best */
continue;
}
- r = best->evr != s->evr ? pool_evrcmp(pool, best->evr, s->evr, EVRCMP_COMPARE) : 0;
+
+ r = 0;
+#ifdef ENABLE_CONDA
+ if (pool->disttype == DISTTYPE_CONDA)
+ r = pool_featurecountcmp(pool, best, s);
+#endif
+ if (r == 0)
+ 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
+#ifdef ENABLE_CONDA
+ if (pool->disttype == DISTTYPE_CONDA)
+ {
+ if (r == 0)
+ r = (best->repo ? best->repo->subpriority : 0) - (s->repo ? s->repo->subpriority : 0);
+ if (r == 0)
+ r = pool_buildversioncmp(pool, best, s);
+ if (r == 0)
+ r = pool_buildflavorcmp(pool, best, s);
+ }
+#endif
if (r < 0)
best = s;
}
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_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)
{
FOR_PROVIDES(p, pp, obs)
{
- Solvable *ps = pool->solvables + p;;
+ Solvable *ps = pool->solvables + p;
if (ps->repo != installed)
continue;
if (ps->name == s->name)
{
FOR_PROVIDES(p, pp, obs)
{
- Solvable *ps = pool->solvables + p;;
+ Solvable *ps = pool->solvables + p;
if (ps->repo != installed)
continue;
if (ps->name == s->name)
}
+/* return true if solvable s obsoletes solvable with id pi */
+static inline int
+is_obsoleting(Pool *pool, Solvable *s, Id pi)
+{
+ Id p, pp, obs, *obsp;
+ Solvable *si = pool->solvables + pi;
+ if (pool->obsoleteusescolors && !pool_colormatch(pool, si, s))
+ return 0;
+ obsp = s->repo->idarraydata + s->obsoletes;
+ while ((obs = *obsp++) != 0) /* for all obsoletes */
+ {
+ FOR_PROVIDES(p, pp, obs) /* and all matching providers of the obsoletes */
+ {
+ if (p != pi)
+ continue;
+ if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, si, obs))
+ continue;
+ return 1;
+ }
+ }
+ return 0;
+}
+
/*
* find update candidates
*
{
/* installed packages get a special upgrade allowed rule */
Pool *pool = solv->pool;
- Id p, pp, n, p2, pp2;
- Id obs, *obsp;
+ Id p, pp, n;
Solvable *ps;
int haveprovobs = 0;
int allowdowngrade = allow_all ? 1 : solv->allowdowngrade;
continue;
ps = pool->solvables + p;
+ if (pool->considered && pool->whatprovideswithdisabled && ps->repo != pool->installed && pool_disabled_solvable(pool, ps))
+ continue;
if (s->name == ps->name) /* name match */
{
if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps))
continue;
else if ((!solv->noupdateprovide || solv->needupdateprovide) && ps->obsoletes) /* provides/obsoletes combination ? */
{
- /* check if package ps obsoletes installed package s */
+ /* check if package ps that provides s->name obsoletes installed package s */
/* implicitobsoleteusescolors is somewhat wrong here, but we nevertheless
* use it to limit our update candidates */
- if ((pool->obsoleteusescolors || pool->implicitobsoleteusescolors) && !pool_colormatch(pool, s, ps))
+ if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps))
continue;
- obsp = ps->repo->idarraydata + ps->obsoletes;
- while ((obs = *obsp++) != 0) /* for all obsoletes */
- {
- FOR_PROVIDES(p2, pp2, obs) /* and all matching providers of the obsoletes */
- {
- Solvable *ps2 = pool->solvables + p2;
- if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps2, obs))
- continue;
- if (p2 == n) /* match ! */
- break;
- }
- if (p2) /* match! */
- break;
- }
- if (!obs) /* continue if no match */
+ if (!is_obsoleting(pool, ps, n))
continue;
- /* here we have 'p' with a matching provides/obsoletes combination
- * thus flagging p as a valid update candidate for s
- */
- haveprovobs = 1;
+ haveprovobs = 1; /* have matching provides/obsoletes combination */
}
else
continue;
for (opp = solv->obsoletes_data + solv->obsoletes[n - solv->installed->start]; (p = *opp++) != 0;)
{
ps = pool->solvables + p;
- if (!allowarchchange && s->arch != ps->arch && policy_illegal_archchange(solv, s, ps))
- continue;
- if (!allowvendorchange && s->vendor != ps->vendor && policy_illegal_vendorchange(solv, s, ps))
- continue;
/* implicitobsoleteusescolors is somewhat wrong here, but we nevertheless
* use it to limit our update candidates */
if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps))
continue;
+ if (!allowarchchange && s->arch != ps->arch && policy_illegal_archchange(solv, s, ps))
+ continue;
+ if (!allowvendorchange && s->vendor != ps->vendor && policy_illegal_vendorchange(solv, s, ps))
+ continue;
queue_push(qs, p);
}
}