/*
* Generic policy interface for SAT solver
- *
+ *
*/
#include <stdio.h>
#include "poolarch.h"
-static Pool *prune_best_version_arch_sortcmp_data;
+static Solver *prune_best_version_arch_sortcmp_data;
/*-----------------------------------------------------------------*/
static int
prune_best_version_arch_sortcmp(const void *ap, const void *bp)
{
- Pool *pool = prune_best_version_arch_sortcmp_data;
+ Solver *solv = prune_best_version_arch_sortcmp_data;
+ Pool *pool = solv->pool;
int r;
Id a = *(Id *)ap;
Id b = *(Id *)bp;
* is not depending on some random solvable order */
na = id2str(pool, pool->solvables[a].name);
nb = id2str(pool, pool->solvables[b].name);
- /* bring selections and patterns to the front */
+ /* bring patterns to the front */
+ /* XXX: no longer needed? */
if (!strncmp(na, "pattern:", 8))
{
if (strncmp(nb, "pattern:", 8))
if (strncmp(na, "pattern:", 8))
return 1;
}
- if (!strncmp(na, "selection:", 10))
- {
- if (strncmp(nb, "selection:", 10))
- return -1;
- }
- else if (!strncmp(nb, "selection:", 10))
- {
- if (strncmp(na, "selection:", 10))
- return 1;
- }
return strcmp(na, nb);
}
+ /* the same name */
+ if (pool->solvables[a].evr == pool->solvables[b].evr && solv->installed)
+ {
+ /* prefer installed solvables */
+ if (pool->solvables[a].repo == solv->installed)
+ return -1;
+ if (pool->solvables[b].repo == solv->installed)
+ return 1;
+ }
return a - b;
}
+
+/*
+ * prune to repository with highest priority
+ *
+ */
+
static void
prune_to_highest_prio(Pool *pool, Queue *plist)
{
int bestprio = 0;
/* prune to highest priority */
- for (i = 0; i < plist->count; i++)
+ for (i = 0; i < plist->count; i++) /* find highest prio in queue */
{
s = pool->solvables + plist->elements[i];
if (i == 0 || s->repo->priority > bestprio)
bestprio = s->repo->priority;
}
- for (i = j = 0; i < plist->count; i++)
+ for (i = j = 0; i < plist->count; i++) /* remove all with lower prio */
{
s = pool->solvables + plist->elements[i];
if (s->repo->priority == bestprio)
plist->count = j;
}
+
/*
* prune_to_recommended
*
* XXX: should we prune to requires/suggests that are already
* fulfilled by other packages?
*/
+
static void
prune_to_recommended(Solver *solv, Queue *plist)
{
plist->count = j;
}
-static void
+void
prune_to_best_arch(Pool *pool, Queue *plist)
{
Id a, bestscore;
/*
* prune_best_version_arch
- *
+ *
* sort list of packages (given through plist) by name and evr
* return result through plist
- *
+ *
*/
-/* FIXME: should prefer installed if identical version */
-
-static void
-prune_to_best_version(Pool *pool, Queue *plist)
+void
+prune_to_best_version(Solver *solv, Queue *plist)
{
+ Pool *pool = solv->pool;
Id best = ID_NULL;
int i, j;
Solvable *s;
return;
POOL_DEBUG(SAT_DEBUG_POLICY, "prune_to_best_version %d\n", plist->count);
- /* prune to best architecture */
- if (pool->id2arch)
-
- prune_best_version_arch_sortcmp_data = pool;
- /* sort by name first */
+ prune_best_version_arch_sortcmp_data = solv;
+ /* sort by name first, prefer installed */
qsort(plist->elements, plist->count, sizeof(Id), prune_best_version_arch_sortcmp);
/* delete obsoleted. hmm, looks expensive! */
{
if (pool->solvables[p].name == s->name)
continue;
+ if (!solv->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p, obs))
+ continue;
for (j = 0; j < plist->count; j++)
{
if (i == j)
{
s = pool->solvables + plist->elements[i];
- POOL_DEBUG(SAT_DEBUG_POLICY, "- %s\n", solvable2str(pool, s));
+ POOL_DEBUG(SAT_DEBUG_POLICY, "- %s[%s]\n",
+ solvable2str(pool, s),
+ (solv->installed && s->repo == solv->installed) ? "installed" : "not installed");
if (!best) /* if no best yet, the current is best */
{
if (pool->solvables[best].evr != s->evr) /* compare evr */
{
- if (evrcmp(pool, pool->solvables[best].evr, s->evr) < 0)
+ if (evrcmp(pool, pool->solvables[best].evr, s->evr, EVRCMP_MATCH_RELEASE) < 0)
best = plist->elements[i];
}
}
plist->count = j;
}
-/* legacy, do not use anymore! */
+
+/* legacy, do not use anymore!
+ * (rates arch higher than version, but thats a policy)
+ */
+
void
-prune_best_version_arch(Pool *pool, Queue *plist)
+prune_best_arch_name_version(Solver *solv, Pool *pool, Queue *plist)
{
+ if (solv && solv->bestSolvableCb)
+ { /* The application is responsible for */
+ return solv->bestSolvableCb(solv->pool, plist);
+ }
+
if (plist->count > 1)
prune_to_best_arch(pool, plist);
if (plist->count > 1)
- prune_to_best_version(pool, plist);
+ prune_to_best_version(solv, plist);
}
/* FIXME: do this different! */
if (inst)
queue_push(plist, inst);
- if (plist->count > 1)
- prune_to_best_arch(pool, plist);
- if (plist->count > 1)
- prune_to_best_version(pool, plist);
+
+ prune_best_arch_name_version(solv, pool, plist);
}
int
-policy_illegal_archchange(Pool *pool, Solvable *s1, Solvable *s2)
+policy_illegal_archchange(Solver *solv, Solvable *s1, Solvable *s2)
{
+ Pool *pool = solv->pool;
Id a1 = s1->arch, a2 = s2->arch;
+ if (solv && solv->archCheckCb)
+ { /* The application is responsible for */
+ return solv->archCheckCb(solv->pool, s1, s2);
+ }
+
/* we allow changes to/from noarch */
if (a1 == a2 || a1 == ARCH_NOARCH || a2 == ARCH_NOARCH)
return 0;
}
int
-policy_illegal_vendorchange(Pool *pool, Solvable *s1, Solvable *s2)
+policy_illegal_vendorchange(Solver *solv, Solvable *s1, Solvable *s2)
{
+ Pool *pool = solv->pool;
Id vendormask1, vendormask2;
+
+ if (solv && solv->vendorCheckCb)
+ { /* The application is responsible for */
+ return solv->vendorCheckCb(solv->pool, s1, s2);
+ }
+
if (s1->vendor == s2->vendor)
return 0;
vendormask1 = pool_vendor2mask(pool, s1->vendor);
return 1;
}
+
+/*
+ * find update candidates
+ *
+ * s: solvable to be updated
+ * qs: [out] queue to hold Ids of candidates
+ * allow_all: 0 = dont allow downgrades, 1 = allow all candidates
+ *
+ */
void
-policy_findupdatepackages(Solver *solv, Solvable *s, Queue *qs, int allowall)
+policy_findupdatepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all)
{
/* installed packages get a special upgrade allowed rule */
Pool *pool = solv->pool;
Id p, *pp, n, p2, *pp2;
Id obs, *obsp;
Solvable *ps;
- Id vendormask;
queue_empty(qs);
+
+ if (solv && solv->updateCandidateCb)
+ { /* The application is responsible for */
+ return solv->updateCandidateCb(solv->pool, s, qs);
+ }
+
/*
* s = solvable ptr
* n = solvable Id
*/
n = s - pool->solvables;
- vendormask = pool_vendor2mask(pool, s->vendor);
/*
* look for updates for s
ps = pool->solvables + p;
if (s->name == ps->name) /* name match */
{
- if (!allowall)
- {
- if (!solv->allowdowngrade && evrcmp(pool, s->evr, ps->evr) > 0)
- continue;
- if (!solv->allowarchchange && s->arch != ps->arch && policy_illegal_archchange(pool, s, ps))
- continue;
- if (!solv->allowvendorchange && s->vendor != ps->vendor && policy_illegal_vendorchange(pool, s, ps))
- continue;
- }
+ if (!allow_all && !solv->allowdowngrade && evrcmp(pool, s->evr, ps->evr, EVRCMP_MATCH_RELEASE) > 0)
+ continue;
}
else if (!solv->noupdateprovide && ps->obsoletes) /* provides/obsoletes combination ? */
{
{
FOR_PROVIDES(p2, pp2, obs) /* and all matching providers of the obsoletes */
{
+ if (!solv->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs))
+ continue;
if (p2 == n) /* match ! */
break;
}
}
else
continue;
+ if (!allow_all && !solv->allowarchchange && s->arch != ps->arch && policy_illegal_archchange(solv, s, ps))
+ continue;
+ if (!allow_all && !solv->allowvendorchange && s->vendor != ps->vendor && policy_illegal_vendorchange(solv, s, ps))
+ continue;
queue_push(qs, p);
}
if (solv->noupdateprovide && solv->obsoletes && solv->obsoletes[n - solv->installed->start])
{
for (pp = solv->obsoletes_data + solv->obsoletes[n - solv->installed->start]; (p = *pp++) != 0;)
- queue_push(qs, p);
+ {
+ ps = pool->solvables + p;
+ if (!allow_all && !solv->allowarchchange && s->arch != ps->arch && policy_illegal_archchange(solv, s, ps))
+ continue;
+ if (!allow_all && !solv->allowvendorchange && s->vendor != ps->vendor && policy_illegal_vendorchange(solv, s, ps))
+ continue;
+ queue_push(qs, p);
+ }
}
}