#include "pool.h"
#include "util.h"
#include "policy.h"
+#include "poolarch.h"
#include "solverdebug.h"
#define RULES_BLOCK 63
return 0;
}
+/* mirrors solver_dep_installed, but returns 2 if a
+ * dependency listed in solv->installsuppdepq was involved */
+static int
+solver_check_installsuppdepq_dep(Solver *solv, Id dep)
+{
+ Pool *pool = solv->pool;
+ Id p, pp;
+ Queue *q;
+
+ if (ISRELDEP(dep))
+ {
+ Reldep *rd = GETRELDEP(pool, dep);
+ if (rd->flags == REL_AND)
+ {
+ int r2, r1 = solver_check_installsuppdepq_dep(solv, rd->name);
+ if (!r1)
+ return 0;
+ r2 = solver_check_installsuppdepq_dep(solv, rd->evr);
+ if (!r2)
+ return 0;
+ return r1 == 2 || r2 == 2 ? 2 : 1;
+ }
+ if (rd->flags == REL_OR)
+ {
+ int r2, r1 = solver_check_installsuppdepq_dep(solv, rd->name);
+ r2 = solver_check_installsuppdepq_dep(solv, rd->evr);
+ if (!r1 && !r2)
+ return 0;
+ return r1 == 2 || r2 == 2 ? 2 : 1;
+ }
+ if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
+ return solver_splitprovides(solv, rd->evr);
+ if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
+ return solver_dep_installed(solv, rd->evr);
+ if (rd->flags == REL_NAMESPACE && (q = solv->installsuppdepq) != 0)
+ {
+ int i;
+ for (i = 0; i < q->count; i++)
+ if (q->elements[i] == dep || q->elements[i] == rd->name)
+ return 2;
+ }
+ }
+ FOR_PROVIDES(p, pp, dep)
+ if (solv->decisionmap[p] > 0)
+ return 1;
+ return 0;
+}
+
+static int
+solver_check_installsuppdepq(Solver *solv, Solvable *s)
+{
+ Id sup, *supp;
+ supp = s->repo->idarraydata + s->supplements;
+ while ((sup = *supp++) != 0)
+ if (solver_check_installsuppdepq_dep(solv, sup) == 2)
+ return 1;
+ return 0;
+}
static Id
autouninstall(Solver *solv, Id *problem)
v = solv->decisionq.elements[i];
solv->decisionmap[v > 0 ? v : -v] = 0;
}
- solv->decisionq_why.count = 0;
- solv->decisionq.count = 0;
+ queue_empty(&solv->decisionq_why);
+ queue_empty(&solv->decisionq);
solv->recommends_index = -1;
solv->propagate_index = 0;
- solv->branches.count = 0;
+ queue_empty(&solv->branches);
/* adapt learnt rule status to new set of enabled/disabled rules */
enabledisablelearntrules(solv);
queue_init(&solv->branches);
queue_init(&solv->weakruleq);
queue_init(&solv->ruleassertions);
+ queue_init(&solv->addedmap_deduceq);
queue_push(&solv->learnt_pool, 0); /* so that 0 does not describe a proof */
queue_free(&solv->branches);
queue_free(&solv->weakruleq);
queue_free(&solv->ruleassertions);
+ queue_free(&solv->addedmap_deduceq);
if (solv->cleandeps_updatepkgs)
{
queue_free(solv->cleandeps_updatepkgs);
queue_free(solv->cleandeps_mistakes);
solv->cleandeps_mistakes = solv_free(solv->cleandeps_mistakes);
}
+ if (solv->update_targets)
+ {
+ queue_free(solv->update_targets);
+ solv->update_targets = solv_free(solv->update_targets);
+ }
+ if (solv->installsuppdepq)
+ {
+ queue_free(solv->installsuppdepq);
+ solv->installsuppdepq = solv_free(solv->installsuppdepq);
+ }
map_free(&solv->recommendsmap);
map_free(&solv->suggestsmap);
map_free(&solv->noobsoletes);
map_free(&solv->updatemap);
+ map_free(&solv->bestupdatemap);
map_free(&solv->fixmap);
map_free(&solv->dupmap);
map_free(&solv->dupinvolvedmap);
solv_free(solv->obsoletes_data);
solv_free(solv->multiversionupdaters);
solv_free(solv->choicerules_ref);
+ solv_free(solv->bestrules_pkg);
solv_free(solv);
}
return solv->noinfarchcheck;
case SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES:
return solv->keepexplicitobsoletes;
+ case SOLVER_FLAG_BEST_OBEY_POLICY:
+ return solv->bestobeypolicy;
+ case SOLVER_FLAG_NO_AUTOTARGET:
+ return solv->noautotarget;
default:
break;
}
case SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES:
solv->keepexplicitobsoletes = value;
break;
+ case SOLVER_FLAG_BEST_OBEY_POLICY:
+ solv->bestobeypolicy = value;
+ break;
+ case SOLVER_FLAG_NO_AUTOTARGET:
+ solv->noautotarget = value;
+ break;
default:
break;
}
{
Pool *pool = solv->pool;
Rule *r;
- Id p, *dp;
+ Id p, pp;
int i;
int mademistake = 0;
continue;
r = solv->rules + solv->featurerules + (i - solv->installed->start);
/* a mistake is when the featurerule is true but the updaterule is false */
- if (r->p)
+ if (!r->p)
+ continue;
+ FOR_RULELITERALS(p, pp, r)
+ if (p > 0 && solv->decisionmap[p] > 0)
+ break;
+ if (!p)
+ continue; /* feature rule is not true */
+ r = solv->rules + solv->updaterules + (i - solv->installed->start);
+ if (!r->p)
+ continue;
+ FOR_RULELITERALS(p, pp, r)
+ if (p > 0 && solv->decisionmap[p] > 0)
+ break;
+ if (p)
+ continue; /* update rule is true */
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "cleandeps mistake: ");
+ solver_printruleclass(solv, SOLV_DEBUG_SOLVER, r);
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "feature rule: ");
+ solver_printruleclass(solv, SOLV_DEBUG_SOLVER, solv->rules + solv->featurerules + (i - solv->installed->start));
+ if (!solv->cleandeps_mistakes)
{
- FOR_RULELITERALS(p, dp, r)
- if (p > 0 && solv->decisionmap[p] > 0)
- break;
- if (p)
- {
- r = solv->rules + solv->updaterules + (i - solv->installed->start);
- if (!r->p)
- continue;
- FOR_RULELITERALS(p, dp, r)
- if (p > 0 && solv->decisionmap[p] > 0)
- break;
- if (!p)
- {
- POOL_DEBUG(SOLV_DEBUG_SOLVER, "cleandeps mistake: ");
- solver_printruleclass(solv, SOLV_DEBUG_SOLVER, r);
- POOL_DEBUG(SOLV_DEBUG_SOLVER, "feature rule: ");
- solver_printruleclass(solv, SOLV_DEBUG_SOLVER, solv->rules + solv->featurerules + (i - solv->installed->start));
- if (!solv->cleandeps_mistakes)
- {
- solv->cleandeps_mistakes = solv_calloc(1, sizeof(Queue));
- queue_init(solv->cleandeps_mistakes);
- }
- queue_push(solv->cleandeps_mistakes, i);
- MAPCLR(&solv->cleandepsmap, i - solv->installed->start);
- solver_reenablepolicyrules_cleandeps(solv, i);
- mademistake = 1;
- }
- }
+ solv->cleandeps_mistakes = solv_calloc(1, sizeof(Queue));
+ queue_init(solv->cleandeps_mistakes);
}
+ queue_push(solv->cleandeps_mistakes, i);
+ MAPCLR(&solv->cleandepsmap, i - solv->installed->start);
+ solver_reenablepolicyrules_cleandeps(solv, i);
+ mademistake = 1;
}
if (mademistake)
solver_reset(solv);
return mademistake;
}
+static void
+prune_to_update_targets(Solver *solv, Id *cp, Queue *q)
+{
+ int i, j;
+ Id p, *cp2;
+ for (i = j = 0; i < q->count; i++)
+ {
+ p = q->elements[i];
+ for (cp2 = cp; *cp2; cp2++)
+ if (*cp2 == p)
+ {
+ q->elements[j++] = p;
+ break;
+ }
+ }
+ queue_truncate(q, j);
+}
+
/*-------------------------------------------------------------------
*
* solver_run_sat
int i, j, n;
Solvable *s;
Pool *pool = solv->pool;
- Id p, *dp;
+ Id p, pp, *dp;
int minimizationsteps;
int installedpos = solv->installed ? solv->installed->start : 0;
if (r->d < 0) /* ignore disabled rules */
continue;
queue_empty(&dq);
- FOR_RULELITERALS(l, dp, r)
+ FOR_RULELITERALS(l, pp, r)
{
if (l < 0)
{
while ((p = pool->whatprovidesdata[d++]) != 0)
if (solv->decisionmap[p] >= 0)
queue_push(&dq, p);
- policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE);
- p = dq.elements[0];
- if (p != i && solv->decisionmap[p] == 0)
+ 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)
{
- rr = solv->rules + solv->featurerules + (i - solv->installed->start);
- if (!rr->p) /* update rule == feature rule? */
- rr = rr - solv->featurerules + solv->updaterules;
- dq.count = 1;
+ policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE);
+ p = dq.elements[0];
+ if (p != i && solv->decisionmap[p] == 0)
+ {
+ rr = solv->rules + solv->featurerules + (i - solv->installed->start);
+ if (!rr->p) /* update rule == feature rule? */
+ rr = rr - solv->featurerules + solv->updaterules;
+ dq.count = 1;
+ }
+ else
+ dq.count = 0;
}
- else
- dq.count = 0;
}
else
{
/* update to best package */
- FOR_RULELITERALS(p, dp, rr)
+ FOR_RULELITERALS(p, pp, rr)
{
if (solv->decisionmap[p] > 0)
{
}
}
}
+ 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);
/* install best version */
if (dq.count)
{
olevel = level;
if (solv->cleandepsmap.size && MAPTST(&solv->cleandepsmap, i - installed->start))
{
+#if 0
POOL_DEBUG(SOLV_DEBUG_POLICY, "cleandeps erasing %s\n", pool_solvid2str(pool, i));
level = setpropagatelearn(solv, level, -i, disablerules, 0);
+#else
+ continue;
+#endif
}
else
{
* the rule is unit */
assert(dq.count > 1);
+ /* prune to cleandeps packages */
+ if (solv->cleandepsmap.size && solv->installed)
+ {
+ Repo *installed = solv->installed;
+ for (j = 0; j < dq.count; j++)
+ if (pool->solvables[dq.elements[j]].repo == installed && MAPTST(&solv->cleandepsmap, dq.elements[j] - installed->start))
+ break;
+ if (j < dq.count)
+ {
+ dq.elements[0] = dq.elements[j];
+ queue_truncate(&dq, 1);
+ }
+ }
+
olevel = level;
level = selectandinstall(solv, level, &dq, disablerules, r - solv->rules);
if (level == 0)
/* at this point we have a consistent system. now do the extras... */
+ /* first decide leftover cleandeps packages */
+ if (solv->cleandepsmap.size && solv->installed)
+ {
+ for (p = solv->installed->start; p < solv->installed->end; p++)
+ {
+ s = pool->solvables + p;
+ if (s->repo != solv->installed)
+ continue;
+ if (solv->decisionmap[p] == 0 && MAPTST(&solv->cleandepsmap, p - solv->installed->start))
+ {
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "cleandeps erasing %s\n", pool_solvid2str(pool, p));
+ olevel = level;
+ level = setpropagatelearn(solv, level, -p, 0, 0);
+ if (level < olevel)
+ break;
+ }
+ }
+ if (p < solv->installed->end)
+ continue;
+ }
+
solv->decisioncnt_weak = solv->decisionq.count;
if (doweak)
{
continue;
if (!solver_is_supplementing(solv, s))
dqs.elements[j++] = p;
+ else if (s->supplements && solv->installsuppdepq && solver_check_installsuppdepq(solv, s))
+ dqs.elements[j++] = p;
}
dqs.count = j;
/* undo turning off */
if (cleandeps_check_mistakes(solv, level))
{
level = 1; /* restart from scratch */
+ systemlevel = level + 1;
continue;
}
}
select = how & SOLVER_SELECTMASK;
if (!noobsmap->size)
map_grow(noobsmap, pool->nsolvables);
+ if (select == SOLVER_SOLVABLE_ALL)
+ {
+ FOR_POOL_SOLVABLES(p)
+ MAPSET(noobsmap, p);
+ }
+ else if (select == SOLVER_SOLVABLE_REPO)
+ {
+ Solvable *s;
+ Repo *repo = pool_id2repo(pool, what);
+ if (repo)
+ FOR_REPO_SOLVABLES(repo, p, s)
+ MAPSET(noobsmap, p);
+ }
FOR_JOB_SELECT(p, pp, select, what)
MAPSET(noobsmap, p);
}
queue_push(&solv->weakruleq, solv->nrules - 1);
}
+static inline void
+add_cleandeps_package(Solver *solv, Id p)
+{
+ if (!solv->cleandeps_updatepkgs)
+ {
+ solv->cleandeps_updatepkgs = solv_calloc(1, sizeof(Queue));
+ queue_init(solv->cleandeps_updatepkgs);
+ }
+ queue_pushunique(solv->cleandeps_updatepkgs, p);
+}
+
+static void
+add_update_target(Solver *solv, Id p, Id how)
+{
+ Pool *pool = solv->pool;
+ Solvable *s = pool->solvables + p;
+ Repo *installed = solv->installed;
+ Id pi, pip;
+ if (!solv->update_targets)
+ {
+ solv->update_targets = solv_calloc(1, sizeof(Queue));
+ queue_init(solv->update_targets);
+ }
+ if (s->repo == installed)
+ {
+ queue_push2(solv->update_targets, p, p);
+ return;
+ }
+ FOR_PROVIDES(pi, pip, s->name)
+ {
+ Solvable *si = pool->solvables + pi;
+ if (si->repo != installed || si->name != s->name)
+ continue;
+ if (how & SOLVER_FORCEBEST)
+ {
+ if (!solv->bestupdatemap.size)
+ map_grow(&solv->bestupdatemap, installed->end - installed->start);
+ MAPSET(&solv->bestupdatemap, pi - installed->start);
+ }
+ if (how & SOLVER_CLEANDEPS)
+ add_cleandeps_package(solv, pi);
+ queue_push2(solv->update_targets, pi, p);
+ /* check if it's ok to keep the installed package */
+ if (s->evr == si->evr && solvable_identical(s, si))
+ queue_push2(solv->update_targets, pi, pi);
+ }
+ 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 != installed)
+ continue;
+ if (si->name == s->name)
+ continue; /* already handled above */
+ if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, si, obs))
+ continue;
+ if (pool->obsoleteusescolors && !pool_colormatch(pool, s, si))
+ continue;
+ if (how & SOLVER_FORCEBEST)
+ {
+ if (!solv->bestupdatemap.size)
+ map_grow(&solv->bestupdatemap, installed->end - installed->start);
+ MAPSET(&solv->bestupdatemap, pi - installed->start);
+ }
+ if (how & SOLVER_CLEANDEPS)
+ add_cleandeps_package(solv, pi);
+ queue_push2(solv->update_targets, pi, p);
+ }
+ }
+ }
+}
+
+static int
+transform_update_targets_sortfn(const void *ap, const void *bp, void *dp)
+{
+ const Id *a = ap;
+ const Id *b = bp;
+ if (a[0] - b[0])
+ return a[0] - b[0];
+ return a[1] - b[1];
+}
+
+static void
+transform_update_targets(Solver *solv)
+{
+ Repo *installed = solv->installed;
+ Queue *update_targets = solv->update_targets;
+ int i, j;
+ Id p, q, lastp, lastq;
+
+ if (!update_targets->count)
+ {
+ queue_free(update_targets);
+ solv->update_targets = solv_free(update_targets);
+ return;
+ }
+ if (update_targets->count > 2)
+ solv_sort(update_targets->elements, update_targets->count >> 1, 2 * sizeof(Id), transform_update_targets_sortfn, solv);
+ queue_insertn(update_targets, 0, installed->end - installed->start);
+ lastp = lastq = 0;
+ for (i = j = installed->end - installed->start; i < update_targets->count; i += 2)
+ {
+ if ((p = update_targets->elements[i]) != lastp)
+ {
+ if (!solv->updatemap.size)
+ map_grow(&solv->updatemap, installed->end - installed->start);
+ MAPSET(&solv->updatemap, p - installed->start);
+ update_targets->elements[j++] = 0; /* finish old set */
+ update_targets->elements[p - installed->start] = j; /* start new set */
+ lastp = p;
+ lastq = 0;
+ }
+ if ((q = update_targets->elements[i + 1]) != lastq)
+ {
+ update_targets->elements[j++] = q;
+ lastq = q;
+ }
+ }
+ queue_truncate(update_targets, j);
+ queue_push(update_targets, 0); /* finish last set */
+}
+
+
+static void
+addedmap2deduceq(Solver *solv, Map *addedmap)
+{
+ Pool *pool = solv->pool;
+ int i, j;
+ Id p;
+ Rule *r;
+
+ queue_empty(&solv->addedmap_deduceq);
+ for (i = 2, j = solv->rpmrules_end - 1; i < pool->nsolvables && j > 0; j--)
+ {
+ r = solv->rules + j;
+ if (r->p >= 0)
+ continue;
+ if ((r->d == 0 || r->d == -1) && r->w2 < 0)
+ continue;
+ p = -r->p;
+ if (!MAPTST(addedmap, p))
+ {
+ /* should never happen, but... */
+ if (!solv->addedmap_deduceq.count || solv->addedmap_deduceq.elements[solv->addedmap_deduceq.count - 1] != -p)
+ queue_push(&solv->addedmap_deduceq, -p);
+ continue;
+ }
+ for (; i < p; i++)
+ if (MAPTST(addedmap, i))
+ queue_push(&solv->addedmap_deduceq, i);
+ if (i == p)
+ i++;
+ }
+ for (; i < pool->nsolvables; i++)
+ if (MAPTST(addedmap, i))
+ queue_push(&solv->addedmap_deduceq, i);
+ j = 0;
+ for (i = 2; i < pool->nsolvables; i++)
+ if (MAPTST(addedmap, i))
+ j++;
+}
+
+static void
+deduceq2addedmap(Solver *solv, Map *addedmap)
+{
+ int j;
+ Id p;
+ Rule *r;
+ for (j = solv->rpmrules_end - 1; j > 0; j--)
+ {
+ r = solv->rules + j;
+ if (r->d < 0 && r->p)
+ solver_enablerule(solv, r);
+ if (r->p >= 0)
+ continue;
+ if ((r->d == 0 || r->d == -1) && r->w2 < 0)
+ continue;
+ p = -r->p;
+ MAPSET(addedmap, p);
+ }
+ for (j = 0; j < solv->addedmap_deduceq.count; j++)
+ {
+ p = solv->addedmap_deduceq.elements[j];
+ if (p > 0)
+ MAPSET(addedmap, p);
+ else
+ MAPCLR(addedmap, p);
+ }
+}
+
+
/*
*
* solve job queue
Pool *pool = solv->pool;
Repo *installed = solv->installed;
int i;
- int oldnrules;
+ int oldnrules, initialnrules;
Map addedmap; /* '1' == have rpm-rules for solvable */
Map installcandidatemap;
Id how, what, select, name, weak, p, pp, d;
Rule *r;
int now, solve_start;
int hasdupjob = 0;
+ int hasbestinstalljob = 0;
solve_start = solv_timems(0);
/* remember job */
queue_free(&solv->job);
queue_init_clone(&solv->job, job);
+ solv->pooljobcnt = pool->pooljobs.count;
+ if (pool->pooljobs.count)
+ {
+ queue_insertn(&solv->job, 0, pool->pooljobs.count);
+ memcpy(solv->job.elements, pool->pooljobs.elements, pool->pooljobs.count * sizeof(Id));
+ }
+ job = &solv->job;
+
+ /* free old stuff */
+ if (solv->update_targets)
+ {
+ queue_free(solv->update_targets);
+ solv->update_targets = solv_free(solv->update_targets);
+ }
+ if (solv->cleandeps_updatepkgs)
+ {
+ queue_free(solv->cleandeps_updatepkgs);
+ solv->cleandeps_updatepkgs = solv_free(solv->cleandeps_updatepkgs);
+ }
+ queue_empty(&solv->ruleassertions);
+ solv->bestrules_pkg = solv_free(solv->bestrules_pkg);
+ solv->choicerules_ref = solv_free(solv->choicerules_ref);
+ if (solv->noupdate.size)
+ map_empty(&solv->noupdate);
+ if (solv->noobsoletes.size)
+ {
+ map_free(&solv->noobsoletes);
+ map_init(&solv->noobsoletes, 0);
+ }
+ solv->updatemap_all = 0;
+ if (solv->updatemap.size)
+ {
+ map_free(&solv->updatemap);
+ map_init(&solv->updatemap, 0);
+ }
+ solv->bestupdatemap_all = 0;
+ if (solv->bestupdatemap.size)
+ {
+ map_free(&solv->bestupdatemap);
+ map_init(&solv->bestupdatemap, 0);
+ }
+ solv->fixmap_all = 0;
+ if (solv->fixmap.size)
+ {
+ map_free(&solv->fixmap);
+ map_init(&solv->fixmap, 0);
+ }
+ solv->dupmap_all = 0;
+ if (solv->dupmap.size)
+ {
+ map_free(&solv->dupmap);
+ map_init(&solv->dupmap, 0);
+ }
+ if (solv->dupinvolvedmap.size)
+ {
+ map_free(&solv->dupinvolvedmap);
+ map_init(&solv->dupinvolvedmap, 0);
+ }
+ solv->droporphanedmap_all = 0;
+ if (solv->droporphanedmap.size)
+ {
+ map_free(&solv->droporphanedmap);
+ map_init(&solv->droporphanedmap, 0);
+ }
+ if (solv->cleandepsmap.size)
+ {
+ map_free(&solv->cleandepsmap);
+ map_init(&solv->cleandepsmap, 0);
+ }
+
+ queue_empty(&solv->weakruleq);
+ solv->watches = solv_free(solv->watches);
+ queue_empty(&solv->ruletojob);
+ if (solv->decisionq.count)
+ memset(solv->decisionmap, 0, pool->nsolvables * sizeof(Id));
+ queue_empty(&solv->decisionq);
+ queue_empty(&solv->decisionq_why);
+ solv->decisioncnt_update = solv->decisioncnt_keep = solv->decisioncnt_resolve = solv->decisioncnt_weak = solv->decisioncnt_orphan = 0;
+ queue_empty(&solv->learnt_why);
+ queue_empty(&solv->learnt_pool);
+ queue_empty(&solv->branches);
+ solv->propagate_index = 0;
+ queue_empty(&solv->problems);
+ queue_empty(&solv->solutions);
+ queue_empty(&solv->orphaned);
+ solv->stats_learned = solv->stats_unsolvable = 0;
+ if (solv->recommends_index)
+ {
+ map_empty(&solv->recommendsmap);
+ map_empty(&solv->suggestsmap);
+ solv->recommends_index = 0;
+ }
+ solv->multiversionupdaters = solv_free(solv->multiversionupdaters);
+
/*
* create basic rule set of all involved packages
* so called: rpm rules
*
*/
+ initialnrules = solv->rpmrules_end ? solv->rpmrules_end : 1;
+ if (initialnrules > 1)
+ deduceq2addedmap(solv, &addedmap);
+ if (solv->nrules != initialnrules)
+ solver_shrinkrules(solv, initialnrules);
+ solv->nrules = initialnrules;
+ solv->rpmrules_end = 0;
+
if (installed)
{
/* check for update/verify jobs as they need to be known early */
switch (how & SOLVER_JOBMASK)
{
case SOLVER_VERIFY:
- if (select == SOLVER_SOLVABLE_ALL)
+ if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid))
solv->fixmap_all = 1;
FOR_JOB_SELECT(p, pp, select, what)
{
s = pool->solvables + p;
- if (!solv->installed || s->repo != solv->installed)
+ if (s->repo != installed)
continue;
if (!solv->fixmap.size)
- map_grow(&solv->fixmap, solv->installed->end - solv->installed->start);
- MAPSET(&solv->fixmap, p - solv->installed->start);
+ map_grow(&solv->fixmap, installed->end - installed->start);
+ MAPSET(&solv->fixmap, p - installed->start);
}
break;
case SOLVER_UPDATE:
if (select == SOLVER_SOLVABLE_ALL)
- solv->updatemap_all = 1;
- FOR_JOB_SELECT(p, pp, select, what)
{
- s = pool->solvables + p;
- if (!solv->installed || s->repo != solv->installed)
- continue;
- if (!solv->updatemap.size)
- map_grow(&solv->updatemap, solv->installed->end - solv->installed->start);
- MAPSET(&solv->updatemap, p - solv->installed->start);
+ solv->updatemap_all = 1;
+ if (how & SOLVER_FORCEBEST)
+ solv->bestupdatemap_all = 1;
+ if (how & SOLVER_CLEANDEPS)
+ {
+ FOR_REPO_SOLVABLES(installed, p, s)
+ add_cleandeps_package(solv, p);
+ }
+ }
+ else if (select == SOLVER_SOLVABLE_REPO)
+ {
+ Repo *repo = pool_id2repo(pool, what);
+ if (!repo)
+ break;
+ if (repo == installed && !(how & SOLVER_TARGETED))
+ {
+ solv->updatemap_all = 1;
+ if (how & SOLVER_FORCEBEST)
+ solv->bestupdatemap_all = 1;
+ if (how & SOLVER_CLEANDEPS)
+ {
+ FOR_REPO_SOLVABLES(installed, p, s)
+ add_cleandeps_package(solv, p);
+ }
+ break;
+ }
+ if (solv->noautotarget && !(how & SOLVER_TARGETED))
+ break;
+ /* targeted update */
+ FOR_REPO_SOLVABLES(repo, p, s)
+ add_update_target(solv, p, how);
+ }
+ else
+ {
+ if (!(how & SOLVER_TARGETED))
+ {
+ int targeted = 1;
+ FOR_JOB_SELECT(p, pp, select, what)
+ {
+ s = pool->solvables + p;
+ if (s->repo != installed)
+ continue;
+ if (!solv->updatemap.size)
+ map_grow(&solv->updatemap, installed->end - installed->start);
+ MAPSET(&solv->updatemap, p - installed->start);
+ if (how & SOLVER_FORCEBEST)
+ {
+ if (!solv->bestupdatemap.size)
+ map_grow(&solv->bestupdatemap, installed->end - installed->start);
+ MAPSET(&solv->bestupdatemap, p - installed->start);
+ }
+ if (how & SOLVER_CLEANDEPS)
+ add_cleandeps_package(solv, p);
+ targeted = 0;
+ }
+ if (!targeted || solv->noautotarget)
+ break;
+ }
+ FOR_JOB_SELECT(p, pp, select, what)
+ add_update_target(solv, p, how);
}
break;
default:
}
}
+ if (solv->update_targets)
+ transform_update_targets(solv);
+
oldnrules = solv->nrules;
FOR_REPO_SOLVABLES(installed, p, s)
solver_addrpmrulesforsolvable(solv, s, &addedmap);
{
solv->dupmap_all = 1;
solv->updatemap_all = 1;
+ if (how & SOLVER_FORCEBEST)
+ solv->bestupdatemap_all = 1;
}
if (!solv->dupmap_all)
hasdupjob = 1;
POOL_DEBUG(SOLV_DEBUG_STATS, "%d of %d installable solvables considered for solving\n", possible, installable);
}
- solver_unifyrules(solv); /* remove duplicate rpm rules */
- solv->rpmrules_end = solv->nrules; /* mark end of rpm rules */
+ if (solv->nrules > initialnrules)
+ solver_unifyrules(solv); /* remove duplicate rpm rules */
+ solv->rpmrules_end = solv->nrules; /* mark end of rpm rules */
+
+ if (solv->nrules > initialnrules)
+ addedmap2deduceq(solv, &addedmap); /* so that we can recreate the addedmap */
POOL_DEBUG(SOLV_DEBUG_STATS, "rpm rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024);
POOL_DEBUG(SOLV_DEBUG_STATS, "rpm rule creation took %d ms\n", solv_timems(now));
assert(solv->dupmap_all && !sr->p);
continue;
}
- if (!solver_samerule(solv, r, sr))
+ if (!solver_rulecmp(solv, r, sr))
memset(sr, 0, sizeof(*sr)); /* delete unneeded feature rule */
else
solver_disablerule(solv, sr); /* disable feature rule */
*/
solv->jobrules = solv->nrules;
- if (solv->cleandeps_updatepkgs)
- {
- queue_free(solv->cleandeps_updatepkgs);
- solv->cleandeps_updatepkgs = solv_free(solv->cleandeps_updatepkgs);
- }
for (i = 0; i < job->count; i += 2)
{
oldnrules = solv->nrules;
+ if (i && i == solv->pooljobcnt)
+ POOL_DEBUG(SOLV_DEBUG_JOB, "end of pool jobs\n");
how = job->elements[i];
what = job->elements[i + 1];
weak = how & SOLVER_WEAK;
p = queue_shift(&q); /* get first candidate */
d = !q.count ? 0 : pool_queuetowhatprovides(pool, &q); /* internalize */
}
+ /* force install of namespace supplements hack */
+ if (select == SOLVER_SOLVABLE_PROVIDES && !d && (p == SYSTEMSOLVABLE || p == -SYSTEMSOLVABLE) && ISRELDEP(what))
+ {
+ Reldep *rd = GETRELDEP(pool, what);
+ if (rd->flags == REL_NAMESPACE)
+ {
+ p = SYSTEMSOLVABLE;
+ if (!solv->installsuppdepq)
+ {
+ solv->installsuppdepq = solv_calloc(1, sizeof(Queue));
+ queue_init(solv->installsuppdepq);
+ }
+ queue_pushunique(solv->installsuppdepq, rd->evr == 0 ? rd->name : what);
+ }
+ }
solver_addjobrule(solv, p, d, i, weak);
+ if (how & SOLVER_FORCEBEST)
+ hasbestinstalljob = 1;
break;
case SOLVER_ERASE:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: %s%serase %s\n", weak ? "weak " : "", how & SOLVER_CLEANDEPS ? "clean deps " : "", solver_select2str(pool, select, what));
if ((how & SOLVER_CLEANDEPS) != 0 && !solv->cleandepsmap.size && installed)
map_grow(&solv->cleandepsmap, installed->end - installed->start);
+ /* specific solvable: by id or by nevra */
name = (select == SOLVER_SOLVABLE || (select == SOLVER_SOLVABLE_NAME && ISRELDEP(what))) ? 0 : -1;
+ if (select == SOLVER_SOLVABLE_ALL) /* hmmm ;) */
+ {
+ FOR_POOL_SOLVABLES(p)
+ solver_addjobrule(solv, -p, 0, i, weak);
+ }
+ else if (select == SOLVER_SOLVABLE_REPO)
+ {
+ Repo *repo = pool_id2repo(pool, what);
+ if (repo)
+ FOR_REPO_SOLVABLES(repo, p, s)
+ solver_addjobrule(solv, -p, 0, i, weak);
+ }
FOR_JOB_SELECT(p, pp, select, what)
{
s = pool->solvables + p;
break;
case SOLVER_UPDATE:
- if ((how & SOLVER_CLEANDEPS) != 0 && installed)
- {
- FOR_JOB_SELECT(p, pp, select, what)
- {
- s = pool->solvables + p;
- if (s->repo != installed)
- continue;
- if (!solv->cleandeps_updatepkgs)
- {
- solv->cleandeps_updatepkgs = solv_calloc(1, sizeof(Queue));
- queue_init(solv->cleandeps_updatepkgs);
- }
- queue_pushunique(solv->cleandeps_updatepkgs, p);
- if (!solv->cleandepsmap.size)
- map_grow(&solv->cleandepsmap, installed->end - installed->start);
- }
- }
POOL_DEBUG(SOLV_DEBUG_JOB, "job: %supdate %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
break;
case SOLVER_VERIFY:
break;
case SOLVER_LOCK:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: %slock %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
- FOR_JOB_SELECT(p, pp, select, what)
+ if (select == SOLVER_SOLVABLE_ALL)
{
- s = pool->solvables + p;
- solver_addjobrule(solv, installed && s->repo == installed ? p : -p, 0, i, weak);
+ FOR_POOL_SOLVABLES(p)
+ solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, i, weak);
+ }
+ else if (select == SOLVER_SOLVABLE_REPO)
+ {
+ Repo *repo = pool_id2repo(pool, what);
+ if (repo)
+ FOR_REPO_SOLVABLES(repo, p, s)
+ solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, i, weak);
}
+ FOR_JOB_SELECT(p, pp, select, what)
+ solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, i, weak);
break;
case SOLVER_DISTUPGRADE:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: distupgrade %s\n", solver_select2str(pool, select, what));
break;
case SOLVER_DROP_ORPHANED:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: drop orphaned %s\n", solver_select2str(pool, select, what));
- if (select == SOLVER_SOLVABLE_ALL)
+ if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid))
solv->droporphanedmap_all = 1;
FOR_JOB_SELECT(p, pp, select, what)
{
{
int j;
if (solv->nrules == oldnrules)
- POOL_DEBUG(SOLV_DEBUG_JOB, " - no rule created\n");
+ POOL_DEBUG(SOLV_DEBUG_JOB, " - no rule created\n");
for (j = oldnrules; j < solv->nrules; j++)
{
- POOL_DEBUG(SOLV_DEBUG_JOB, " - job ");
+ POOL_DEBUG(SOLV_DEBUG_JOB, " - job ");
solver_printrule(solv, SOLV_DEBUG_JOB, solv->rules + j);
}
}
solv->infarchrules = solv->infarchrules_end = solv->nrules;
if (hasdupjob)
- {
- solver_addduprules(solv, &addedmap);
- solver_freedupmaps(solv); /* no longer needed */
- }
+ solver_addduprules(solv, &addedmap);
else
solv->duprules = solv->duprules_end = solv->nrules;
+ if (solv->bestupdatemap_all || solv->bestupdatemap.size || hasbestinstalljob)
+ solver_addbestrules(solv, hasbestinstalljob);
+ else
+ solv->bestrules = solv->bestrules_end = solv->nrules;
+
+ if (hasdupjob)
+ solver_freedupmaps(solv); /* no longer needed */
+
if (1)
solver_addchoicerules(solv);
else
solv->choicerules = solv->choicerules_end = solv->nrules;
+ if (0)
+ {
+ for (i = solv->featurerules; i < solv->nrules; i++)
+ solver_printruleclass(solv, SOLV_DEBUG_RESULT, solv->rules + i);
+ }
/* all rules created
* --------------------------------------------------------------
* prepare for solving
map_free(&installcandidatemap);
queue_free(&q);
- POOL_DEBUG(SOLV_DEBUG_STATS, "%d rpm rules, 2 * %d update rules, %d job rules, %d infarch rules, %d dup rules, %d choice rules\n", solv->rpmrules_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);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "%d rpm rules, 2 * %d update rules, %d job rules, %d infarch rules, %d dup rules, %d choice rules, %d best rules\n", solv->rpmrules_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);
POOL_DEBUG(SOLV_DEBUG_STATS, "overall rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024);
/* create weak map */
MAPSET(&solv->weakrulemap, p);
}
+ /* enable cleandepsmap creation if we have updatepkgs */
+ if (solv->cleandeps_updatepkgs && !solv->cleandepsmap.size)
+ map_grow(&solv->cleandepsmap, installed->end - installed->start);
+ /* no mistakes */
+ if (solv->cleandeps_mistakes)
+ {
+ queue_free(solv->cleandeps_mistakes);
+ solv->cleandeps_mistakes = solv_free(solv->cleandeps_mistakes);
+ }
+
/* all new rules are learnt after this point */
solv->learntrules = solv->nrules;
makeruledecisions(solv);
POOL_DEBUG(SOLV_DEBUG_SOLVER, "problems so far: %d\n", solv->problems.count);
- /* no mistakes */
- if (solv->cleandeps_mistakes)
- {
- queue_free(solv->cleandeps_mistakes);
- solv->cleandeps_mistakes = solv_free(solv->cleandeps_mistakes);
- }
-
/*
* ********************************************
* solve!
void
solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res)
{
+ Pool *pool = solv->pool;
Map installedmap;
- pool_create_state_maps(solv->pool, &solv->decisionq, &installedmap, 0);
- pool_trivial_installable_noobsoletesmap(solv->pool, &installedmap, pkgs, res, solv->noobsoletes.size ? &solv->noobsoletes : 0);
+ int i;
+ pool_create_state_maps(pool, &solv->decisionq, &installedmap, 0);
+ pool_trivial_installable_noobsoletesmap(pool, &installedmap, pkgs, res, solv->noobsoletes.size ? &solv->noobsoletes : 0);
+ for (i = 0; i < res->count; i++)
+ if (res->elements[i] != -1)
+ {
+ Solvable *s = pool->solvables + pkgs->elements[i];
+ if (!strncmp("patch:", pool_id2str(pool, s->name), 6) && solvable_is_irrelevant_patch(s, &installedmap))
+ res->elements[i] = -1;
+ }
map_free(&installedmap);
}
}
}
}
+
+void
+pool_job2solvables(Pool *pool, Queue *pkgs, Id how, Id what)
+{
+ Id p, pp;
+ how &= SOLVER_SELECTMASK;
+ queue_empty(pkgs);
+ if (how == SOLVER_SOLVABLE_ALL)
+ {
+ FOR_POOL_SOLVABLES(p)
+ queue_push(pkgs, p);
+ }
+ else if (how == SOLVER_SOLVABLE_REPO)
+ {
+ Repo *repo = pool_id2repo(pool, what);
+ Solvable *s;
+ if (repo)
+ FOR_REPO_SOLVABLES(repo, p, s)
+ queue_push(pkgs, p);
+ }
+ else
+ {
+ FOR_JOB_SELECT(p, pp, how, what)
+ queue_push(pkgs, p);
+ }
+}
+
+int
+pool_isemptyupdatejob(Pool *pool, Id how, Id what)
+{
+ Id p, pp, pi, pip;
+ Id select = how & SOLVER_SELECTMASK;
+ if ((how & SOLVER_JOBMASK) != SOLVER_UPDATE)
+ return 0;
+ if (select == SOLVER_SOLVABLE_ALL || select == SOLVER_SOLVABLE_REPO)
+ return 0;
+ if (!pool->installed)
+ return 1;
+ FOR_JOB_SELECT(p, pp, select, what)
+ if (pool->solvables[p].repo == pool->installed)
+ 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;
+ }
+ }
+ }
+ }
+ return 1;
+}