solv->decisionmap[vv] = v > 0 ? 1 : -1;
IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
{
- Solvable *s = solv->pool->solvables + vv;
+ Solvable *s = pool->solvables + vv;
if (v < 0)
- POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "conflicting %s (assertion)\n", pool_solvable2str(solv->pool, s));
+ POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "conflicting %s (assertion)\n", pool_solvable2str(pool, s));
else
- POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "installing %s (assertion)\n", pool_solvable2str(solv->pool, s));
+ POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "installing %s (assertion)\n", pool_solvable2str(pool, s));
}
continue;
}
solv->decisionmap[vv] = v > 0 ? 1 : -1;
IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
{
- Solvable *s = solv->pool->solvables + vv;
+ Solvable *s = pool->solvables + vv;
if (v < 0)
- POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "conflicting %s (weak assertion)\n", pool_solvable2str(solv->pool, s));
+ POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "conflicting %s (weak assertion)\n", pool_solvable2str(pool, s));
else
- POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "installing %s (weak assertion)\n", pool_solvable2str(solv->pool, s));
+ POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "installing %s (weak assertion)\n", pool_solvable2str(pool, s));
}
continue;
}
FOR_RULELITERALS(v, pp, r)
{
if (DECISIONMAP_TRUE(v)) /* the one true literal */
- continue;
+ abort();
vv = v > 0 ? v : -v;
MAPSET(&involved, vv);
}
analyze_unsolvable_rule(solv, r, &weakq, &rseen);
FOR_RULELITERALS(v, pp, r)
{
- if (DECISIONMAP_TRUE(v)) /* the one true literal */
+ if (DECISIONMAP_TRUE(v)) /* the one true literal, i.e. our decision */
+ {
+ if (v != solv->decisionq.elements[idx])
+ abort();
continue;
+ }
vv = v > 0 ? v : -v;
MAPSET(&involved, vv);
}
}
static void
+queue_prunezeros(Queue *q)
+{
+ int i, j;
+ for (i = 0; i < q->count; i++)
+ if (q->elements[i] == 0)
+ break;
+ if (i == q->count)
+ return;
+ for (j = i++; i < q->count; i++)
+ if (q->elements[i])
+ q->elements[j++] = q->elements[i];
+ queue_truncate(q, j);
+}
+
+static int
+replaces_installed_package(Pool *pool, Id p, Map *noupdate)
+{
+ Repo *installed = pool->installed;
+ Solvable *s = pool->solvables + p, *s2;
+ Id p2, pp2;
+ Id obs, *obsp;
+
+ if (s->repo == installed && !(noupdate && MAPTST(noupdate, p - installed->start)))
+ return 1;
+ FOR_PROVIDES(p2, pp2, s->name)
+ {
+ s2 = pool->solvables + p2;
+ if (s2->repo == installed && s2->name == s->name && !(noupdate && MAPTST(noupdate, p - installed->start)))
+ return 1;
+ }
+ if (!s->obsoletes)
+ return 0;
+ obsp = s->repo->idarraydata + s->obsoletes;
+ while ((obs = *obsp++) != 0)
+ {
+ FOR_PROVIDES(p2, pp2, obs)
+ {
+ s2 = pool->solvables + p2;
+ if (s2->repo != pool->installed || (noupdate && MAPTST(noupdate, p - installed->start)))
+ continue;
+ if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, s2, obs))
+ continue;
+ if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2))
+ continue;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void
+prune_dq_for_future_installed(Solver *solv, Queue *dq)
+{
+ Pool *pool = solv->pool;
+ int i, j;
+ for (i = j = 0; i < dq->count; i++)
+ {
+ Id p = dq->elements[i];
+ if (replaces_installed_package(pool, p, &solv->noupdate))
+ dq->elements[j++] = p;
+ }
+ if (j)
+ queue_truncate(dq, j);
+}
+
+
+static void
reorder_dq_for_future_installed(Solver *solv, int level, Queue *dq)
{
Pool *pool = solv->pool;
- int i, j, haveone = 0, dqcount = dq->count;
+ int i, haveone = 0, dqcount = dq->count;
int decisionqcount = solv->decisionq.count;
Id p;
Solvable *s;
dq->elements[i] = 0;
}
}
- for (i = j = 0; i < dq->count; i++)
- if (dq->elements[i])
- dq->elements[j++] = dq->elements[i];
- queue_truncate(dq, j);
+ queue_prunezeros(dq);
FOR_REPO_SOLVABLES(solv->installed, p, s)
if (solv->decisionmap[p] == level + 1)
solv->decisionmap[p] = 0;
int i;
IF_POOLDEBUG (SOLV_DEBUG_POLICY)
{
- POOL_DEBUG (SOLV_DEBUG_POLICY, "creating a branch:\n");
+ POOL_DEBUG (SOLV_DEBUG_POLICY, "creating a branch [data=%d]:\n", data);
for (i = 0; i < dq->count; i++)
POOL_DEBUG (SOLV_DEBUG_POLICY, " - %s\n", pool_solvid2str(pool, dq->elements[i]));
}
#if 0
{
int i;
- printf("branch group level %d [%d-%d] %d %d:\n", solv->branches.elements[end - 1], start, end, solv->branches.elements[end - 4], solv->branches.elements[end - 3]);
+ printf("branch group level %d [%d-%d] %d %d:\n", solv->branches.elements[end - 1], end - solv->branches.elements[end - 2], end, solv->branches.elements[end - 4], solv->branches.elements[end - 3]);
for (i = end - solv->branches.elements[end - 2]; i < end - 4; i++)
printf("%c %c%s\n", i == pos ? 'x' : ' ', solv->branches.elements[i] >= 0 ? ' ' : '-', pool_solvid2str(pool, solv->branches.elements[i] >= 0 ? solv->branches.elements[i] : -solv->branches.elements[i]));
}
return setpropagatelearn(solv, level, p, disablerules, why, reason);
}
+static void
+prune_yumobs(Solver *solv, Queue *dq, Id ruleid)
+{
+ Pool *pool = solv->pool;
+ Rule *r;
+ Map m;
+ int i, j, rid;
+
+ map_init(&m, 0);
+ for (i = 0; i < dq->count - 1; i++)
+ {
+ Id p2, pp, p = dq->elements[i];
+ if (!p || !pool->solvables[p].obsoletes)
+ continue;
+ for (rid = solv->yumobsrules, r = solv->rules + rid; rid < solv->yumobsrules_end; rid++, r++)
+ if (r->p == -p)
+ break;
+ if (rid == solv->yumobsrules_end)
+ continue;
+ if (!m.size)
+ map_grow(&m, pool->nsolvables);
+ else
+ MAPZERO(&m);
+ for (; rid < solv->yumobsrules_end; rid++, r++)
+ {
+ if (r->p != -p)
+ continue;
+ FOR_RULELITERALS(p2, pp, r)
+ if (p2 > 0)
+ MAPSET(&m, p2);
+ }
+ for (j = i + 1; j < dq->count; j++)
+ if (MAPTST(&m, dq->elements[j]))
+ dq->elements[j] = 0;
+ }
+ map_free(&m);
+ queue_prunezeros(dq);
+}
+
+
/*-------------------------------------------------------------------
*
* select and install
if (dq->count > 1)
policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE);
/* if we're resolving rules and didn't resolve the installed packages yet,
- * do some special supplements ordering */
+ * do some special pruning and supplements ordering */
if (dq->count > 1 && solv->do_extra_reordering)
- reorder_dq_for_future_installed(solv, level, dq);
+ {
+ prune_dq_for_future_installed(solv, dq);
+ if (dq->count > 1)
+ reorder_dq_for_future_installed(solv, level, dq);
+ }
+ /* check if the candidates are all connected via yumobs rules */
+ if (dq->count > 1 && solv->yumobsrules_end > solv->yumobsrules)
+ prune_yumobs(solv, dq, ruleid);
/* if we have multiple candidates we open a branch */
if (dq->count > 1)
createbranch(solv, level, dq, 0, ruleid);
map_free(&solv->droporphanedmap);
map_free(&solv->cleandepsmap);
map_free(&solv->allowuninstallmap);
+ map_free(&solv->excludefromweakmap);
+
solv_free(solv->favormap);
solv_free(solv->decisionmap);
return solv->install_also_updates;
case SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED:
return solv->only_namespace_recommended;
+ case SOLVER_FLAG_STRICT_REPO_PRIORITY:
+ return solv->strict_repo_priority;
default:
break;
}
case SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED:
solv->only_namespace_recommended = value;
break;
+ case SOLVER_FLAG_STRICT_REPO_PRIORITY:
+ solv->strict_repo_priority = value;
+ break;
default:
break;
}
}
olevel = level;
level = selectandinstall(solv, level, dq, disablerules, i, SOLVER_REASON_RESOLVE_JOB);
+ r = solv->rules + i; /* selectandinstall may have added more rules */
if (level <= olevel)
{
if (level == olevel)
{
if (specialupdaters && (d = specialupdaters[i - installed->start]) != 0)
{
+ int j;
/* special multiversion handling, make sure best version is chosen */
if (rr->p == i && solv->decisionmap[i] >= 0)
queue_push(dq, i);
while ((p = pool->whatprovidesdata[d++]) != 0)
if (solv->decisionmap[p] >= 0)
queue_push(dq, p);
+ for (j = 0; j < dq->count; j++)
+ {
+ Id p2 = dq->elements[j];
+ if (pool->solvables[p2].repo != installed)
+ continue;
+ d = specialupdaters[i - installed->start];
+ while ((p = pool->whatprovidesdata[d++]) != 0)
+ {
+ if (solv->decisionmap[p] >= 0 || pool->solvables[p].repo == installed)
+ continue;
+ if (solvable_identical(pool->solvables + p, pool->solvables + p2))
+ queue_push(dq, p); /* identical to installed, put it on the list so we have a repo prio */
+ }
+ }
if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start])
prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq);
if (dq->count)
Rule *r;
int origlevel = level;
Id p, *dp;
+ int focusbest = solv->focus_best && solv->do_extra_reordering;
+ Repo *installed = solv->installed;
/*
* decide
}
if (i == solv->nrules)
i = 1;
- if (solv->focus_best && solv->do_extra_reordering && i >= solv->featurerules)
+ if (focusbest && i >= solv->featurerules)
continue;
r = solv->rules + i;
if (r->d < 0) /* ignore disabled rules */
if (r->d == 0 || solv->decisionmap[-r->p] <= 0)
continue;
}
+ if (focusbest && r->d != 0 && installed)
+ {
+ /* make sure at least one negative literal is from a new package */
+ if (!(r->p < 0 && pool->solvables[-r->p].repo != installed))
+ {
+ dp = pool->whatprovidesdata + r->d;
+ while ((p = *dp++) != 0)
+ if (p < 0 && solv->decisionmap[-p] > 0 && pool->solvables[-p].repo != installed)
+ break;
+ if (!p)
+ continue; /* sorry */
+ }
+ }
if (dq->count)
queue_empty(dq);
if (r->d == 0)
queue_truncate(dq, blkcnt);
break;
}
+ if (solv->decisionmap[p] < 0)
+ continue;
if (dqmap)
{
if (!MAPTST(dqmap, p))
}
else
{
- if (solv->decisionmap[p] < 0)
- continue;
if (solv->process_orphans && solv->installed && pool->solvables[p].repo == solv->installed && (solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - solv->installed->start))))
continue;
}
queue_truncate(plist, j);
}
+static void
+prune_exclude_from_weak(Solver *solv, Queue *plist)
+{
+ int i, j;
+ for (i = j = 0; i < plist->count; i++)
+ {
+ Id p = plist->elements[i];
+ if (!MAPTST(&solv->excludefromweakmap, p))
+ plist->elements[j++] = p;
+ }
+ if (i != j)
+ queue_truncate(plist, j);
+}
+
static int
resolve_weak(Solver *solv, int level, int disablerules, Queue *dq, Queue *dqs, int *rerunp)
{
continue;
if (solv->havedisfavored && solv->favormap[i] < 0)
continue; /* disfavored supplements, do not install */
+ if (solv->excludefromweakmap.size && MAPTST(&solv->excludefromweakmap, i))
+ continue; /* excluded for weak deps, do not install */
queue_push(dqs, i);
}
}
if (dq->count && solv->havedisfavored)
prune_disfavored(solv, dq);
+ /* filter out weak_excluded recommended packages */
+ if (solv->excludefromweakmap.size)
+ prune_exclude_from_weak(solv, dq);
+
/* filter out all packages obsoleted by installed packages */
/* this is no longer needed if we have (and trust) reverse obsoletes */
if ((dqs->count || dq->count) && solv->installed)
return level;
}
+int
+solver_check_unneeded_choicerules(Solver *solv)
+{
+ Pool *pool = solv->pool;
+ Rule *r, *or;
+ Id p, pp, p2, pp2;
+ int i;
+ int havedisabled = 0;
+
+ /* check if some choice rules could have been broken */
+ for (i = solv->choicerules, r = solv->rules + i; i < solv->choicerules_end; i++, r++)
+ {
+ if (r->d < 0)
+ continue;
+ or = solv->rules + solv->choicerules_info[i - solv->choicerules];
+ if (or->d < 0)
+ continue;
+ FOR_RULELITERALS(p, pp, or)
+ {
+ if (p < 0 || solv->decisionmap[p] <= 0)
+ continue;
+ FOR_RULELITERALS(p2, pp2, r)
+ if (p2 == p)
+ break;
+ if (!p2)
+ {
+ /* did not find p in choice rule, disable it */
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "disabling unneeded choice rule #%d\n", i);
+ solver_disablechoicerules(solv, r);
+ havedisabled = 1;
+ break;
+ }
+ }
+ }
+ return havedisabled;
+}
+
/*-------------------------------------------------------------------
*
* solver_run_sat
continue;
}
+ if (solv->choicerules != solv->choicerules_end && solver_check_unneeded_choicerules(solv))
+ {
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "did choice rule minimization, rerunning solver\n");
+ solver_reset(solv);
+ level = 0; /* restart from scratch */
+ continue;
+ }
+
if (solv->solution_callback)
{
solv->solution_callback(solv, solv->solution_callback_data);
continue;
if (solv->favormap && solv->favormap[p] > solv->favormap[solv->branches.elements[lastsi]])
continue; /* current selection is more favored */
+ if (replaces_installed_package(pool, p, &solv->noupdate))
+ continue; /* current selection replaces an installed package */
if (!(MAPTST(&solv->recommendsmap, p) || solver_is_supplementing(solv, pool->solvables + p)))
{
lasti = lastsi;
if (s->repo == installed)
{
queue_push2(solv->update_targets, p, p);
+ FOR_PROVIDES(pi, pip, s->name)
+ {
+ Solvable *si = pool->solvables + pi;
+ if (si->repo == installed && si->name == s->name && pi != p)
+ queue_push2(solv->update_targets, pi, p);
+ }
return;
}
identicalp = 0;
p = -r->p;
if (!MAPTST(addedmap, p))
{
- /* should never happen, but... */
+ /* this can happen with complex dependencies that have more than one pos literal */
if (!solv->addedmap_deduceq.count || solv->addedmap_deduceq.elements[solv->addedmap_deduceq.count - 1] != -p)
queue_push(&solv->addedmap_deduceq, -p);
continue;
if (p > 0)
MAPSET(addedmap, p);
else
- MAPCLR(addedmap, p);
+ MAPCLR(addedmap, -p);
}
}
#endif
static void
+solver_add_exclude_from_weak(Solver *solv)
+{
+ Queue *job = &solv->job;
+ Pool *pool = solv->pool;
+ int i;
+ Id p, pp, how, what, select;
+for (i = 0; i < job->count; i += 2)
+ {
+ how = job->elements[i];
+ if ((how & SOLVER_JOBMASK) != SOLVER_EXCLUDEFROMWEAK)
+ continue;
+ if (!solv->excludefromweakmap.size)
+ map_grow(&solv->excludefromweakmap, pool->nsolvables);
+ what = job->elements[i + 1];
+ select = how & SOLVER_SELECTMASK;
+ if (select == SOLVER_SOLVABLE_REPO)
+ {
+ Repo *repo = pool_id2repo(pool, what);
+ if (repo)
+ {
+ Solvable *s;
+ FOR_REPO_SOLVABLES(repo, p, s)
+ MAPSET(&solv->excludefromweakmap, p);
+ }
+ }
+ FOR_JOB_SELECT(p, pp, select, what)
+ MAPSET(&solv->excludefromweakmap, p);
+ }
+}
+
+static void
setup_favormap(Solver *solv)
{
Queue *job = &solv->job;
int hasbestinstalljob = 0;
int hasfavorjob = 0;
int haslockjob = 0;
+ int hasblacklistjob = 0;
+ int hasexcludefromweakjob = 0;
solve_start = solv_timems(0);
map_zerosize(&solv->bestupdatemap);
solv->fixmap_all = 0;
map_zerosize(&solv->fixmap);
+ solv->dupinvolvedmap_all = 0;
map_zerosize(&solv->dupmap);
map_zerosize(&solv->dupinvolvedmap);
solv->process_orphans = 0;
map_zerosize(&solv->droporphanedmap);
solv->allowuninstall_all = 0;
map_zerosize(&solv->allowuninstallmap);
+ map_zerosize(&solv->excludefromweakmap);
map_zerosize(&solv->cleandepsmap);
map_zerosize(&solv->weakrulemap);
solv->favormap = solv_free(solv->favormap);
name_s = s;
}
solver_addjobrule(solv, -p, 0, 0, i, weak);
+#ifdef ENABLE_LINKED_PKGS
+ if (solv->instbuddy && installed && s->repo == installed && solv->instbuddy[p - installed->start] > 1)
+ solver_addjobrule(solv, -solv->instbuddy[p - installed->start], 0, 0, i, weak);
+#endif
}
/* special case for "erase a specific solvable": we also
* erase all other solvables with that name, so that they
}
}
FOR_JOB_SELECT(p, pp, select, what)
- solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
+ {
+ s = pool->solvables + p;
+ solver_addjobrule(solv, installed && s->repo == installed ? p : -p, 0, 0, i, weak);
+#ifdef ENABLE_LINKED_PKGS
+ if (solv->instbuddy && installed && s->repo == installed && solv->instbuddy[p - installed->start] > 1)
+ solver_addjobrule(solv, solv->instbuddy[p - installed->start], 0, 0, i, weak);
+#endif
+ }
if (solv->nrules != oldnrules)
haslockjob = 1;
break;
POOL_DEBUG(SOLV_DEBUG_JOB, "job: %s %s\n", (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? "favor" : "disfavor", solver_select2str(pool, select, what));
hasfavorjob = 1;
break;
+ case SOLVER_BLACKLIST:
+ POOL_DEBUG(SOLV_DEBUG_JOB, "job: blacklist %s\n", solver_select2str(pool, select, what));
+ hasblacklistjob = 1;
+ break;
+ case SOLVER_EXCLUDEFROMWEAK:
+ POOL_DEBUG(SOLV_DEBUG_JOB, "job: excludefromweak %s\n", solver_select2str(pool, select, what));
+ hasexcludefromweakjob = 1;
+ break;
default:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n");
break;
else
solv->yumobsrules = solv->yumobsrules_end = solv->nrules;
+ if (hasblacklistjob)
+ solver_addblackrules(solv);
+ else
+ solv->blackrules = solv->blackrules_end = solv->nrules;
+
+ if (hasexcludefromweakjob)
+ solver_add_exclude_from_weak(solv);
+
if (solv->havedisfavored && solv->strongrecommends && solv->recommendsruleq)
solver_addrecommendsrules(solv);
else
solv->recommendsrules = solv->recommendsrules_end = solv->nrules;
+ if (solv->strict_repo_priority)
+ solver_addstrictrepopriorules(solv, &addedmap);
+ else
+ solv->strictrepopriorules = solv->strictrepopriorules_end = solv->nrules;
+
if (1)
solver_addchoicerules(solv);
else
map_free(&installcandidatemap);
queue_free(&q);
- POOL_DEBUG(SOLV_DEBUG_STATS, "%d pkg rules, 2 * %d update rules, %d job rules, %d infarch rules, %d dup rules, %d choice rules, %d best rules, %d yumobs rules\n", solv->pkgrules_end - 1, solv->updaterules_end - solv->updaterules, solv->jobrules_end - solv->jobrules, solv->infarchrules_end - solv->infarchrules, solv->duprules_end - solv->duprules, solv->choicerules_end - solv->choicerules, solv->bestrules_end - solv->bestrules, solv->yumobsrules_end - solv->yumobsrules);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "%d pkg rules, 2 * %d update rules, %d job rules, %d infarch rules, %d dup rules, %d choice rules, %d best rules, %d yumobs rules\n",
+ solv->pkgrules_end - 1,
+ solv->updaterules_end - solv->updaterules,
+ solv->jobrules_end - solv->jobrules,
+ solv->infarchrules_end - solv->infarchrules,
+ solv->duprules_end - solv->duprules,
+ solv->choicerules_end - solv->choicerules,
+ solv->bestrules_end - solv->bestrules,
+ solv->yumobsrules_end - solv->yumobsrules);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "%d black rules, %d recommends rules, %d repo priority rules\n",
+ solv->blackrules_end - solv->blackrules,
+ solv->recommendsrules_end - solv->recommendsrules,
+ solv->strictrepopriorules_end - solv->strictrepopriorules);
POOL_DEBUG(SOLV_DEBUG_STATS, "overall rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024);
/* create weak map */
pool_create_state_maps(solv->pool, &solv->decisionq, installedmap, conflictsmap);
}
-/*-------------------------------------------------------------------
- *
- * decision introspection
- */
-
-int
-solver_get_decisionlevel(Solver *solv, Id p)
-{
- return solv->decisionmap[p];
-}
-
-void
-solver_get_decisionqueue(Solver *solv, Queue *decisionq)
-{
- queue_free(decisionq);
- queue_init_clone(decisionq, &solv->decisionq);
-}
-
-int
-solver_get_lastdecisionblocklevel(Solver *solv)
-{
- Id p;
- if (solv->decisionq.count == 0)
- return 0;
- p = solv->decisionq.elements[solv->decisionq.count - 1];
- if (p < 0)
- p = -p;
- return solv->decisionmap[p] < 0 ? -solv->decisionmap[p] : solv->decisionmap[p];
-}
-
-void
-solver_get_decisionblock(Solver *solv, int level, Queue *decisionq)
-{
- Id p;
- int i;
-
- queue_empty(decisionq);
- for (i = 0; i < solv->decisionq.count; i++)
- {
- p = solv->decisionq.elements[i];
- if (p < 0)
- p = -p;
- if (solv->decisionmap[p] == level || solv->decisionmap[p] == -level)
- break;
- }
- if (i == solv->decisionq.count)
- return;
- for (i = 0; i < solv->decisionq.count; i++)
- {
- p = solv->decisionq.elements[i];
- if (p < 0)
- p = -p;
- if (solv->decisionmap[p] == level || solv->decisionmap[p] == -level)
- queue_push(decisionq, p);
- else
- break;
- }
-}
-
-int
-solver_describe_decision(Solver *solv, Id p, Id *infop)
-{
- int i;
- Id pp, why;
-
- if (infop)
- *infop = 0;
- if (!solv->decisionmap[p])
- return SOLVER_REASON_UNRELATED;
- pp = solv->decisionmap[p] < 0 ? -p : p;
- for (i = 0; i < solv->decisionq.count; i++)
- if (solv->decisionq.elements[i] == pp)
- break;
- if (i == solv->decisionq.count) /* just in case... */
- return SOLVER_REASON_UNRELATED;
- why = solv->decisionq_why.elements[i];
- if (infop)
- *infop = why > 0 ? why : -why;
- if (why > 0)
- return SOLVER_REASON_UNIT_RULE;
- i = solv->decisionmap[p] >= 0 ? solv->decisionmap[p] : -solv->decisionmap[p];
- return solv->decisionq_reason.elements[i];
-}
-
-
-void
-solver_describe_weakdep_decision(Solver *solv, Id p, Queue *whyq)
-{
- Pool *pool = solv->pool;
- int i;
- int level = solv->decisionmap[p];
- int decisionno;
- Solvable *s;
-
- queue_empty(whyq);
- if (level < 0)
- return; /* huh? */
- for (decisionno = 0; decisionno < solv->decisionq.count; decisionno++)
- if (solv->decisionq.elements[decisionno] == p)
- break;
- if (decisionno == solv->decisionq.count)
- return; /* huh? */
- i = solv->decisionmap[p] >= 0 ? solv->decisionmap[p] : -solv->decisionmap[p];
- if (solv->decisionq_reason.elements[i] != SOLVER_REASON_WEAKDEP)
- return; /* huh? */
-
- /* 1) list all packages that recommend us */
- for (i = 1; i < pool->nsolvables; i++)
- {
- Id *recp, rec, pp2, p2;
- if (solv->decisionmap[i] <= 0 || solv->decisionmap[i] >= level)
- continue;
- s = pool->solvables + i;
- if (!s->recommends)
- continue;
- if (!solv->addalreadyrecommended && s->repo == solv->installed)
- continue;
- recp = s->repo->idarraydata + s->recommends;
- while ((rec = *recp++) != 0)
- {
- int found = 0;
- FOR_PROVIDES(p2, pp2, rec)
- {
- if (p2 == p)
- found = 1;
- else
- {
- /* if p2 is already installed, this recommends is ignored */
- if (solv->decisionmap[p2] > 0 && solv->decisionmap[p2] < level)
- break;
- }
- }
- if (!p2 && found)
- {
- queue_push(whyq, SOLVER_REASON_RECOMMENDED);
- queue_push2(whyq, i, rec);
- }
- }
- }
- /* 2) list all supplements */
- s = pool->solvables + p;
- if (s->supplements && level > 0)
- {
- Id *supp, sup, pp2, p2;
- /* this is a hack. to use solver_dep_fulfilled we temporarily clear
- * everything above our level in the decisionmap */
- for (i = decisionno; i < solv->decisionq.count; i++ )
- {
- p2 = solv->decisionq.elements[i];
- if (p2 > 0)
- solv->decisionmap[p2] = -solv->decisionmap[p2];
- }
- supp = s->repo->idarraydata + s->supplements;
- while ((sup = *supp++) != 0)
- if (solver_dep_fulfilled(solv, sup))
- {
- int found = 0;
- /* let's see if this is an easy supp */
- FOR_PROVIDES(p2, pp2, sup)
- {
- if (!solv->addalreadyrecommended && solv->installed)
- {
- if (pool->solvables[p2].repo == solv->installed)
- continue;
- }
- if (solv->decisionmap[p2] > 0 && solv->decisionmap[p2] < level)
- {
- queue_push(whyq, SOLVER_REASON_SUPPLEMENTED);
- queue_push2(whyq, p2, sup);
- found = 1;
- }
- }
- if (!found)
- {
- /* hard case, just note dependency with no package */
- queue_push(whyq, SOLVER_REASON_SUPPLEMENTED);
- queue_push2(whyq, 0, sup);
- }
- }
- for (i = decisionno; i < solv->decisionq.count; i++)
- {
- p2 = solv->decisionq.elements[i];
- if (p2 > 0)
- solv->decisionmap[p2] = -solv->decisionmap[p2];
- }
- }
-}
-
void
pool_job2solvables(Pool *pool, Queue *pkgs, Id how, Id what)
{
int
pool_isemptyupdatejob(Pool *pool, Id how, Id what)
{
- Id p, pp, pi, pip;
+ Id p, pp;
Id select = how & SOLVER_SELECTMASK;
if ((how & SOLVER_JOBMASK) != SOLVER_UPDATE)
return 0;
return 0;
/* hard work */
FOR_JOB_SELECT(p, pp, select, what)
- {
- Solvable *s = pool->solvables + p;
- FOR_PROVIDES(pi, pip, s->name)
- {
- Solvable *si = pool->solvables + pi;
- if (si->repo != pool->installed || si->name != s->name)
- continue;
- return 0;
- }
- if (s->obsoletes)
- {
- Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
- while ((obs = *obsp++) != 0)
- {
- FOR_PROVIDES(pi, pip, obs)
- {
- Solvable *si = pool->solvables + pi;
- if (si->repo != pool->installed)
- continue;
- if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, si, obs))
- continue;
- if (pool->obsoleteusescolors && !pool_colormatch(pool, s, si))
- continue;
- return 0;
- }
- }
- }
- }
+ if (replaces_installed_package(pool, p, 0))
+ return 0;
return 1;
}
-int
-solver_alternatives_count(Solver *solv)
-{
- Id *elements = solv->branches.elements;
- int res, count;
- for (res = 0, count = solv->branches.count; count; res++)
- count -= elements[count - 2];
- return res;
-}
-
-int
-solver_get_alternative(Solver *solv, Id alternative, Id *idp, Id *fromp, Id *chosenp, Queue *choices, int *levelp)
-{
- int cnt = solver_alternatives_count(solv);
- int count = solv->branches.count;
- Id *elements = solv->branches.elements;
- if (choices)
- queue_empty(choices);
- if (alternative <= 0 || alternative > cnt)
- return 0;
- elements += count;
- for (; cnt > alternative; cnt--)
- elements -= elements[-2];
- if (levelp)
- *levelp = elements[-1];
- if (fromp)
- *fromp = elements[-4];
- if (idp)
- *idp = elements[-3];
- if (chosenp)
- {
- int i;
- *chosenp = 0;
- for (i = elements[-2]; i > 4; i--)
- {
- Id p = -elements[-i];
- if (p > 0 && solv->decisionmap[p] == elements[-1] + 1)
- {
- *chosenp = p;
- break;
- }
- }
- }
- if (choices)
- queue_insertn(choices, 0, elements[-2] - 4, elements - elements[-2]);
- return elements[-4] ? SOLVER_ALTERNATIVE_TYPE_RECOMMENDS : SOLVER_ALTERNATIVE_TYPE_RULE;
-}
-
const char *
solver_select2str(Pool *pool, Id select, Id what)
{
case SOLVER_DISFAVOR:
strstart = "disfavor ";
break;
+ case SOLVER_BLACKLIST:
+ strstart = "blacklist ";
+ break;
default:
strstart = "unknown job ";
break;
return pool_tmpappend(pool, s, "]", 0);
}
-const char *
-solver_alternative2str(Solver *solv, int type, Id id, Id from)
-{
- Pool *pool = solv->pool;
- if (type == SOLVER_ALTERNATIVE_TYPE_RECOMMENDS)
- {
- const char *s = pool_dep2str(pool, id);
- return pool_tmpappend(pool, s, ", recommended by ", pool_solvid2str(pool, from));
- }
- if (type == SOLVER_ALTERNATIVE_TYPE_RULE)
- {
- int rtype;
- Id depfrom, depto, dep;
- char buf[64];
- if (solver_ruleclass(solv, id) == SOLVER_RULE_CHOICE)
- id = solver_rule2pkgrule(solv, id);
- if (solver_ruleclass(solv, id) == SOLVER_RULE_RECOMMENDS)
- id = solver_rule2pkgrule(solv, id);
- rtype = solver_ruleinfo(solv, id, &depfrom, &depto, &dep);
- if ((rtype & SOLVER_RULE_TYPEMASK) == SOLVER_RULE_JOB)
- {
- if ((depto & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_PROVIDES)
- return pool_dep2str(pool, dep);
- return solver_select2str(pool, depto & SOLVER_SELECTMASK, dep);
- }
- if (rtype == SOLVER_RULE_PKG_REQUIRES)
- {
- const char *s = pool_dep2str(pool, dep);
- return pool_tmpappend(pool, s, ", required by ", pool_solvid2str(pool, depfrom));
- }
- sprintf(buf, "Rule #%d", id);
- return pool_tmpjoin(pool, buf, 0, 0);
- }
- return "unknown alternative type";
-}
-