/*
- * Copyright (c) 2007, Novell Inc.
+ * Copyright (c) 2007-2008, Novell Inc.
*
* This program is licensed under the BSD license, read LICENSE.BSD
* for further information
}
#endif
- if (n == 1 && p > d)
+ if (n == 1 && p > d && !solv->rpmrules_end)
{
/* smallest literal first so we can find dups */
n = p; p = d; d = n; /* p <-> d */
*
*/
-void
+static void
enableweakrules(Solver *solv)
{
int i;
s = pool->solvables + what;
if (solv->noobsoletes.size && MAPTST(&solv->noobsoletes, what))
break;
+ if (s->obsoletes)
+ {
+ Id obs, *obsp;
+ obsp = s->repo->idarraydata + s->obsoletes;
+ while ((obs = *obsp++) != 0)
+ FOR_PROVIDES(p, pp, obs)
+ {
+ if (pool->solvables[p].repo != installed)
+ continue;
+ if (!solv->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p, obs))
+ continue;
+ MAPSET(&solv->noupdate, p - installed->start);
+ }
+ }
FOR_PROVIDES(p, pp, s->name)
{
- if (pool->solvables[p].name != s->name)
+ if (!solv->implicitobsoleteusesprovides && pool->solvables[p].name != s->name)
continue;
if (pool->solvables[p].repo == installed)
MAPSET(&solv->noupdate, p - installed->start);
{
case SOLVER_INSTALL_SOLVABLE:
s = pool->solvables + what;
+ if (s->obsoletes)
+ {
+ Id obs, *obsp;
+ obsp = s->repo->idarraydata + s->obsoletes;
+ while ((obs = *obsp++) != 0)
+ FOR_PROVIDES(p, pp, obs)
+ {
+ if (pool->solvables[p].repo != installed)
+ continue;
+ if (!solv->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p, obs))
+ continue;
+ if (MAPTST(&solv->noupdate, p - installed->start))
+ continue;
+ r = solv->rules + solv->updaterules + (p - installed->start);
+ if (r->d >= 0)
+ continue;
+ enablerule(solv, r);
+ IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
+ {
+ POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling ");
+ solver_printrule(solv, SAT_DEBUG_SOLUTIONS, r);
+ }
+ }
+ }
FOR_PROVIDES(p, pp, s->name)
{
- if (pool->solvables[p].name != s->name)
+ if (!solv->implicitobsoleteusesprovides && pool->solvables[p].name != s->name)
continue;
if (pool->solvables[p].repo != installed)
continue;
}
}
-#if CODE10
-/*-------------------------------------------------------------------
- * add patch atom requires
- */
-
-static void
-addpatchatomrequires(Solver *solv, Solvable *s, Id *dp, Queue *q, Map *m)
-{
- Pool *pool = solv->pool;
- Id fre, *frep, p, *pp, ndp;
- Solvable *ps;
- Queue fq;
- Id qbuf[64];
- int i, used = 0;
-
- queue_init_buffer(&fq, qbuf, sizeof(qbuf)/sizeof(*qbuf));
- queue_push(&fq, -(s - pool->solvables));
- for (; *dp; dp++)
- queue_push(&fq, *dp);
- ndp = pool_queuetowhatprovides(pool, &fq);
- frep = s->repo->idarraydata + s->freshens;
- while ((fre = *frep++) != 0)
- {
- FOR_PROVIDES(p, pp, fre)
- {
- ps = pool->solvables + p;
- addrule(solv, -p, ndp);
- used = 1;
- if (!MAPTST(m, p))
- queue_push(q, p);
- }
- }
- if (used)
- {
- for (i = 1; i < fq.count; i++)
- {
- p = fq.elements[i];
- if (!MAPTST(m, p))
- queue_push(q, p);
- }
- }
- queue_free(&fq);
-}
-#endif
/*-------------------------------------------------------------------
POOL_DEBUG(SAT_DEBUG_RULE_CREATION, "package %s [%d] is not installable\n", solvable2str(pool, s), (Id)(s - pool->solvables));
addrule(solv, -n, 0); /* uninstallable */
}
-#if CODE10
- patchatom = 0;
- if (s->freshens && !s->supplements)
- {
- const char *name = id2str(pool, s->name);
- if (name[0] == 'a' && !strncmp(name, "atom:", 5))
- patchatom = 1;
- }
-#endif
/*-----------------------------------------
* check requires of s
break;
}
- /* if nothing found, check for freshens
- * (patterns use this)
- */
- if (!sup && s->freshens)
- {
- supp = s->repo->idarraydata + s->freshens;
- while ((sup = *supp++) != ID_NULL)
- if (dep_possible(solv, sup, m))
- break;
- }
-
/* if nothing found, check for enhances */
if (!sup && s->enhances)
{
if (dep_possible(solv, sup, m))
break;
}
- /* if notthing found, goto next solvables */
+ /* if nothing found, goto next solvables */
if (!sup)
continue;
addrpmrulesforsolvable(solv, s, m);
* Evaluate each term affected by the decision (linked through watches)
* If we find unit rules we make new decisions based on them
*
+ * Everything's fixed there, it's just finding rules that are
+ * unit.
+ *
* return : 0 = everything is OK
* rule = conflict found in this rule
*/
solver_printrule(solv, SAT_DEBUG_PROPAGATE, r);
}
- /* 'pkg' was just decided
- * now find other literal watch, check clause
- * and advance on linked list
+ /* 'pkg' was just decided (was set to FALSE)
+ *
+ * now find other literal watch, check clause
+ * and advance on linked list
*/
if (pkg == r->w1)
{
/*
* The other literal is FALSE or UNDEF
+ *
*/
if (r->d)
{
- /* not a binary clause, try to move our watch.
- * search for a literal that is not other_watch and not FALSE
+ /* Not a binary clause, try to move our watch.
+ *
+ * Go over all literals and find one that is
+ * not other_watch
+ * and not FALSE
+ *
* (TRUE is also ok, in that case the rule is fulfilled)
*/
if (r->p /* we have a 'p' */
- && r->p != other_watch /* which is watched */
+ && r->p != other_watch /* which is not watched */
&& !DECISIONMAP_FALSE(r->p)) /* and not FALSE */
{
p = r->p;
}
else /* go find a 'd' to make 'true' */
{
- /* foreach 'd' */
+ /* foreach p in 'd'
+ we just iterate sequentially, doing it in another order just changes the order of decisions, not the decisions itself
+ */
for (dp = pool->whatprovidesdata + r->d; (p = *dp++) != 0;)
- if (p != other_watch /* which is not watched */
- && !DECISIONMAP_FALSE(p)) /* and not FALSE */
- break;
+ {
+ if (p != other_watch /* which is not watched */
+ && !DECISIONMAP_FALSE(p)) /* and not FALSE */
+ break;
+ }
}
if (p)
static void
run_solver(Solver *solv, int disablerules, int doweak)
{
- Queue dq; /* local decisionqueue */
+ Queue dq; /* local decisionqueue */
+ Queue dqs; /* local decisionqueue for supplements */
int systemlevel;
int level, olevel;
Rule *r;
POOL_DEBUG(SAT_DEBUG_STATS, "solving...\n");
queue_init(&dq);
+ queue_init(&dqs);
/*
* here's the main loop:
}
}
+ if (level < systemlevel)
+ {
+ POOL_DEBUG(SAT_DEBUG_STATS, "resolving job rules\n");
+ for (i = solv->jobrules, r = solv->rules + i; i < solv->jobrules_end; i++, r++)
+ {
+ Id l;
+ if (r->d < 0) /* ignore disabled rules */
+ continue;
+ queue_empty(&dq);
+ FOR_RULELITERALS(l, dp, r)
+ {
+ if (l < 0)
+ {
+ if (solv->decisionmap[-l] <= 0)
+ break;
+ }
+ else
+ {
+ if (solv->decisionmap[l] > 0)
+ break;
+ if (solv->decisionmap[l] == 0)
+ queue_push(&dq, l);
+ }
+ }
+ if (l || !dq.count)
+ continue;
+ if (!solv->updatesystem && solv->installed && dq.count > 1)
+ {
+ int j, k;
+ for (j = k = 0; j < dq.count; j++)
+ {
+ Solvable *s = pool->solvables + dq.elements[j];
+ if (s->repo == solv->installed)
+ dq.elements[k++] = dq.elements[j];
+ }
+ if (k)
+ dq.count = k;
+ }
+ olevel = level;
+ level = selectandinstall(solv, level, &dq, 0, disablerules);
+ if (level == 0)
+ {
+ queue_free(&dq);
+ return;
+ }
+ if (level <= olevel)
+ break;
+ }
+ systemlevel = level + 1;
+ if (i < solv->jobrules_end)
+ continue;
+ }
+
+
/*
* installed packages
*/
if (level <= olevel)
break;
}
+ systemlevel = level + 1;
if (i < solv->installed->end)
continue;
- systemlevel = level;
}
+ if (level < systemlevel)
+ systemlevel = level;
+
/*
* decide
*/
POOL_DEBUG(SAT_DEBUG_STATS, "installing recommended packages\n");
queue_empty(&dq);
+ queue_empty(&dqs);
for (i = 1; i < pool->nsolvables; i++)
{
if (solv->decisionmap[i] < 0)
continue;
if (solv->decisionmap[i] > 0)
{
+ /* installed, check for recommends */
Id *recp, rec, *pp, p;
s = pool->solvables + i;
- /* installed, check for recommends */
+ if (solv->ignorealreadyrecommended && s->repo == solv->installed)
+ continue;
/* XXX need to special case AND ? */
if (s->recommends)
{
else
{
s = pool->solvables + i;
- if (!s->supplements && !s->freshens)
+ if (!s->supplements)
continue;
if (!pool_installable(pool, s))
continue;
- if (solver_is_supplementing(solv, s))
+ if (!solver_is_supplementing(solv, s))
+ continue;
+ if (solv->ignorealreadyrecommended && solv->installed)
+ queue_pushunique(&dqs, i); /* needs filter */
+ else
queue_pushunique(&dq, i);
}
}
+ if (solv->ignorealreadyrecommended && dqs.count)
+ {
+ /* turn off all new packages */
+ for (i = 0; i < solv->decisionq.count; i++)
+ {
+ p = solv->decisionq.elements[i];
+ if (p < 0)
+ continue;
+ s = pool->solvables + p;
+ if (s->repo && s->repo != solv->installed)
+ solv->decisionmap[p] = -solv->decisionmap[p];
+ }
+ /* filter out old supplements */
+ for (i = 0; i < dqs.count; i++)
+ {
+ p = dqs.elements[i];
+ s = pool->solvables + p;
+ if (!s->supplements)
+ continue;
+ if (!solver_is_supplementing(solv, s))
+ queue_pushunique(&dq, p);
+ }
+ /* undo turning off */
+ for (i = 0; i < solv->decisionq.count; i++)
+ {
+ p = solv->decisionq.elements[i];
+ if (p < 0)
+ continue;
+ s = pool->solvables + p;
+ if (s->repo && s->repo != solv->installed)
+ solv->decisionmap[p] = -solv->decisionmap[p];
+ }
+ }
if (dq.count)
{
if (dq.count > 1)
POOL_DEBUG(SAT_DEBUG_STATS, "done solving.\n\n");
queue_free(&dq);
+ queue_free(&dqs);
}
oldnrules = solv->nrules;
/*
- * add rules for suggests, [freshens,] enhances
+ * add rules for suggests, enhances
*/
addrpmrulesforweak(solv, &addedmap);
POOL_DEBUG(SAT_DEBUG_STATS, "added %d rpm rules because of weak dependencies\n", solv->nrules - oldnrules);
solv->featurerules = solv->nrules; /* mark start of feature rules */
if (installed)
{
- /* foreach installed solvable */
+ /* foreach possibly installed solvable */
for (i = installed->start, s = pool->solvables + i; i < installed->end; i++, s++)
{
- /*
- * patterns use this
- */
-
- if (s->freshens && !s->supplements)
- {
- const char *name = id2str(pool, s->name);
- if (name[0] == 'a' && !strncmp(name, "atom:", 5))
- {
- addrule(solv, 0, 0);
- continue;
- }
- }
-
if (s->repo != installed)
{
addrule(solv, 0, 0); /* create dummy rule */
POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** Add update rules ***\n");
solv->updaterules = solv->nrules;
+
if (installed)
{ /* foreach installed solvables */
/* we create all update rules, but disable some later on depending on the job */
{
Rule *sr;
-#if CODE10
- /* no update rules for patch atoms */
- if (s->freshens && !s->supplements)
- {
- const char *name = id2str(pool, s->name);
- if (name[0] == 'a' && !strncmp(name, "atom:", 5))
- {
- addrule(solv, 0, 0);
- continue;
- }
- }
-#endif
if (s->repo != installed)
{
addrule(solv, 0, 0); /* create dummy rule */
continue;
}
+
addupdaterule(solv, s, 0); /* allowall = 0: downgrades allowed */
-
+
/*
* check for and remove duplicate
*/
/* if redoq.count == 0 we already found all recommended in the
* solver run */
- if (redoq.count || solv->dontinstallrecommended || !solv->dontshowinstalledrecommended)
+ if (redoq.count || solv->dontinstallrecommended || !solv->dontshowinstalledrecommended || solv->ignorealreadyrecommended)
{
Id rec, *recp, p, *pp;