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->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);
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 */
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)
{
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))
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 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;
/* 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
* use addedmap bitmap to make sure we don't create rules twice
* 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 */
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)
{
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))
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)
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));
*/
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_UPDATE:
- if ((how & SOLVER_CLEANDEPS) != 0 && installed)
- {
- if (how == SOLVER_SOLVABLE_ALL || (how == SOLVER_SOLVABLE_REPO && what == installed->repoid))
- {
- FOR_REPO_SOLVABLES(installed, p, s)
- {
- 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);
- }
- }
- 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:
{
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);
}
}
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);
}