/*
- * 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;
{
case SOLVER_INSTALL_SOLVABLE: /* install specific solvable */
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
*/
if (!installed || pool->solvables[n].repo != installed)
{ /* not installed */
- if (s->obsoletes)
+ int noobs = solv->noobsoletes.size && MAPTST(&solv->noobsoletes, n);
+ if (s->obsoletes && !noobs)
{
obsp = s->repo->idarraydata + s->obsoletes;
/* foreach obsoletes */
}
}
}
-/**
- * FIXME
- * This looks wrong, since its outside of the obsoletes loop so it probably prevents multiple installs of the same name
- *
- */
- /* foreach provider of s->name */
FOR_PROVIDES(p, pp, s->name)
{
- if (!solv->implicitobsoleteusesprovides /* implicit obsoletes due to same name are not matched against provides, just names */
- && s->name != pool->solvables[p].name)
+ Solvable *ps = pool->solvables + p;
+ /* we still obsolete packages with same nevra, like rpm does */
+ /* (actually, rpm mixes those packages. yuck...) */
+ if (noobs && (s->name != ps->name || s->evr != ps->evr || s->arch != ps->arch))
+ continue;
+ if (!solv->implicitobsoleteusesprovides && s->name != ps->name)
continue;
addrule(solv, -n, -p);
}
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);
*/
#define DECISIONMAP_TRUE(p) ((p) > 0 ? (decisionmap[p] > 0) : (decisionmap[-p] < 0))
#define DECISIONMAP_FALSE(p) ((p) > 0 ? (decisionmap[p] < 0) : (decisionmap[-p] > 0))
+#define DECISIONMAP_UNDEF(p) (decisionmap[(p) > 0 ? (p) : -(p)] == 0)
/*-------------------------------------------------------------------
*
* make decision and propagate to all rules
*
* Evaluate each term affected by the decision (linked through watches)
+ * If we find unit rules we make new decisions based on them
*
- * If the decision was positive (true), we're done since the whole term is true
- * If the decision was negative (false), we must force the other literal of
- * the conjunctive normal form (CNF) to true.
+ * Everything's fixed there, it's just finding rules that are
+ * unit.
*
* return : 0 = everything is OK
- * watched rule = there is a conflict
+ * rule = conflict found in this rule
*/
static Rule *
POOL_DEBUG(SAT_DEBUG_PROPAGATE, "----- propagate -----\n");
- /* foreach non-propagated decision */
+ /* foreach non-propagated decision */
while (solv->propagate_index < solv->decisionq.count)
{
/*
* 'pkg' was just decided
- *
* negate because our watches trigger if literal goes FALSE
- * If a literal goes TRUE in a CNF (terms of (x|y)), we're done for this term
*/
pkg = -solv->decisionq.elements[solv->propagate_index++];
solver_printruleelement(solv, SAT_DEBUG_PROPAGATE, 0, -pkg);
}
- /* foreach rule involving 'pkg' */
+ /* foreach rule where 'pkg' is now FALSE */
for (rp = watches + pkg; *rp; rp = next_rp)
{
r = solv->rules + *rp;
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)
{
/*
* This term is already true (through the other literal)
+ * so we have nothing to do
*/
if (DECISIONMAP_TRUE(other_watch))
continue;
/*
- * The other literal is false, try to get a 'true'
+ * The other literal is FALSE or UNDEF
+ *
*/
if (r->d)
{
- /* not a binary clause, check if we need to move our watch.
+ /* Not a binary clause, try to move our watch.
+ *
+ * Go over all literals and find one that is
+ * not other_watch
+ * and not FALSE
*
- * search for a literal that is not other_watch and not false
- * (true is also ok, in that case the rule is fulfilled)
+ * (TRUE is also ok, in that case the rule is fulfilled)
*/
if (r->p /* we have a 'p' */
- && r->p != other_watch /* which is not what we just checked */
- && !DECISIONMAP_TRUE(-r->p)) /* and its not already decided 'negative' */
+ && r->p != other_watch /* which is not watched */
+ && !DECISIONMAP_FALSE(r->p)) /* and not FALSE */
{
- p = r->p; /* we must get this to 'true' */
+ 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 what we just checked */
- && !DECISIONMAP_TRUE(-p)) /* and its not already decided 'negative' */
- break;
+ {
+ if (p != other_watch /* which is not watched */
+ && !DECISIONMAP_FALSE(p)) /* and not FALSE */
+ break;
+ }
}
- /*
- * if p is free to watch, move watch to p
- */
if (p)
{
+ /*
+ * if we found some p that is UNDEF or TRUE, move
+ * watch to it
+ */
IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
{
if (p > 0)
watches[p] = r - solv->rules;
continue;
}
-
- /* !p */
+ /* search failed, thus all unwatched literals are FALSE */
} /* not binary */
/*
- * unit clause found, force other watch to TRUE
+ * unit clause found, set literal other_watch to TRUE
*/
- if (DECISIONMAP_TRUE(-other_watch)) /* decided before to 'negative' */
+ if (DECISIONMAP_FALSE(other_watch)) /* check if literal is FALSE */
return r; /* eek, a conflict! */
IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
solver_printrule(solv, SAT_DEBUG_PROPAGATE, r);
}
- /*
- * decide: 'other_watch' to 'true'
- */
if (other_watch > 0)
decisionmap[other_watch] = level; /* install! */
else
map_free(&solv->suggestsmap);
map_free(&solv->noupdate);
map_free(&solv->weakrulemap);
+ map_free(&solv->noobsoletes);
sat_free(solv->decisionmap);
sat_free(solv->rules);
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 < systemlevel && solv->installed && solv->installed->nsolvables)
{
- /*
- * Normal run (non-updating)
- * Keep as many packages as possible
- */
if (!solv->updatesystem)
{
+ /*
+ * Normal run (non-updating)
+ * Keep as many packages installed as possible
+ */
POOL_DEBUG(SAT_DEBUG_STATS, "installing old packages\n");
for (i = solv->installed->start; i < solv->installed->end; i++)
olevel = level;
level = setpropagatelearn(solv, level, i, disablerules);
- if (level == 0) /* done */
+ if (level == 0) /* unsolvable */
{
queue_free(&dq);
return;
if (!dq.count && solv->decisionmap[i] != 0)
continue;
olevel = level;
- /* FIXME: i is handled a bit different because we do not want
+ /* FIXME: it is handled a bit different because we do not want
* to have it pruned just because it is not recommened.
* we should not prune installed packages instead
*/
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);
}
return SOLVER_PROBLEM_NOTHING_PROVIDES_DEP;
}
}
- assert(!solv->allowselfconflicts);
- assert(s->conflicts);
- conp = s->repo->idarraydata + s->conflicts;
- while ((con = *conp++) != 0)
- FOR_PROVIDES(p, pp, con)
- if (p == -r->p)
- {
- *depp = con;
- return SOLVER_PROBLEM_SELF_CONFLICT;
- }
- assert(0);
+ if (!solv->allowselfconflicts && s->conflicts)
+ {
+ conp = s->repo->idarraydata + s->conflicts;
+ while ((con = *conp++) != 0)
+ FOR_PROVIDES(p, pp, con)
+ if (p == -r->p)
+ {
+ *depp = con;
+ return SOLVER_PROBLEM_SELF_CONFLICT;
+ }
+ }
+ /* should never happen */
+ *depp = 0;
+ return SOLVER_PROBLEM_RPM_RULE;
}
s = pool->solvables - r->p;
if (installed && !solv->fixsystem && s->repo == installed)
/* if both packages have the same name and at least one of them
* is not installed, they conflict */
- if (s->name == s2->name && (!installed || (s->repo != installed || s2->repo != installed)))
+ if (s->name == s2->name && !(installed && s->repo == installed && s2->repo == installed))
{
- *depp = 0;
- *sourcep = -r->p;
- *targetp = -r->w2;
- return SOLVER_PROBLEM_SAME_NAME;
+ /* also check noobsoletes map */
+ if ((s->evr == s2->evr && s->arch == s2->arch) || !solv->noobsoletes.size
+ || ((!installed || s->repo != installed) && !MAPTST(&solv->noobsoletes, -r->p))
+ || ((!installed || s2->repo != installed) && !MAPTST(&solv->noobsoletes, -r->w2)))
+ {
+ *depp = 0;
+ *sourcep = -r->p;
+ *targetp = -r->w2;
+ return SOLVER_PROBLEM_SAME_NAME;
+ }
}
/* check conflicts in both directions */
}
}
/* check obsoletes in both directions */
- if ((!installed || s->repo != installed) && s->obsoletes)
+ if ((!installed || s->repo != installed) && s->obsoletes && !(solv->noobsoletes.size && MAPTST(&solv->noobsoletes, -r->p)))
{
obsp = s->repo->idarraydata + s->obsoletes;
while ((obs = *obsp++) != 0)
}
}
}
- if ((!installed || s2->repo != installed) && s2->obsoletes)
+ if ((!installed || s2->repo != installed) && s2->obsoletes && !(solv->noobsoletes.size && MAPTST(&solv->noobsoletes, -r->w2)))
{
obsp = s2->repo->idarraydata + s2->obsoletes;
while ((obs = *obsp++) != 0)
}
}
}
- if (solv->implicitobsoleteusesprovides && (!installed || s->repo != installed))
+ if (solv->implicitobsoleteusesprovides && (!installed || s->repo != installed) && !(solv->noobsoletes.size && MAPTST(&solv->noobsoletes, -r->p)))
{
FOR_PROVIDES(p, pp, s->name)
{
return SOLVER_PROBLEM_PACKAGE_OBSOLETES;
}
}
- if (solv->implicitobsoleteusesprovides && (!installed || s2->repo != installed))
+ if (solv->implicitobsoleteusesprovides && (!installed || s2->repo != installed) && !(solv->noobsoletes.size && MAPTST(&solv->noobsoletes, -r->w2)))
{
FOR_PROVIDES(p, pp, s2->name)
{
}
}
/* all cases checked, can't happen */
- assert(0);
+ *depp = 0;
+ *sourcep = -r->p;
+ *targetp = 0;
+ return SOLVER_PROBLEM_RPM_RULE;
}
/* simple requires */
- assert(s->requires);
- reqp = s->repo->idarraydata + s->requires;
- while ((req = *reqp++) != 0)
+ if (s->requires)
{
- if (req == SOLVABLE_PREREQMARKER)
- continue;
- dp = pool_whatprovides(pool, req);
- if (d == 0)
+ reqp = s->repo->idarraydata + s->requires;
+ while ((req = *reqp++) != 0)
{
- if (*dp == r->w2 && dp[1] == 0)
+ if (req == SOLVABLE_PREREQMARKER)
+ continue;
+ dp = pool_whatprovides(pool, req);
+ if (d == 0)
+ {
+ if (*dp == r->w2 && dp[1] == 0)
+ break;
+ }
+ else if (dp - pool->whatprovidesdata == d)
break;
}
- else if (dp - pool->whatprovidesdata == d)
- break;
+ if (req)
+ {
+ *depp = req;
+ *sourcep = -r->p;
+ *targetp = 0;
+ return SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE;
+ }
}
- assert(req);
- *depp = req;
+ /* all cases checked, can't happen */
+ *depp = 0;
*sourcep = -r->p;
*targetp = 0;
- return SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE;
+ return SOLVER_PROBLEM_RPM_RULE;
}
*
*/
+ /* create noobsolete map if needed */
+ for (i = 0; i < job->count; i += 2)
+ {
+ how = job->elements[i] & ~SOLVER_WEAK;
+ what = job->elements[i + 1];
+ switch(how)
+ {
+ case SOLVER_NOOBSOLETES_SOLVABLE:
+ case SOLVER_NOOBSOLETES_SOLVABLE_NAME:
+ case SOLVER_NOOBSOLETES_SOLVABLE_PROVIDES:
+ if (!solv->noobsoletes.size)
+ map_init(&solv->noobsoletes, pool->nsolvables);
+ if (how == SOLVER_NOOBSOLETES_SOLVABLE)
+ {
+ MAPSET(&solv->noobsoletes, what);
+ break;
+ }
+ FOR_PROVIDES(p, pp, what)
+ {
+ if (how == SOLVER_NOOBSOLETES_SOLVABLE_NAME && !pool_match_nevr(pool, pool->solvables + p, what))
+ continue;
+ MAPSET(&solv->noobsoletes, p);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
map_init(&addedmap, pool->nsolvables);
queue_init(&q);
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;
- }
- }
-
- /* FIXME: Huh ? Impossile !, we only loop over installed here */
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
- /* FIXME: Huh ? Impossile !, we only loop over installed here */
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
*/
POOL_DEBUG(SAT_DEBUG_JOB, "job: weaken deps %s\n", solvable2str(pool, s));
weaken_solvable_deps(solv, what);
break;
+ case SOLVER_NOOBSOLETES_SOLVABLE:
+ POOL_DEBUG(SAT_DEBUG_JOB, "job: no obsolete %s\n", solvable2str(pool, pool->solvables + what));
+ break;
+ case SOLVER_NOOBSOLETES_SOLVABLE_NAME:
+ POOL_DEBUG(SAT_DEBUG_JOB, "job: no obsolete name %s\n", dep2str(pool, what));
+ break;
+ case SOLVER_NOOBSOLETES_SOLVABLE_PROVIDES:
+ POOL_DEBUG(SAT_DEBUG_JOB, "job: no obsolete provides %s\n", dep2str(pool, what));
+ break;
}
/*
/* 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;